Tải bản đầy đủ (.pdf) (75 trang)

Các dự án ứng dụng lập trình IOT với ESP8266 trong Arduino

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.62 MB, 75 trang )

Bốn dự án ứng dụng lập trình IOT với
ESP8266 trong Arduino


Mục lục
Giới thiệu ...................................................................................................................................................... 3
Chuẩn bị: Cài đặt ESP8266 để lập trình trong Arduino. ................................................................................ 3
Dự án 1: Lập trình đồng hồ LED 7 đoạn dùng ESP8266 và DS1307 ............................................................ 10
Dự án 2: Điều khiển ESP8266 bằng giọng nói với Google Assistant ........................................................... 31
Dự án 3 - Giải mã dữ liệu thời tiết qua cấu trúc JSON trong Arduino ........................................................ 38
Dự án 4 - WiFiManager cho ESP8266 – tự động kết nối, cấu hình, quản lý SSID và Password .................. 53


Giới thiệu
ESP8266 tương đối phổ thông ở Việt Nam và chi phí cũng không quá cao. Trong tài liệu này, tôi giới thiệu
các dự án tôi đã lập trình với ESP8266 cho các bạn tham khảo. Công cụ dùng để lập trình là Arduino IDE

Chuẩn bị: Cài đặt ESP8266 để lập trình trong Arduino.

NodeMCU là bo mạch khai thác khả năng của chip esp8266. Nó kết hợp các chức năng của WIFI, vi xử lý
và ngôn ngữ LUA. ESP8266 NodeMCU cung cấp






Giống các chân IO phần cứng Arduino
API điền khiển sự kiện cho các ứng dụng mạng
10 chân GPIO từ D0 – D10, có chức năng PWM, IIC, giao tiếp SPI, 1-Wire và ADC trên chân A0
Kết nối mạng wifi (có thể là sử dụng như điểm truy cập và/hoặc trạm máy chủ lưu trữ một, máy


chủ web), kết nối internet để lấy hoặc tải lên dữ liệu.
Chi phí phù hợp cho các dự án Internet of Things (IoT)

PHẦN CỨNG
Module ESP8266


1) Cài Arduino dành cho chip ESP8266 WiFi trong Arduino IDE và xem các bài code mẫu trong đó
2) Chạy và chỉnh sửa các bài code mẫu để kiểm tra các chân D0 , GPIO-16 cũng như các chân cấu hình
Ghi chú – để sử dụng bo mạch NodeMCU V1 hoặc V2 hoặc V3 trong Arduino IDE, bạn không cần chép
firmware với công cụ using nodemcu flasher. Nó chỉ yêu cầu khi sử dụng ngôn ngữ LUA.
Bạn có thể theo dõi video hướng dẫn chép firware sau:
Bước 1: Lập sơ đồ chân của NodeMCU ESP-12E

* Chip ESP8266 sử dụng điện áp 3.3V , bạn có thể lấy mức điện áp từ trên bo Arduino.
* NodeMCU ESP-12E có thể nối với nguồn 5V sử dụng cáp micro USB hoặc chân Vin có sẵn trên bo.
* Các chân ESP8266 chỉ sử dụng điện áp 3.3V , không sử dụng điện áp 5V tại các chân ngõ vào.
Khi sử dụng với các chân I/O 5V, bạn cần sử dụng mạch chuyển đổi từ 5V sang 3.3V
Tải : source of images .
/>
* Github – NodeMCU
/>
* Github-esp8266/ Arduino
/>

Bước 2: cài đặt chương trình lõi Arduino cho NodeMCU ESP-12E dùng chương trình quản lý bo
Arduino

Chép đường link sau từ trang Github
/>


Dán link vào Arduino IDE trong File -> PreferencesĐóng và khởi động lại Arduino IDE.
Bước 3 : Tools – Boards Manager

Vào Tools – Boards manager và tìm ESP8266 và cài đặt thư viện có tiêu đề ESP8266 by ESP community .


Khởi động Arduino IDE lại lần nữa
Bước 4: chọn NodeMCU Board trong Arduino IDE

Vào Tools – Boards kéo xuống cuối danh sách chọn NodeMCU 1.0 ( ESP-12EModule).


Chọn tên Port đã kết nối tới nodeMCU, phần còn lại để mặc định
Bước 5: LED Blink – kết nối với led bên ngoài

Chúng ra sẽ nối LED trực tiếp vào chân GPIO16 hoặc D0 của NodeMCU (không cần điện trở hạn dòng).
Bước 6: chạy ví dụ LED Blink
Vào File – Examples – ESP8266 – Blink


Trong video tôi đã sửa lại để LED nháy nhanh hơn, nhưng bạn có thể bỏ qua và up mã nguồn vào ESP
xem kết quả.
Ghi chú: Nếu bản Arduino IDE 1.6.7 bị lỗi bạn hãy trở lại bản arduino 1.6.5


Dự án 1: Lập trình đồng hồ LED 7 đoạn dùng ESP8266 và DS1307

Trên thị trường có bán sẵn đồng hồ LED 7 đoạn dùng chip thời gian thực, nhưng kích thước các đồng hồ
đó đa số đều nhỏ. Trong dự án này, tôi làm 1 đồng hồ dùng LED 7 đoạn loại lớn để hiển thị thời gian.

Điểm đặc thù của đồng hồ là dùng chip wifi ESP8266 để tự động cập nhật thời gian từ internet, sau đó
lưu thông tin thời gian vào DS1307 và hiển thị lên LED 7 đoạn.
Ưu điểm



Cập nhật thời gian thực từ Internet.
Loại bỏ các phím nhấn vật lý

Linh kiện phần cứng
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

LED 7 đoạn loại lớn sử dụng nguồn dương chung
Module wifi ESP8266 nodeMCU
Module đồng hồ thời gian thực DS1307 hoặc tương đương
Pin CMOS dùng cho module đồng hồ
IC 74HC595 + đế cho IC
Mạch giảm áp DC mini
2 bóng đèn LED làm nháy giây. Trong dự án này tôi sử dụng 2 bóng LED 5050 RGB có sẵn trong

kho linh kiện.
Bo mạch thí nghiệm để gắn linh kiện
5 Điện trở 1K
5 Transistor A1015
1 điện trở 330ohm
Nguồn 5VDC


Module giảm áp DC dùng hiển thị
Sơ đồ khối hiển thị
Tôi tự quy ước các chân của LED 7 đoạn, theo quy ước thì chúng ta sẽ không sử dụng chân số 3 và chân
số 6. Trước khi bạn sử dụng LED 7 đoạn, bạn cần kiểm tra các phân đoạn có giống trong hình tôi mô tả
hay không, nếu không bạn hãy tự vẽ lại thứ tự các phân đoạn theo LED thực tế.
Chúng ta sẽ kết nối 4 LED 7 đoạn lại với nhau, các phân đoạn sẽ được nối song song với nhau, các đoạn
từ A đến G sẽ kết nối với nhau thành từng dây dẫn điện riêng cho mỗi đoạn. Các chân nguồn của LED 7
đoạn sẽ được nối vào chân C của transistor A1015. Chân B của A1015 nối với điện trở 1K hoặc 10K dùng
cho chân tín hiệu từ 74HC595. Chân E của A1015 dùng cấp nguồn cho LED 7 đoạn
Như vậy chúng ta có 11 đường tín hiệu trên khối LED 7 đoạn gồm 7 đường tín hiệu phân đoạn và 4
đường điều khiển tắt mở các LED, chúng ta có 1 ma trận 7X4 dùng để hiển thị thông tin.


Sơ đồ kết nối 4 LED 7 đoạn thành ma trận 7x4. Đường màu đỏ chính là chân số 10 trên LED 7 đoạn



Sơ đồ kết nối LED 7 đoạn với 74HC595.
Theo thiết kế IC1 sẽ điều khiển 7 đường dữ liệu hiển thị số và IC2 sẽ tắt mở 1 trong 4 LED, như vậy trong
1 thời gian chỉ có 1 LED 7 đoạn được hiển thị, do chạy với tốc độ cao bạn sẽ thấy cả 4 LED hiển thị cùng
lúc.
Theo sơ đồ thiết kế dưới thì dữ liệu hiển thị LED 7 đoạn xuất trước rồi mới tới dữ liệu tắt mở 1 trong 4

led 7 đoạn. Nếu trong quá trình thi công thứ tự 2 IC bị đảo lại khi lập trình cũng phải đảo lại thứ tự xuất
dữ liệu ra IC 74HC595.



Sơ đồ IC đồng hồ DS1307

Sơ đồ kết nối DS1307 – ESP8266 – 74HC595


Vấn đề cấp nguồn
Do các LED 7 đoạn chạy điện áp tốii đa là 4.3V, dưới
dư mức này, LED có thể sẽ không sángg nên ta ccần sử
dụng module hạ áp DC Mini để điều
u chỉnh
ch điện áp cho nó để đảm bảo LED sử dụng
ng lâu b
bền, đồng thời
cũng làm nguồn cung cấp
p cho module ESP8266.
Lấy mức điện
n áp 3.3V trên module ESP8266 để
đ cung cấp
p cho module DS1307 vì các tín hi
hiệu xuất cho
ESP8366 chỉ nên sử dụng ở mứcc 3.3V và cũng
c
lấy mức điện áp này cung cấp
p cho LED báo giây vì LED đỏ
chỉ sáng ở mức 1.8V, cần sử dụng

ng thêm điện
đi trở 330ohm tại chân dương của LED để hạạn dòng cho LED
nháy giây này.
Lập trình hiển thị LED 7 đoạn
//Pin connected to latch pin (ST_CP) of 74HC595
#define LATCH_PIN 15 //D8
//Pin connected to clock pin (SH_CP) of 74HC595
#define CLOCK_PIN 14 //pin D5


//Pin connected to Data in (DS) of 74HC5
#define DATA_PIN 13 //pin D7
#define SDA_PIN 5
#define SCL_PIN 4
//Các biến lưu dữ liệu
byte numbers[10]; //biến lưu giá trị từ 0 đến 9
byte selectNumber[4]; // biến lưu giá trị tắt mở các LED từ 0 đến 3
byte displayNumber[4];
int hours = 90; // biến kiểm tra hiển thị
int minutes = 12;
void setup() {
pinMode(LATCH_PIN, OUTPUT);
//segment: EABGFDC
// các giá trị dạng nhị phân để dể thay đổi khi cần thiết, giá trị 0 đèn sáng, giá trị 1 đèn tắt
numbers[0] = 0b00010001;
numbers[1] = 0b11011101;
numbers[2] = 0b00101001;
numbers[3] = 0b10001001;
numbers[4] = 0b11000101;
numbers[5] = 0b10000011;

numbers[6] = 0b00000011;
numbers[7] = 0b11010001;
numbers[8] = 0b00000001;
numbers[9] = 0b10000001;
// các giá trị chọn LED


selectNumber[0] = 0xFD;
selectNumber[1] = 0xFB;
selectNumber[2] = 0xF7;
selectNumber[3] = 0xEF;
}

void loop() {
displayNumber[3] = numbers[hour / 10]; // lấy phần nguyên
displayNumber[2] = numbers[hour % 10]; // lấy phần dư của số
displayNumber[1] = numbers[minute / 10];
displayNumber[0] = numbers[minute % 10];

for (int j = 0; j < 4; j++) {
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(LATCH_PIN, 0);
shiftOut(DATA_PIN, CLOCK_PIN, selectNumber[j]);
shiftOut(DATA_PIN, CLOCK_PIN, displayNumber[j]);
digitalWrite(LATCH_PIN, 1);
delay(5);
}
}
// viết lại hàm shiftOut thay cho hàm của Arduino
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {

int i = 0;
int pinState;


pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);

digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);

for (i = 7; i >= 0; i--) {
digitalWrite(myClockPin, 0);
pinState = myDataOut & (1 << i) ? 1 : 0;
//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}
Lập trình hiển thị đồng hồ và cập nhật thời gian từ Internet
Trong mã nguồn, sử dụng thư viện Time để xử lý thông tin thời gian. Xem trong mã nguồn đính kèm tài
liệu này.
Múi giờ của Việt Nam là 7
Địa chỉ của chip đồng hồ là 0x68
#include <Wire.h>
#include <ESP8266WiFi.h>



#include <WiFiUdp.h>
#include <TimeLib.h>

//Pin connected to latch pin (ST_CP) of 74HC595
#define LATCH_PIN 15 //D8
//Pin connected to clock pin (SH_CP) of 74HC595
#define CLOCK_PIN 14 //pin D5
////Pin connected to Data in (DS) of 74HC5
#define DATA_PIN 13 //pin D7
#define SDA_PIN 5
#define SCL_PIN 4
#define DS1307 0x68
#define WLAN_SSID "ten_mang"
#define WLAN_PASS "password_mang_wifi"
// khai báo các biến và mảng lưu giá trị thời gian
int my_second, my_minute, my_hour, my_day, my_wday, my_month, my_year;
byte numbers[10];
byte selectNumber[4];
byte displayNumber[4];
unsigned int localPort = 2390;

// local port to listen for UDP packets

// A UDP instance to let us send and receive packets over UDP
static const char ntpServerName[] = "time.nist.gov";
const int timeZone = 7;
/* Số byte dữ liệu sẽ đọc từ DS1307 */
const byte NumberOfFields = 7;



const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
WiFiUDP Udp;

time_t getNtpTime();
//khai báo các hàm, trong các phiên bản mới hơn của Arduino có thể bỏ qua bước này
void digitalClockDisplay();
void printDigits(int digits);
void sendNTPpacket(IPAddress &address);

void setup() {
Wire.begin(SDA_PIN, SCL_PIN);
Serial.begin(115200);

pinMode(LATCH_PIN, OUTPUT);

//segment: EABGFDC
//thứ tự các phân đoạn có thể không giống với cách khai báo của tôi, các bạn tự thay đổi theo thực tế đi
dây dữ liệu của bạn, bít đầu tiên từ bên phải là chân Q0, nó luôn luôn là 1, chúng ta không sử dụng chân
Q0.
numbers[0] = 0b00010001;
numbers[1] = 0b11011101;
numbers[2] = 0b00101001;
numbers[3] = 0b10001001;
numbers[4] = 0b11000101;
numbers[5] = 0b10000011;



numbers[6] = 0b00000011;
numbers[7] = 0b11010001;
numbers[8] = 0b00000001;
numbers[9] = 0b10000001;

selectNumber[0] = 0xFD;
selectNumber[1] = 0xFB;
selectNumber[2] = 0xF7;
selectNumber[3] = 0xEF;

Serial.println("Connecting to Wi-Fi");

WiFi.mode(WIFI_STA);
WiFi.begin (WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("WiFi connected");
Udp.begin(localPort);
setSyncProvider(getNtpTime);
setSyncInterval(300);
setTime(hour(), minute(), second(), weekday(), day(), month() , year() );
// khởi động chân đếm giây trên module DS1307
set1hz();


}

void loop() {

readDS1307();
// xuất giá trị ra Terminal console để kiểm tra
digitalClockDisplay();
// tính toán giá trị trước khi xuất ra LED 7 đoạn
displayNumber[0] = numbers[my_hour / 10];
displayNumber[1] = numbers[my_hour % 10];
displayNumber[2] = numbers[my_minute / 10];
displayNumber[3] = numbers[my_minute % 10];
// mở từng LED và hiển thị từng số lên LED
for (int j = 0; j < 4; j++) {
digitalWrite(LATCH_PIN, 0);
shiftOut(DATA_PIN, CLOCK_PIN, displayNumber[j]);
shiftOut(DATA_PIN, CLOCK_PIN, selectNumber[j]);
digitalWrite(LATCH_PIN, 1);
delay(5);
}
}

/*-------- NTP code ----------*/
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP server's ip address


while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
// get a random server from the pool
WiFi.hostByName(ntpServerName, ntpServerIP);
Serial.print(ntpServerName);
Serial.print(": ");

Serial.println(ntpServerIP);
sendNTPpacket(ntpServerIP);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");


×