2016/04/10

Arduino Yún:範例草稿碼Bridge、從瀏覽器操控腳位

這一篇玩玩Bridge程式庫裡的BridgeServer(舊稱YunServer)與BridgeClient(舊稱YunClient)這兩個類別,程式碼主要都來自於Arduino官方範例草稿碼Bridge

我的Yún與開發主機位於同一個區域網路內,我的Arduino軟體開發環境是1.6.7版。首先從瀏覽器登入Yún,開啟REST API存取權限為OPEN。

底下是範例程式碼,這支程式碼的功能是讓我們從別台電腦的瀏覽器控制Arduino的腳位。

#include <Bridge.h>
#include <BridgeServer.h>
#include <BridgeClient.h>

// Yún的網站伺服器,會把所有HTTP請求(/arduino)轉送給BridgeServer
BridgeServer server; // 預設會聆聽連接埠5555

void setup() {
    Serial.begin(57600);
    while(!Serial && millis() < 9000){
    }
   
    Serial.print("Starting Bridge...");
    Bridge.begin();
    Serial.println("done.");

    // 只接受從localhost來的連線
    server.listenOnLocalhost();
    server.begin();
}

void loop() {
    // 不斷呼叫accept,檢查是否有連線
    BridgeClient client = server.accept();

    // 若client有值,代表有連線
    if(client){
        process(client); // 處理請求
        client.stop(); // 關閉連線,也會釋放掉相關資源
    }

    delay(50); // 暫停50毫秒
}

void process(BridgeClient client) {
    // 讀取URL網址
    String command = client.readStringUntil('/');

    // 判斷,做該做的事情
    if(command == "digital"){
        digitalCommand(client);
    }
    else if(command == "analog"){
        analogCommand(client);
    }
    else if(command == "mode"){
        modeCommand(client);
    }
}

void digitalCommand(BridgeClient client){
    int pin, value;

    pin = client.parseInt(); // 哪個腳位
   
    if(client.read() == '/'){ // 若下個字元是'/'
        // 代表這個URL應會類似於"/digital/13/1",要寫入
        value = client.parseInt();
        digitalWrite(pin, value);
    }
    else{ // 若不是,則是讀取
        value = digitalRead(pin);
    }

    // 回送回應給瀏覽器
    client.print(F("Pin D"));
    client.print(pin);
    client.print(F(" set to "));
    client.println(value);

    // 把腳位狀態儲存在內部的鍵值配對空間
    String key = "D";
    key += pin;
    Bridge.put(key, String(value));
}

void analogCommand(BridgeClient client) {
    int pin, value;

    pin = client.parseInt();

    if(client.read() == '/'){
        value = client.parseInt();
        analogWrite(pin, value);

        client.print(F("Pin D"));
        client.print(pin);
        client.print(F(" set to analog "));
        client.println(value);

        String key = "D";
        key += pin;
        Bridge.put(key, String(value));
    }
    else{
        value = analogRead(pin);

        client.print(F("Pin A"));
        client.print(pin);
        client.print(F(" reads analog "));
        client.println(value);

        String key = "A";
        key += pin;
        Bridge.put(key, String(value));
    }
}

void modeCommand(BridgeClient client) {
    int pin = client.parseInt();

    // 下個字元必須是'/'
    if (client.read() != '/') {
        client.println(F("error"));
        return;
    }

    String mode = client.readStringUntil('\r');

    if(mode == "input"){
        pinMode(pin, INPUT);
       
        client.print(F("Pin D"));
        client.print(pin);
        client.print(F(" configured as INPUT!"));
    }
    else if(mode == "output"){
        pinMode(pin, OUTPUT);
       
        client.print(F("Pin D"));
        client.print(pin);
        client.print(F(" configured as OUTPUT!"));
    }
    else{
        client.print(F("error: invalid mode "));
        client.print(mode);
    }
}


然後從別台電腦的瀏覽器,輸入類似底下的網址,請把arduino.local換成你的Yún的IP位址。當Yun看到網址「/arduino」時,不會做什麼處理,都會轉交給草稿碼(ATmega32U4)。

把腳位13設為輸出模式:
http://arduino.local/arduino/mode/13/output
瀏覽器上會看到回應:
Pin D13 configured as OUTPUT!

把腳位13設為高電位,其連接的LED會亮起:
http://arduino.loca/arduino/digital/13/1
瀏覽器上會看到回應:
Pin D13 set to 1

把腳位13設為低電位,其連接的LED會熄滅:
http://arduino.loca/arduino/digital/13/0
瀏覽器上會看到回應:
Pin D13 set to 0

腳位3輸出PWM128:
http://arduino.loca/arduino/analog/3/128
瀏覽器上會看到回應: 
Pin D3 set to analog 128

讀取類比腳位A0(對應腳位編號18)的值:
http://arduino.loca/arduino/analog/18
瀏覽器上類似底下的回應:
Pin A18 reads analog 253


參考資料:

9 comments:

  1. 大大 您好!
    想像您請教問題
    在下目前想要開發一個使用WI-FI控制和通訊的自走車(使用PC和Android)
    目前遇到的問題是不知道要怎麼選控制板
    使用Arduino YUN有內建WI-FI,但GPIO不夠用,可能要使用74HC595之類的來擴充
    或是使用Arduino MEGA2560 的GPIO數量足夠,可是要再擴充WI-FI
    想請問大大建議要用種哪種方式來開發較為容易?謝謝

    ReplyDelete
    Replies
    1. 沒有建議,根據你的需求自行選擇,各有好壞。

      或可根據你最看重的核心功能,假設是wi-fi連網,
      然後選你最熟悉的wi-fi技術,例如yun。
      接著再想辦法擴充腳位。能夠擴充腳位的IC,不只595,例如I2C介面的MCP23017。

      另外可想辦法縮減所需腳位的數量,
      如果連接一大堆LED,是否可採用更進階的LED模組,僅用幾個腳位、便可控制一大堆LED。

      Delete
  2. 感謝大大的幫忙
    因為核心控制部份是WI-FI,而目前物連網資旋應該是YUN較多吧?
    在下需要控制的IO約25~27個,其實也只比YUN的多一些

    ReplyDelete
    Replies
    1. > 應該是YUN較多吧?
      不一定。
      Yun滿貴的。
      wi-fi有很多其他選擇,esp8266、linkit 7688、等。

      Delete
  3. 感謝大大的建議!
    目前決定先用MEGA 2560 + MEGA SENSOR SHIELD + YUN SHIELD(或其他WIFI模組)
    配合參考大大的書來做測試(這樣WIFI的部份如果不適合,就可以再做更換)

    ReplyDelete
  4. 不好意思請問一下
    用另一個電腦去控制也要和YUN在同一個區域網路內在可以控制嘛??
    麻煩了

    ReplyDelete
    Replies
    1. 能連得到就可控制。
      不在同一區域網路的話,要設定路由器。

      Delete
  5. 大大您好!
    如果我想要讓兩個yun互傳訊號
    請問可以用什麼方式嗎?
    謝謝

    ReplyDelete
    Replies
    1. 紅外線、藍牙、wifi、I2C、SPI、序列介面、XBee、...

      Delete