/*
Basic ESP8266 MQTT example
RTC User Memoryを使用するDeelSleepモードのテスト
Build for WeMos D1 R2 & Mini
*/
ADC_MODE(ADC_VCC);
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
//#define SLEEP 5 //
5秒
//#define SLEEP 60 // 1分
#define SLEEP 600 // 10分
//#define SLEEP 3600 // 1時間
#define LED_PIN 4
// Update these with values suitable for your network.
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
const char* mqtt_server = "MQTTブローカーのIPアドレス";
WiFiClient espClient;
PubSubClient client(espClient);
Ticker ticker1;
char topic[50];
char payload[50];
//RTC memory(512Byte)の定義
struct {
uint32_t crc32; // CRC
uint32_t counter;
byte data[504]; // User Data
} rtcData;
// Calculate CRC
uint32_t calculateCRC32(const uint8_t *data, size_t
length)
{
uint32_t crc = 0xffffffff;
while (length--) {
uint8_t c = *data++;
for (uint32_t i = 0x80; i > 0; i
>>= 1) {
bool bit = crc &
0x80000000;
if (c & i) {
bit = !bit;
}
crc <<= 1;
if (bit) {
crc ^=
0x04c11db7;
}
}
}
return crc;
}
// Print RTC memory
void printMemory(int sz) {
char buf[3];
// for (int i = 0; i < sizeof(rtcData); i++) {
for (int i = 0; i < sz; i++) {
sprintf(buf, "%02X", rtcData.data[i]);
Serial.print(buf);
if ((i + 1) % 32 == 0) {
Serial.println();
}
else {
Serial.print(" ");
}
}
Serial.println();
}
// Connect AP
void setup_wifi() {
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Wait for WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
// Receive MQTT topic
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();
}
// Connect MQTT server
int server_connect() {
char clientid[20];
sprintf(clientid,"ESP8266-%6x",ESP.getChipId());
Serial.print("clientid=");
Serial.println(clientid);
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(clientid)) {
Serial.println("connected");
// ... and resubscribe
client.subscribe("inTopic");
return 1;
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
return 0;
}
}
void flush_led() {
static bool flag = true;
if (flag) digitalWrite(LED_PIN,LOW);
if (!flag) digitalWrite(LED_PIN,HIGH);
flag=!flag;
}
void display_Running_Sketch (void){
String the_path = __FILE__;
int slash_loc = the_path.lastIndexOf('/');
String the_cpp_name =
the_path.substring(slash_loc+1);
int dot_loc = the_cpp_name.lastIndexOf('.');
String the_sketchname = the_cpp_name.substring(0,
dot_loc);
Serial.print("\nArduino is running Sketch: ");
Serial.println(the_sketchname);
Serial.print("Compiled on: ");
Serial.print(__DATE__);
Serial.print(" at ");
Serial.print(__TIME__);
Serial.print("\n");
}
void setup() {
delay(1000);
Serial.begin(115200);
display_Running_Sketch();
//RTC memoryからデータを読み込む
if (ESP.rtcUserMemoryRead(0, (uint32_t*)
&rtcData, sizeof(rtcData))) {
Serial.println("Read: ");
printMemory(10);
//読み込んだデータでCRC32を計算する
uint32_t crcOfData =
calculateCRC32(((uint8_t*) &rtcData) + 4,
sizeof(rtcData) - 4);
Serial.print("CRC32 of data: ");
Serial.println(crcOfData, HEX);
Serial.print("CRC32 read from RTC: ");
Serial.println(rtcData.crc32, HEX);
//CRC32が一致しないので初回起動時
if (crcOfData != rtcData.crc32) {
Serial.println("CRC32 in
RTC memory doesn't match CRC32 of data. Data is probably
invalid!");
rtcData.counter = 0;
for (int i = 0; i <
sizeof(rtcData); i++) {
rtcData.data[i]
= 0;
}
}
//CRC32が一致したのでDeelSleepからの復帰
else {
Serial.println("CRC32 check
ok, data is probably valid.");
Serial.print("counter=");
Serial.println(rtcData.counter);
rtcData.counter++;
}
}
//CRC32を再計算
rtcData.crc32 = calculateCRC32(((uint8_t*)
&rtcData) + 4, sizeof(rtcData) - 4);
//RTC memoryにデータを書き込む
//電源不足でAPに接続できないときはカウンターが+1以上になる
if (ESP.rtcUserMemoryWrite(0, (uint32_t*)
&rtcData, sizeof(rtcData))) {
Serial.println("Write: ");
printMemory(10);
}
//初回は起動を確認するためLEDをFlush
if (rtcData.counter == 0) {
pinMode(LED_PIN,OUTPUT);
digitalWrite(LED_PIN,LOW);
ticker1.attach_ms(50, flush_led);
}
//APに接続
setup_wifi();
if (rtcData.counter == 0) {
ticker1.detach();
digitalWrite(LED_PIN,LOW);
}
//mqtt brokerに接続
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
if (server_connect()) {
sprintf(topic,"Battery/ESP8266-%6x",ESP.getChipId());
sprintf(payload,"%08x %d
%d",rtcData.counter,ESP.getVcc(),SLEEP);
// sprintf(payload,"%02x%02x%02x%02x",
//
rtcData.data[3],rtcData.data[2],rtcData.data[1],rtcData.data[0]);
Serial.print(topic);
Serial.print(":");
Serial.println(payload);
client.publish(topic, payload);
client.disconnect();
}
delay(1000);
WiFi.disconnect();
//DEEP SLEEPモード突入命令
Serial.println("DEEP SLEEP START!!");
uint32_t time_us = SLEEP * 1000 * 1000;
ESP.deepSleep(time_us , WAKE_RF_DEFAULT);
}
void loop() {
client.loop();
}
|