-
-
Save chaeplin/e78ecaa11ee05c62865c to your computer and use it in GitHub Desktop.
| /* | |
| system_rtc_mem_write | |
| Function: | |
| During deep sleep, only RTC still working, so maybe we need to save some user data in RTC memory. | |
| Only user data area can be used by user. | |
| |<--------system data--------->|<-----------------user data--------------->| | |
| | 256 bytes | 512 bytes | | |
| Note: | |
| RTC memory is 4 bytes aligned for read and write operations. Parameter des_addr means block number(4 bytes per block). | |
| So, if we want to save some data at the beginning of user data area, des_addr will be 256/4 = 64, save_size will be data length. | |
| Prototype: | |
| bool system_rtc_mem_write ( | |
| uint32 des_addr, | |
| void * src_addr, | |
| uint32 save_size | |
| ) | |
| Parameter: | |
| uint32 des_addr : destination address (block number) in RTC memory, des_addr >=64 | |
| void * src_addr : data pointer. | |
| uint32 save_size : data length ( byte) | |
| Return: | |
| true: succeed | |
| false: fail | |
| system_rtc_mem_read | |
| Function: | |
| Read user data from RTC memory. Only user data area should be accessed by the user. | |
| |<--------system data--------->|<-----------------user data--------------->| | |
| | 256 bytes | 512 bytes | | |
| Note: | |
| RTC memory is 4 bytes aligned for read and write operations. | |
| Parameter src_addr means block number(4 bytes per block). | |
| So, to read data from the beginning of user data area, src_addr will be 256/4=64, save_size will be data length. | |
| Prototype: | |
| bool system_rtc_mem_read ( | |
| uint32 src_addr, | |
| void * des_addr, | |
| uint32 save_size | |
| ) | |
| Parameter: | |
| uint32 src_addr : source address (block number) in rtc memory, src_addr >= 64 | |
| void * des_addr : data pointer | |
| uint32 save_size : data length, byte | |
| Return: | |
| true: succeed | |
| false: fail | |
| */ | |
| #include <ESP8266WiFi.h> | |
| #include <PubSubClient.h> | |
| #include "/usr/local/src/ap_setting.h" | |
| extern "C" { | |
| #include "user_interface.h" | |
| } | |
| //-- | |
| #define RTC_MAGIC 12345678 | |
| typedef struct _tagPoint { | |
| uint32 magic ; | |
| uint32 salt; | |
| uint32 nemo; | |
| } RTC_TEST; | |
| RTC_TEST rtc_mem_test; | |
| #define IPSET_STATIC { 192, 168, 10, 7 } | |
| #define IPSET_GATEWAY { 192, 168, 10, 1 } | |
| #define IPSET_SUBNET { 255, 255, 255, 0 } | |
| #define IPSET_DNS { 192, 168, 10, 10 } | |
| IPAddress ip_static = IPSET_STATIC; | |
| IPAddress ip_gateway = IPSET_GATEWAY; | |
| IPAddress ip_subnet = IPSET_SUBNET; | |
| IPAddress ip_dns = IPSET_DNS; | |
| //--- | |
| String macToStr(const uint8_t* mac); | |
| void sendmqttMsg(char* topictosend, String payload); | |
| //--- | |
| const char* ssid = WIFI_SSID; | |
| const char* password = WIFI_PASSWORD; | |
| IPAddress mqtt_server = MQTT_SERVER; | |
| char* topic = "pubtest"; | |
| String clientName; | |
| long lastReconnectAttempt = 0; | |
| long lastMsg = 0; | |
| int test_para = 1; | |
| unsigned long startMills; | |
| WiFiClient wifiClient; | |
| PubSubClient client(mqtt_server, 1883, wifiClient); | |
| void goingToSleepNoRF() | |
| { | |
| // 3 sec | |
| Serial.println("going to sleep with no rf"); | |
| //system_deep_sleep_set_option(4); | |
| //system_deep_sleep(10000000); | |
| ESP.deepSleep(3000000, WAKE_RF_DISABLED); | |
| } | |
| void goingToSleepWithRF() | |
| { | |
| // 3 sec | |
| Serial.println("going to sleep with rf"); | |
| //system_deep_sleep_set_option(0); | |
| //system_deep_sleep(10000000); | |
| ESP.deepSleep(1, WAKE_RF_DEFAULT); | |
| } | |
| void rtc_count() | |
| { | |
| // system_rtc_mem_read(64... not work, use > 64 | |
| system_rtc_mem_read(100, &rtc_mem_test, sizeof(rtc_mem_test)); | |
| Serial.print("=================> rtc mem mgic / salt / nemo : "); | |
| Serial.print(rtc_mem_test.magic); | |
| Serial.print(" / "); | |
| Serial.print(rtc_mem_test.salt); | |
| Serial.print(" / "); | |
| Serial.println(rtc_mem_test.nemo); | |
| if (rtc_mem_test.magic != RTC_MAGIC) { | |
| Serial.println("===============> rtc mem init..."); | |
| rtc_mem_test.magic = RTC_MAGIC; | |
| rtc_mem_test.salt = 0; | |
| rtc_mem_test.nemo = 0; | |
| } | |
| rtc_mem_test.salt++; | |
| rtc_mem_test.nemo++; | |
| boolean reportnow = false; | |
| if ( rtc_mem_test.nemo > 10 || rtc_mem_test.nemo == 1) { | |
| reportnow = true; | |
| rtc_mem_test.nemo = 1; | |
| } | |
| if (system_rtc_mem_write(100, &rtc_mem_test, sizeof(rtc_mem_test))) { | |
| Serial.println("rtc mem write is ok"); | |
| } else { | |
| Serial.println("rtc mem write is fail"); | |
| } | |
| if (reportnow == false) { | |
| if ( rtc_mem_test.nemo == 10 ) { | |
| goingToSleepWithRF(); | |
| } else { | |
| goingToSleepNoRF(); | |
| } | |
| } | |
| } | |
| boolean reconnect() | |
| { | |
| if (!client.connected()) { | |
| if (client.connect((char*) clientName.c_str())) { | |
| Serial.println("===> mqtt connected"); | |
| } else { | |
| Serial.print("---> mqtt failed, rc="); | |
| Serial.println(client.state()); | |
| } | |
| } | |
| return client.connected(); | |
| } | |
| void wifi_connect() | |
| { | |
| if (WiFi.status() != WL_CONNECTED) { | |
| // WIFI | |
| Serial.println(); | |
| Serial.print("===> WIFI ---> Connecting to "); | |
| Serial.println(ssid); | |
| delay(10); | |
| WiFi.mode(WIFI_STA); | |
| WiFi.begin(ssid, password); | |
| WiFi.config(IPAddress(ip_static), IPAddress(ip_gateway), IPAddress(ip_subnet), IPAddress(ip_dns)); | |
| int Attempt = 0; | |
| while (WiFi.status() != WL_CONNECTED) { | |
| Serial.print(". "); | |
| Serial.print(Attempt); | |
| delay(100); | |
| Attempt++; | |
| if (Attempt == 250) | |
| { | |
| Serial.println(); | |
| Serial.println("-----> Could not connect to WIFI"); | |
| ESP.restart(); | |
| delay(200); | |
| } | |
| } | |
| Serial.println(); | |
| Serial.print("===> WiFi connected"); | |
| Serial.print(" ------> IP address: "); | |
| Serial.println(WiFi.localIP()); | |
| } | |
| } | |
| void setup() | |
| { | |
| startMills = millis(); | |
| Serial.begin(74880); | |
| Serial.println(""); | |
| Serial.println("rtc mem test"); | |
| Serial.println(wifi_station_get_auto_connect()); | |
| WiFi.setAutoConnect(true); | |
| rtc_count(); | |
| wifi_connect(); | |
| clientName += "esp8266-"; | |
| uint8_t mac[6]; | |
| WiFi.macAddress(mac); | |
| clientName += macToStr(mac); | |
| clientName += "-"; | |
| clientName += String(micros() & 0xff, 16); | |
| } | |
| void loop() | |
| { | |
| if (WiFi.status() == WL_CONNECTED) { | |
| if (!client.connected()) { | |
| long now = millis(); | |
| if (now - lastReconnectAttempt > 200) { | |
| lastReconnectAttempt = now; | |
| if (reconnect()) { | |
| lastReconnectAttempt = 0; | |
| } | |
| } | |
| } else { | |
| long now = millis(); | |
| if (now - lastMsg > test_para) { | |
| lastMsg = now; | |
| String payload = "{\"startMills\":"; | |
| payload += (millis() - startMills); | |
| payload += ",\"salt\":"; | |
| payload += rtc_mem_test.salt; | |
| payload += ",\"FreeHeap\":"; | |
| payload += ESP.getFreeHeap(); | |
| payload += ",\"RSSI\":"; | |
| payload += WiFi.RSSI(); | |
| payload += "}"; | |
| sendmqttMsg(topic, payload); | |
| } | |
| client.loop(); | |
| goingToSleepNoRF(); | |
| } | |
| } else { | |
| wifi_connect(); | |
| } | |
| } | |
| void sendmqttMsg(char* topictosend, String payload) | |
| { | |
| if (client.connected()) { | |
| Serial.print("Sending payload: "); | |
| Serial.print(payload); | |
| unsigned int msg_length = payload.length(); | |
| Serial.print(" length: "); | |
| Serial.println(msg_length); | |
| byte* p = (byte*)malloc(msg_length); | |
| memcpy(p, (char*) payload.c_str(), msg_length); | |
| if ( client.publish(topictosend, p, msg_length)) { | |
| Serial.println("Publish ok"); | |
| free(p); | |
| //return 1; | |
| } else { | |
| Serial.println("Publish failed"); | |
| free(p); | |
| //return 0; | |
| } | |
| } | |
| } | |
| String macToStr(const uint8_t* mac) | |
| { | |
| String result; | |
| for (int i = 0; i < 6; ++i) { | |
| result += String(mac[i], 16); | |
| if (i < 5) | |
| result += ':'; | |
| } | |
| return result; | |
| } |
@donnib store json array to rtcmem !!. thanks. I will use it.
http://lowreal.net/2016/01/10/1 --->
'''
include <Arduino.h>
extern "C" {
include <user_interface.h>
};
// system_rtc_mem_write() 先のブロックアドレス。
// 4 bytes で align されており、先頭256bytes はシステム予約領域
// 64 から書けるはずだが、65 以降でないとうまくいかなかった。。
static const uint32_t USER_DATA_ADDR = 66;
// ハッシュ関数 (FNV) CRC でいいけどコード的に短いのでFNV
static uint32_t fnv_1_hash_32(uint8_t *bytes, size_t length) {
static const uint32_t FNV_OFFSET_BASIS_32 = 2166136261U;
static const uint32_t FNV_PRIME_32 = 16777619U;
uint32_t hash = FNV_OFFSET_BASIS_32;;
for(size_t i = 0 ; i < length ; ++i) hash = (FNV_PRIME_32 * hash) ^ (bytes[i]);
return hash;
}
// struct の hash (先頭にあることを想定) を除くデータ部分のハッシュを計算する
template
uint32_t calc_hash(T& data) {
return fnv_1_hash_32(((uint8_t*)&data) + sizeof(data.hash), sizeof(T) - sizeof(data.hash));
}
struct {
// retain data
uint32_t hash;
uint16_t count;
uint8_t send;
uint16_t etc2;
} retain_data;
void post_sensor_data();
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
Serial.println("Initializing...");
// データ読みこみ
bool ok;
ok = system_rtc_mem_read(USER_DATA_ADDR, &retain_data, sizeof(retain_data));
if (!ok) {
Serial.println("system_rtc_mem_read failed");
}
Serial.print("retain_data.count = ");
Serial.println(retain_data.count);
// ハッシュが一致していない場合、初期化されていないとみなし、初期化処理を行う
uint32_t hash = calc_hash(retain_data);
if (retain_data.hash != hash) {
Serial.println("retain_data may be uninitialized");
retain_data.count = 0;
retain_data.send = 0;
}
// データの変更処理(任意)
retain_data.count++;
if (!retain_data.send) {
// 4回に1度送信する
retain_data.send = retain_data.count % 4 == 0;
} else {
Serial.println("send data");
retain_data.send = 0;
// なんか定期的に書きこみたい処理
post_sensor_data();
}
// 書きこみ処理。hash を計算していれておく
retain_data.hash = hash = calc_hash(retain_data);
ok = system_rtc_mem_write(USER_DATA_ADDR, &retain_data, sizeof(retain_data));
if (!ok) {
Serial.println("system_rtc_mem_write failed");
}
// 動作確認用のダミー
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
if (retain_data.send) {
ESP.deepSleep(1e6, WAKE_RF_DEFAULT);
} else {
// sendしない場合は WIFI をオフで起動させる
ESP.deepSleep(1e6, WAKE_RF_DISABLED);
}
}
void loop() {
}
// dummy
void post_sensor_data() {
for (uint i = 0; i < 5; i++) {
digitalWrite(13, HIGH);
delay(300);
digitalWrite(13, LOW);
delay(300);
}
}
'''
Hi, Thanks for posting this. I like your example, it's what i do. I took some of your code and replaced mine. I have implemented an error count to keep track if i get errors. I dunno, i have implemented following and now i'll see how long time it will survive on count 0.
Here is my full code :