วันพฤหัสบดีที่ 16 กุมภาพันธ์ พ.ศ. 2560

Iteadstudio GPS Shield


บทความนี้เราจะลองมาใช้งาน GPS Shield กับ บอร์ด Arduino UNO กัน แต่ก่อนจะเข้าเรื่องผมขออธิบายหลักการเบื้องต้นของ GPS ซะหน่อยนะครับ GPS (Global Positioning System) เป็นระบบบอกพิกัดบนโลกที่อาศัยตำแหน่งของดาวเทียม GPS เป็นพิกัดอ้างอิง โดยเครื่องรับ GPSสามารถคำนวณตำแหน่งบนพื้นโลกได้จากการวัดระยะทางระหว่างเครื่องรับและดาวเทียม GPS ซึ่งต้องมีอย่างน้อย ดวง (ดูภาพที่ 1) เพื่อที่จะสามารถนำเอาความสัมพันธ์ไปสร้างเป็นสมการ 4 สมการซึ่งจำเป็นสำหรับการคำนวณหาตัวแปล 4 ตัว (Xr, Yr, Zr และ cdt)
ภาพที่ 1: ระยะทางระหว่างดาวเทียม 4 ดวงและเครื่องรับสัญญาณ GPS
โดยการประมวลสัญญาณและการคำนวณทั้งหมดจะเกิดขึ้นใน GPS module (GPS antenna + GPS shield) ซึ่งสุดท้ายแล้วข้อมูลสำคัญต่างๆที่คำนวณได้ไม่ว่าจะเป็น Latitude, Longitude เวลา จำนวนดาวเทียมที่เครื่องรับมองเห็น และอื่นๆ จะถูกจับรวมกันให้อยู่ใน Format มาตรฐานที่เรียกว่า NMEA (ดูตัวอย่างในภาพที่ 2) ซึ่งมีด้วยกันอยู่หลายรูปแบบ โดยรายละเอียดของ NMEA สามารถดูได้ที่
http://www.gpsinformation.org/dale/nmea.htm   
การที่จะดึงข้อมูล (Parsing) แต่ละค่าที่อยู่ในประโยค NMEA ออกมาใช้งานได้นั้น เราจำเป็นต้องมีโปรแกรมหรือฟังชั่นช่วยจัดการ
ภาพที่ 2: ตัวอย่างประโยค NMEA และความหมายของข้อมูลแต่ละส่วนในประโยค
ในตอนที่ ของบทความนี้จะอธิบายไลบรารี่ที่ชื่อว่า TinyGPS (ดาวน์โหลดที่ถูกพัฒนาขึ้นเพื่อใช้ในการจัดการข้อมูลในประโยค NMEA และจะทำการทดสอบไลบรารี่นี้ โดยที่ยังไม่จำเป็นต้องต่อบอร์ด Arduino เข้ากับ GPS Shield ส่วนในตอนที่ ของบทความจะอธิบายการใช้งานTinyGPS ร่วมกับGPS Shield ซึ่งจะนำเสนอในครั้งถัดไป
หลังจากดาวน์โหลดไลบรารี่ TinyGPSPlus มาแล้วให้ติดตั้งตามที่เคยอธิบายไว้ในบทความเรื่อง "การติดตั้ง Library บน Arduino IDEหลังจากติดตั้งไลบรารี่ TinyGPSPlus เรียบร้อยแล้วจะสามารถลองเล่นกับตัวอย่าง Sketch ที่มาพร้อมกับไลบรารี่นี้ได้ ซึ่งในเวอร์ชั่นล่าสุด (v9.3) จะมีตัวอย่างให้มาทั้งหมด 7 ตัวอย่าง แต่ในบทความตอนที่ 1 นี้ เราจะทดสอบตัวอย่างที่ชื่อว่า BasicExample ซึ่งจะเอาไว้ check ว่า TinyGPSPlus ทำงานได้ปกติหรือเปล่า 

โปรแกรมที่ 1: BasicExample.ino
 #include <TinyGPS++.h>
/* 
   This sample sketch should be the first you try out when you are testing a TinyGPS++
   (TinyGPSPlus) installation.  In normal use, you feed TinyGPS++ objects characters from
   a serial NMEA GPS device, but this example uses static strings for simplicity.
*/

// A sample NMEA stream.
const char *gpsStream =
  "$GPRMC,045103.000,A,3014.1984,N,09749.2872,W,0.67,161.46,030913,,,A*7C\r\n"
  "$GPGGA,045104.000,3014.1985,N,09749.2873,W,1,09,1.2,211.6,M,-22.5,M,,0000*62\r\n"
  "$GPRMC,045200.000,A,3014.3820,N,09748.9514,W,36.88,65.02,030913,,,A*77\r\n"
  "$GPGGA,045201.000,3014.3864,N,09748.9411,W,1,10,1.2,200.8,M,-22.5,M,,0000*6C\r\n"
  "$GPRMC,045251.000,A,3014.4275,N,09749.0626,W,0.51,217.94,030913,,,A*7D\r\n"
  "$GPGGA,045252.000,3014.4273,N,09749.0628,W,1,09,1.3,206.9,M,-22.5,M,,0000*6F\r\n";

// The TinyGPS++ object
TinyGPSPlus gps;

void setup()
{
  Serial.begin(115200);

  Serial.println(F("BasicExample.ino"));
  Serial.println(F("Basic demonstration of TinyGPS++ (no device needed)"));
  Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();

  while (*gpsStream)
    if (gps.encode(*gpsStream++))
      displayInfo();

  Serial.println();
  Serial.println(F("Done."));
}

void loop()
{
}

void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}

ซึ่งผลของการ รัน โปรแกรมที่ 1 ที่ถูกแสดงบน serial monitor จะเป็นดังนี้ 

นาย สุธรรม แสงทรง

อ้างอิง

https://www.arduitronics.com/article/40/iteadstudio-gps-shield-part-1

Micro WebServer จาก ESP8266 และ Arduino

วันนี้ทางผมเอาตัวอย่างการใช้งาน #ESP8266 กับ สร้าง Wifi Web Server แบบราคา super สุดคุ้ม เป็นตัวอย่าง Web Site ง่ายๆ นะครับ ใครเอาใช้ ใครเอาขายไม่แบ่งเงิน แล้วมัน Hang อย่าพึงบ่นนะครับ
capture-20140928-190019

วงจร ต่อประมาณนี้ครับ แต่ที่เพิ่มไป คือ ต่อ VR ที่ A0 สำหรับ อ่านค่า
<img class="wp-image-6330 size-medium" src="http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-300×300.jpg" alt="ต่อเพียง 5 สาย ทำงานได้" width="300" height="300" srcset="http://www.ayarafun viagra prix en tunisie.com/wp-content/uploads/2014/09/IMG_20140928_123145-300×300.jpg 300w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-150×150.jpg 150w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-1024×1024.jpg 1024w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-50×50.jpg 50w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-100×100.jpg 100w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-500×500.jpg 500w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-1000×1000.jpg 1000w, http://www.ayarafun.com/wp-content/uploads/2014/09/IMG_20140928_123145-120×120.jpg 120w” sizes=”(max-width: 300px) 100vw, 300px” />
ต่อเพียง 5 สาย ทำงานได้
PINOUT
PINOUT
ตัวอย่างการทำ Web Server
#include <SoftwareSerial.h>
#define SSID  "ssssssssss"
#define PASS  "xxxxxxxxxx"

SoftwareSerial dbgSerial(10, 11); // RX, TX
void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  Serial.setTimeout(500);
  dbgSerial.begin(9600);  //can't be faster than 19200 for softserial
  
 
  //test if the module is ready
  sendAndWait( "AT","OK",10);
  
  //Change to mode 1 
  //sendAndWait("AT+CWMODE=1","no change","OK",100);
  Serial.println("AT+CWMODE=1");
  delay(100);
  
  // connect to router
  connectWiFi(SSID,PASS);

  //set the multiple connection mode
  sendAndWait("AT+CIPMUX=1","OK",100);
  
  //set the server of port 80 check "no change" or "OK"
  sendAndWait("AT+CIPSERVER=1,80","no change",100);
  
  //print the ip addr
  dbgSerial.println("ip address:");
  Serial.println("AT+CIFSR");
  delay(100);
  while ( Serial.available() ) {
    dbgSerial.write(Serial.read());
  }  
  dbgSerial.println();
  
  dbgSerial.println( "Start Webserver" );
}

void loop() {
  while (Serial.available() >0 )
  {
    char c = Serial.read();
    if (c == 71) {
      dbgSerial.println("Send Web Request");
      webserver();
      delay(500);
    }
  }
}

void http(String output) 
{
  Serial.print("AT+CIPSEND=0,");
  Serial.println(output.length());
  if (Serial.find(">"))
  {
    //Serial.println(output);
    sendAndWait(output,"SEND OK",10);
  }   
}

// Get the data from the WiFi module and send it to the debug serial port
boolean sendAndWait(String AT_Command, char *AT_Response, int wait){
  dbgSerial.print(AT_Command);
  Serial.println(AT_Command);
  delay(wait);
  while ( Serial.available() > 0 ) {
    if ( Serial.find(AT_Response)  ) {
        dbgSerial.print(" --> ");
        dbgSerial.println(AT_Response);
 return 1;
    }     
  }
  dbgSerial.println(" fail!");
  return 0;
}

void webserver(void) {
 char temp1[10];
 dtostrf(analogRead(A0),1,2,temp1);
 http("<title>Ayarafun Webserver</title><H3>Welcome to My Real Micro Site Web Server</H3><p>Value A0 = "+ String(temp1) +"</p>");
 //delay(1000);
 sendAndWait("AT+CIPCLOSE=0","",500);
}
boolean connectWiFi(String NetworkSSID,String NetworkPASS)
{
  String cmd = "AT+CWJAP=\"";
  cmd += NetworkSSID;
  cmd += "\",\"";
  cmd += NetworkPASS;
  cmd += "\"";
  
  //dbgSerial.println(cmd);  
  //sendAndWait(cmd,"OK",10);
  Serial.println(cmd);
  delay(100);
  while ( Serial.available() ) {
    dbgSerial.write(Serial.read());
  }  
}

นาย สุธรรม แสงทรง

อ้างอิง

http://www.ayarafun.com/2014/09/micro-webserver-from-esp8266-and-arduino/

[Arduino] Basic Task#11 การใช้งาน Moisture Sensor

สวัสดีครับ วันนี้ผมจะมาสอนใช้งาน Moisture Sensor หรือเซนเซอร์ตรวจจับความชื้นในดิน ตัวเซนเซอร์ที่ว่านี้ก็มีหลายแบบเลยทีเดียว แต่ตัวที่นำเอามาพูดวันนี้จะเป็นตัวที่ใช้ Output ได้ทั้งค่า Digital และ Analog 
บางคนอาจจะสงสัยว่าเอามาสอนทำไมเพราะใครๆก็น่าจะใช้เป็นกันอยู่แล้ว อย่างไรก็ตาม ตอนนี้เป็นช่วงเปิดเทอมใหม่ของมหาวิทยาลัยหลายแห่ง ซึ่งเด็กปี 4 หลายๆคนคงเพิ่งหัดเริ่มใช้ Arduino เพื่อไว้ทำโปรเจ็ค โปรเจ็คที่เห็นบ่อยมากก็คงหนีไม่พ้นระบบรดน้ำต้นไม้อัจฉริยะ ระบบที่ว่านี่ก็ประกอบไปด้วยเซนเซอร์วัดความชื้น เซนเซอร์วัดแสง โมดูลส่งข้อมูลไร้สาย(อาจจะเป็น RF หรือ Wi-Fi) รีเลย์ โซลีนอยด์วาวล์ และ จอแสดงผล เอามายำผสมกัน 
--------------------------------------------------
กลับมาที่เรื่องของเซนเซอร์ เราจะมาดูวิธีการใช้งานเบื้องต้นกันครับ ในบทความนี้จะสอนแต่ analog แต่เดี๋ยวจะบอกวิธีใช้ค่า digital ให้ทีหลังครับ
หน้าตาเซนเซอร์ก็เป็นแบบนี้ มีสองส่วน ส่วนแรกจะเป็นวงจร Digital/Analog ส่วนที่สองจะเป็นแผ่นไว้จิ้มลงดิน(probe) และจะมีสายไฟมาให้ 5 เส้น
ป.ล. มีคนถามว่าสายหายไปไหน 1 เส้น คือมันมี 5 เส้นอยู่แล้วครับ เพราะขา A0 กับ D0 เขาไม่ใช้พร้อมกัน
เอาล่ะ เริ่มจากต่อสายระหว่างตัววงจรกับ probe ใช้สายไฟ 2 เส้น ต่อสายสลับกันได้

จากนั้นต่อสายโยงจากโมดูลเข้าตัวบอร์ด Arduino ตามรูปเลยครับ

จากนั้นให้เปิดคอม แล้วก็อปโค้ดด้านล่างมาใส่ในโปรแกรม Arduino IDE แล้วทำการอัพโหลดโค้ดและเปิด Serial Monior ไว้เลย
ในโค้ดนี้มีการใช้ map ฟังก์ชันแปลงค่าจาก 1023 - 0 ให้เป็น 0% - 100% เนื่องจากตอนที่ไม่ได้เอา probe ปักดิน (เปรียบได้กับดินแห้ง ความต้านทานสูงมาก ในทางอุดมคติคือ R = infinity แต่ความเป็นจริงเป็นไปไม่ได้) จะได้ค่า analog 1023 เลยทำให้โชว์ 0% แทน ตรงกันข้าม สมมุติดินเปียกมากจนความต้านทานน้อย ค่า analog จะเหลือ 100 กว่าๆ เอาเป็นว่าผมเปลี่ยน analog ให้เป็น 0 ละกันจะได้ไม่งง คือไร้ความต้านทาน R = 0 จะได้ค่า 100% คือชื้นมากสุด (ความเป็นจริงคือยังไงดินเปียกๆก็มีความต้านทาน แค่สมมุติให้ดู และจริงๆแล้วจะได้ความชื้นไม่เกิน 70% แม้จะเอา probe จุ่มน้ำตรงๆ ไม่ผ่านดิน เพราะน้ำก็มีความต้านทานเช่นกัน ยิ่งน้ำบริสุทธิ์ความต้านทานจะสูงมาก
ส่วนเหตุผลที่ทำไมตอนที่ดินแห้งได้ค่า analog เป็น 1023 หรือตอนดินเปียกได้ค่า analog ต่ำๆ รวมถึงทฤษฎีต่างๆ มีอธิบายไว้ที่ท้ายบทความครับ
---------------------------------

กลับมาที่ Serial Monitor จะเห็นว่าโชว์ 0%

เมื่อเอานิ้วสัมผัสระหว่าง probe สองอัน จะเห็นค่าความชื้นเพิ่มเป็น 1% เพราะผิวหนังคนนำกระแสไฟฟ้าได้ กระแสจะไหลข้ามไปถึงกันได้นิดหน่อย

เมื่อเอานิ้วหลายนิ้วมาสัมผัส จะได้ % เพิ่มขึ้นอีก
-----------------------------------
ทีนี้มาลองกับฟองน้ำดูบ้าง (พอดีผมไม่มีกระถางต้นไม้) เมื่อทาบเฉยๆก็ไม่มีอะไร ความชื้น 0% เพราะฟองน้ำเพิ่งซื้อมาเพิ่งแกะ ยังไม่ได้จุ่มน้ำเลย


ต่อมาผมได้เอาฟองน้ำไปจุ่มน้ำ เมื่อเอา probe มาทาบ จะเห็นว่าความชื้นอยู่ที่ 23%

คราวนี้ลองกด probe ลงบนฟองน้ำ จนมีหยดน้ำไหลออกจากฟองน้ำ จะเห็นว่า ความชื้นพุ่งสูงเป็น 46%

ต่อมาลองเอา Probe จุ่มน้ำเลย กระแสไหลได้ดี จะเห็นค่าความชื้นพุ่งเป็น 67% ความจริงถ้ารดน้ำจนดินเปียกขนาดนี้ สงสัยต้นไม้รากเน่าแน่ 555

บางคนอาจจะคิดว่าทำไมจุ่มน้ำแล้วไม่ได้ค่าความชื้น 100% ก็เพราะน้ำมีความต้านทานดังที่บอกไปแล้ว จริงๆแล้วเราควรเรียกเจ้าเซนเซอร์นี้ว่าตัววัดความต้านทานระหว่่าง Probe มากกว่าเซนเซอร์วัดความชื้นนะครับ เพราะจริงๆหลักการก็คือวัดความต้านทานในตัวกลางระหว่าง probe นั่นแหละ แค่เอามาประยุกต์ใช้วัดความชื้นได้
ถ้าอยากให้โชว์ความชื้น 100% ก็บัดกรีลวดระหว่าง probe หรือไม่ก็เอา Probe ออกแล้วเอาสายไฟเชื่อมเข้าด้วยกัน คือ R = 0 Ohm ดังภาพ กระแสไหลถึงกันสบายมาก (จริงๆก็มีความต้านทานในสายไฟอยู่ดีนั่นแหละ แต่น้อยมากๆๆ ว่าแต่ R = pl/A จำกันได้ไหมสูตรนี้)
------------------------------------------

ถ้าหากใครใช้แต่ค่า Analog Output จริงๆสร้างเองได้เลยนะครับ ใช้ตัวต้านทาน 10KOhm กับตะปู 2 ตัว ง่ายดี หรือใครมีไอซี LM393 กับตัวต้านทานปรับค่าได้อยู่แล้ว ก็สร้างวงจร Digital Output เองได้เหมือนกัน ไม่ต้องซื้อเซนเซอร์นี้ให้เสียเงิน
-------------------------------------------
สำหรับการใช้งานแบบ Digital ไม่ยากเลยครับ เอาเป็นว่าย้ายขา A0 เป็น D0 ส่วนขาที่ Arduino ก็ใช้ A0 เหมือนเดิมได้ และกำหนด pinMode ให้ A0 เป็น Input ด้วย เพื่อใช้ A0 เป็นขา digital จากนั้นก็ใช้ digitalRead(A0); อ่านค่าเอา โดยปรับตัวต้านทานให้ได้ค่าตามต้องการ ปกติถ้าไฟ LED ติด 2 ดวงที่เซนเซอร์จะหมายถึงค่าดิจิตอลคือ LOW ถ้าเอา probe ไปปักดินแล้วเทน้ำนิดหน่อย แล้วปรับ R จน LED ดับดวงนึง คือได้ค่า High แล้วเราก็เอามาเขียนโปรแกรมได้ ว่าถ้าค่ามัน LOW ก็คือความชื้นน้อยกว่าที่เราตั้งไว้ให้รีเลย์จ่ายไฟเพื่อเปิดก็อกโชลีนอยด์ที่ไปต่อกับปริงเกอร์ให้มันรดน้ำ เป็นต้น
หากใครงงในส่วนของการใช้ค่าดิจิตอล ถามมาในเพจได้ครับ พอดีติดงาน เลยเขียนบทความนี้แบบรีบๆ
-------------------------------------------
ต่อมาเป็นหลักการทำงานของเซนเซอร์นี้ มันคงน่าอายถ้าเราซื้อของมาใช้ เขียนโปรแกรมเป็น แต่มีคนถามว่ามันทำงานได้ยังไง แล้วเราตอบไม่รู้
ให้ดูในรูปนี้ครับ เป็น Schematic ของคนที่ผลิต
ตรง K1 คือ Probe โดยที่เลข 1 Probe ซ้าย และเลข 2 Probe ขวา เราต่อสลับกันได้
ส่วน P1 คือที่ตัวฟ้าๆจะมี 4 ขาที่เราใช้นั่นแหละ เลข 4 Vcc / เลข 3 GND / เลข 2 OUT คือ D0 / เลข 1 AC คือ A0 
จะเห็นว่าไฟ LED D1 จะติดตลอดเพราะต่อระหว่างไฟ Vcc กับ Gnd และมี R 1KOhm จำกัดกระแสที่ไหลผ่าน LED 
ส่วนไฟ LED D2 จะติดเมื่อ OUT เป็น LOW เพราะ LOW ก็เทียบได้กับ Ground และ LED D2 ดับเมื่อ OUT เป็น HIGH เพราะแรงดันเปรียบได้กับ Vcc จึงไม่มีกระแสไหลผ่าน LED จริงๆ OUT เป็น 3.5V ไฟก็ไม่ติดแล้ว เพราะแรงดันตกคร่อม LED ต้องมี 2V ขั้นต่ำ แต่ Vcc หักกับ OUT เหลือแรงดัน 1.5V ตกคร่อมระหว่าง LED และ R 1K ไฟจึงไม่ติด
ในส่วนของ LM393 จะใช้เป็นวงจร Comparator ได้ 2 ตัว ตามที่เห็นว่ามี A+ A- OUTA  B+ B- OUT B แต่ในที่นี้เราใช้แค่ตัวเดียวคือ A โดยนำค่าแรงดันที่ได้จาก voltage divider ระหว่าง R10K และความต้านทานระหว่าง probe มาใช้เป็น A+ และใช้แรงดันที่ได้จาก Trimpot หรือ R ตัวสีฟ้าๆที่ปรับค่าได้และต่ออยู่ระหว่าง 5V และ GND มาเป็น A- จากนั้นไอซีจะนำ A+ และ A- มาเปรียบเทียบกันและให้เอาพุตเป็น OUTA
ส่วน Capacitor 104 คือ 100nF หรือ 0.1uF (10 x 10^4 x 10^-12 F) นิยมใช้ต่อระหว่าง Vcc และ GND เพื่อลดสัญญาณรบกวน
-------------------------------
กลับมาที่ในส่วนของวงจร analog 
จะเห็นว่ามีคำว่า Soil Resistivity คือความต้านทานจำเพาะดิน มีหน่วยเป็น Ohm-m คือมีพื้นที่มาเกี่ยวข้อง แต่ในบทความนี้ถ้าเห็นคำว่า Soil Resistivity ผมจะให้มันหมายถึง Resistance of soil คือความต้านทานของดินระหว่าง Probe มีหน่วยเป็น Ohm

ต่อมามาดูอันนี้กัน ตัวอย่างถ้าดินแห้งมากๆ มีความต้านทานสูงถึง 20 เมกกะโอห์มในจุดที่วัด จะได้ค่าแรงดันจาก Voltage Divider เป็น 4.998V และถ้าแปลงเป็นค่า analog จะได้ 1022.59 แต่ค่า analog จะเป็นจำนวนเต็มจึงปัดขึ้นได้เป็น 1023 (ภาษาอังกฤษใช้คำว่า round แทนการปัดเลข)

ตัวอย่างต่อมา สมมุติให้ดินเปียกมากๆ ความต้านทานก็เหลือน้อย สักประมาณ 500 โอห์ม จะได้ analog ออกมาเป็น 49 ค่าต่ำมาก 

ต่อมา สุดท้ายแล้ว หากเราใช้จะคำนวณกลับหาความต้านทานดินระหว่าง Probe โดยรู้ analog value จาก Serial Monitor จะทำได้อย่างไร
ก็ง่ายๆคือเรารู้อยู่แล้ว Input Voltage คือ 5V และ R อีกตัวนอกจากความต้านทานดินที่เอามาทำ Voltage Diver คือ 10K Ohm ที่เหลือก็แปลงค่า Analog เป็น Output Voltage และแก้สมการดังภาพล่าง
สมมุติให้ดินค่อนข้างเปียก และค่าที่อ่านได้จาก Serial Monitor เป็น 300 
จะได้ Vout เป็น 1.47V เอาไปแทนในสมการ ย้ายข้างไปมาก็จะได้คำตอบ แต่ถ้าจะง่ายๆเลยก็ใช้ wolfram alpha ช่วยคำนวณ จะได้ว่าความต้านทาน 4.16 KOhm
จบแล้วครบ บทความนี้รีบเขียนเนื่องจากไม่ค่อยว่าง แต่ก็มีคนมาถาม เลยจัดให้ครับ หากงงตรงไหนก็ถามได้ หรือผิดพลาดตรงไหนก็ขออภัยด้วยครับ
----------------------------------
CODE:

นาย สุธรรม แสงทรง

อ้างอิง

https://www.i2book.in.th/article/19/arduino-basic-task11-การใช้งาน-moisture-sensor-2

ทดลองรีโมต (IR-Remote) กับ Arduino

สำหรับรีโมต อุปกรณ์ง่ายๆ ราคาไม่แพงมาก ที่เรียกว่า เป็นจุดเปลี่ยนชีวิตเลยว่าได้ครับ คนนอนสบาย ง่อยกันไปเลย สำหรับประวัติของรีโมตถูกสร้างโดย ดร โรเบิร์ต แอดเลอร์ (Dr. Robert Adler) ดร. ทางฟิสิกส์ครับ โดยเวอร์ชั่นแรก ใช้คลื่นเสียง ultrasonic ส่งข้อมูล ยังไม่ได้ใช้ IR และราคาประมาณ 1 ใน 3 ของราคาทีวีในตอนนั้น เชื่อไหมว่าราคาขนาดนี้ มันก้อขายไปแล้วว่า 9 ล้านตัว
example2
สำหรับบทความตอนนี้ เราจะมาทดลองใช้ IR Receiver บน Arduino กันดีกว่าครับ เราจะได้ทำโปรเจค ที่ควบคุมจาก รีโมต ได้ แถมหาได้ง่าย ราคาประหยัด
โดยทางรีโมต และ ตัว IR Receiver เราใช้ชุดสำหรับรูป ที่หาได้จาก ในร้านของทาง ayarafun shop นะครับ ซึ่งจริง IR หาซื้อได้จากร้านในบ้านหม้อ และรีโมต เราจะเอาของที่บ้านมาก็ได้ครับ ก้อสามารถเทียบ และ ไปประยุกต์กันได้ครับ
remote_front_view

1. วิธีการติดตั้งLibraries

1. download library ไปใส่ใน
2. จากนั้น copy ไปใส่ใน [mydocument]\Documents\Arduino\libraries
 remote1
 หรือ [drive]\arduino-x.y.z\libraries
remote2
 แนะนำ เก็บไว้ใน my document ดีกว่า เผื่อเราเปลี่ยนเวอร์ชั่น arduinoในอนาคตครับ
***สำหรับการใช้งาน ทดสอบกับ arduino 1.0.3 นะครับ ถ้าต่ำกว่าอาจจะทำงานไม่ได้
 3. เปิดโปรแกรม arduino ขึ้นมาใหม่ เราจะเจอว่าใน example จะมี ตัวอย่างการใช้งาน remote ถือว่าจบการติดตั้ง
remote3

2. การ wiring ส่วน Hardware

สำหรับการใช้งาน IR Receiver Module จะเป็นลักษณะด้านภาพ มี สามขา ไฟเลี้ยง , Ground และ Data Out เราเพียงต่อขา Data Out ของ IR Receiver Module ต่อกับ บอร์ด Arduino โมดุล เท่านั้น ก็ใช้งานได้แล้ว
ในที่นี้ เราจะต่อ Signal Out เข้ากับขา D11 ของ Arduino ดังภาพ หลังจากนั้น เราแค่ config libraries ของ arduino ก่อนการใช้งานว่า เราต่อขา Signal Out ของ IR Receiver Module ที่พิน D11 ใช้งานได้ครับ
remote_pinout

3. การทดสอบ

มาดูตัวอย่างแรกของการใช้งาน ทดสอบว่า รีโมตส่งข้อมูล และ บอร์ด arduino เรารับข้อมูลได้
ตัวอย่าง Code ที่ 1
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <IRremote.h>
 
int RECV_PIN = 11;
 
IRrecv irrecv(RECV_PIN);
 
decode_results results;
 
int on = 0;
unsigned long last = millis();
 
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Hello");
}
 
void loop() {
 
  if (irrecv.decode(&results)) { 
    if (millis() - last > 50) {
      if ( (results.value != 0xFFFFFFFF) && (results.value != 0x00) )
         Serial.println(results.value, HEX);
      irrecv.resume(); // Receive the next value 
    }
    last = millis();     
    irrecv.resume(); // Receive the next value
  }
}
จากตัวอย่างแรก ให้เราเปิด Serial Monitor เมื่อเรากดรีโมต มันจะขึ้น Code ซึง Code นี้ รีโมตแต่ล่ะยีห้อ แต่ล่ะปุ่มจะส่งออกมาไม่เหมือนกันครับ สำหรับอันนี้ เราได้จากกดปุ่ม 1-9 บนรีโมตตัวเล็กของเราครับ
capture-20130719-095744
FD08F7
FD8877
FD48B7
FD28D7
FDA857
FD6897
FD18E7
FD9867
FD58A7
จากตัวอย่างโปรแกรม ค่าของรีโมต code มันจะถูกเก็บไว้ใน ตัวแปร results.value คราวนี้เราจะเอาไปให้กด remote แล้วเอาไปทำอะไร ก็เริ่มจากตรงนี้ล่ะครับ อันนี้เราลองหารีโมตที่ถูกใจดูครับ สำหรับคนอยากได้เล็ก พกสะดวก จัดอันนี้ไปนะครับ
ตัวอย่าง Code ที่ 2
ตัวอย่างที่ 2 เราจะประยุกต์ใช้ รีโมตเพื่อควบคุม LED ครับ ลองดูจากตัวอย่างแล้วก็ทำดูนะครับ
example2
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <IRremote.h>
 
int RECV_PIN = 11;
 
IRrecv irrecv(RECV_PIN);
decode_results results;
 
#define OUTPUT_COUNT 4
 
unsigned long last = millis();
 
long remote_key[]={0xFD08F7,0xFD8877,0xFD48B7,0xFD28D7};
 
const byte outputPins[OUTPUT_COUNT] = {2, 3, 4, 5};
 
struct keypad {
  boolean state;
};
 
keypad output[OUTPUT_COUNT];
 
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Hello");
 
  for (int i=0;i<OUTPUT_COUNT;i++) {
       pinMode(outputPins[i], OUTPUT);
       output[i].state = LOW;
   }
}
 
void loop() {
    unsigned long currentMillis = millis();
    if (irrecv.decode(&results)) {
         if (currentMillis - last > 50) {
 
        //Serial.println(results.value, HEX);
 
         if ( (results.value != 0xFFFFFFFF) && (results.value != 0x00) ) {
            for (int val=0;val<OUTPUT_COUNT;val++) {      
                if ( results.value == remote_key[val] )  {
 
                    if (output[val].state==LOW) {
                        Serial.print ("ch[");
                        Serial.print(val);
                        Serial.println("] ON");
                        output[val].state=HIGH;
                    } else {                     
                        output[val].state=LOW;
                        Serial.print ("ch[");
                        Serial.print(val);
                        Serial.println("] OFF");                       
                    }
 
                }      
            }
         }
 
         for (int i=0;i<OUTPUT_COUNT;i++)
             digitalWrite(outputPins[i], output[i].state);
 
         }
 
      last = currentMillis;     
      irrecv.resume(); // Receive the next value
 
    }
}
}
ตัวอย่างที่สอง เป็นการประยุกต์ง่ายๆ เอามาเปิดปิด LED ครับ พื้นฐานของทุกสิ่งในโลกเลย เปิด ปิด LED ทางผม ก็เก็บค่า remote ที่กดปุ่ม 1,2,3,4 ไว้ มันจะได้ค่า FD08F7 , FD8877, FD48B7, FD28D7 และเก็บไว้ในตัวแปร array remote_key[]  สำหรับรีโมตรุ่นอื่นจะได้ค่าอื่นนะครับ
จากนั้นทุกครั้ง ที่มีการกดรีโมต โปรแกรมส่วนนี้จะเอาค่าที่อ่านได้มาตรวจสอบ ว่าตรงกับ index ที่เท่าไร พอได้ index ก็เอาไป map กับ LED ที่ติดไว้ครับ กดเลขไหน เลขนั้นจะสว่าง กดอีกที่มันก็ดับครับ บอกแล้ว เขียนแบบง่าย เน้นให้ผู้อ่าน เอาไปใช้ต่อง่ายๆนะ ก็จบไปแล้วตัวอย่างการใช้ IR-Receive หวังว่าชาวนักประดิษฐ์อย่างเรา จะเอาไปต่อยอด ในผลงานสิ่งประดิษฐ์ กันได้นะครับ
นาย สุธรรม แสงทรง
อ้างอิง
http://www.ayarafun.com/2013/07/ir-remote-with-arduino/