Tóm tắt vai trò của từng linh kiện trong hệ thống: Hệ thống gồm
Arduino đóng vai trò xử lý trung tâm:
- Thực hiện thu thập dữ liệu từ các sensor : độ ẩm, Nhiệt độ, thời gian, độ ẩm đất. - Xử lý theo thuật toán mong muốn và đưa ra quyết định Tưới / Không tưới thông
qua chân D4 để đóng/ cắt relay.
- Gửi data về độ ẩm, Nhiệt độ, Độ ẩm đất sang cho Module Sim800A gửi lên Server.
- Gửi cảnh báo nhiệt độ, Độ ẩm đất khi vượt ngưỡng qua SIM800A. Module SIM800A Giao tiếp với Arduino để gửi SMS và data lên server. 1. Thực Hiện Gửi data lên sever :
Tiến Hành kết nối theo sơ đồ phần cứng giữa Arduino và Sim800A :
Tạo dashbards cho hệ thống bằng cách truy cập vào https://demo.thingsboard.io/ Tạo một new device make public và lấy Acess token
Như đã nói ở phần trước, Các trang web này hoạt động theo giao thức API, HTTP mục đích lấy access token nhằm mục đích giúp sim 800A gửi data theo cú pháp đến sever hợp lệ.
Tiến hành nạp code mẫu cho arduino với Acess token:
// This sketch demonstrates connecting and sending telemetry // using ThingsBoard SDK and GSM modem, such as SIM900 //
// Hardware: // - Arduino Uno
// - SIM900 Arduino shield connected to Arduino Uno // Select your modem:
#define TINY_GSM_MODEM_SIM800 // #define TINY_GSM_MODEM_SIM808 // #define TINY_GSM_MODEM_SIM900 // #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_BG96 // #define TINY_GSM_MODEM_A6 // #define TINY_GSM_MODEM_A7 // #define TINY_GSM_MODEM_M590 // #define TINY_GSM_MODEM_ESP8266 #include <TinyGsmClient.h> #include <SoftwareSerial.h> #include "ThingsBoard.h" // Your GPRS credentials
// Leave empty, if missing user or pass const char apn[] = "internet";
const char user[] = ""; const char pass[] = "";
// See https://thingsboard.io/docs/getting-started-guides/helloworld/ // to understand how to obtain an access token
#define TOKEN "hyc3BmwKsDqVkdXuKaQs" #define THINGSBOARD_SERVER "demo.thingsboard.io" #define THINGSBOARD_PORT 80
// Baud rate for debug serial
#define SERIAL_DEBUG_BAUD 115200 // Serial port for GSM shield
SoftwareSerial serialGsm(7, 8); // RX, TX pins for communicating with modem #ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(serialGsm, Serial); TinyGsm modem(debugger);
#else // Initialize GSM modem TinyGsm modem(serialGsm); #endif // Initialize GSM client TinyGsmClient client(modem); // Initialize ThingsBoard instance
ThingsBoardHttp tb(client, TOKEN, THINGSBOARD_SERVER, THINGSBOARD_PORT);
// Set to true, if modem is connected bool modemConnected = false; void setup() {
// Set console baud rate
Serial.begin(SERIAL_DEBUG_BAUD); // Set GSM module baud rate
serialGsm.begin(115200); delay(3000);
// Lower baud rate of the modem.
// This is highly practical for Uno board, since SoftwareSerial there // works too slow to receive a modem data.
serialGsm.write("AT+IPR=9600\r\n"); serialGsm.end();
serialGsm.begin(9600);
// Restart takes quite some time
Serial.println(F("Initializing modem...")); modem.restart();
String modemInfo = modem.getModemInfo(); Serial.print(F("Modem: "));
Serial.println(modemInfo);
// Unlock your SIM card with a PIN //modem.simUnlock("1234"); }
void loop() { delay(1000);
if (!modemConnected) {
Serial.print(F("Waiting for network...")); if (!modem.waitForNetwork()) { Serial.println(" fail"); delay(10000); return; } Serial.println(" OK"); Serial.print(F("Connecting to ")); Serial.print(apn);
if (!modem.gprsConnect(apn, user, pass)) { Serial.println(" fail");
delay(10000); return;
}
Serial.println(" OK"); }
// Uploads new telemetry to ThingsBoard using HTTP.
// See https://thingsboard.io/docs/reference/http-api/#telemetry-upload-api // for more details
Serial.println("Sending temperature data...");
tb.sendTelemetryFloat("temperature",32.54+0.03*random(1,100) ); Serial.println("Sending humidity data...");
tb.sendTelemetryFloat("humidity", 51.23); Serial.println("Sending Soil Humidity data..."); tb.sendTelemetryFloat("Soil Humidity", 89.23); }
Khi kết nối lần đầu tiên thành công Các biến arduino send cho thingsboard sẽ được note lại và có thể sử dụng được:
Bây giờ chúng ta có thể tiến hành thiết kế giao diện cho dashboard này :
Sau khi sever đã ok có thể tiến hành chỉnh lại code cho chức năng SMS cảnh báo độ ẩm. Sơ đồ thuật toán :
Điều Chỉnh lại code theo sơ đồ trên :
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib #include "RTClib.h"
#define TINY_GSM_MODEM_SIM800 RTC_DS3231 rtc;
#include "AHT20.h" AHT20 AHT;
#include <Wire.h>
#include <TinyGsmClient.h> #include <SoftwareSerial.h> #include "ThingsBoard.h" // Your GPRS credentials
// Leave empty, if missing user or pass const char apn[] = "internet";
const char user[] = ""; const char pass[] = "";
// See https://thingsboard.io/docs/getting-started-guides/helloworld/ // to understand how to obtain an access token
#define TOKEN "j9jxH3be4ThAODL62UEv" // ACCESS TOKEN from Dashboard
#define THINGSBOARD_SERVER "demo.thingsboard.io" // link from Dashboard
#define THINGSBOARD_PORT 80 #define CB_do_am A0
// Baud rate for debug serial
#define SERIAL_DEBUG_BAUD 115200 // Serial port for GSM shield
SoftwareSerial serialGsm(7, 8); // RX, TX pins for communicating with modem #ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(serialGsm, Serial); TinyGsm modem(debugger); #else // Initialize GSM modem TinyGsm modem(serialGsm); #endif // Initialize GSM client TinyGsmClient client(modem); // Initialize ThingsBoard instance
// Set to true, if modem is connected bool modemConnected = false;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
int gio, phut, thoigian;
int h_pre = 0, do_am_dat, do_am_nguong = 100; float humi, temp;
String RxBuff = ""; // Khai bao bo dem nhan du lieu int Index_Rxdata = -1; // vi tri cua chuoi nhan duoc
const String myphone = "03******";// nhập số điện thoại của người sử dụng
//const int PWR_KEY = 4; const int status_led = 13;
void Gsm_Init(); // Cau hinh Module Sim800C void Gsm_MakeCall(String phone); // Ham goi dien
void Gsm_MakeSMS(String phone, String content); // Ham nhan tin void tinhieu_cambien(); void setup() { Serial.begin(9600); Serial.setTimeout(100); AHT.begin(); if (! rtc.begin()) { Serial.println("Couldn't find RTC"); while (1); } if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call:
}
// When time needs to be re-set on a previously configured device, the // following line sets the RTC to the date & time this sketch was compiled // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call:
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
pinMode(status_led, OUTPUT); //Khai bao ngo ra chan dieu khien relay digitalWrite(status_led, LOW); //Khoi tao trang thai ngo ra ban dau pinMode(4, OUTPUT); //pinMode(5, OUTPUT); //pinMode(6, OUTPUT); digitalWrite(4, LOW); //digitalWrite(5, HIGH); //digitalWrite(6, HIGH);
//pinMode(2, INPUT_PULLUP); //D4 is output, connect LED on board //attachInterrupt(0, tinhieu_cambien, FALLING);
GSM_Init(); //GSM_MakeCall(myphone); //GSM_MakeSMS(myphone,"I'm a test"); } void loop() { delay(1000);
int ret = AHT.getSensor(&humi, &temp); if (ret) // GET DATA OK
{
float nhiet_do = (temp);
float huminity = 100.0 * (temp); }
else // GET DATA FAIL {
Serial.println("GET DATA FROM ATH20 FAIL"); }
if (!modemConnected) {
Serial.print(F("Waiting for network...")); if (!modem.waitForNetwork()) { Serial.println(" fail"); delay(10000); return; } Serial.println(" OK"); Serial.print(F("Connecting to ")); Serial.print(apn);
if (!modem.gprsConnect(apn, user, pass)) { Serial.println(" fail"); delay(10000); return; } modemConnected = true; Serial.println(" OK"); }
// Uploads new telemetry to ThingsBoard using HTTP.
// See https://thingsboard.io/docs/reference/http-api/#telemetry-upload-api // for more details
Serial.println("Sending temperature data..."); tb.sendTelemetryFloat("temperature", nhiet_do ); Serial.println("Sending humidity data...");
tb.sendTelemetryFloat("humidity", huminity ); DateTime now = rtc.now();
int h = now.hour(); int p = now.minute();
// Serial.println(h); // Serial.println(p); Serial.println(gio); // Serial.println(phut);
//--- check độ ẩm đất sau mỗi giờ và gửi thông tin cho người sử dụng---
if ((h == (h_pre + 1)) | h == 0) // khi h hiện tại thay đổi or tại 0h
{
do_am_dat = analogRead(CB_do_am); h_pre = h; //lưu giá trị h hiện tại. if (do_am_dat <= nguong_do_am) {
digitalWrite(4, HIGH); String content_sms;
content_sms = "Do Am Qua Thap, Se thuc hien tuoi cay";) // gửi tin nhắn khi vượt ngưỡng
GSM_MakeSMS(myphone, content_sms); }
}
//---Thực hiện ct hẹn giờ---
if (((h * 60 + p) >= (gio * 60 + phut)) & ((h * 60 + p) <= (gio * 60 + phut + thoigian)) & (! digitalRead(4)))
{
digitalWrite(4, HIGH); // Dong Relay de bat den // Bat bong den String content_sms;
content_sms = "Bom da duoc Bat";
GSM_MakeSMS(myphone, content_sms);
}
if (Serial.available()) { //Khi co tin nhan gui den module sim thi tien hanh doc va dieu khien
serialEvent_GSM(); }
void tinhieu_cambien() { GSM_MakeCall(myphone);
bool statusLed = !digitalRead(status_led); digitalWrite(status_led, statusLed); }
//----Ham phuc vu ngat khi nhan tin nhan SMS ve SIM800L--- void serialEvent_GSM() {
while (Serial.available()) { //Doi den khi co du lieu nhan ve char inChar = (char)Serial.read(); //Doc 1 byte du lieu vua nhan RxBuff += inChar; //Ghi byte do vao bo dem RxBuff if (RxBuff.length() >= 128) {
RxBuff = ""; }
} int i;
Index_Rxdata = RxBuff.indexOf("BATDEN"); // Tim vi tri cua chuoi "sw1on" trong bo dem nhan RxBuff
if (Index_Rxdata >= 0) // Neu {
Index_Rxdata = -1; //
RxBuff = ""; // Xoa bo dem
digitalWrite(4, HIGH); // Dong Relay de bat den // Bat bong den if (digitalRead(4)) {
String content_sms;
content_sms = "Den da duoc Bat";
GSM_MakeSMS(myphone, content_sms); }
}
Index_Rxdata = RxBuff.indexOf("TIMER"); // Tim vi tri cua chuoi "sw1on" trong bo dem nhan RxBuff
if (Index_Rxdata >= 0) // Neu tim thay "LAMP_ON" trong RxBuff
{
String h = RxBuff.substring(RxBuff.indexOf("R") + 1, RxBuff.indexOf("H")); String p = RxBuff.substring(RxBuff.indexOf("H") + 1, RxBuff.indexOf("P")); String d = RxBuff.substring(RxBuff.indexOf("P") + 1);
gio = h.toInt(); phut = p.toInt(); thoigian = d.toInt();
String str = "Den se bat vao luc:" + String(gio) + String('h') + String(phut) + String('p') + " trong " + String(thoigian) + " phut" ;
//
//Serial.println(str);
Index_Rxdata = -1; //
RxBuff = ""; // Xoa bo dem String content_sms;
content_sms = str;
GSM_MakeSMS(myphone, content_sms); }
Index_Rxdata = RxBuff.indexOf("SETDOAM"); // Tim vi tri cua chuoi "sw1on" trong bo dem nhan RxBuff
if (Index_Rxdata >= 0) // Neu tim thay "LAMP_ON" trong RxBuff
{
String do_am = RxBuff.substring(RxBuff.indexOf("SETDOAM") + 1); do_am_dat = do_am.toInt();
String str = "set do am dat:" + String(do_am_dat) + " /1024" ;//set độ ẩm đặt theo thang đo ADC max =1024
//
//Serial.println(str);
Index_Rxdata = -1; //
RxBuff = ""; // Xoa bo dem String content_sms;
content_sms = str;
GSM_MakeSMS(myphone, content_sms); }
Index_Rxdata = RxBuff.indexOf("TATDEN"); // Tim vi tri cua chuoi "sw1on" trong bo dem nhan RxBuff
if (Index_Rxdata >= 0) // Neu tim thay "LAMP_ON" trong RxBuff
{
Index_Rxdata = -1; //
RxBuff = ""; // Xoa bo dem
digitalWrite(4, LOW); // Dong Relay de bat den // Bat bong den if (!digitalRead(4)) {
String content_sms;
content_sms = "Den da duoc Tat";
GSM_MakeSMS(myphone, content_sms); }
}
Index_Rxdata = RxBuff.indexOf("KIEMTRA"); // Gui tin nhan bao trang thai cua cac relay dieu khien
if (Index_Rxdata >= 0) { String content_sms; if (digitalRead(4)) {
content_sms = "Den dang Bat";
GSM_MakeSMS(myphone, content_sms); } else {
content_sms = "Den dang Tat";
GSM_MakeSMS(myphone, content_sms); }
}
RxBuff = ""; }
//---Cau hinh module GSM--- void GSM_Power_On() {
digitalWrite(4, HIGH); // Du chan PWR_KEY len cao it nhat 1s delay(1500); // o day ta de 1,5s
delay(100); // cac ban xem trong Hardware designed sim800C de hieu ro hon
}
void GSM_Init() {
Serial.println("ATE0"); // Tat che do phan hoi (Echo mode) delay(2000);
Serial.println("AT+IPR=9600"); // Dat toc do truyen nhan du lieu 9600 bps delay(2000);
Serial.println("AT+CMGF=1"); // Chon che do TEXT Mode delay(2000);
Serial.println("AT+CLIP=1"); // Hien thi thong tin nguoi goi den delay(2000);
Serial.println("AT+CNMI=2,2"); // Hien thi truc tiep noi dung tin nhan delay(2000);
}
void GSM_MakeCall(String phone) {
Serial.println("ATD" + phone + ";"); // Goi dien delay(10000); // Sau 10s
Serial.println("ATH"); // Ngat cuoc goi delay(2000);
}
void GSM_MakeSMS(String phone, String content) {
Serial.println("AT+CMGS=\"" + phone + "\""); // Lenh gui tin nhan delay(3000); // Cho ky tu '>' phan hoi ve Serial.print(content); // Gui noi dung
Serial.print((char)26); // Gui Ctrl+Z hay 26 de ket thuc noi dung tin nhan va gui tin di
delay(5000); // delay 5s
}
Vì lý do mã AT rất rườm rà và khó nhớ. Nên Em xin phép được viết một app nhỏ để thực hiện việt gửi tin nhắn đến SIM800 bằng http://ai2.appinventor.mit.edu/ . Nội dung giao diện và block được thể hiện như bên dưới.
Chương 5