Первое знакомство с Arduino
Подготавливаясь к очередному конкурсу по информатике, возникла идея создать что-то более... Материальное. Отойти на секунду от программ и сделать реально работающее устройство с практической полезностью.
Так, вспомнив о том, что с наступлением холодов, практически каждый день наш школьный завхоз бегает сутра по кабинетам и смотрит температуру в классе. А на дворе, напоминаю, 2019 год. Интернет. Технологии. IoT, в конце концов....
В общем, возникла мысль облегчить очередные бессмысленные человеческие страдания. Избавить от ненужной рутины. Сделать так, чтобы человек мог в любой момент нажать кнопочку и посмотреть показатели по всем кабинетам.
Первая попытка была сделана на Arduino. Схема подключения:
В целом, это выглядело неплохо. Проблема была в том, что никак не получалось одновременно считывать показания с датчика температуры платой Arduino, и при этом считывать их же WiFi модулем esp01. Вдобавок, нельзя было через Arduino обратиться к WiFi модулю, как к объекту, чтобы, например, узнать его IP адрес и вывести его на экран.
Получилось так, что Arduino Uno в связке с ESP01 нам не подошла. Было решено перейти на плату NodeMCU v3 с встроенным модулем WiFi esp8266.
Процесс подготовки среды Arduino IDE для работы с платой легко гуглится, например тут.
Далее, схема подключения выглядит так:
Результат выглядит компактнее. Вдобавок, появилась возможность вывести на экран имя WiFi-сети и IP адрес.
Ну и в качестве заметки, код для всего этого дела:
//Для использования платы esp8266 #include <ESP8266WiFi.h> //Для отправки данных на сервер #include <Adafruit_MQTT.h> #include <Adafruit_MQTT_Client.h> //Для использования датчика температурі #include <DHT.h> // для экрана #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <Fonts/FreeSans9pt7b.h> #include <Fonts/Picopixel.h>
Adafruit_SSD1306 display(2); //обьявляем дисплей String kab = "Room 31"; //номер кабінету, в якому встановлено датчик
/* Настройка датчика температуры */
/* Настройка WIFI */
#define WLAN_SSID "Lirik-WiFi" //Put your SSID here #define WLAN_PASS "DeZertiR" //Put you wifi password here
/* Настройка доступа к сервису ADAFRUIT IO */
#define AIO_SERVER "io.adafruit.com" #define AIO_SERVERPORT 1883 // use 8883 for SSL #define AIO_USERNAME "Lirik" //Put your Adafruit userid here #define AIO_KEY "95159500d3064173a00d56fc27534b4f" //Put your Adafruit IO key here
DHT dht(DHTPIN, DHTTYPE); float temp_c; // Для записи значения температуры с датчика float hum_per; // Для записи значения влажности с датчика String webString=""; // String to display // Generally, you should use "unsigned long" for variables that hold time unsigned long previousMillis = 0; // will store last temp was read const long interval = 2300; // interval at which to read sensor
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server. WiFiClient client; // or... use WiFiFlientSecure for SSL //WiFiClientSecure client;
// Store the MQTT server, username, and password in flash memory.
const char MQTT_SERVER[] = AIO_SERVER; const char MQTT_USERNAME[] = AIO_USERNAME; const char MQTT_PASSWORD[] = AIO_KEY;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details. Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_USERNAME, MQTT_PASSWORD);
/************************* Feeds ***************************************/
// Setup a feed called 'temp' for publishing. // Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname> //Блок датчика температуры кабинета на сайте Adafruit const char temp_cEED[] = AIO_USERNAME "/feeds/dht-home"; Adafruit_MQTT_Publish temp = Adafruit_MQTT_Publish(&mqtt, temp_cEED);
const char temp_hEED[] = AIO_USERNAME "/feeds/hum-home"; Adafruit_MQTT_Publish hum = Adafruit_MQTT_Publish(&mqtt, temp_hEED);
/********************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration // for some reason (only affects ESP8266, likely an arduino-builder bug). void MQTT_connect();
void setup() { Serial.begin(115200); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //подключаем дисплей по адресу 0x3C delay(10);
dht.begin(); // initialize temperature sensor
Serial.println(F("MQTT Temp"));
// Connect to WiFi access point. Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println();
Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP());
// Get initial temp
temp_c = dht.readTemperature(true); Serial.println(); Serial.print("Initial Temp: "); Serial.println(temp_c); Serial.println(); }
int delayTime = 300000; //Wait 5 minutes before sending data to web int startDelay = 0;
void loop() { // Ensure the connection to the MQTT server is alive (this will make the first // connection and automatically reconnect when disconnected). See the MQTT_connect // function definition further below. MQTT_connect();
// Now we can publish stuff!
if (millis() - startDelay < delayTime) { Serial.println ("waiting delaytime");
} else { temp_c = dht.readTemperature(false); //считываем температуру в Цельсиях hum_per = dht.readHumidity(); startDelay = millis(); Serial.print(F("\nSending temp: ")); Serial.print(temp_c); Serial.print("..."); Serial.print(hum_per); Serial.print("..."); if (! temp.publish(temp_c)) { //Publish to Adafruit Serial.println(F("Failed")); } else { Serial.println(F("Sent!")); } if (! hum.publish(hum_per)) { //Publish to Adafruit Serial.println(F("Failed")); } else { Serial.println(F("Sent!")); } } // ping the server to keep the mqtt connection alive // NOT required if you are publishing once every KEEPALIVE seconds
if(! mqtt.ping()) { mqtt.disconnect(); }
//Малюємо інтерфейс display.clearDisplay(); // очищаємо дисплей display.setTextColor(WHITE); // задаємо тексту чорний колір //display.setTextSize(1); // задаємо розмір тексту 1 display.setFont(&Picopixel); display.setCursor(3, 6); // встановлюєм початок написання імені WiFi display.print(WLAN_SSID); // виводимо значення імені WiFi display.setCursor(3, 12); display.print(WiFi.localIP()); display.setFont(); // вертаємо стандартний шрифт display.setCursor(80, 3); // встановлюєм початок написання імені WiFi display.print(kab); // виводимо значення імені WiFi
display.setCursor(3, 17); // встановлюєм початок написання назви показника вологості display.print("Humidity,%"); // виводимо значення вологості display.setCursor(10, 35); // встановлюєм початок написання процента вологості display.setFont(&Picopixel); display.setTextSize(3); display.print(dht.readHumidity()); // виводимо значення вологості з датчика display.setFont(); display.setCursor(80, 17); // встановлюєм початок написання назви показника вологості display.setTextSize(1); display.print("Temp,C"); // виводимо текст температури display.setCursor(75, 35); // встановлюєм початок написання значення температури display.setTextSize(3); display.setFont(&Picopixel); display.print(dht.readTemperature(false)); // виводимо значення температури з датчику display.setFont(); display.setCursor(3, 50); // встановлюєм початок написання підпису display.setTextSize(1); //display.print("KZZSO #3,Zhovti Vody"); // виводимо підпис display.print("By Stadnik Vladislav"); display.display(); // виводим все це що звеху на дисплей
Serial.println(dht.readHumidity()); Serial.println(dht.readTemperature(false)); }
// Function to connect and reconnect as necessary to the MQTT server. // Should be called in the loop function and it will take care if connecting. void MQTT_connect() { int8_t ret;
// Stop if already connected. if (mqtt.connected()) { return; }
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3; while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected Serial.println(mqtt.connectErrorString(ret)); Serial.println("Retrying MQTT connection in 5 seconds..."); mqtt.disconnect(); delay(1000); // wait 1 seconds retries--; if (retries == 0) { // basically die and wait for WDT to reset me while (1); } } Serial.println("MQTT Connected!"); }