先上代碼。
完整的代碼,可以直接運行哦。
代碼中包括了 自動連接WiFi 連接MQTT 繼電器控制 LED燈的控制 OLED的顯示
#include <DHTesp.h> #include <WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h> #include <Wire.h> #include <String.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define OLED_MOSI 13 #define OLED_CLK 14 #define OLED_DC 17 #define OLED_CS 16 #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); const char* ssid = "xz220"; const char* password = "00000000"; const char* mqtt_server = "0.0.0.0"; const char* TOPIC = "home/devices/onoff/"; // 訂閱信息主題 const char* client_id = "clientId-ApjJZcy9Dh"; // 標識當前設備的客戶端編號 WiFiClient espClient; // 定義wifiClient實例 PubSubClient client(espClient); // 定義PubSubClient的實例 long lastMsg = 0; DHTesp dht; int dhtPin = 19; int heatPin = 18; //WiFi自動連接 void setup_wifi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } //randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } //MQTT收到消息的回調 void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); // 打印主題信息 Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); // 打印主題內容 } Serial.println(); if ((char)payload[0] == '1') { digitalWrite(BUILTIN_LED, HIGH); // 亮燈 } else { digitalWrite(BUILTIN_LED, LOW); // 熄燈 } } //MQTT連接 void reconnect() { while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect(client_id)) { Serial.println("connected"); // 連接成功時訂閱主題 client.subscribe(TOPIC); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { Serial.begin(115200); pinMode(heatPin, OUTPUT); // 定義加熱繼電器 pinMode(BUILTIN_LED, OUTPUT); // 定義板載LED燈為輸出方式 setup_wifi(); //執行Wifi初始化,下文有具體描述 client.setServer(mqtt_server, 1883); //設定MQTT服務器與使用的端口,1883是默認的MQTT端口 client.setCallback(callback); //設定回調方式,當ESP8266收到訂閱消息時會調用此方法 dht.setup(dhtPin, DHTesp::DHT11); display.begin(SSD1306_SWITCHCAPVCC);//開始啟動的語句 display.setTextColor(WHITE);//開像素點發光 } static const unsigned char PROGMEM str1[] = { 0x00, 0x00, 0x33, 0xFC, 0x1B, 0x0C, 0x1B, 0x0C, 0xC3, 0xFC, 0x63, 0x0C, 0x63, 0x0C, 0x1B, 0xFC, 0x18, 0x00, 0x37, 0xFE, 0xF6, 0xF6, 0x36, 0xF6, 0x36, 0xF6, 0x36, 0xF6, 0x3F, 0xFF, 0x00, 0x00 /*"溫",0*/ }; static const unsigned char PROGMEM str2[] = { 0x01, 0x80, 0x00, 0xC0, 0x3F, 0xFF, 0x33, 0x30, 0x33, 0x30, 0x3F, 0xFE, 0x33, 0x30, 0x33, 0x30, 0x33, 0xF0, 0x30, 0x00, 0x3F, 0xF8, 0x36, 0x18, 0x63, 0x30, 0x61, 0xE0, 0xC7, 0x38, 0x3C, 0x0F /*"度",2*/ }; static const unsigned char PROGMEM str3[] = { 0x00, 0x00, 0x37, 0xFC, 0x1E, 0x0C, 0x1E, 0x0C, 0xC7, 0xFC, 0x66, 0x0C, 0x66, 0x0C, 0x1F, 0xFC, 0x19, 0xB0, 0x31, 0xB0, 0xFD, 0xB6, 0x37, 0xBC, 0x33, 0xB8, 0x31, 0xB0, 0x3F, 0xFF, 0x00, 0x00 /*"濕",1*/ }; static const unsigned char PROGMEM str4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 /*":",0*/ }; //火圖標 static const unsigned char PROGMEM pic1[] = { 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x33, 0xFC, 0x00, 0x00, 0x33, 0xFC, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFD, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0x7F, 0x80, 0x01, 0xFF, 0x3F, 0xC0, 0x01, 0xFE, 0x3F, 0xC0, 0x0D, 0xFE, 0x1F, 0xC0, 0x0E, 0xFC, 0x1F, 0xC0, 0x0F, 0xF8, 0x1F, 0xC0, 0x0F, 0xF0, 0x1F, 0xC0, 0x0F, 0xF1, 0xB7, 0xC0, 0x0F, 0xF3, 0xC7, 0xC0, 0x0F, 0xB3, 0xC7, 0xC0, 0x07, 0x87, 0xE7, 0xC0, 0x07, 0xDF, 0xE7, 0x80, 0x03, 0xDF, 0xE7, 0x00, 0x01, 0xCF, 0xEF, 0x00, 0x00, 0xEF, 0xEC, 0x00, 0x00, 0x77, 0xCC, 0x00, }; //保溫圖標 static const unsigned char PROGMEM pic2[] = { 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x00, 0x07, 0x83, 0x81, 0xC0, 0x03, 0x83, 0xC1, 0xE0, 0x03, 0xC1, 0xC1, 0xE0, 0x01, 0xC1, 0xE0, 0xE0, 0x01, 0xC1, 0xE0, 0xE0, 0x01, 0xC1, 0xE0, 0xE0, 0x03, 0xC1, 0xC0, 0xE0, 0x03, 0xC3, 0xC1, 0xE0, 0x07, 0x83, 0x83, 0xC0, 0x07, 0x07, 0x83, 0x80, 0x0F, 0x07, 0x07, 0x80, 0x0E, 0x0F, 0x07, 0x00, 0x0E, 0x0E, 0x07, 0x00, 0x0E, 0x0F, 0x07, 0x00, 0x0F, 0x07, 0x07, 0x80, 0x07, 0x07, 0x83, 0x80, 0x07, 0x07, 0x83, 0xC0, 0x07, 0x03, 0x83, 0xC0, 0x07, 0x03, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; void loop() { if (!client.connected()) { reconnect(); } client.loop(); long now = millis(); //兩秒刷新溫濕度數據並顯示 if (now - lastMsg > 2000) { lastMsg = now; //讀取溫濕度傳感器數據 TempAndHumidity lastValues = dht.getTempAndHumidity(); //將數據通過MQTT實時發送到服務器 String str = client_id; //const char*類型轉string類型 String Mestr = "{\"client_id\":\"" + str + "\",\"Temperature\":" + String(lastValues.temperature, 0) + ",\"Humidity\":" + String(lastValues.humidity, 0) + "}"; //通過串口輸出測試 Serial.println(Mestr); char buf[Mestr.length()]; Mestr.toCharArray(buf, Mestr.length()+1); client.publish("home/status/", buf); //通過串口輸出 //Serial.println("Temperature: " + String(lastValues.temperature, 0)); //Serial.println("Humidity: " + String(lastValues.humidity, 0)); //清除顯示內容 display.clearDisplay(); //定義顯示內容 文字 display.setTextSize(2); display.setCursor(60, 1); display.println(String(lastValues.temperature, 0)); display.setCursor(60, 18); display.println(String(lastValues.humidity, 0)); //定義顯示內容 字符 display.drawBitmap(10, 0, str1, 16, 16, 1); display.drawBitmap(26, 0, str2, 16, 16, 1); display.drawBitmap(46, 0, str4, 16, 16, 1); display.drawBitmap(10, 16, str3, 16, 16, 1); display.drawBitmap(26, 16, str2, 16, 16, 1); display.drawBitmap(46, 16, str4, 16, 16, 1); //判斷溫度控制繼電器 if (lastValues.temperature < 38 ) { display.drawBitmap(90, 0, pic1, 30, 32, 1); digitalWrite(heatPin, HIGH); // 繼電器開 } else { display.drawBitmap(90, 0, pic2, 30, 32, 1); digitalWrite(heatPin, LOW); // 繼電器關 } //顯示以上定義內容 display.display(); } }
串口輸出
MQTT訂閱主題打印
模塊實拍
顯示實拍