วันอาทิตย์ที่ 17 พฤศจิกายน พ.ศ. 2562

Module:Environment:Dust

Dust Sensor Module

    โมดูลตรวจจับฝุ่น ทำการประมาณอนุภาคเล็กๆต่อปริมาตรอากาศ รุ่นที่ราคาถูกหน่อยใช้หลักการกระเจิงของแสง  อนุภาคขนาดต่างๆจะมีการกระเจิงแตกต่างกัน เซนเซอร์จะมีพัดลมดูดอากาศปริมาณน้อยเข้าไปผ่านตัววัด ดังนั้นค่าอาจจะไม่ได้สะท้อนความเป็นจริงของอากาศบริเวณนั้น นึกถึงน้ำขุ่นบริเวณต่างๆมันฟุ้งไม่เท่ากันอากาศก็เหมือนกัน จากประสบการณ์ค่าที่วัดได้จะแกว่งมาก เซนเซอร์สองตัววางติดกันค่าที่วัดได้อาจจะต่างกันถึง 10 หน่วยเลยทีเดียว แต่ค่าที่วัดโดยเฉลี่ยถ้าวัดถี่หน่อยทั้งวันก็จะใกล้เคียงกัน 

Plantower PMS x003

  รุ่น PMS1003, PMS3003, PMS5003, PMS6003, PMS7003 ใช้งานง่านผ่าน Serial Port ถือเป็นรุ่นยอดนิยมหาซื้อง่าย วิธีใช้งานเหมือนกัน ค่ามีการปรับเทียบจากโรงงานแล้ว(calibrate)  มีรุ่นที่ใช้เป็น I2C ด้วยแต่หาซื้อยากผมยังไม่เคยใช้ และมีรุ่นพิเศษที่เป็นรหัสลงท้าย ST จะอ่านอุณหภูมิ ความชื้น และ Formaldehyde ได้แต่หาซื้อยากราคาแพงรุ่นใหม่กว่าไม่ได้ต่างกันแต่มีขนาดเล็กลงมาก







  เซนเซอร์ต้องการไฟเลี้ยง 5V  แต่ขา RX TX ใช้ 3.3v ที่ผมเคยใช้คือ PMS7003 และ PMS5003 เป็นรุ่นยอดนิยมมี 6 สายที่ใช้งานได้
 ใช้ 4 เส้น(5v,GND,RX,TX) ก็ทำงานได้  
  • +5V - ไฟเลี้ยงเซนเซอร์
  •  0V  - Ground
  • TX  ส่งข้อมูลให้ไปต่อที่ RX ของไมโครคอนโทรลเลอร์
  • RX  รับข้อมูลให้ไปต่อที่ TX ของไมโครคอนโทรลเลอร์
  • Set ปกติปล่อยลอย(ไม่ต้องต่อ) หรือ ต่อวงจร Pullup 10K กับ GPIO ให้ High เพื่อ Wakeup หรือ Lowเพื่อ Sleep
  • Reset - ปกติปล่อยลอย(ไม่ต้องต่อ) หรือต่อ Pullup 10K กับ GPIO ถ้า ส่งลอจิก Low เพื่อ reset ตัวเซนเซอร์
ภาพล่างเป็นตัวอย่างขาของ PMS5003 จะมีสายที่มีหัวต่อสองด้านมา ผมตัดแล้วต่อวงจรหรือเข้าหัวเพื่อเชื่อมกับอุปกรณ์
 แนะนำให้ดูจาก DataSheet ของแต่ละรุ่นจะได้ต่อสายไม่พลาด
การใช้งานแบบทั่วอ่านค่าต่อแค่ 5V,Ground และ TX มันจะส่งค่า PM10 PM2.5 และ PM1 มาเรื่อยๆ
ถ้าจะรับคำสั่งเพื่อเซ็ตค่าก็ต้องต่อ RX กับ TX ของ MCU ทุกคำสั่งหรือข้อมูลจะขึ้นต้นด้วย 2 ไบต์แรก x42, x4D มีโหมดและคำสั่งดังนี้(ไปอ่าน Data Sheet จะมีอธิบาย)  ตอนส่งคำสั่งก็จะมีการตอบสนองกลับมา
Activate passive mode:
- request: 42 4D E1 00 00 01 70
- response: 42 4D 00 04 E1 00 01 74 

Activate active mode:
- request: 42 4D E1 00 01 01 71
- response: 42 4D 00 04 E1 01 01 75

Initiate measurement in passive mode:
- request: 42 4D E2 00 00 01 71
- response: one data telegram

Send to sleep:
- request: 42 4D E4 00 00 01 73
- response: 42 4D 00 04 E4 00 01 77 

Wake-up:
- request: 42 4D E4 00 01 01 74
- response: none


โดยสรุปจ่ายไฟจะเป็นโหมด Active จะมี respond เป็นค่าข้อมูลฝุ่นมาเรื่อยๆ ไม่หยุด ถ้าค่าฝุ่นมีการเปลี่ยนแปลงมากก็จะส่งถี่หน่อย ถ้าจะเปลี่ยนโหมดต้องส่งคำสั่ง เช่นส่งคำสั่งเพื่อเปลี่ยนเป็น Passive ต่างจาก Active ตรงที่ ถ้าต้องการอ่านค่าก็ต้อง ส่งคำสั่งเพื่อขอค่า  เซนเซอร์มีอายุการใช้งาน(ประมาณ 1-3 ปี) เราควรให้มัน Sleep เป็นระยะเพื่อยืดอายุการทำงานของเซนเซอร์ ถ้าจะอ่านค่าอีกทีต้อง Wakeup ล่วงหน้า 30 วินาทีแล้วค่อยเริ่มอ่านค่า จากประสบการณ์ที่เคยใช้จะมีโอกาสที่ส่งคำสั่ง sleep แล้วเซนเซอร์ไม่ยอม Sleep  แนะนำให้ใช้ขา set เพื่อควบคุมการ wakeup/sleep เนื่องจากเป็นเซนเซอร์ที่ใช้ภายในอาคาร ถ้าใช้ภายนอก ใช้ในครัว หรือในห้องน้ำ อาจจะต้องมีการออกแบบตัวป้องกันที่ดีพอเพราะฝุ่นหรือละอองน้ำอนุภาคใหญ่จะเข้าไปในตัวเซนเซอร์ได้ 
    สามารถใช้งานกับอุปกรณ์ทุกตัวที่รองรับการสื่อสารผ่านซีเรียลพอร์ต (ESP32,ESP8266,Raspberry PI,คอมพิวเตอร์ ฯลฯ) สามารถใช้ USB2Serial เพื่อใช้ต่อกับคอมพิวเตอร์ได้(PC/Mac ดูในภาพ) 

ESP32/ESP8266 ใช้ง่ายแค่ให้ติดตั้งไลบารี่ PMS เพิ่มจาก Library Manager แนะนำให้ดูตัวอย่างที่มากับ Library หรือจะอ่านค่าจาก Serial แล้วดึงออกมาเองก็ได้

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
1213
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
//ESP32: อ่านค่าจากเซนเซอร์วัดฝุ่น PMS1003, PMS3003, PMS5003, PMS6003, PMS7003
//
#include "PMS.h"  // PMS Library by Mariusz Kachi Version 1.1.0
PMS pms(Serial2); // ต่อเซนเซอร์ที่ Serial2
PMS::DATA data;
#define RXD2 13 // ต่อ TX ของเซนเซอร์
#define TXD2 12 // ต่อ RX ของเซนเซอร์
void setup()
{
  Serial.begin(9600);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);   
  pms.passiveMode();    // ใช้โหมด passive mode ต้อง requestRead 
}
void loop()
{
  Serial.println("Waking up, wait 30 seconds for stable readings...");
  pms.wakeUp(); //ปลุกเซนเซอร์ขึ้นมาทำงาน
  delay(30000);
  Serial.println("Send read request...");
  pms.requestRead(); //ขอข้อมูล จากเซนเซอร์ ของโหมด passive
  Serial.println("Reading data...");
  if (pms.readUntil(data))
  {
    Serial.print("PM 1.0 (ug/m3): ");
    Serial.println(data.PM_AE_UG_1_0);

    Serial.print("PM 2.5 (ug/m3): ");
    Serial.println(data.PM_AE_UG_2_5);

    Serial.print("PM 10.0 (ug/m3): ");
    Serial.println(data.PM_AE_UG_10_0);
  }
  else
  {
    Serial.println("No data.");
  }
  Serial.println("Going to sleep for 60 seconds.");
  pms.sleep(); //พักการทำงานของเซนเซอร์
  delay(60000);
}

สำหรับ Raspberry PI  ต้องเปิดใช้งาน Serial Port ก่อน สำหรับคอมพิวเตอร์(PC/Mac) ให้ต่อผ่าน USB to Serial Adapter มีโค้ดตัวอย่างหาได้ง่ายส่วนใหญ่เป็น Python ผมเขียนไม่เป็นเลยหาที่เป็น JavaScript(Node.js) มี Library ให้ใช้งานแต่ปัญหาเยอะเหมือนกัน ยังมีไลบารีพื้นฐาน  Node SerialPort ซึ่งจำเป็นต้องคอมไฟล์โค้ดด้วย สำหรับ Windows ต้องติดตั้ง C++ build tools ก่อน เนื่องจาก Library สำหรับอ่านค่าฝุ่นมีปัญหาและไม่ได้อัปเดต ผมเลยเขียนแบบง่ายๆขึ้นมาเองใช้แค่ Node SerialPort แก้ค่า COM3 เป็นค่าของเครื่องที่ใช้คร้บ สำหรับ Linux จะเป็นหน้าตาประมาณนี้ /dev/ttyAMA0


 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
72
73
74
var SerialPort = require("serialport")
var serialPort = new SerialPort("COM3", {
	baudRate: 9600,
})
function processData(info) {
	var s = ""
	for (var j = 0; j < info.length; j++) {
		s = s + ":" + info[j].toString(16)
	}
	console.log("Data", info)
	var temp2, tem1, pm1, pm2_5, pm10, n03, n05, n1, n25, n5, n10
	pm1 = (info[4] << 8) | info[5]
	pm2_5 = (info[6] << 8) | info[7]
	pm10 = (info[8] << 8) | info[9]
	console.log("pm1 :" + pm1 + ", pm2.5 :" + pm2_5 + ", pm10 :" + pm10)

	pm1 = (info[10] << 8) | info[11]
	pm2_5 = (info[12] << 8) | info[13]
	pm10 = (info[14] << 8) | info[15]
	console.log("pm1a:" + pm1 + ", pm2.5a:" + pm2_5 + ", pm10a:" + pm10)

	n03 = (info[16] << 8) | info[17]
	n05 = (info[18] << 8) | info[19]
	n1 = (info[20] << 8) | info[21]
	n25 = (info[22] << 8) | info[23]
	n5 = (info[24] << 8) | info[25]
	n10 = (info[26] << 8) | info[27]

	console.log("n03:" + n03 + ",n05:" + n05 + ",n1:" + n1 + 
                ",n25:" + n25 + ",n5:" + n5 + ",n10:" + n10)
}

function init() {
	serialPort.on("open", function () {
		// sleep  0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73
		// wakeup 0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74
		// active 0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71
		// passive 0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70
		// request read 0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71
		serialPort.write(Buffer.from([0x42, 0x4d, 0xe4, 0x00, 0x01, 0x01
                    , 0x74, 0x42, 0x4d, 0xe1, 0x00, 0x01, 0x01, 0x71]), 
                function (err) {
			if (err) {
				return console.log("Error on write : ", err.message)
			}
			console.log("message written")
		})
		var sign = 0
		counter = 0
		a = new Array(32).fill(0)

		serialPort.on("data", function (data) {
			//console.log('data received: ' + data);
			//console.log( data[0].toString() + ":"+ data.byteLength );
			for (var i = 0; i < data.byteLength; i++) {
				if (counter == 0 && data[0] != 0x42) return
				if (counter == 1 && data[i] != 0x4d) {
					counter = 0
					return
				}
				a[counter] = data[i]
				counter++
				if (counter == a.length) {
					counter = 0
					sign = 1
				}
				//process array
				if (sign) {
					sign = 0
					processData(a)
				}
			}
		})
	})
}
init()

ผมแก้ไข Library จากของเดิมใหม่แต่มีหลายไฟล์ ไว้ขึ้น Git แล้วจะมาอัปเดตที่นี้ครับ

เพิ่มเติม


Shinyei Model PPD42NS Dust Sensor

เป็นเซนเซอร์แบบอนาล็อก คิดว่าน่าจะต้องมีเครื่องวัดที่เที่ยงตรงอีกตัวแล้วทำการ calibrate  ผมมีอยู่ตัวหนึ่งถ้ามีเวลาจะเอามาลองใช้ ตอนนี้ให้ดูตัวอย่างในลิงค์นี้ จะต้องต่อ Voltage Devider เพื่อให้ใช้กับ 3.3โวลต์ได้



ข้อมูลทั่วไป



วันเสาร์ที่ 9 พฤศจิกายน พ.ศ. 2562

ESP32:Coding:Basic

โค้ดสำหรับผู้เริ่มหัดใช้งาน

  สำหรับผู้เริ่มต้นใช้ ESP32 ต้องสามารถอัปโหลดโปรแกรมขึ้นบอร์ดให้ได้ก่อน แล้วลองใช้โค้ดตัวอย่างที่มีใน Arduino IDE สำรวจ บอร์ดของเราก่อนว่ามี ปุ่มหรือไฟ LED ให้ใช้งานหรือไม่  ดูจากคู่มือบอร์ดที่เราใช้ ตัวอย่างในหน้านี้อาจจะมีการดัดแปลงเล็กน้อยเพื่อให้สะดวกต่อการใช้งาน  แนะนำให้เลือกโค้ดที่ ใช้ ปุ่มBOOT, LED ,Wifi ,Blue, tooth , sensor ที่มากับบอร์ด จะได้ไม่ต้องต่ออุปกรณ์เพิ่ม พอคุ้นเคยแล้วถึงเริ่มต่ออุปกรณ์แล้วเขียนโค้ดเพื่อใช้งาน
ตัวอย่างที่อยู่ใน Arduino IDE


จากภาพ Build in Example จะเป็นตัวอย่างที่ใช้กับ Arduino  บางตัวอย่างใช้กับ ESP32 ได้ บางตัวอย่างก็ใช้ไม่ได้ เช่นที่ใช้ฟังก์ชั่น analogWrite() ซึ่ง ESP32 ไม่รองรรับ ส่วนตัวอย่างที่ใช้ได้กับ ESP32 จะอยู่จะอยู่ด้านล่างๆ ที่เขียนว่า Example for [ชื่อบอร์ด ESP32]
สำหรับวิธีการใช้ฟังชั่นต่างๆและไวยากรภาษา C สามารถดูได้จากเมนู Help/Reference ใน Arduino IDE ได้เลย

Examples/01.Basics/Blink

ตัวอย่างไฟกระพริบทุกๆหนึ่งวินาที ถ้าบอร์ดมี LED ในตัวหรือ แล้วเลือกบอร์ดบน Arduino IDE ได้ถูกรุ่น จะมีการประกาศค่า LED_BUILTIN ไว้เรียบร้อยแล้ว ว่าเป็นขาไหน (บางรุ่นก็ไม่ประกาศก็จะคอมไฟล์ไม่ผ่าน) ผมขอแก้นิดหน่อยเพื่อให้คอมไฟล์กับบอร์ดไหนก็ได้ แต่ต้องแก้ค่า led_pin ให้ตรงกับขาที่เป็น LED

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int led_pin = 13; //ใส่เลขขา LED หรือใช้ LED_BUILTIN ก็ได้
void setup() {
  pinMode(led_pin, OUTPUT); //กำหนดให้ led_pin เป็น OUTPUT(ส่งค่าออก)
}
void loop() {
  digitalWrite(led_pin, HIGH);   // เปิดไฟ (HIGH มีค่าเป็น 1)
  delay(1000);                   // รอ 1000 มิลลิวินาที(1วินาที)
  digitalWrite(led_pin, LOW);    // ปิดไฟ (LOW มีค่าเป็น 0)
  delay(1000);                   // รอ 1000 มิลลิวินาที(1วินาที)
}

pinMode(pin_number, INPUT);  กำหนด ขา(pin_number)ให้เป็นขาสำหรับรับค่า INPUT (กำหนดได้ 3 ค่า INPUT, OUTPUT, INPUT_PULLUP)
digitalWrite(pin_number, 0_or_1);  คำสั่งนี้จะเขียน 0(LOW) หรือ 1(HIGH) ไปที่ขาที่กำหนดใน pin_number
delay(1000) จะเป็นการหยุดรอ เป็นจำนวนมิลลิวินาที ดังนั้น 1000มิลลิวินาทีก็คือหนึ่งวินาที
ลองเปลี่ยนค่า delay แล้วดูการเปลี่ยนแปลงของการกระพริบ สำหรับผู้ที่ต่อไฟ LED เพิ่มเอง ควรใช้ตัวต้านทานซัก 330 - 1K โอมห์ ร่วมด้วย ระวัง LED ต่อกลับข้างไฟจะไม่ติด
 ต่อหลอด LED กับ ESP32

Examples/02.Digital/Button

กดปุ่มเพื่อปิดหรือเปิดไฟ บอร์ดหลายรุ่นมีปุ่ม Boot ซึ่งต่อกับขา 0 เรานำมาใช้ได้ (ปุ่ม EN หรือ Reset ไม่สามารถอ่านค่าด้วยโค้ดได้)คล้ายตัวอย่างที่แล้วเพิ่มการอ่านปุ่มเข้ามา ใช้ปุ่มเพื่อปิดเปิด LED มีการแก้โค้ดเดิมนิดหน่อยให้กระชับขึ้น


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const int buttonPin = 0;// เลขขาที่ต่อปุ่ม ปุ่ม BOOT อยู่ที่ขา 0
const int ledPin =  4;  // ใส่เลขขา LED หรือใช้ LED_BUILTIN ก็ได้
int buttonState = 0;    // ตัวแปรเก็บสถานะ LOW/HIGH ของปุ่ม
void setup() {
  pinMode(ledPin, OUTPUT);   //กำหนดให้ ledPin เป็น OUTPUT(ส่งค่าออก)
  pinMode(buttonPin, INPUT); //กำหนดให้ buttonPin เป็น INPUT(รับค่าเข้า)
}
void loop() {
  buttonState = digitalRead(buttonPin);
  digitalWrite(ledPin, buttonState);
}

digitalRead(pin_number); ฟังก์ชั่นนี้จะอ่านค่าสถานะ(0 หรือ 1 )จากขา
โปรแกรมอ่านสถานะของปุ่มด้วย digitalRead ไปเก็บในตัวแปร buttonState แล้วนำค่าใน buttonState ส่งออกไปด้วย digitalWrite สู่หลอด LED
ปุ่ม BOOT จะให้ค่าเป็น LOW ก่อนกดปุ่มแล้วจะให้ HIGH เมื่อกดปุ่ม


คำถาม : ถ้าจะให้ปุ่มทำงานตรงกันข้ามกับที่เป็นอยู่ตอนนี้จะต้องแก้โค้ดอย่างไร

ถ้าบอร์ดไม่มีปุ่ม BOOT หรืออยากต่อปุ่มเอง จำเป็นต้องใช้วงจร Pull Up เพื่อให้ขาอยู่สถานะที่ถูกต้อง ใน ESP32 มีวงจร Pull up อยู่ในตัวสามารถเรียกใช้ได้เลย ให้ต่อสวิตซ์ด้านหนึ่งกับ GND อีกด้านต่อกับขาใดขาหนึ่งที่อ่านค่าดิจิตอลได้ นำโค้ด ก่อนหน้ามาแก้ตรง
pinMode(buttonPin, INPUT); 
ให้เป็น
pinMode(buttonPin, INPUT_PULLUP); 



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const int buttonPin = 6;// เลขขาที่ต่อปุ่มที่ขา 6
const int ledPin =  22;  // ใส่เลขขา LED ที่ขา 22
int buttonState = 0;    // ตัวแปรเก็บสถานะ LOW/HIGH ของปุ่ม
void setup() {
  pinMode(ledPin, OUTPUT);   //กำหนดให้ ledPin เป็น OUTPUT(ส่งค่าออก)
  pinMode(buttonPin, INPUT_PULLUP); //กำหนดให้ buttonPin เป็น INPUT(รับค่าเข้า)
}
void loop() {
  buttonState = digitalRead(buttonPin);
  digitalWrite(ledPin, buttonState);
}

ปุ่มต่อขา16 หลอด LED ต่อขา 22 ใช้ตัวต้านทาน 1Kโอมห์

Examples/01.Basics/DigitalReadSerial

   เวลาบอร์ดต่อก้บคอมพิวเตอร์จะติดต่อสื่อสารกันผ่านพอร์ตซีเรียล เป็นการสื่อสารแบบอนุกรม ส่งข้อมูลเรียงๆกันไปเป็นจังหวะ(baud rate)ที่รู้กันระหว่างสองฝั่ง จะไม่อธิบายรายละเอียดในที่นี้  ขอให้รู้เพียงว่าเป็นการสื่อสารประเภทหนึ่งก็พอ  ขณะอัปโหลดโปรแกรมจะใช้เพื่อส่งโปรแกรมที่คอมไพล์เสร็จแล้วไปใส่ไว้ในบอร์ด หลังจากนั้นพอร์ตซีเรียลก็จะนำไปใช้งานอื่นได้ ตัวอย่างนี้จะใช้เพื่อส่งข้อความจากบอร์ดไปคอมพิวเตอร์ มีประโยชน์มากคือใช้ดีบักโปรแกรม เพราะบอร์ดส่วนใหญ่จะไม่มีจอแสดงผล ส่งข้อมูลกลับมาที่จอคอมพิวเตอร์จะได้รู้ว่าโปรแกรมทำงานไปถึงไหนแล้ว ตัวแปรมีค่าอะไร ในเมนู Tools/Serial Monitor จะมีโปรแกรมสำหรับรับและส่งค่าไปที่พอร์ตซีเรียล ถ้าข้อมูลที่ส่งมาเป็นตัวเลขเรานำมาแสดงเป็นกราฟได้ด้วย  Tools/Serial Plotter 


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int pushButton = 0; 
void setup() {
  Serial.begin(9600); //ความเร็วหรือจังหวะการรับส่งข้อมูล
  pinMode(pushButton, INPUT);
}
void loop() {
  int buttonState = digitalRead(pushButton);
  Serial.println(buttonState);//ส่งค่า 0 หรือ 1 ไปที่พอร์ตซีเรียล
  delay(10); 
}
ตัวอย่างโค้ดจะอ่านค่าจากปุ่ม BOOT แล้วส่งค่าไปที่พอร์ตซีเรียล ถ้าเปิด Serial Monitor จะเห็นค่า 0 กับ 1 ทีละบรรทัด
Serial.begin(9600); ฟังก์ชั่นนี้จะกำหนดจังหวะการรับส่ง่ข้อมูล ใน Serial Monitor ก็ต้องเซ็ตเป็นค่าเดียวกันถึงจะรับส่งข้อมูลได้
Serial.println(buttonState); ส่งค่า buttonState ไปออกพอร์ตซีเรียล และปิดท้ายด้วยขึ้นบรรทัดใหม่(ส่งอักขระ Enter) ถ้าใช้ Serial.print() จะไม่มีเครื่องหมายขึ้นบรรทัดใหม่ปิดท้าย

DigitalReadSerial แสดงใน Serial Plotter

Examples/ESP32/Touch/TouchRead

ESP32 มีปุ่มสัมผัส ไม่ต้องต่ออะไรเพิ่มแค่ใช้นิ้วมือแตะก็พอ ใช้การตรวจสอบประจุไฟฟ้าที่ขา จะมีบางขาที่ทำปุ่มสัมผัสได้  ยกตัวอย่าง(ภาพล่าง)ผังการวางขาของบอร์ดรุ่นหนึ่ง เราจะเห็น Touch5 อยู่ขา 12 จะสำหรับบอร์ดนี้ T5 จะแทนค่า 12 (มี T0-T9)




โค้ดของโปรแกรมตัวอย่างจะคล้ายกับ DigitalReadSerial ที่ผ่านมาแต่ค่าที่อ่านได้จะไม่ใช่ 0/1 จะเป็นค่าที่ไม่ค่อยนิ่งเท่าไหร่ขึ้นกับความชื้นและวิธีการสัมผัส ทดสอบโดยใช้นิ้วแตะที่ขา T5 เราสามารถใช้เลข 12 แทนก็ได้


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void setup()
{
  Serial.begin(115200); //จังหวะการส่งข้อมูล
  delay(1000); // give me time to bring up serial monitor
  Serial.println("ESP32 Touch Test");
}
void loop()
{
  Serial.println(touchRead(T5));// อ่านค่าจากขา T5 แล้วส่งออกพอร์ตซีเรียล
  delay(1000);
}
ในกราฟด้านล่างเมื่อแตะขา 12 ค่าจะตกลงมา
TouchRead แสดงค่าใน Serial Plotter


เพิ่มเติม

Examples/ESP32/Fading/LEDSoftwareFade

การปรับความสว่างของหลอด LED สามารถใช้การต่อตัวต้านทานแบบปรับค่าได้อนุกรมกัน โวลต์ตกคร่อมหลอดไฟก็จะอยู่ระหว่าง 0-3.3โวลต์(อนาล็อก)  แต่ ESP32 ไม่สามารถส่งค่าออกเป็นอนาล็อกได้  เลยส่งเป็นสัญญาณ เปิดปิดถี่ๆสลับกัน ถ้าไฟสว่างก็ให้ช่วงการเปิดนานกว่าปิด ถ้าหรี่ไฟก็ให้มีช่วงที่ปิดนานขึ้น การทำแบบนี้เรียก PWM  ขา GPIOs 34 ถึง 39 ใช้ PWM ไม่ได้ อ่านเพิ่มเติมได้จากลิงค์ด้านล่าง
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const int ledPin=2; // ใส่เลขขา LED หรือใช้ LED_BUILTIN ก็ได้
const int freq = 5000;     // ความถี่
const int ledChannel = 0;  // ช่องของ PWM ,มี 16 channel
const int resolution = 8; // ความละเอียด 8บิต
void setup(){
  ledcSetup(ledChannel, freq, resolution); //ช่อง,ความถี่,ความละเอียด
  ledcAttachPin(ledPin, ledChannel);// เชื่อม channel เข้ากับขา GPIO
}
void loop(){
  // increase the LED brightness
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){   
    ledcWrite(ledChannel, dutyCycle);// ส่งเออกป็น PWM ที่ channel ที่กำหนด
    delay(15);
  }
}

เพิ่มเติม

Examples/ESP32/HallSensor

ในตัวชิป ESP32 จะมีเซนเซอร์วัดสนามแม่เหล็ก เราสามารถเรียกดูค่าได้จากฟังก์ชั่น hallRead()  ให้นำแม่เล็กแรงสูงมาจ่อที่ชิป แล้วดูค่าผ่าน Serial Plotter

1
2
3
4
5
6
7
8
//อ่านค่าจาก Hall Sensor ไปแสดงที่ Serial
//ใช้แม่เหล็กแรงสูงเพื่อทดสอบ
void setup() {
  Serial.begin(9600);
}
void loop() { 
  Serial.println(hallRead());
}

Examples/Wifi/WifiScan

   ค้นหา Wifi Access Point ที่อยู่ใกล้เคียงแล้วแสดงชื่อพร้อมความแรงสัญญาณ ตัวอย่างนี้จะใช้ Library เพิ่มเติมโดยตรงบรรทัดแรกจะเห็น
#include "ไฟล์ header ของ Library"
สามารถศึกษาการใช้ไลบารี่เพิ่มเติมได้ที่นี้


 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
#include "WiFi.h" //ใช้ Library เกี่ยวกับ Wifi
void setup()
{
    Serial.begin(115200);
    WiFi.mode(WIFI_STA); //ใช้โหมด Station
    WiFi.disconnect(); //ตัดการเชื่อมต่อกัย Access point (ถ้าต่ออยู่)
    delay(100);
    Serial.println("Setup done");
}
void loop()
{
    Serial.println("scan start");
    int n = WiFi.scanNetworks(); //ค้นหา Access Point ที่อยู่รอบๆ,n จำนวนที่พบ
    Serial.println("scan done");
    if (n == 0) {
        Serial.println("no networks found");
    } else {
        Serial.print(n);
        Serial.println(" networks found");
        for (int i = 0; i < n; ++i) {
            // Print SSID and RSSI for each network found
            Serial.print(i + 1);
            Serial.print(": ");
            Serial.print(WiFi.SSID(i)); //Service Set Identifier(ชื่อ Access Point)
            Serial.print(" (");
            Serial.print(WiFi.RSSI(i)); //Received signal strength(ความแรงสัญญาณ)
            Serial.print(")");
            Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN)?" ":"*");
            delay(10);
        }
    }
    Serial.println("");
    delay(5000); //รอซักครู่ก่อนค้นหารอบต่อไป
}

WifiScan: ชื่อ Accesspoint แสดงใน Serial Monitor

Examples/Wifi/WifiAccessPoint

    ตัวอย่างนี้ยาวหน่อย เป็นการสั่งปิดเปิดไฟผ่านเวป ESP32 จะกระจายสัญญาณ Wifi (Access Point) สามารถใช้มือถือหรือคอมพิวเตอร์เชื่อมต่อได้แต่ออกอินเตอร์เน็ตไม่ได้ เปิดเวปบราวเซอร์แล้วไปที่ IP Address ของ ESP32 ก็จะเห็นหน้าเวป มีลิงค์ให้เลือกปิดเปิดหลอด LED ที่อยู่บนบอร์ด
การสื่อสารด้วยเวป(โปรโตคอล HTTP) จะประกอบไปด้วย request กับ response
Request: คอมพิวเตอร์ร้องขอไปที่เซิร์ฟเวอร์
Response: เวปเซิร์ฟเวอร์ตอบกลับมา
เช่นมือถือ(client)ร้องขอหน้าเวป https://www.google.com
เวปเซิร์ฟเวอร์ของ google ตอบกลับโดยส่งหน้าเวปกลับมาแสดงที่มือถือ ลองดูวีดีโอของโค้ดที่เราจะลองอัปโหลด


โค้ดก็อปไปใช้ได้เลย

 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
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
//#define LED_BUILTIN 2   //ถ้าบอร์ดมีการกำหนดค่านี้แล้วให้คอมเมนต์บรรทัดนี้ออกหรือกำหนดเลขขาให้ถูกถ้าไม่มี
const char *ssid = "yourAP"; //ชื่อ Access point ที่เราสร้างขึ้น
const char *password = "yourPassword"; //รหัสผ่านของ Access point
WiFiServer server(80);
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");
  WiFi.softAP(ssid, password); // ถ้าไม่ต้องการให้มีการใส่รหัสผ่านให้เอา password ออก
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();
  Serial.println("Server started");
}

void loop() {
  WiFiClient client = server.available();   // รอ client ติดต่อมา
  if (client) {                             // มีอุปกรณ์(client)ต่อเชื่อมเข้ามา
    Serial.println("New Client.");          
    String currentLine = "";                // สร้าง String เพื่อเก็บข้อมูลจาก client
    while (client.connected()) {            // ลูปวนรอขณะที่มีการเชื่อมต่อจาก client
      if (client.available()) {             // ถ้ามีข้อมูลที่ยังสามารถอ่านได้จาก client
        char c = client.read();             // อ่านมาหนึ่งไบต์เก้บไว้ในตัวแปร c (อ่านทีละตัวอักษร)
        Serial.write(c);                    
        if (c == '\n') {                    // ถ้าขึ้นบรรทัดใหม่(อักขระ new line)
          // ถ้าพบการขึ้นบรรรทัดใหม่ ที่ต้นบรรทัด(currentLine เป็น 0 )
          // อีกความหมายหนึ่งก็คือเจอขึ้นบรรทัดใหม่สองรอบ จะเป็นการจบ  HTTP request ดังนั้นส่ง response ได้
          if (currentLine.length() == 0) {
            // ต้องส่งสามบรรทัดก่อนส่งข้อมูล 1.ส่วนหัว, 2.ชนิดข้อมูล, 3.ตบท้ายด้วยบรรทัดว่างๆ
            client.println("HTTP/1.1 200 OK"); // ส่วนหัวของ HTTP จะต้องส่งโค้ดบอกสถานะ
            client.println("Content-type:text/html"); //เพื่อให้ client รู้ว่าข้อมูลที่ส่งกลับเป็น HTML
            client.println();//บรรทัดว่าง
            // ส่งข้อมูลเป็นหน้าเวปกลับไป
            client.print("Click <a href=\"/H\">here</a> to turn ON the LED.<br>");
            client.print("Click <a href=\"/L\">here</a> to turn OFF the LED.<br>");
            client.println();// ปิดจบด้วยบรรทัดว่าง
            break; //ออกจากลูป while
          } else {    
            currentLine = ""; //จบหนึ่งบรรทัดทำให้ว่างเตรียมบรรทัดใหม่
          }
        } else if (c != '\r') { // ถ้าคุณได้อักขระใดๆที่ไม่ใช่ carriage return
          currentLine += c;     // เอาตัวอักษรนั้นไปต่อในบรรทัด( carriage return จะทิ้งไป)
        }

        // ถ้าได้ "GET /H" หรือ "GET /L" ในท้ายบรรทัด// ถ้าได้ "GET /H" หรือ "GET /L" ในท้ายบรรทัด
        if (currentLine.endsWith("GET /H")) {
          digitalWrite(LED_BUILTIN, HIGH);   // เปิดไฟ
        }
        if (currentLine.endsWith("GET /L")) {
          digitalWrite(LED_BUILTIN, LOW);    // ปิดไฟ
        }
      }
    }//จบ while
    client.stop(); //จบการเชื่อมต่อกับ client
    Serial.println("Client Disconnected.");
  }
}

โค้ดนี้จำเป็นต้องมีความรู้เรื่องเวปและ HTML มาบ้าง ส่วนโค้ดที่เป็นแสดงหน้าเวปจะเป็นสองบรรทัดล่างนี้
Click here to turn ON the LED
Click here to turn OFF the LED

แต่เวลาเขียนเป็นโค้ดภาษา C ถ้าตัวหนังสือจะแสดงเครื่องหมายคำพูดต้องใช้เครื่องหมาย \ ไว้หน้าเสมอเพื่อจะได้ไม่กลายเป็นหมายคำพูดของต้นและท้ายประโยค
เวลาเปิดไฟคลิ้กที่ลิงค์ก็จะไปที่ http://192.168.4.1/H ถ้าปิดไฟจะเป็นลิงค์ http://192.168.4.1/L




วันอาทิตย์ที่ 3 พฤศจิกายน พ.ศ. 2562

ESP32:Board:DOIT ESP32 DevKit V1

DOIT ESP32 DevKit V1 

    เป็นบอร์ด ESP32 จาก DOIT บอร์ดนี้ราคาถูกดี เท่าที่เห็นมีสองรุ่นคือ 30 ขากับ 36 ขา ดันเขียนชื่อเหมือนกันเลยมันออกจะสับสนอยู่ การใช้ไม่ต่างกันมันเรียงขาเหมือนกัน 36 ขาก็มีขาเพิ่มขึ้นจาก แค่ 30ขา ก็มากเกินพอสำหรับงานทั่วๆไปแล้ว  LED_BUILTIN อยู่ GPIO 2

ภาพจาก Github
แบบ 36 ขา(ภาพจาก smartarduino)



แบบ 30 ขา




Pin Layout30 ขา จาก https://playelek.com 



Pin Layout30 ขา จาก randomnerdtutorials


   แต่ที่เห็นทั่วๆไปผมคิดว่ามันเป็นตัวก็อป (จีนก็อปจีน ตัวหนังสือที่อยู่บนบอร์ดมันจะไม่ค่อยชัดเท่าไหร่) บอร์ดนี้มีเรื่องจุกจิกกวนใจในการใช้หน่อย
    อันแรกขนาดบอร์ดค่อนข้างกว้าง เวลาใส่ในบอร์ดทดลองมันจะเหลือช่องเสียบแค่แถวเดียวกข้างเดียว ถ้าเอามาใช่้ทดลองนิดๆหน่อยๆ แค่แถวเดียวก็เหลือเฟือ แต่ก็จะไม่ค่อยมีช่องว่างพอที่จะวางอุปกรณ์อื่นๆ ต้องจัมป์สายไปตรงที่ว่างๆหน่อย อีกวิธีหนึ่งก็ให้บอร์ดนี้ขี่คร่อมสองบอร์ด แต่ก็เป็นข้อดีอันหนึ่งเพราะว่ากว้างพอที่จะใส่ตัวอักษรแสดงว่าขาไหนเป็นขาไหนได้ไว้ด้านบนได้ รุ่นอื่นมันแคบต้องใส่ไว้ด้านล่าง รุ่นเลียนแบบตัวอักษร มันก็ไม่ค่อยชัดอ่านยากหน่อย
    อันที่สองเวลาอัปโหลดด้วย Arduino IDE มันต้องกดปุ่มทุกครั้ง พอขึ้นตัวหนังสือแล้ว กดปุ่ม EN พร้อม BOOT แล้วปล่อย EN ก่อนถึงจะอัปโหลดได้  ต้องทำทุกครั้งก็น่ารำคาญเหมือนกัน ควรต่อตัวเก็บประจุ (1-10uF) ตรงขา EN (บนซ้ายสุด) จะได้อัปโหลดโปรแกรมโดยไม่ต้องกดปุ่ม การใช้งานเหมือนกับบอร์ดรุ่นอื่นๆ สะดวกสามารถใช้งานผ่าน Arduino IDE ได้โดยตรง

ข้อมูลเพิ่มเติม


  • ข้อมูลของบอร์ดนี้ดูได้ที่นี้ (ไม่ค่อยช่วยอะไรเท่าไหร่)
  • สำหรับคนที่ใช้ Fritzing ในการออกแบบสามารถดาว์นโหลดได้ที่นี้
  • ไดร์เวอร์สำหรับติดต่อกับคอมพิวเตอร์ CP210x USB to UART Bridge VCP Drivers


วันศุกร์ที่ 1 พฤศจิกายน พ.ศ. 2562

ESP32:Board:ESP32-CAM

Board ESP32-CAM

ESP32-CAM

  ขนาดเล็ก มีกล้องรุ่น OV2640 ในตัว กล้องไม่ค่อยดีมากแค่ 2 ล้านพิกเซลล์ มีตัวอ่านการ์ด Micro SD มีปุ่ม Reset หนึ่งปุ่ม มีไฟแฟลช (แทนที่หลอด LED อยู่ที่ขา 4)   ปุ่ม Reset อยู่ใต้บอร์ดถ้าต่อบนบอร์ดทดลองจะกดไม่ได้ ถ้าจะอัปโหลดโปรแกรมต้องต่อปุ่ม Boot (ใส่สวิตซ์ระหว่างขา GND กํบ GPIO 0) และต่อสายกับ USB2Serial เอง ทำให้รกรุงรังกับต้นทุนสูง  ไม่ค่อยเหมาะสำหรับนักเรียนที่จะนำมาหัดใช้
ตอนอัปโหลดโปรแกรมเลือกบอร์ดเป็น ESP32 Wrover Module กดปุ่ม Boot กับ Reset แล้วปล่อย Reset แล้วค่อยปล่อยปุ่ม Boot ตามมา บางเวปบอกให้ต่อ GPIO 0 กับ GND เลยไม่ต้องทำปุ่ม Boot


สามารถทดสอบบอร์ดแบบง่ายๆ ด้วยโค้ดแบบง่ายจะทำไฟแฟลชกระพริบ
#define LED_BUILTIN 4
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   
  delay(1000);           
  digitalWrite(LED_BUILTIN, LOW);
  delay(5000);  
}



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

ESP32:Board: D1 Mini

Board D1 MINI ESP32


LILYGO® TTGO Mini32 V2.0 ESP32


    เป็นบอร์ดที่สั้นแต่อ้วน ออกแบบให้ต่อเป็นชั้นๆ (Shield)ซ้อนขึ้นไปได้ งานออกมาจะเรียบร้อยดี คล้ายๆ M5Stack แต่ถูกกว่ามาก สามารถใช้ร่วมกับ Shield ของ WEMOS D1 ผมเลยลองซื้อมา ข้อดีคือมีขาให้เลือกหลายแบบมาก มีขาสำรองมาให้ไว้ทำบอร์ดเสริม รุ่นนี้กว้างหน่อยวางบนบอร์ดทดลองไม่เหลือช่องต่อด้านข้างเลย  แต่เราใช้สายจัมป์ต่อช่องต่อ shield ด้านบนก็ได้
    รุ่นนี้เป็นรุ่นที่แปลกที่มีหลายยี่ห้อทำออกมา การวางขาเหมือนกันเลยคงเป็นเพราะ ความนิยม Shield ของรุ่น D1 ที่เป็นชิป ESP-8266 ใน Arduino IDE โค้ดอัปโหลดโปรแกรมอัตโนมัติ ทดสอบบอร์ดด้วยโค้ด Blink
#define LED_BUILTIN 22
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW)
  delay(1000);
}

สามารถเลือกบอร์ดเป็น MH ET LIVE ESP32MiniKit หรือ WEMOS D1 MINI ESP32 ก็ได้ ไม่ว่าเลือกเป็นบอร์ดไหนก็ทำงานได้เหมือนกัน ที่ผมได้มาหน้าตาเหมือนด้านล่าง แต่จะไม่มีโลโก้ Wemos ในเวป wemos.cc ไม่มีรุ่น D1 สำหรับ ESP32 แต่มีบอร์ดขายและมีบอร์ดให้เลือกใน Arduino IDE น่าแปลกเหมือนกัน
MH ET LIVE ESP32MiniKit





ESP32:Board:Lolin32

Board Lolin32

    บอร์ดแคบ มีเอกลักษณ์อันหนึ่งคือขาสองข้างจำนวนไม่เท่ากัน (ซ้าย 16 ขวา20) ใน Arduino IDE ใช้เป็น WEMOS LOLIN32 เป็นรุ่นประหยัดไฟอีกรุ่นหนึ่ง อัปโหลดโค้ดอัตโนมัติ มีปุ่ม Reset แค่ปุ่มเดียว ค่าของ LED_BUILTIN  จะเป็นขา  5

Lolin32 (retired)
ทดสอบด้วยโค้ด Blink 

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW)
  delay(1000);
}



เพิ่มเติม

ESP32:Board:Lolin32 Lite

Board Lolin32 Lite

    ถึงจะเป็นบอร์ดเลิกผลิดแล้วแต่ยังมาขายกันอยู่ ไม่ได้ใช้โมดูลเลยมีเนื้อที่พอจะสกรีนเลขขาเห็นชัดเจนบนบอร์ด   ขาไม่เยอะ(26ขา) ถือว่าเป็นบอร์ดที่แคบและสั้น ราคาไม่แพง เสียบบอร์ดทดลองจะเหลือช่องเสียบสองด้านด้านละหนึ่งช่อง

Lolin32 Lite (retired)

ดาว์นโหลดโปรแกรมอัตโนมัติ ไม่มีบุ่ม Boot ใช้ USB2Serial รุ่น CH340 ไม่มี LED แสดงสถานะใช้งาน มี LED ที่ใช้ปิดเปิดได้ที่ขา 22 กินไฟน้อยกว่ารุ่นปรกติ  เวลาใช้ Arduino IDE ไม่มีบอร์ดให้เลือกตรงๆ ให้เลือกเป็น ESP32 Dev Module ทดสอบด้วยโค้ด Blink ต้องแก้เล็กน้อยเป็นดังนี้

#define LED_BUILTIN 22
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW)
  delay(1000);
}

รุ่นนี้มีตัวก็อปอาจจะเจอตัวที่มีปัญหาการชาร์ต  มันอาจจะไม่ตัดไฟหลังชาร์ตเต็ม  ไม่เหมาะกับการชาร์ตทิ้งไว้ตลอดเวลา อาจจะทำให้แบ็ตบวมได้ 


เพิ่มเติม


Module:Control:IFR 520

MOSFET Module  สวิตซ์ปิดเปิดไฟเหมือน Relay แต่เป็น Solid state (ไม่มีส่วนที่เคลื่อนไหว) มันทำงานที่ความถี่สูงได้เหมาะกับเอาไปใช้งาน PWM ...