Search This Blog

Saturday, September 19, 2015

Controlling Your Hardware from the Web Using Arduino

Arduino Ethernet shield 2 ကိုသုံးပြီး အင်တာနက်ကနေ သင့်ရဲ့ hardware တွေကို လှမ်းပြီး ထိန်းတဲ့အကြောင်း ဆွေးနွေးချင်ပါတယ်။ Arduino Ethernet 2 Library ကိုသုံးပြီး server အနေနဲ့ နမူနာတခု၊ client အနေနဲ့ တမျိုး စမ်းကြည့်ပါမယ်။ နောက်ဆုံး version Arduino IDE ကို သုံးဖို့လိုပါတယ်။ ဒီနမူနာမှာတော့ Arduino IDE 1.7.6 ကိုသုံးထားပါတယ်။ Arduino Uno ကို Ethernet shield 2 တပ်ထားတဲ့ပုံကို အောက်မှာ ပြထားပါတယ်။


Figure. Arduino Uno paired with Arduino Ethernet shield 2.


As a Web Server


Ethernet ကို စတင်တဲ့အခါ Ethernet Shield 2 ရဲ့ MAC address ကို ထည့်ပေးဖို့လိုပါတယ်။ သူ့ရဲ့ MAC address က shield 2 ပေါ်က စတစ်ကာပေါ်မှာ ရေးထားတဲ့ နံပါတ်ပါ။ အခုနမူနာမှာ Arduino ကို IP address အလိုအလျောက်ချပေးဖို့ လိုတဲ့ အတွက် သင့်ရဲ့ router က DHCP enable ဖြစ်ဖို့လိုပါတယ်။ Arduino ကို web server အနေနဲ့ သုံးတဲ့ အခါ client ဆီကနေ blank line (new line character -"\n" တွေကြားထဲမှာ "\r" ကလွဲလို့ ဘာမှ မရှိပဲ နှစ်ခါဆက်တိုက်) ရရင် ဆက်သွယ်မှုပြီးပြီ လို့ယူဆပါမယ်။
// MAC address that is found on the sticker pasted on Ethernet shield v2
byte mac[]={0x90, 0xA2, 0xDA, 0x0F, 0xF9, 0x51};

// Initialize the Ethernet server (port 80 is default for HTTP)
EthernetServer server(80);
EthernetClient client;

Ethernet shield 2 မှာ SD Card reader လည်းတခါထဲပါပါတယ်။ သူတို့က SPI ကို မျှသုံးကြတာမို့ Ethernet ကိုသုံးနေချိန်မှာ SD card ရဲ့ enable pin ဖြစ်တဲ့ pin 4 ကို high ပေးပြီး disable လုပ်ထားဖို့လိုပါတယ်။
pinMode(4, OUTPUT);//to disable SD card
digitalWrite(4, HIGH);
  
Serial.print("Beginning Ethernet...");
if (!Ethernet.begin(mac)) { Serial.println("failed."); return; }
else {Serial.println("success.");}
  
Serial.println("Starting server...");
server.begin();
  
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());

ဒီနမူနာမှာ digital output အနေနဲ့ အနီရောင် LED၊ analog output အနေနဲ့ အစိမ်းရောင် LED တို့ကို web browser တခုကနေလှမ်းဆက်သွယ်ပြီး ထိန်းပါမယ်။ Arduino ကို ဆက်ထားတဲ့ switch တခုရဲ့ status ကို လည်း အဲဒီ web page မှာ 5 seconds တခါ update လုပ်ပေးနေပါမယ်။ ပရိုဂရမ်အစမှာ Ethernet ကို စပြီးတဲ့အခါ router ကချပေးတဲ့ IP address ကို serial မှာ ပြန်ရိုက်ပြပါမယ်။


Figure. IP address of the Arduino Shield 2 is shown in Serial Monitor.


ပရိုဂရမ်ကို အောက်မှာ ပြထားပါတယ်။ မူရင်းကုဒ်ကို GitHub - Arduino Ethernet Shield 2 မှာဒေါင်းလုပ် လုပ်နိုင်ပါတယ်။
// Name: web_server_led.ino
// By: Yan Naing Aye
// Description: Arduino Uno paired with Ethernet shield v2 as a web server 
// that controls an LED
// http://cool-emerald.blogspot.sg/

#include <SPI.h>
#include <Ethernet2.h>

//Start of Declaration for Hardware ------------------------------------
class MyHardware {
   public:
      int RLED_Pin; 
      int RLED_Val;
      int GLED_Pin;   
      int GLED_Val;
      int SW1_Pin;   
      int SW1_Val;
      MyHardware();
      void begin();
      void update();
};
MyHardware::MyHardware() {
  RLED_Pin=5;   
  RLED_Val=0;
  GLED_Pin=6;   
  GLED_Val=128;
  SW1_Pin=0;   
  SW1_Val=0;
}
void MyHardware::begin() {
  pinMode(RLED_Pin, OUTPUT);
  digitalWrite(RLED_Pin, RLED_Val);
  
  pinMode(GLED_Pin, OUTPUT);
  analogWrite(GLED_Pin, GLED_Val);
  
  pinMode(SW1_Pin, INPUT);
  SW1_Val = digitalRead(SW1_Pin);
}
void MyHardware::update() { 
 //Start of Switch 1 input-------------------- 
  SW1_Val = digitalRead(SW1_Pin);
  //End of Switch 1 ------------------------------------
  
}
MyHardware H;
//End of Declaration for Hardware ------------------------------------

// MAC address that is found on the sticker pasted on Ethernet shield v2
byte mac[]={0x90, 0xA2, 0xDA, 0x0F, 0xF9, 0x51};

// Initialize the Ethernet server (port 80 is default for HTTP)
EthernetServer server(80);
EthernetClient client;

enum ServerState { Chk_END, Chk_NORMAL, Chk_CONTROL };
ServerState s = Chk_END;

char c;

void setup() {
  Serial.begin(9600);
  H.begin();
  
  pinMode(4, OUTPUT);//to disable SD card
  digitalWrite(4, HIGH);
  
  Serial.print("Beginning Ethernet...");
  if (!Ethernet.begin(mac)) { Serial.println("failed."); return; }
  else {Serial.println("success.");}
  
  Serial.println("Starting server...");
  server.begin();
  
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  // listen for incoming clients
  client = server.available();
  if (client) {
    Serial.println("New client.");
    while (client.connected()) {
      if (client.available()) {
        c = client.read(); Serial.write(c); //read and echo        
        if (s == Chk_CONTROL) ProcessCmd(c);
        
        //check and update the server state
        if(c=='?') s=Chk_CONTROL; 
        else if(c=='\n'){ 
          if(s==Chk_END) { HTTP_Response(); break;}
          else s=Chk_END;
        } 
        else if(c!='\r') { s=Chk_NORMAL; }
      }
    }
    delay(1);// give the web browser time to receive the data
    client.stop();// close the connection
    Serial.println("Client disconnected.");
    Ethernet.maintain();
  }
  H.update();
}

void ProcessCmd(char c) {
  //Start of red LED digital output--------------------
  if(c=='R') {            
    H.RLED_Val=client.parseInt(); 
    digitalWrite(H.RLED_Pin, H.RLED_Val); 
  }
  //End of red LED ------------------------------------
  
  //Start of Green LED analog output--------------------
  else if(c=='G') {            
    H.GLED_Val=client.parseInt(); 
    analogWrite(H.GLED_Pin, H.GLED_Val);
  }
  //End of Green LED ------------------------------------
}
void HTTP_Response() {
  // send a standard http response header
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("Connection: close"); 
  client.println("Refresh: 5");  // refresh the page automatically every 5 sec
  client.println();
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");
  client.println("<meta name='referrer' content='none'>");
  client.println("<script>");
  client.println("function SendCtrl(c,v){");
  client.println("window.location.href = \"?\"+c+\"=\"+v;");
  client.println("}");
  client.println("</script>");
  client.println("</head>");
  client.println("<body>");
  
  //Start of red LED digital output--------------------
  client.println("<div>");
  char* cStr[]={"255", "128"};
  char* vStr[]={"1", "0"};
  client.println("<br/>Click this button to toggle the red LED: ");
  client.print("<button name='R' type='button' style='background-color: rgb(");
  client.print(cStr[H.RLED_Val]); 
  client.println(",0,0);'onclick='SendCtrl(this.name,this.innerHTML);'>");
  client.println(vStr[(int)H.RLED_Val]);
  client.println("</button><br/>");
  client.println("</div>");
  //End of red LED ------------------------------------
  
  //Start of Green LED analog output--------------------
  client.println("<div>");
  client.println("<br/>Drag the slider to adjust the brightness of green LED: ");
  client.print("<input name='G' type='range' value='");
  client.print(String(H.GLED_Val)); 
  client.println("' min='0' max='255'");
  client.println(" onchange='SendCtrl(this.name,this.value);'>");
  client.println("</div>");
  //End of Green LED ------------------------------------
  
  //Start of Switch 1 input--------------------
  client.println("<div>");
  if(!H.SW1_Val) { client.println("<p style='color:rgb(0,255,0);'>SW1 ON</p>");}
  else { client.println("<p style='color:rgb(128,0,0);'>SW1 OFF</p>");}
  client.println("</div>");
  //End of Switch 1 ------------------------------------
  
  client.println("</body>");
  client.println("</html>");  
}

ဒီပရိုဂရမ်ကို စပြီးတဲ့ အခါ Serial Monitor မှာကြည့်လိုက်ရင် Ethernet ဆက်သွယ်မှု အောင်မြင်တဲ့အခါ သူ့ရဲ့ IP address ကို တွေ့ရပါမယ်။ ပြီးရင် အဲဒီ IP address ကို သူ့နဲ့ local network တစ်ခုထဲမှာရှိတဲ့ ကွန်ပျူတာ ဒါမှမဟုတ် ဖုန်း အစရှိတဲ့ ပစ္စည်းတခုခုရဲ့ web browser ရဲ့ address bar မှာ ရိုက်ထည့်လိုက်မယ်ဆိုရင် Arduino microcontroller ကပို့လိုက်တဲ့ web page မှာ သူနဲ့ ဆက်ထားတဲ့ hardware တွေရဲ့ လက်ရှိအခြေအနေတွေကို ပြနေတာကို တွေ့ရမှာပါ။ Toggle ခလုပ်ကို နှိပ်လိုက်ရင် အနီရောင် LED ကအဖွင့်အပိတ် လုပ်တာကို တွေ့ရမှာဖြစ်ပြီး၊ slide bar ကို အတိုးအလျော့လုပ်ရင် အစိမ်းရောင် LED ရဲ့ အမှိန်အလင်း ကလိုက်ပြောင်းတာကို တွေ့နိုင်မှာပါ။ Arduino ကို ဆက်ထားတဲ့ ခလုပ်ကို အဖွင့်အပိတ် လုပ်ရင်လည်း ON, OFF အခြေအနေဟာ web page မှာ မကြာခင်မှာ update ဖြစ်သွားပါမယ်။


Figure. Controlling and checking the hardware from a web browser.


Local network မှာရှိတဲ့ဖုန်းကနေလည်း လှမ်းထိန်းကြည့်လို့ရပါတယ်။ အင်တာနက်ရှိတဲ့ ဘယ်နေရာက နေမဆိုလှမ်းထိန်းဖို့ အတွက်တော့ router မှာ အဲဒီ mac address အတွက် IP address ကို reserve လုပ်လို့ရပါတယ်။ ပြီးရင် router မှာ port forwarding လုပ်ဖို့လိုပါတယ်။ နောက်တခါ router ရဲ့ IP address အတွက် dynamic dns ကို setup လုပ်နိုင်ရင် ပိုကောင်းပါတယ်။



As a Web Client


Web client နမူနာ အနေနဲ့ Arduino က မြန်မာပြက္ခဒိန် နှစ် ၁၅၀၀ website ကနေ လက်ရှိနေ့ မြန်မာရက်စွဲကို သွားဖတ်ပြီး Serial Monitor မှာ ပြတဲ့ နမူနာလေးကိုပြထားပါတယ်။
// Based on a work at https://www.arduino.cc/en/Tutorial/WebClient

#include <SPI.h>
#include <Ethernet2.h>
// MAC address that is found on the sticker pasted on Ethernet shield v2
byte mac[]={0x90, 0xA2, 0xDA, 0x0F, 0xF9, 0x51};

// Initialize the Ethernet server (port 80 is default for HTTP)
char server[]="mc1500.com";//name address for server
char page[]="mcalrp.php";//page to open
EthernetClient client;
void setup() {
  Serial.begin(9600);
  
  pinMode(4, OUTPUT);//to disable SD card
  digitalWrite(4, HIGH);
  
  Serial.print("Beginning Ethernet...");
  if (!Ethernet.begin(mac)) { Serial.println("failed."); return; }
  else {Serial.println("success.");}
  
  // give the Ethernet shield a second to initialize:
  delay(1000);
  
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());
  
  Serial.println("connecting...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.print("GET /");
    client.print(page);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("connection failed");
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
}



Reference:
[1] Jeremy Blum, "Exploring Arduino: Tools and Techniques for Engineering Wizardry", Wiley; 1 edition, July 2013. exploringarduino.com
[2] https://www.arduino.cc/en/Tutorial/WebServer
[3] http://labs.arduino.org/Ethernet+2+Library
[4] http://labs.arduino.org/EthernetServer%28%29
[5] https://www.arduino.cc/en/Tutorial/WebClient

No comments:

Post a Comment