วันอังคารที่ 19 ธันวาคม พ.ศ. 2560

[ถาม-ตอบ คำถามที่มักถามบ่อยๆ] กดปุ่ม ต่ำกว่า 5 วินาที ติด เกินกว่า 5 วินาทีดับ โคดแบบกระชับๆ

คำถาม

ขออนุญาตสอบถามนะครับ 
"ผมต้องการเขียนโคด กดสวิตซ์ค้างไว้5วินาทีขึ้นไปแล้วปล่อยหลอดLEDจะไม่ติด 
แต่ถ้ากดสวิตช์ค้างไว้ไม่ถึง5วินาทีแล้วปล่อยก่อนหลอดLEDจะติด" ฯลฯ...

https://web.facebook.com/photo.php?fbid=1507160482712496&set=gm.1686822391360531&type=3&ifg=1


่ตอบคำถาม
โคดที่กระชับ แบบ clean code สะอาดๆ



วันพุธที่ 4 ตุลาคม พ.ศ. 2560

WatchDog ใน ESP8266


ใน ESP8266 มี WatchDog ป้องกัน การทำงานวนค้างอยู่ 2 แบบ
คือ Hardware Watchdog และ Software Watchdog

แต่ละแบบแตกต่างกันอย่างไรไปดูกัน



เวลาเกิด Hardware Watchdog
จะขึ้นข้อความมาเป็น rst cause: 4  ดังรูป

วันเสาร์ที่ 16 กันยายน พ.ศ. 2560

บันทึก ค่า string ใน EEPROM และการอ่านค่าขึ้นมาใน Arduino


EEPROM เป็นอะไรที่สะดวกดีในการบันทึกข้อมูล
ลงใน rom ของ อุปกรณ์อิเลคโทรนิค
สำหรับใน Arduino ตามปกติแล้วจะบันทึกและอ่านได้ทีละ byte
ในการบันทึกและอ่านค่า แบบ string พวกข้อความกลับไม่ได้มีตระเตรียมไว้
หากเขียนปกติต้องค่อยๆ เรียงทีละ byte ซึ่งยุ่งยากมากๆ

เลยต้องพึ่งวิธีพิเศษขึ้น
วิธีทำที่สั้นสุดจะเป็นดังนี้


วันศุกร์ที่ 15 กันยายน พ.ศ. 2560

Arduino 2 ตัว ยิง String หากัน ทาง I2C


มีคนมาตั้งกระทู้ใน กลุ่ม Arduino Thailand
ว่า I2C ยิง String แต่อีกฝั่งดันรับเป็น char ตัวแรก เท่านั้นทำไงดี

เนื่องด้วย I2C ยิงหากัน
หากจะส่งรับหากัน
หลักการไม่ยาก

คือ ฝั่งส่ง ก็ใช้ Wire.println();
และ ฝั่งรับ ก็ใช้ Wire.readStringUntil('\n');
เพียงเท่านี้ ก็ทำให้ การสื่อสาร แบบ I2C ระหว่าง Arduino 2 ตัว รับค่ากันได้ราบรื่น

ตัวอย่าง code ที่เขียนสด ไม่ได้ทดสอบผล
แต่ผู้ตั้งกระทู้ท่านนั้น ได้เอาไปใช้ ก็บอกว่าได้ผลตามต้องการ

ตัวอย่าง code เป็นดังนี้


วันอังคารที่ 29 สิงหาคม พ.ศ. 2560

มาทำให้บอร์ด Arduino ทั้งหลาย สามารถใช้ฟังกชั่น printf() ได้ดีกว่า

หลายอาทิตย์ก่อน มีคนมาตั้งคำถามในกลุ่ม
อยากจะแสดงเวลาบน LCD แบบมีเลข 0 นำด้วยถ้าเลขต่ำว่า 10
ซึ่งตามปกติการแสดงบน lcd จะเขียนด้้วย print() อย่างนี้

//--------------------------------------------------
   int hour = 12; 

   int minute = 5; 
   int sec = 9;

   if( hour <10 ) lcd.print("0");
   lcd.print(hour);
   lcd.print(":");
   if( minute <10 ) lcd.print("0");
   lcd.print(minute);
   lcd.print(":");
   if( sec <10 ) lcd.print("0");
  lcd.print(sec);
//--------------------------------------------------

แต่บน ESP8266 เราสามารถเขียนโดยใช้
ฟังกชั่น print ที่กำหนด format ได้
หรือ ที่เรียกว่า ฟังกชั่น printf()
ซึ่งจะเหลือบรรทัดเดียวดังนี้

//--------------------------------------------------
lcd.printf("%02d:%02d:%02d", hour, minute, sec);
//-------------------------------------------------


ปรากฏว่า บน Arduino กลับไม่รองรับ
การใช้ printf() ซะงั้น !?!!!!
วันนี้พอมีเวลาเลยมาทำให้ฝั่งบน Arduino
สามารถ ใช้ ฟังกชั่น printf() ได้ด้วยเลยดีกว่า
ซึ่งจะทำให้ โคดมีความเรียบร้อยขึ้นมาก


-------------------------------------------------------------
วิธีทำ
=====
1) ให้ไป download 2 files
คือ ไฟล์ Print.h และ Print.cpp นี้มา
ผู้เขียนอัพโหลดไว้ที่
https://github.com/TridentTD/Arduino_Printf


2) จากนั้นให้เข้าไปที่ โฟลเดอร์
C:\Users\..ชื่อuser..\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.18\cores\arduino
แล้วเอาไปแทนที่ในโฟลเดอร์นั้น
เพียงเท่านี้ Arduino ของคุณ
ก็จะสามารถใช้ printf()
ได้ทั้ง บน lcd หรือแม้กระทั่ง บน Serial monitor ได้
ทำให้โคดมีความเรียบง่ายและสั้นขึ้น ในลัดนิ้วมือเดียว



-------------------------------------------------------------

วันอาทิตย์ที่ 13 สิงหาคม พ.ศ. 2560

เทคนิคเล็กๆ กับการ แสดงสถานะการเชื่อมต่อ WiFi ด้วย LED ใน ESP8266

ปกติการเชื่อมต่อสัญญาณไวไฟ ของ ESP8266
มักจะใช้ Serial Monitor เป็น จุดแสดงว่า ESP8266 ได้เชื่อมต่อ WiFi สำเร็จแล้วหรือยัง
แต่ End-User ที่ไม่ได้มีการใช้ Serial Monitor จะไม่สามารถรู้ว่าขณะนี้ การเชื่อมต่อไวไฟ เป็นอย่างไร

มีวิธีทำให้ End-User ก็สามารถทราบว่าไวไฟได้เชื่อมต่อแล้วหรือยังด้วย
เทคนิคง่ายๆ ดังนี้


ให้เพิ่ม

extern "C" {
#include "user_interface.h"
}

เข้าไปส่วนต้นของ code
จากนั้นก่อนที่ จะสั่งให้ WiFi เริ่มต้นทำงาน ด้วย WiFi.begin(ssid, password);
ก็ให้เพิ่มบรรทัดนี้เข้าไป

wifi_status_led_install(2,  PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);

ส่วนอื่นๆ การเชื่อมต่อไวไฟ ให้เขียนตาม code ปกติ
เพียงเท่านี้ หาก ESP8266 ไวไฟ ยังไม่เชื่อมต่อ ไฟจะกระพริบที่ LED  GPIO2
แต่หากไวไฟ เชื่อมต่อสำเร็จ ไฟจะสว่างหยุดการกระพริบ
ก็จะช่วยให้ End-User ก็สามารถทราบว่าไวไฟได้เชื่อมต่อสำเร็จแล้วได้
หมายเหตุ
สำหรับ ESP-01 ให้เปลี่ยนเป็นค่าดังนี้แทน

wifi_status_led_install(0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);






วันอาทิตย์ที่ 6 สิงหาคม พ.ศ. 2560

วันเสาร์ที่ 24 มิถุนายน พ.ศ. 2560

ESP32 กับการทำงานแบบ MultiCore! เมื่อหลายหัวดีกว่าหัวเดียว

ESP32 เป็น ชิพ ที่ พัฒนา ยิ่งขึ้นไปกว่า ชิพ ESP8266 
คือ เพิ่มทั้งคุณสมบัติ WiFi และ Bluetooth เข้าไปในตัว
นอกจากนี้คือ การที่มี Core อยู่ 2 Core

#ว่าง่ายๆ คือ เหมือนมี 2 หัวคิด ต่างประมวลผลแยกกัน ในคนๆเดียว

ไหนๆ มีถึง 2 Core กันแล้ว
เรามาแบ่ง งานให้เจ้า ESP32 ที่มี 2 หัวช่วยกันทำงานดีกว่า

ตัวอย่าง code
----------------
โคดนี้ ผู้เขียนเขียนจำลองให้เสมือน
มี setup() และ loop() อยู่ 2 ชุด
ให้แต่ละ Core ไว้กันทำงานแยกกันคิด

อย่างจะให้ Core ไหน คิดประมวลผล
ก็จับวางสิ่งที่ต้องการให้ทำ ไว้ใน setup() loop() ของ Core นั้นๆได้เลย

หมายเหตุ
-----------
ปกติแล้ว Core#0  นั้น ตามปกติจะถูกทำงานด้าน Processing ตลอดจนถึง WDT
ส่วนอีกคอร์  Core#1 จะถูกใช้ทำงานด้าน Application, Code ที่สั่งให้ทำงาน
ตัวอย่างนี้เป็น โคตที่ ปลุก Core#0 ขึ้นมาทำงานด้าน Application ไปพร้อมๆกับ Core#1 ด้วยกัน




















วันอังคารที่ 20 มิถุนายน พ.ศ. 2560

เล่นกับเวลาใน Mongoose-OS (พังพอน โอเอส)

วิธีแสดงค่าเวลา นาฬิกาปัจจุบัน บน mongoose-os



Mongoose-OS เป็น os อีกตัวสำหรับ ESP8266, ESP32 ฯลฯ
ที่ใช้ภาษา javascript แบบย่อ โดยมีเอนจิ้น mJS
ใช้ในการเขียนได้

ข้อดีอย่างนึง ตัว Mongoos-os
เมื่อทำการ flash ลง ESP8266 แล้ว
หลัง boot ทาง os จะมีการ sync เวลามาให้อัตโนมัติ
โดยเราไม่ต้องไปจัดการเพิ่มอะไรอีกเลย
ทำให้ เราดึงเวลามาใช้ได้ตรงตาม Internet time ได้ง่ายๆเลย
และหากจะกำหนดเวลาตาม นาฬิกาที่่แน่นอน
เช่นการเปิดปิด ไฟ ก็เป็นไปได้อย่างรวดเร็ว

code นี้จะเป็นตัวอย่าง
การแสดงเวลา Clock บน ESP8266
ที่ได้รับการ sync จาก Internetอัตโนมัติแล้ว
ด้วยโคดที่สั้นมากๆ ดังนี้

[init.js]
--------------------------------------------------
load('api_timer.js');
Timer.set(1000, true, function() {
let timezone = 7;
print(Timer.fmt("%T", timezone*3600+Timer.now()) );
}, null);
--------------------------------------------------
อธิบาย
load('api_timer.js');
........ คือ การ load library api_timer.js เข้ามา
Timer.set( เวลาที่ delay, วนรอบซ้ำไหม, function ที่ให้ทำงาน)
....... คือ การ กำหนด loop การทำงานของ function ที่ต้องการให้มีการทำงานซ้ำๆไปเรื่อยๆได้
Timer.fmt( รูปแบบที่จะให้แสดงเวลา, time );
....... คือ function แปลงเวลา time ไปแสดงผลตามรูปแบบที่กำหนด
TImer.now()
........ คือ ค่าเวลา time ณ ปัจจุบัน ที่ได้รับการ sync แล้ว ในหน่วยวินาที เมื่อทำการ บวก ปรับเวลาตาม timezone ก็จะเป็นเวลา time ณ ปัจจุบันของประเทศนั้นๆ

เป็นเรื่องกระทัดรัดดีงามของทาง Mongoose-OS
ที่ได้ทำการ sync เวลาที่ถูกต้องมาให้อัตโนมัติตั้งแต่แรกต่อ internet


















   
หากต้องการเปิด/ปิด ไม่ให้มีการ sync เวลาแต่เริ่มสตาร์ท ESP8266, ESP32 ฯลฯ




วันจันทร์ที่ 12 มิถุนายน พ.ศ. 2560

เปลี่ยน "ธีม" ให้ Arduino IDE เป็นแบบ Sublime Editor


Arduino IDE เป็น Editor พร้อมๆกับ เครื่องมือที่สำหรับพัฒนาโคด
สำหรับ อุปกรณ์บอร์ดไมโครคอนโทรลเลอร์ Arduino
แต่สามารถรองรับ บอร์ดอื่นๆ ได้ด้วยเป็นอย่างดี

ตามปกติแล้ว Arduino IDE จะมีพื้นเป็นสีขาว
แต่ตัว Arduino IDE ยังสามารถเปลี่ยน ธีม (Theme) ลูกเล่นสีสรร
ในการเขียน code ได้ ช่วยในการกวาดสายตาในการเขียน code ได้เป็นอย่างดี

โทนสี ธีม นี้จะเป็นการทำ ธีม แบบใกล้เคียงกับที่ใน Sublime Editor ใช้

สามารถเข้าไป download ธีมได้ที่
https://github.com/TridentTD/TridentArduinoTheme





วันพฤหัสบดีที่ 8 มิถุนายน พ.ศ. 2560

ล้าง ESP8266 ใหม่ๆ กันดีกว่า

เวลาเขียน ESP8266 ใช้งานไปในงานนึงๆ
อาจจะมีการ กำหนดตั้ง WiFi เป็นแบบ AccessPoint Mode
นั่นหมายถึง เรามีการนำมา ESP8266 มาปล่อย Hotspot ออกไป
เพื่อให้ อุปกรณ์ WiFi อื่นๆ เข้ามาเป็นลูกข่าย
ทำนองเดียวกับ น้องๆ Router

อย่างไรก็ตามพอเรา นำ ESP8266 กลับมาใช้ในงานอื่นๆ
ที่ไม่ต้องมีการใช้ WiFi แบบ Access Point Mode
แม้ไม่มีการสั่งเปิด Mode นี้ขึ้นมา
แต่ ชื่อ Access Point เดิมที่เคยตั้งไว้ ได้ถูกบันทึกใน ESP8266
ไว้ไม่ได้มีการลบทิ้งแต่อย่างใด

ทำให้ชื่อ Access Point ยังโชว์หรา
อุปกรณ์ WiFi อื่นๆ จะเห็นชื่อ ซึ่งไม่เป็นที่ต้องการ

เราสามารถทำการล้าง ESP8266 ใหม่หมดจด
ด้วย option  "erase_flash" ใน esptool.py โดยใช้เวลาเพียงเสี้ยววินาทีด้วยคำสั่งดังนี้

esptool.py  --port <COM PORT>   erase_flash


ตย.  อุปกรณ์ ESP8266 ต่อที่ COM4
esptool.py  --port COM4  erase_flash

เพียงเท่านี้ Access Point เดิมๆ ที่ไม่ได้เรียกใช้ ก็จะถูกลบทิ้งไป
ไม่ปรากฏเวลา อุปกรณ์ WiFi อื่น กำหนดค้นหา แม่ข่าย WiFi


หมายเหตุ
- ให้ลง ภาษา Python แล้ว เข้าไป download   "esptool.py" ได้ที่
https://github.com/espressif/esptool/blob/master/esptool.py

วันจันทร์ที่ 15 พฤษภาคม พ.ศ. 2560

ESP8266 กับการเขียนแบบ Multitask


ในบางครั้งเรามีความจำเป็นต้องการทำงานหลายๆงานในคราวเดียวกัน
ในการควบคุม ต่างๆบน ESP8266

แต่ในระหว่างงานหนึ่งๆ เราอาจจะมีการใช้คำสั่ง delay()
ซึ่งทำให้ งานที่เหลือ ต้องคอยหยุดชะงักไปด้วย
ซึ่งไม่เป็นการสะดวกอย่างยิ่ง

ตัวอย่างเช่น เรามี งาน 3 Task
Task แรก เราต้องการไฟกระพริบติดดับๆ เป็นระยะๆ ทุก 1 วินาที

uint8_t state;
void setup() {
        state = HIGH;
        pinMode(2, OUTPUT);
        pinMode(2, state);

}
void loop() {
        state = state == HIGH ? LOW : HIGH;
        pinMode(2, state);
        delay(1000);
}

Task ที่สอง
เราต้องการให้มีการแสดงค่าทาง Serial ทุกๆ 5 วินาที

 void loop()  {
        Serial.println("Print Loop Start");
        delay(5000);
        Serial.println("Print Loop End");
        delay(5000);
 }


และ Task ที่สาม อาจจะต้องการให้มีอ่านค่าเม็มโมรี่ที่เหลือ ทุกๆ 10วินาที
void loop() {
        Serial.print("Free Heap: ");
        Serial.print(ESP.getFreeHeap());
        Serial.println(" bytes");
        delay(10000);
}

ตามปกติในแต่ละ Task การใช้ delay(1000)  delay(5000)  และ delay(10000)
( 1 วินาที , 5 วินาที, 10 วินาที)
หากไปใช้ร่วมกันจะเกิดความสะดุดส่งผลกระทบต่อ Task ไปได้อื่นๆด้วย
เช่น ไฟอาจจะไม่กระพริบทุกๆวินาทีต่อเนื่องด้วยดี ตามต้องการ ขึ้นได้

แต่ใน ESP8266 เราสามารถหลีกเลี่ยงไม่ให้ งานทั้ง 3 นี้ต้องมาสะดุดกัน
เสมือนเราเขียนแต่ละ task แต่จับมาร่วมทำงานพร้อมกัน
ที่เรียกว่าการทำงานแบบ Multitasking


ติดตั้ง Library  Esp8266Scheduler

ก่อนอื่นให้เปิดหน้าต่าง Library Manager ขึ้นมาแล้วเพิ่มไลบรารี่ ที่ชื่อว่า Esp8266Scheduler
เข้าไปให้เรียบร้อยเสียก่อน





การเขียน CODE (ตัวอย่างใน example)

Task1 : ให้เขียน code ดังนี้

class BlinkTask : public Task { 
protected:
    void setup() {
        state = HIGH;
        pinMode(2, OUTPUT);
        pinMode(2, state);
    }
    void loop() {
        state = state == HIGH ? LOW : HIGH;
        pinMode(2, state);
        delay(1000);
    } 
private:
    uint8_t state;
} blink_task;



Task 2: ให้เขียน code ดังนี้
class PrintTask : public Task {
protected:
    void loop()  {
        Serial.println("Print Loop Start");
        delay(5000);
        Serial.println("Print Loop End");
        delay(5000);
    }
} print_task;

 Task3 : ให้เขียน code ดังนี้

class MemTask : public Task {
public:
    void loop() {
        Serial.print("Free Heap: ");
        Serial.print(ESP.getFreeHeap());
        Serial.println(" bytes");
        delay(10000);
    }
} mem_task;

ส่วน Code หลัก ให้ ใส่ #include และ setup(), loop() หลัก ตามปกติการเขียนโคดแบบ Arduino
ให้เขียนดังนี้


#include <Arduino.h>
#include <Scheduler.h>
 
         /* ใส่ Task ที่ต้องการตรงบริเวณนี้ */
void setup() {
    Serial.begin(115200);
    Serial.println("");
    delay(1000); 
    Scheduler.start(&blink_task);
    Scheduler.start(&print_task);
    Scheduler.start(&mem_task);
    Scheduler.begin();
void loop() {}

โดย Task ทั้ง 3 ให้ใส่ไว้ก่อน setup() หลัก ของการเขียนแบบ Arduino
หรือจะแยกเป็นไฟล์ต่างหาก แล้ว #include เข้ามาก็ได้

วันศุกร์ที่ 12 พฤษภาคม พ.ศ. 2560

OverClock เพิ่มความเร็วให้ ESP8266 กันดีกว่า

ปกติแล้ว ตาม สเปค ESP82660 จะทำงานที่ 80MHz
ในขณะที่ Arduino UNO R3 จะทำงานที่ 16MHz เท่านั้น

แต่ๆ 80MHz ยังไม่จุใจพอ
ความจริงแล้วเราสามารถปรับให้ ความเร็วเพิ่มไปอีกเท่าตัวเป็น 160MHz กันได้


วิธีเขียนโคดไม่ยากครับเพียงเพิ่มคำสั่งเหล่านี้ลงใน Arduino IDE เวลา sketch


extern "C" { 

#include "user_interface.h" 
}

void setup(){

   //system_update_cpu_freq(80);
   system_update_cpu_freq(160);
}


void loop() {

   //.......
}
เพียงเท่านี้ ก็จะสามารถเพิ่มความเร็ว ESP8266 ได้จุใจกันเลย