本文旨在補充《超圖解Arduino互動設計入門》第十六章「網路家電控制」單元,增加另一個網頁控制範例,以及說明使用指標(pointer)設定多重字串陣列的語法。
本文將把《Arduino網路遠端遙控家電開關(一)》製作的HTML頁面,放到Arduino控制板上執行。首先把網頁裡面,不會變動的HTML碼和CSS樣式,存入Arduino的程式記憶體(相關說明請參閱16-4頁):
// 儲存HTML檔頭 P(htmlHead) = "<!doctype html><html>" "<head><meta charset='utf-8'>" "<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'>" "<title>arduino@home</title>"; // 儲存CSS樣式 P(myCSS) = "<style type='text/css'>body {font-family:'微軟正黑體','黑體-繁',sans-serif;background-color:#CCC;}\n" ".sw {margin:0 0.5em;font-weight:bolder;}\n" ".on {color:#F00;}\n" ".off {color:#090;}\n" "#lights {border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;background-color:#FFFFFF;padding:1px;}\n" "#lights ul {list-style-type:none;padding-left:0px;font-size:24pt;}\n" "#lights ul li {margin:10px 0;border-bottom:1px dotted #CCCCCC;padding-bottom:5px;}\n" "#lights ul li a {display:block;text-decoration:none;color:#000;}\n</style>"; // 儲存HTML頁腳 P(htmlFoot) = "</body></html>";
底下是Webduino程式庫所需,處理預設命令(亦即:顯示首頁)的程式碼(相關說明請參閱16-4頁):
void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) { server.httpSuccess(); if (type != WebServer::HEAD) { // 顯示網頁內容 showPage(server); } }
實際負責顯示網頁內容的程式碼,寫在名叫showPage()的自訂函數中,它接收一個WebServer類型的參數,透過這個參數,程式將能把網頁輸出給用戶端。
定義控制腳位編號及名稱
程式一開始,定義3個常數,儲存Arduino的控制輸出腳位,以及控制腳位的名字(如:”檯燈”和“熔岩燈”),好讓程式能產生動態頁面。
與控制腳位相關的3個常數定義如下:
// Arduino的輸出腳位編號 const byte swPins[] = {3, 5, 6, 7, 8, 9}; // 用指標陣列存放控制腳位名稱,參閱下文說明。 const char *swNames[] = {"檯燈", "壁燈", "吊燈", "落地燈", "熔岩燈", "藤球燈"}; // 共有6個控制輸出端 const byte NUM_OF_SW = 6;
Arduino官方的Ethernet以太網路控制板,當中的數位腳位編號4,保留給SD記憶卡的晶片選擇線使用,請不要挪做他用。
數位10~13腳是SPI介面的預設腳位,用於控制以太網路晶片,也請不要使用。
建立多重字串陣列指標
我們需要先定義好每個控制腳位的名稱,才能讓後續的迴圈程式取用。如5-15頁提到的,Arduino程式(C語言)採用陣列來存放字串,那麼,要儲存一組字串,就需要用到二維陣列了。
假設要在str陣列中儲存“str 1”, “str 2”和“str 3”這三個字串,底下兩種寫法都行:
假如每一組字串的長度不固定,元素的長度必須要確保能存入最長的字串,例如,以下的字串陣列中,“Android”佔7 個字元,因此元素的長度至少必須是8。
但是,那些用不滿8個字元空間的短字串(如:“iOS”),剩餘的空間就浪費掉了。
比較好的寫法是採用指標,如書本8-41頁提到,我們可以用指標變數來存取陣列元素。底下的敘述建立了一個包含3個指標元素的陣列,分別參照到3個字元陣列:
用指標記錄多個字串,就不會有空間被浪費掉。
因此,本程式透過一個名叫swNames的指標陣列,儲存6個控制腳位名稱。
動態顯示控制腳位狀態的網頁
讀取控制腳位值,並以HTML網頁形式輸出給用戶端的自訂函數,showPage()的程式原始碼如下,其中的for迴圈,將讀取6個控制腳位狀態,進而動態組成清單項目(<li>標籤)和超連結(<a>標籤)元素。
如果讀取到的數位腳是高電位,就在網頁上顯示ON;若是低電位,則顯示OFF:
接收並處理開關的查詢字串值
本單元的範例網頁裡的每個開關選項,都是超連結。每個選項連結都連到Arduino的自訂命令“sw”,並且附帶傳送id參數。例如,第一個選項的連結是“sw?id=0”,也就是以GET方式,傳送id為0的參數給sw頁面(請參閱16-31頁的「接收並處理透過GET方法傳送的查詢字串」單元):
本程式的setup()函數,指定將sw頁面的請求,交給自訂函數getCmd處理:
void setup() { // 設定輸出腳位 for (byte i = 0; i < NUM_OF_SW; i++) { pinMode(swPins[i], OUTPUT); } Ethernet.begin(mac, ip, gateway, subnet); webserver.setDefaultCommand(&defaultCmd); // 處理「首頁」請求 webserver.addCommand("sw", &getCmd); // 處理「sw頁面」請求 webserver.begin(); }
自訂函數getCmd()的程式原始碼如下,因為預期的參數(亦即,id)和數值(0~5),都沒有超過兩個字,因此,筆者將接收URL參數的陣列長度設定成3(含字串結尾的Null字元)。
下載Arduino網路遠端家電控制的原始碼
Arduino官方的以太網路擴充板(Arduino Ethernet Shield),大約消耗180mA電流(W5100晶片本身約消耗150mA);Arduino UNO Rev 3控制板本身約消耗50mA電流(參閱《認識與實驗Arduino的睡眠模式》這篇貼文),兩者合計約230mA。
測試時如果發生不穩定的狀況,例如,顯示的網頁不完整,或者無法如預期般接收參數控制的情況,請將Arduino控制板接上外接電源再測試,不要接電腦的USB電源供電。
我目前有個小問題
買的RFID為SPI介面
SPI使用網路上的副程式
我很好奇SPI中的MIMO是傳什麼資料出去
給我的電子標籤,使電子標籤能夠回傳資料到MOMI
還有所謂的SPI介面,MIMO式都發送固定的資料嗎??
所以只要把鮑率改成一樣就行了嗎
還有鮑率是只SCK的部分嗎??
你指的MIMO和MOMI應該是MISO和MOSI,它們都是序列訊號傳輸線(請參閱8-11頁說明),傳送的資料格式要看周邊設備而定,如8-20頁程式透過SPI介面,向MAX7219分別傳遞暫存器位址和資料,如果換成其他類型的IC,資料內容就不同了,詳細要查IC的規格書。
如8-44頁提到的,MAX7219的頻率上限是10MHz,只要時脈速率在這個範圍內,傳遞資料都沒問題。其他類型的IC需要查閱規格書。
thanks,
jeffrey
老師你好:
請教書本上:10-1 電路
5V —>經過電組 330 歐母,經過可變電組10K歐母,接到 LED 陽極
如無 330歐母,限流電組,當可變電組10K歐母,調到 0歐母時,會有大電流產生
那這樣5V與接地會短路,你指的大電流是這個意思?
那麼 LED 也會燒毀?
hi jxchen:
抱歉,剛剛發現10-2頁的可變電阻電路有誤,正確如下:
實際的接線圖大致像這樣:
其實直接把LED接上Arduino的5V,並不會燒毀,但是我不知道這樣可以維持多久。為了避免折損LED的壽命,請加上限流電阻。
thanks,
jeffrey
原來書本電路有錯,感謝老師的幫忙與解豁
感謝你讓我發現錯誤 😛
thanks,
jeffrey
請問作者大大:
上面的實體圖,是怎麼畫出來的,是有專用的軟體嗎?或是您自己畫的
因為現在學生真的要用這種圖,他們才看得懂,願意學,所以想請教作者是否有專用軟體以拉元件的方式來畫這種3D的立體圖,就我所知的只有FRITIZING有2D的元件符號,123D也是2D的元件符號,還沒看過3D實體的軟體,謝謝回復
tanj老師:
這些插圖是我用Flash軟體,搭配滑鼠畫出來的,並沒有使用現成的圖庫。
thanks,
jeffrey
請問老師
我看這個程式碼是使用迴圈的方式,偵測腳位是否為高電位,或是低電位。
原本的章節裡,可以delay(1000) 的方式來讓開關只開啟一秒鐘,
簡單說就是做成只接觸一下
因為我是要控制鐵捲門的,傳統上鐵捲門都是壓一下就有反應,不需要一直壓者。
迴圈程式應該怎麼改寫好? 先謝謝老師囉!
hi bullets:
可能因為減速齒輪比、門窗高度不同、機械老化…等因素,我們無法得知鐵捲門的精確捲動時間,所以不應該依據時間來決定要啟動多久。
鐵捲門通常都是採用類似下圖的結構,透過極限開關來判斷是否捲到底或者捲到頂:
當捲門往下移動時,程式要判斷是否碰觸到sw1開關;若往上捲,則判斷是否碰到sw0。
thanks,
jeffrey
老師,我了解你畫圖的意思
但是我目前遇上的問題是…..
我是把鐵捲門的 上、暫停、下 三個按鈕 (有通電)
我把這三個迴路裝進四路繼電器中,由Arduino UNO 去控制繼電器開關
我透過下列程式
digitalwrite(UP,High)
delay(1000)
digitalwrite(UP,Down)
這樣,就可以模擬出手指頭去觸碰開關按鈕,達成電路的接通
依照老師的意思是希望我去接極限開關,但是這要爬很高去尋找馬達裡的極限開關,其實不好找
所以我才使用牆壁上的按鈕開關,搭配繼電器控制
這篇教學的網頁控制,是比書上的漂亮多了
但是程式碼控制,是利用迴圈,尋找 i 的變化,來達到要嘛是ON , 要嘛是OFF
好像沒有辦法,讓原本是OFF 的按鈕,按下ON 後的一秒鐘,在自動轉回OFF 啊!
雖然稍微看得懂老師的程式碼,但是我自己卻不知怎麼改。
只好再次請教老師了….
showPage函數裡的迴圈只是讀取腳位的狀態,負責控制開關的是getCmd函數。因此,修改開關程式碼要從getCmd函數下手。
這是修改後的程式碼,將在按下任何開關後,自動在一秒鐘內關閉它。
另外,原始碼的HTML敘述的檔頭區,增加了每1秒更新(重新整理)並重新導向到首頁的敘述:
<meta http-equiv=’refresh’ content=’1;url=192.168.1.25′>
請將其中的IP位址改成你的IP位址。程式碼我沒有實機驗證過,應該可行。
thanks,
jeffrey
老師您好,
我測試過您的程式碼,原則上是可以使用….. (一秒鐘控制,沒有問題)
但是,
這段程式碼確有問題,我試跑後發現他會接在網址後面,並不會回到首頁
也就是說 http://192.168.1.25/192.168.1.25
請問老師這應該怎麼修正才好?
請將重新導向的敘述改成:
<meta http-equiv=’refresh’ content=’1′>
再測試看看,下載檔案已經更新。
thanks,
jeffrey
老師,我上傳修正後的程式碼….
結果變成,1秒後自動refresh,偏偏又是1秒中斷
這樣例如我切第一個按鈕後,結果繼電器就變成每1秒切斷一次,又重整,再切斷
陷入無限循環的窘境
我去查過老師的程式碼,html的自動導向程式碼的確是那樣寫的,
但是我搞不清楚這是為什麼,難道是函數不支援這樣寫嗎?
我明天會在控制板上測試看看。
thanks,
jeffrey
hi bullets:
會造成無限循環的原因是瀏覽器不停地重新整理,並傳送id=xxx的訊息,所以只要不帶URL參數地將瀏覽器導回首頁即可,請把meta敘述改成:
<meta http-equiv=’refresh’ content=’1;url=http://192.168.1.25′>
不過這種方式的缺點就是整個頁面會不停地更新,比較好的解決方式是透過JavaScript的XMLHttpRequest物件,或者jQuery的ajax方法,發起一個非同步的伺服端資料請求,這樣只需要更新部分頁面區域,不過這部份的背景概念已超出書本內容。
但是它們背後的基本概念是一樣的:Web伺服器無法主動傳遞資料給用戶端,因此前端必須主動反覆連線到伺服器端,才能獲得最新的資料。
此例更新畫面的目的,是要讓網頁上的控制按鈕能反映出被控制端的狀態(ON或OFF)。
如果不需要反映控制端的ON, OFF狀態(一般的控制器都是如此),就不需要加上meta敘述了。
另一個可以考慮的方向是,也許你可以建立一個類似定時器的「時間」值設定欄位,讓用戶輸入時間值來決定控制端的執行時間,按下按鈕之後,就交給Arduino執行,這樣也就不太需要持續更新頁面了。
thanks,
jeffrey
老師,有沒有Arduino Ethernet Shield R3版的教學
hi luck:
Ethernet Shield R3版,只是為了和Uno R3板相容,在板子上增加幾個接點,除此之外,硬體和程式庫和舊版都一樣。
thanks,
jeffrey
因為他宣告函數有小變動,想測試一個簡單的Web server,都連不到,老師寫的編譯不能成功(有些定義函數不同有改)
Arduino程式的作用是指揮Arduino控制板本體上的微控制器,無論我們替Arduino加上那一種介面或擴展卡,都不會影響程式編譯過程。
若出現編譯錯誤,那是程式本身或者程式庫有問題。
如果把Arduino的乙太擴展卡當成巴士,Arduino控制板就相當於司機;我們的程式是告訴司機如何開車,不是直接操縱車子。請問你的Arduino軟體是1.0.5版嗎?
thanks,
jeffrey
對,1.0.5-r2版
你用Arduino內建的範例,例如:檔案→範例→Ethernet→WebServer,編譯看看。
如果出現錯誤訊息,請把訊息內容張貼出來,謝謝!
thanks,
jeffrey
http://i.imgur.com/tPKvWm4.jpg
左邊是老師做的教學原始碼,會編譯錯誤(不太懂怎改,可能有宣告有點問題)
右邊是arduino提供的範例,是可以用
我有一台無線AP,網路插WAN_Port,桌電插port1,arduino插port3,有開NAT功能跟DHCP伺服器指派IP
桌電的DHCP指派的IP是192.168.2.101,順推arduino就是192.168.2.102
在Web Server範例裡面要改DHCP給的IP → IPAddress ip(192.168.2.102);
可以連,顯示的出網頁,但只能用在內網,要連到同的AP的網域IP才能顯是網頁(桌電跟UNO都是由DHCP指派的IP才連的到)
如果從外面的網路像手機3G(外網)要連近arduino這個Web Server,是連不到的
有辦法使用外網去連到arduino這個Web Server(對外可被連線的IP),小弟有疑惑的地方
謝謝老師很有耐心指導
從編譯的錯誤訊息可以看出,Arduino找不到指定的程式庫。請將Webduino和Streaming程式庫放入libraries資料夾,再重新啟動Arduino工具程式,即可順利編譯。
至於從外部連網到家裡的網路設備,你需要開啟路由器上的虛擬伺服器或DMZ,並且用ISP分配給你的IP位址連接。不同廠牌的路由器設定都太一樣,請搜尋相關關鍵字。
thanks,
jeffrey
用 arduino 1.0.6 無法complier 成功
請問能否提供這兩個 .h file?
“WebServer.h”
“Streaming.h”
謝謝
hi poundi:
Webduino 1.7版程式庫和Arduino 1.0.6版不相容,請改用1.0.5版編譯。”WebServer.h”包含在Webduino裡面,下載網址:
Webduino
Streaming
thanks,
jeffrey
老師,請問byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
是不是MAC=DE:AD:BE:EF:FE:ED
這是自定義MAC碼??一定要這樣嗎??如果自行另外定義一組mac碼可行嗎?
另外為什麼再無線ap裡面看不到Arduino Web Server他的名稱跟MAC號碼
指能看的到電腦的名稱,電腦的MAC
但是我設定虛擬伺服器,輸入DHCP指派的IP,他名稱顯示OFFLINE(應該是離線),卻可以使用(有測試實驗)
目前有初步的小成功,對外網要定義gateway跟subnet
是的,自定義的MAC位址可以修改,詳細請參閱15-8頁。
thanks,
jeffrey
老師您好,我最近在做Arduino WIFI相關的專題
但是我卡在WIFI設定好之後電腦可以連 但是不知道該從何下手
我的WIFI是要做成client端去連PC server
然後透過程式或虛擬網頁去連到APPserver
我應該在arduino裡面加甚麼
或是在server端加甚麼程式碼去抓取arduino wifi傳送的資料?
還有我想問,如果做成client端是否要一個AP?
那AP裡面有哪些必要的設定?
hi harry:
Arduino官網的WiFi程式庫頁面,有詳細列舉WiFi的詳細指令,並附帶範例程式碼,像WiFiWebClient(無線Web用戶端)範例。
你可以把Arduino + WiFi看待成一般的瀏覽器,它讀取的資料就是Web伺服器提供的內容,沒有什麼特別的設定。
我並沒有購買WiFi擴充介面,因為從DIY的角度來看,這個介面卡的價格可以購買兩、三個TP-LINK TL-WR703N無線路由器;而此無線路由器具備嵌入式Linux系統,與Arduino相連,發揮的空間比單純WiFi擴充卡大得多(呃…慚愧的是,它到現在還靜靜躺在我的抽屜裡…)
thanks,
jeffrey
老師您好:
您說的WiFiWebClient(無線Web用戶端)範例我有試過
但是他好像要一個AP,而AP的設定就直接預設值就可以了嗎?
另外我是使用WiFi擴充版 KSB004這個
裡面的手冊和範例也用過了
但是現在想要實作從Arduino中跑數值,透過WiFi讓它顯示在電腦上
不知道要如何使用…所以想問問老師
是要利用電腦跑程式碼讓他去抓嗎還是?
hi harry:
使用WiFi無線網路,當然要有無線基地台,不然怎麼連網?無線基地台並不需要為Arduino做特別的設定。
根據Arduino WiFi擴充板的官方說明頁,連接硬體的注意事項:
1. 數位7, 10~13腳,是WiFi擴充板與Arduino的通訊腳,請不要使用這些腳位。
2. 數位4腳,是WiFi板子上的SD記憶卡模組的晶片選擇(SS)腳位。
就像用電腦和手機連接WiFi網路之前,需要先搜尋並指定要連接的WiFi基地台一樣,Arduino程式也需要指定連接的WiFi基地台(透過SSID識別名稱),並且視情況設定密碼和IP位址。
底下的程式用於搜尋WiFi網路,並且在「序列埠監控視窗」顯示:
1. WiFI擴充板的MAC位址
2. 搜尋到的WiFi網路名稱(SSID)、訊號強度(Signal,dBm值)以及加密方式(Encryption)。
老師您好
我測試出來結果我的MAC位置都是0
這代表這塊WIFI版有問題嗎?
還是我沒有設定呢?
我也有將他RESET過了也還是顯示0:0:0:0:0
我的Serial顯示這些
Initializing Wifi…
MAC: 0:0:0:0:0:0
Scanning available networks…
** Scan Networks **
number of available networks:0
我有開著AP但也是搜尋不到
用家裡的數據機的WIFI也不能…
官方的WiFi擴充板有下列四個燈號:
L9(黃):連接到數位9腳
LINK(綠):亮燈代表已連上網路
ERROR(紅):亮燈代表通訊錯誤
DATA(藍):在傳送與接收資料時會閃爍
不過,如果連板子的MAC位址都讀不到,WiFi擴充板可能有問題…
thanks,
jeffrey
老師您好
那這樣這塊板子就不能用了嗎?
有甚麼方法解決嗎?
另外既然他沒辦法顯示MAC Address
那為什麼他能夠用內建的程式碼…
我有用它內建程式碼變成AP
然後電腦和手機能夠連上
但就是沒辦法搜尋到附近AP…
所以一直沒辦法使用範例程式碼來測試
這樣的話,擴充卡的硬體本身沒有故障,應該能透過更新韌體解決。官網Upgrading the WiFi shield firmware這篇貼文有詳細的說明(需要透過Flip軟體更新HDG104和AT32UC3兩個韌體)。
很抱歉,我沒有這張擴充卡,無法示範詳細的步驟。
thanks,
jeffrey
老師您好:
我想在你的程式再結合藍芽控制
但結合後某些腳位不能控制
能幫我看看是什麼問題嗎
謝謝
char val1;
int relay1=8;
int relay2=7;
int relay3=6;
int relay4=5;
int relay5=3;
void setup()
{
Serial.begin(9600); // 設定Serial 傳輸速度
pinMode(relay1,OUTPUT);
pinMode(relay2,OUTPUT);
pinMode(relay3,OUTPUT);
pinMode(relay4,OUTPUT);
pinMode(relay5,OUTPUT);
}
void loop()
{
val1=Serial.read();
switch(val1)
{
//////////////////////////////////////////////////////////////////////////////////
case ‘q’ :
digitalWrite(relay1,HIGH); //
break;
case ‘a’ :
digitalWrite(relay1,LOW); //
break;
//////////////////////////////////////////////////////////////////////////////////
case ‘w’ :
digitalWrite(relay2,HIGH); //
break;
case ‘s’ :
digitalWrite(relay2,LOW); //
break;
//////////////////////////////////////////////////////////////////////////////////
case ‘e’ :
digitalWrite(relay3,HIGH); //
break;
case ‘d’ :
digitalWrite(relay3,LOW); //
break;
/////////////////////////////////////////////////////////////////////////////////
case ‘r’ :
digitalWrite(relay4,HIGH); //
break;
case ‘f’ :
digitalWrite(relay4,LOW); //
break;
/////////////////////////////////////////////////////////////////////////////////
case ‘t’ :
digitalWrite(relay4,HIGH); //
break;
case ‘g’ :
digitalWrite(relay4,LOW); //
break;
/////////////////////////////////////////////////////////////////////////////////
}
}
hi leo:
檢查序列埠是否有新的資料傳入,請使用Serial.available()方法(請參閱5-21頁說明),程式碼改成:
thanks,
jeffrey
您好 想請問
如果想用Ardunio利用WIFI取得上網後,
再結合RFID模組,將偵測到的卡號傳到網頁該怎麼做呢?
hi tang:
妳的問題範圍太大,應該要分成:
1. 先搞懂網路概念
2. 使用HTML製作出你需要的網頁
3. 實驗把你的HTML置入Arduino的Web伺服器程式
4. 實驗將RFID數值存入陣列,並顯示在Arduino的「序列埠監控視窗」。
5. 把上面兩個程式結合在一起。
以上的內容,書本都有提到。
have fun!
jeffrey
老師您好
我把問題整理成google 文件
懇請老師協助
感謝您
https://docs.google.com/presentation/d/18G0bSK1awzOl4ekyd_rhlWsjGAXbJofY7rElEaNlqqA/edit#slide=id.p
hi 小藍:
以太網路卡採用SPI介面與Arduino連線,所以CS腳一定要接(請參閱8-11頁說明),請先接在第10腳看看。
關於Leonardo板的SPI腳位,請參閱Arduino Leonardo控制板的數位14~17腳、類比A6~A11腳以及SPI腳位介紹
thanks,
jeffrey
老師您好:
依本單元的程式,想再增加書本中16_1_3監控遠端的溫濕度值,請老師指點 , 感謝您.
hi ming:
DIY-16-1的程式碼就是把溫濕度值顯示在網頁上,因此,你只要按照該程式輸出網頁的敘述寫法,應用在本文的頁面即可。
thanks,
jeffrey
老師您好:
1. 我在P(htmlHead)中 , 有加入這一行”” , 但溫度無法自動更新 .
2. 程式碼不知要如何傳給老師指導.
謝謝!
咦?請問你加入的refresh(重新整理頁面)敘述是類似這樣嗎?
have fun!
jeffrey
老師你好,我想請教一下,關於我想使用手機上網連線是ARDUINO
我在程式中的IP改成我宿舍分配給我的IP
static byte mac[] = { 0xF0, 0x7B, 0xCB, 0x4B, 0x7C, 0x9F };
IPAddress ip(192, 168, 1, 178);
IPAddress subnet(255, 255, 255, 0);
IPAddress gateway(192, 168, 1, 1);
但手機測試後無法連線
是因為宿舍的網路關係還是我需要實體IP還是我需要在程式裡更改什麼設定呢
麻煩老師了
hi 默默:
請先用宿舍中,相同網域(區域)的電腦連結看看。如果你的手機是用3G/4G上網,那肯定連不上宿舍的Arduino,因為學校分配給你的是區域網路IP。
thanks,
jeffrey
老師您好
我想用網路控制舵機轉動
ON是將舵機轉到90度
OFF是將舵機轉到10度
請問我程式應該如何修改呢
伺服馬達的控制程式挺簡單的,請先參考動手做11-1單元的「自製機械手臂」程式原始碼,自己改寫看看。
thanks,
jeffrey
趙老師,想請教一下:
小弟買了一塊網路擴充模組 w5100 ,
http://arduino.cc/en/Main/ArduinoEthernetShield
它不是應該有提供 poe 供電的功能嗎?
我把它接上有 poe 供電功能的 switch 上,網路卡上的燈號卻沒有亮起來呢?
請教:
是還有什麼地方有設定之類的嗎?
hi honda:
W5100模組只有預留PoE模組的焊接孔,PoE功能需要額外購買Ag9000-S系列模組並自行焊接,像這個Ag9120-S模組。
thanks,
jeffrey
再次請敎老師:
查了半天有關arduCam 如:OV2640攝影機的使用,
觀念上始終無法將arduino和arduCam在軟硬體上成功的串接起來
不知老師是否有 arduino 連結 ArduCAM 的線路圖及程式碼的文章,
可讓我解惑..
謝謝
ArduCam是對岸的創客研發出的產品,你可以在他們的官方網站找到教學文件和範例程式,我沒有這塊介面卡。或者,你也可以向經銷商索取相關資料。
thanks,
jeffrey
老師您好:
請教老師
如果有8個輸出腳2,3,4 5, 6, 7, 8, 9
將使用2 3 4輸出腳,當按下按鈕啟動,已跑馬燈的形式隨機亮燈,在按一下停止,這應該要如何做呢?
如果運用這篇的Code 應該要如何改成隨機亮燈呢?
hi ted:
根據你的程式需求,我大概會這樣寫:
建立一個陣列,儲存LED燈腳位。
依據腳位數量,隨機產生一個值。
把隨機值當作陣列的索引,點亮該陣列元素存放的LED腳位。
產生隨機值,如果隨機值和之前的相同,就再產生一個隨機值,直到不同為止。
熄滅目前的LED。
:
請拿出筆、紙,把自己的想法整理一遍。這些基本指令書本裡面都有談到。
thanks,
jeffrey
感謝老師的回覆
我是有用random這指令,到老師這個Code來做測試,當按下按鈕確實會動作,不過網頁OFF按鈕沒切換到ON按鈕,程式也成無限迴圈的狀態,網頁就當了,有沒有辦法讓他等待我再按一次按鈕停止動作呢?
你的意思是,當Arduino隨機閃燈時,網頁也「同步」顯示LED狀態嗎?因為上文的程式會在Arduino每次改變狀態時,就更新網頁給前端,考量到Arduino的效能和網路所造成的延遲,你可能需要重新思考一下解決方案。
如果閃爍的頻率不高,或許用AJAX網頁可以辦到;也就是當LED燈狀態改變,Arduino可以向網頁發出一段JSON資料,例如:{“on”:2}代表目前點亮的是第2腳,網頁的JavaScript解析之後,再更新網頁畫面。
另外兩個可行的「非同步」方式:
1. 隨機ON, OFF動畫交給JavaScript處理,等到用戶在手機按下某按鈕,再送出訊號交給Arduino點亮。
2. 隨機點亮Arduino的LED燈,網頁上呈現「處理中」之類的訊息,等用戶按下按鈕,Arduino傳回點亮的LED更新畫面。
have fun!
jeffrey
感謝老是這麼認真地回覆
我看到這裡個網址是讓兩顆 LED 交互閃爍開關切換,跟我要做的是很接近
http://webduino.io/tutorials/tutorial-02-2led.html
不過看完了他的Code之後,不是清楚要如何改寫在Arduion 上面測試
><"
能麻煩老師 給個寫個範例參考嗎? Orz
你修改的程式會讓網頁「當掉」,應該是處理頁面內容的函式,例如getCmd(),當中的迴圈沒有終止。
defaultCmd()和getCmd()函式用於處理「網頁」相關內容;若要讓Arduino反覆執行一段程式碼(如:閃爍LED),請將它放在loop()函式。
例如,你可以先宣告一個全域變數,儲存LED的狀態:
接著在getCmd()或者你設定的函式中,接收HTML表單值,並藉此設定LED的狀態:
建立一個讓LED閃爍的自訂函式:
在loop()函式中呼叫閃爍LED的函式:
大致上就是這樣,建議你先從閃爍單一LED開始實驗,再改成多個LED的版本。
thanks,
jeffrey
Jeffrey 您好
我現在正在練習「動手作 16-5 使用繼電器控制家電開關」
請問如果我不想要破壞原有家電的電源線以做到智慧家電,
我能不能用以下的電路連線方式達到同樣的目的?
這樣的線路安排是ok的嗎?謝謝
https://www.evernote.com/l/ADTecocvnSdI2bg7iLFIbI9z0-wPR1dVTu0
沒錯!我也是用延長線改的。
have fun!
jeffrey
Dear Jeffrey
謝謝您這麼快速的回應
再請問您一個問題
網路上看到一種說法︰
為了怕電壓過大,
所以可以在繼電器裝上保險絲。
請問您是否知道這部份應當如何實作?
謝謝!
保險絲通常是保護電路不受過大的電流破壞,如果有疑慮,你應該挑選耐電流大一點的繼電器,而不是加裝保險絲。或者,你可以將繼電器焊接在具備「過電流保護」的延長插座,這樣最簡單,
thanks,
jeffrey
感謝^_^~老師的解惑 測試了一段時間,終於有看到效果了
不過還有問題要請教老師,我是使用2~9的輸出,設計6個按鈕,而前三個輸出(2~4)為一個按鈕來控制隨機變燈,其他輸出各自對應1個按鈕,遇到問題就是當我按下隨機變燈時,按鈕確實有動作,可是接著我按其他按鈕的時候,它直接關掉我”隨機變燈”按鈕的動作
><"~Oh My God!
而且"隨機變燈"按鈕換會有延遲(思考中…),還有老師之前提到的產生隨機值,如果隨機值和之前的相同,就再產生一個隨機值,直到不同為止。
我有想過這個問題,不過不知道該如何寫,有嘗試用randomSeed看不出效果…
以下測試是修改老師的Code 麻煩老幫我檢查看看…
https://mega.co.nz/#!CQgkyZTS!12hQCaWRHfjA_Q6bZQ_M6daPQ85p-8QhohmriIecH-k
檢查數值是否重複的方法,最簡單就是用一個迴圈,比較目前的值和之前的值,如果一樣,就再產生一個,直到不同為止。因為電腦的執行速度很快,用戶不會察覺這一點延遲。
thanks,
jeffrey
謝謝老師這麼快速的回應^_^
不過我這問題是不知要如何解決,我設了6個按鈕,第1個按鈕控制2~4的輸出來做隨機變燈的功能,按下第1個按鈕時,功能有在動作,當按其它5個按鈕時,本身對應按鈕的功能有動作,不過卻把第1個按鈕的功能給關掉了….不知到程式哪邊干擾到了><"
以下是測試的Code 麻煩老師幫我看一下 謝謝
https://mega.co.nz/#!CQgkyZTS!12hQCaWRHfjA_Q6bZQ_M6daPQ85p-8QhohmriIecH-k
老師你好 之前提到的問題已處理好了…
不過我剩下最後一個問題是,我設6個按鈕中的第1個按鈕為(隨機
亮燈)的功能,當按下按鈕功能雖有正常運作,不過按鈕上的OFF文字
不會切換為ON文字,點即確實有開跟關的功能,其他5個按鈕都正
常運作….這發生了甚麼事(卻只有第1個按鈕有問題><")
能麻煩老師幫我看下這Code 哪邊寫錯嗎?
https://mega.co.nz/#!6dIxRAAb!YhSCFFdh7SRdVaw8MUd5kV-fBVTtwBan55GarFuWdlY
老師你好~之前提到到問題 都處理好了 ^^”
這邊還有個問題是,當我按下第1個按鈕讓2~4輸出為隨機亮燈,其餘5個按鈕單純的切換開關,可是第1個按鈕卻無法切換Button上的文字OFF 變 ON,功能還是有動作,而其他5個按鈕都可正常切換,真不知道哪邊寫錯了而干擾到第1個按鈕嗎?
想請老師幫我看看哪邊寫錯了…
https://mega.co.nz/#!6dIxRAAb!YhSCFFdh7SRdVaw8MUd5kV-fBVTtwBan55GarFuWdlY
因為showPage()函式依據腳位的狀態顯示ON, OFF,你可以改寫其中的判斷條件 digitalRead(swPins[i]) == 1 敘述,改用一個陣列暫存ON, OFF狀態值,不要直接讀取數位腳的狀態,或者額外加入切換顯示第一個按鈕的程式碼。
have fun!
jeffrey
老師你好
我想說在接完整個電路之前
先測試是否能夠開關燈
所以我把pin腳位改到13去控制板上的電燈
是可以開燈
但都是按一下 閃一下 而且網頁上一直都是顯示off
想問老師要怎麼修正 因為我不太懂用web控制的方法嗚嗚 ˊˋ
hi kevin:
乙太網路卡採用SPI介面與Arduino相連(請參閱15-24頁),所以第13腳不能挪作他用。
thanks,
jeffrey
對耶對耶
謝謝老師的迅速回覆太感動了嗚嗚嗚
居然忘記這麼重要的東西還在那蝦改哈哈 = =
老師你好
我想請問網路家電控制這個單元,如何用時間來控制,就是可以自行設定時間(10分鐘、1小時…等),他會自動開跟關,這要如何處理呢?
hi ted:
需要長時間計時的場合,建議搭配採用I2C介面的DS1307即時鐘IC,市面上很容易買到這種模組。搭配RTClib程式庫,可輕鬆設置定時觸發的時間。以RTClib提供的DS1307範例程式為例:
// 取得現在的時間
DateTime now = rtc.now();
// 未來一小時的時間
// 註:60分 x 60秒 = 3600秒
DateTime future (now.unixtime() + 3600);
在你的loop()函式中,不停地讀取目前的時間,再和預設的「未來」時間相減,即可判斷是否已到預設的時間,例如:
// 取得現在的時間
DateTime now = rtc.now();
:
if (future – now.unixtime() <= 0) {
// 時間到…執行開關動作
// 重新設定future時間
future (now.unixtime() + 3600);
}
另外,你也可以參考並改寫datecalc(日期計算)的範例程式。
thanks,
jeffrey
感謝老師這麼快的回覆
所以說要做到設定時間的功能,就需要用到DS1307即時鐘IC囉!
他最多可控制多少個開關的時間呢? 例如:開關A設5分鐘開,開關B設10分鐘開,會衝突道嗎?
而我要如何從網頁傳送信號到Arduino板上,他才知道我所設定的時間。
我來研究看看….
DS1307晶片的作用是提供微處理器一個穩定的時間資料,「定時」功能是靠自訂的程式完成,跟DS1307晶片無關。所以,如果你設定了5個「定時」時段,那就寫5個判斷條件…至於從網頁傳出資料,用POST或GET方法都行。
thanks,
jeffrey
老師你好
請問那使用millis()可以做到「定時」功能嗎?
老師書上是寫,當按下按鈕跟放開的時間相減,就知道按了多少時間,那當我按下按鈕儲存他的現在時間,再和預設的「未來」設定的時間相減要如何做呢?
下面程式當時間大於10秒就會亮,不過這時millis()遠遠大於10秒,例如要做到按下10秒後亮,再按一次10秒後關….
void Timer()
{
if(LED_State)
{
time = millis();
if(time >10*1000)
{
digitalWrite(2, HIGH);
}
}
}
可以用millis()計算經過時間,但是,其實Arduino已經有多個計時器相關程式庫可用,像SimpleTimer,它已經幫我們把millis()包裝成簡易使用的計時程式。
請在此SimpleTimer的GitHub頁面下載程式庫,底下是取自arduino.cc上的範例程式碼:
其中,setInterval()會不停地執行指定的函式,setTimeout()則會在時間到時,執行一次指定的函式,你可以利用它來撰寫定時執行的程式。
thanks,
jeffrey
謝謝老師得回覆
那使用SimpleTimer的話,要如何讓他當按下按鈕就開始計時,例如10秒後亮燈,在按一次按鈕10秒後熄燈呢?
而下面是用老師書上13-39範例來修改
https://mega.co.nz/#!PYREGJQB!wJU6zq7NJKoKYvx8l8rVr6nfjmH7g_aDN6-_c_Ft5gc
當我按下按鈕(網頁顯示SET)開始計時10秒後,輸出PIN2 LED有亮,當我在按一次,以樣開始計時10秒後LED就暗。
我現在遇到的問題是,當開始計時途中,再按下按鈕如何將計時功能關掉呢?
還有就是按下按鈕時,網頁顯示按鈕是紅色,如果當計時結束或中斷如何讓他變回綠色呢?應該說要如何讓他知道計時結束或中斷…
使用SimpleTimer程式庫,只要告訴它「幾微秒之後」要觸發哪個函式即可。以底下的程式碼為例,在序列埠監控視窗輸入’1’,即可打開LED,過了10秒之後,LED就熄滅:
這開關的邏輯蠻單純的,其餘部份就麻煩你動腦筋了。
thanks,
jeffrey
老師你好
有個問題就是,如何像設定鬧鐘的方式,譬如說按下開關要鬧鐘12:00響,在時間還沒到的期間,就把它關掉,當然12:00不會響了。
開始計時的時間內如何讓他停止計時(暫停),時間到了也不會有動作…Orz
搭配ds1307即時鐘模組就沒有這個問題了,它就像使用電池運作的時鐘一樣,即使電器產品因為停電而無法運作,時鐘仍舊繼續轉動。模組使用的水銀(鋰)電池,足夠它運作好幾年。
謝謝老師的回覆
不好意思再次倒擾…
其實我想的功能不是要,當電器產品因為停電而無法運作,時鐘仍舊繼續轉動 ><"。
是當在已設定好的時間內,按下啟動才開始計時,而在計時的這段期間臨時或突然不想要計時,因該如何中斷計時器,就像給計時器一個開關一樣。
最近試了好久還是想不出如何控制….
老師你好~~~
我想詢問一下
我們是用cc3000wifi模組+三軸+arduino uno 板來做專題
在cc3000 wifi 模組上架設一個網站來接收三軸的值
然後利用手機的APP去抓取網站上的值並判讀他的資料
我們是利用網路上提供的範例程式來修改
目前我們已可以連線
但在連線的部分
發現如果cc3000連手機分享出來的行動網路
要從別人手機裡看到網頁
別人的手機也必須連上同一個行動網路然後輸入他產生出來的ip才有辦法看到網頁裡的東西
那我們應該要怎麼樣修改或是怎麼做,任何人只要在有網路的情況下在瀏覽器上打ip就可以看到網頁呢~~
hi kirby:
你要設定讓cc3000 wifi模組連接到無線網路基地台;一般的基地台都具備虛擬伺服器(virtual server)或者虛擬非軍事區(DMZ)的功能,讓你指定將某個IP的裝置(如:cc3000 wifi模組)公開到網際網路上。
詳細的設定方式請參閱說明書或洽詢廠商。
thanks,
jeffrey
老師你好 最近研究了一陣子 還是不知如何來暫停計時的功能,麻煩老師幫我看以下 感激…
我修改的Code
https://mega.co.nz/#!vJYyHQIZ!kEYxH8IDVNGNOB6KXXHbTjBD6Q80iTzxTSAokmdMjeo
hi ted:
SimpleTimer程式庫本身就有提供暫停計時的功能,函式名稱叫toggle()。
底下的程式使用setInterval()每秒執行一次repeatMe()。在序列埠監控視窗輸入’1’即可啟動計時器,輸入’2’可暫停或重新啟動計時器:
thanks,
jeffrey
謝謝老了回覆 研究了之後現在知道如何使用了 謝謝
老師寫的Code 是可以寫是讓秒數在 Serial Monitor顯示,我有嘗試顯示在網頁上,不過他都只會顯示一開始的秒數出值,如果按刷新網頁是可以看見秒數有在變化,不過這樣按刷新又會再觸發計時的功能
老師你好
如果我要讓顯示秒數在網頁上呈現應該要如何做,雖然有顯示出開始的出值,不過要一直按重新仔入才看到數字的變化,不過這樣也導致相同的功能也一直的重複觸發,這應該要往哪邊做修改呢?
在網頁前端執行計時功能,需要透過JavaScript語言執行,網路上有很多相關的例子,市面上也有不少JavaScript書籍,再麻煩自行參考。
thanks,
jeffrey
老師你好:
我有看書上的 家電控制範例,裡面有用POST來傳遞使用者輸入的”你好”。
我有一些問題想請教老師:
1. 怎麼讓網頁(webduino) 開啟一個.txt檔,讓裡面的文字可以透過網頁來傳遞?
2. 在網頁上要怎麼加上 copy、paste 的功能? webduino有支援嗎?
3. 可以讓輸入網頁的資料分批送過來嗎? 網頁可以自己做字元辨識,並轉成數值,送給Arduino嗎?
hi brian:
畢竟Arduino UNO只是個8位元控制器,效能有限,當作網路控制器的終端沒問題,例如,接收命令控制電器的開關,或者傳回感測器的數據。
但是你的需求比較像是架設一般功能的網站(非控制器或感測器節點),像剪貼或字元辨識功能,那是透過瀏覽器端執行的JavaScript程式完成,跟後端(如:Arduino或其他網站伺服器程式)沒有直接的關聯性。
thanks,
jeffrey
老師您好!
我使用您的程式碼後
出現
diy16_6.ino:7:23: fatal error: WebServer.h: No such file or directory
compilation terminated.
編譯時發生錯誤
不知道是甚麼情況呢?
新手上路><
hi joe:
當你看到錯誤訊息中,出現某某.h檔發生錯誤時,通常都是Arduino找不到程式庫檔案。
另外,若你使用的Arduino編輯器是1.0.5之後的版本,請確認你有複製新版的Webduino程式庫,請參閱「《超圖解Arduino互動設計入門》第二版補充說明」。
thanks,
jeffrey
老師您好:
我使用你動手做的第16個單元,所提供的範例去測試,程式裡
我有修改的部分如下(我用1024個數字字元去測試):
1.
char name[16], value[10001];
while (server.readPOSTparam(name, 16, value, 10001))
我發現,每次只要宣告為如此,瀏覽器就跳不到SW網頁,它
會一直等在form。
2.
char name[16], value[1025];
while (server.readPOSTparam(name, 16, value, 1025))
網頁有正常秀出1024個字
3.
char name[16], value[10001];
while (server.readPOSTparam(name, 16, value, 1025))
瀏覽器就跳不到SW網頁,它在form網頁等待。
4.
char name[16], value[501];
while (server.readPOSTparam(name, 16, value, 10001)){ 網頁秀出2048個字,有效的(跟pattern一樣的約600個)
從以上的結果來看,還是看不出來,問題到底卡在哪裡?
第4個情況更怪?
老師,我想要達成透過網頁送給arduino,10000個字元,並正確
秀在網頁上的目標,請老師指引,謝謝。
因為ATmega328P處理器的SRAM(主記憶體)只有2KB。你的需求,在個人電腦或Raspberry Pi之類的Linux微控制器,執行PHP, Node.js等的後端程式,很容易完成。
如同我之前的回應,Arduino適合當作網路控制器或感測器節點,若需要大量的資訊處理機能,請選用其他控制器。
thanks,
jeffrey
謝謝老師的回覆,我目前還是想選用Arduino 板。
我手上的控制器是 Arduino Mega 2560,SRAM有8K。
我也試著將 value[10001],存入程式記憶體了,可是還是不行。
請問老師,到底是卡在哪裡呢? 是 Arduino記憶體不夠,還是網頁function等的問題? 請老師指引,謝謝。
你可以使用MemoryFree程式庫,參考範例檔測試剩餘的可用記憶體。
thanks,
jeffrey
老師你好
我想判斷輸出腳的電位
再用XBEE來傳字元訊號
這是我寫的
val=digitalRead(3);
switch(val)
{
case (HIGH):
Serial.print(‘A’);
delay(5000);
break;
case (LOW):
Serial.print(‘B’);
delay(5000);
break;
}
可是XBEE會瘋狂一直傳字元 我只能藉由delay來減緩的一直傳送字元的速度
有沒有辦法把它改成傳送一次就好 直到的電位改變 在傳送一次呢?
從你的程式看來,你的XBee模組應該是設置成AT命令模式(請參閱「XBee模組通訊實驗(四):廣播通信、AES 加密及AT命令模式」),那麼,XBee模組只會在序列埠有資料輸入時,才會發送訊號,因此並不需要加入delay()敘述。
請檢查你的XBee模組設定,看看是否不小心更動到API模式(AP)或取樣速率(IR)等設置。
thanks,
jeffrey