ラズベリーパイに温湿度データを送信するデバイスの作成です。
###全体のレイアウト
ユニバーサル基板に部品をはんだ付けしています。
##回路
SHT31とssd1306を並列でi2c接続します。
とはいっても4つの線を並列に繋ぐだけ。簡単簡単。
####i2cアドレスの確認
配線が決まったらブレッドボードでアドレスの確認をします。
コードはこのページを参照しました。
コードを走らせて、出てきたアドレスをメモします。
この場合は、SHT31が0x45、ssd1306が0x3Cでした。
####ESP32に書き込む
/*
* =========WiFi Config==========
*/
#include "WiFi.h"
#include "AsyncUDP.h"
#include <stdio.h>
const char * ssid = "ssid";
const char * password = "ssidのパスワード";
//IPアドレスは複数のESP32全て同一にします。
AsyncUDP udp;
IPAddress ESP32_ip(192,168,x,x);
IPAddress server_ip(192,168,x,x);
IPAddress gateway(192,168, x, x);
IPAddress subnet(255, 255, 255, 0);
IPAddress DNS(192, 168, x, x);
//ESP32に固有番号を振る
int deviceNo = 1;
#define ssd1306_Address 0x3C //ssd1306のi2cアドレス
#define SHT31_Address 0x45 // SHT31のI2Cアドレス
WiFiServer server(80);
const int LEDPIN = 2;
const int PORTNO = 1234;
/*
* =========SHT31 Config==========
*/
#include <SPI.h>
#include <Arduino.h>
#include <Wire.h>
#include "AE_SHT31.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
// SHT31のアドレスを設定
AE_SHT31 SHT31 = AE_SHT31(SHT31_Address);
float temp,humi;
/*
* =========SeepSleep Config==========
*/
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 9 /* Time ESP32 will go to sleep (in seconds) */
RTC_DATA_ATTR int bootCount = 0;
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
void setup() {
// シリアル通信を9600bpsに設定
Serial.begin(9600);
// シリアルに文字を出力
// SHT31をソフトリセット
SHT31.SoftReset();
// 内蔵ヒーター 0:OFF 1:ON
SHT31.Heater(0);
if(!display.begin(SSD1306_SWITCHCAPVCC,ssd1306_Address )) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
//ssd1306の表示設定
display.drawPixel(10, 10, WHITE);
display.setTextSize(2);
display.setTextColor(WHITE);
temp = SHT31_TEMP();
humi = SHT31_HUMI();
/*
* =========ディスプレイ表示==========
*/
display.clearDisplay();
display.setCursor(0,0);
display.print(" ");
display.print(temp);
display.println(" 'C");
display.print(" ");
display.print(humi);
display.println(" %");
display.display();
/*
* =========WiFi Setup==========
*/
pinMode(LEDPIN,OUTPUT);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
WiFi.config(ESP32_ip, gateway, subnet, DNS);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WiFi Failed");
while(1) {
delay(1000);
}
}
if(udp.connect(server_ip, PORTNO)) {
Serial.println("UDP connected");
udp.onPacket([](AsyncUDPPacket packet) {
Serial.print("UDP Packet Type: ");
Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
Serial.print(", From: ");
Serial.print(packet.remoteIP());
Serial.print(":");
Serial.print(packet.remotePort());
Serial.print(", To: ");
Serial.print(packet.localIP());
Serial.print(":");
Serial.print(packet.localPort());
Serial.print(", Length: ");
Serial.print(packet.length());
Serial.print(", Data: ");
Serial.write(packet.data(), packet.length());
Serial.println();
//reply to the client
packet.printf("Got %u bytes of data", packet.length());
});
}
}
void loop()
{
temp = SHT31_TEMP();
humi = SHT31_HUMI();
/*
* =========ディスプレイ表示==========
*/
display.clearDisplay();
display.setCursor(0,0);
display.print(" ");
display.print(temp);
display.println(" 'C");
display.print(" ");
display.print(humi);
display.println(" %");
display.display();
/*
* =========UDP送信==========
*/
//dtostrf(変換する値,変換後の総文字数,小数点以下の桁数,変換後格納する変数);
char udpStr1[6];
char udpStr2[6];
char buf[10];
dtostrf(temp,5,2,udpStr1);
dtostrf(humi,5,2,udpStr2);
sprintf(buf,"%d,%s,%s",deviceNo,udpStr1,udpStr2);
Serial.println(buf);
udp.broadcastTo(buf, PORTNO);
/*
* =========後処理==========
*/
Ltika();
ESP32_Sleep(10*60);
}
/*
* =========SHT31の温湿度取得==========
*/
float SHT31_TEMP(){
// SHT31から温度データを取得
SHT31.GetTempHum();
return SHT31.Temperature();
}
float SHT31_HUMI(){
// SHT31から湿度データを取得
SHT31.GetTempHum();
return SHT31.Humidity();
}
/*
* =========ESP32 DeepSleep==========
*/
void ESP32_Sleep(int sleepime){
delay(1000); //Take some time to open up the Serial Monitor
++bootCount;
print_wakeup_reason();
esp_sleep_enable_timer_wakeup(sleepime * uS_TO_S_FACTOR);
esp_deep_sleep_start();
}
/*
* =========Lチカ==========
*/
void Ltika(){
for (int i=0;i<3;i++){
digitalWrite(LEDPIN,HIGH);
delay(100);
digitalWrite(LEDPIN,LOW);
delay(100);
}
}
204行目の、sprintf(buf,"%d,%s,%s",deviceNo,udpStr1,udpStr2);
でデバイスNo・温度・湿度のデータをカンマ区切りでまとめて送信しています。
これは後にUDP受信した後に、ポジション毎にデータを振り分ける為です。
###起動
マイコンに書き込み、起動すると、ディスプレイに温湿度が表示されます。
通信に成功すると、ESP32ボード上の青色LEDが3回点滅します。
次はラズベリーパイ側の記事を書く予定です。