Zapis danych do pamięci EEPROM - baza danych - kamil2234 - 02-02-2017
Mam tu taki kawałek kodu, którego zadaniem jest zapisać ustawienia do bazy w pamięci EEPROM i potem je odczytać. Wszystko fajnie, działa, ale kod jest nieelegancki i trudny w utrzymaniu. Chcąc rozwijać aplikację dodanie kolejnego pola wymaga sporo pracy. Pamięć podłączona po i2c.
Kod: #include <Wire.h>
#include <I2C_EEPROM.h>
AT24C32<0x57> eep; //for RTC3231
#define offsetof(s,m) (size_t)&(((s *)NULL)->m)
struct MySetingsTab {
char struct_start[10];
char wifi_ssid[255];
char wifi_password[255];
int svrport;
int dhcp;
int ip_0;
int ip_1;
int ip_2;
int ip_3;
int nm_0;
int nm_1;
int nm_2;
int nm_3;
int gw_0;
int gw_1;
int gw_2;
int gw_3;
int dns_p0;
int dns_p1;
int dns_p2;
int dns_p3;
int dns_s0;
int dns_s1;
int dns_s2;
int dns_s3;
char system_login[255];
char system_password[255];
// setings for sleep mode option - work if this option is active
int active_time;
int sleep_time;
// setings for remote raporting sensor values
int remote_raporting;
int frequency_sec;
char remote_url[255];
char struct_end[10];
} mysetingstab, setingsfromdb;
size_t offset_struct_start = offsetof (MySetingsTab, struct_start);
size_t offset_wifi_ssid = offsetof (MySetingsTab, wifi_ssid);
size_t offset_wifi_password = offsetof (MySetingsTab, wifi_password);
size_t offset_svrport = offsetof (MySetingsTab, svrport);
size_t offset_dhcp = offsetof (MySetingsTab,dhcp);
size_t offset_ip_0 = offsetof (MySetingsTab, ip_0);
size_t offset_ip_1 = offsetof (MySetingsTab, ip_1);
size_t offset_ip_2 = offsetof (MySetingsTab, ip_2);
size_t offset_ip_3 = offsetof (MySetingsTab, ip_3);
size_t offset_nm_0 = offsetof (MySetingsTab, nm_0);
size_t offset_nm_1 = offsetof (MySetingsTab, nm_1);
size_t offset_nm_2 = offsetof (MySetingsTab, nm_2);
size_t offset_nm_3 = offsetof (MySetingsTab, nm_3);
size_t offset_gw_0 = offsetof (MySetingsTab, gw_0);
size_t offset_gw_1 = offsetof (MySetingsTab, gw_1);
size_t offset_gw_2 = offsetof (MySetingsTab, gw_2);
size_t offset_gw_3 = offsetof (MySetingsTab, gw_3);
size_t offset_dns_p0 = offsetof (MySetingsTab,dns_p0);
size_t offset_dns_p1 = offsetof (MySetingsTab,dns_p1);
size_t offset_dns_p2 = offsetof (MySetingsTab, dns_p2);
size_t offset_dns_p3 = offsetof (MySetingsTab, dns_p3);
size_t offset_dns_s0 = offsetof (MySetingsTab,dns_s0);
size_t offset_dns_s1 = offsetof (MySetingsTab,dns_s1);
size_t offset_dns_s2 = offsetof (MySetingsTab, dns_s2);
size_t offset_dns_s3 = offsetof (MySetingsTab, dns_s3);
size_t offset_system_login = offsetof (MySetingsTab, system_login);
size_t offset_system_password = offsetof (MySetingsTab, system_password);
size_t offset_active_time = offsetof (MySetingsTab, active_time);
size_t offset_sleep_time = offsetof (MySetingsTab, sleep_time);
size_t offset_remote_raporting = offsetof (MySetingsTab, remote_raporting);
size_t offset_frequency_sec = offsetof (MySetingsTab, frequency_sec);
size_t offset_remote_url = offsetof (MySetingsTab, remote_url);
size_t offset_struct_end = offsetof (MySetingsTab, struct_end);
void SaveDefaultSystemSettings(){
// tworzę tabelę
Serial.println("Creating Default Table...");
strcpy(mysetingstab.struct_start ,"start");
strcpy(mysetingstab.wifi_ssid ,"smartnet");
strcpy(mysetingstab.wifi_password ,"1234567890abcdf987654321wiara ze sie uda");
mysetingstab.svrport = 80;
mysetingstab.dhcp = 1;
mysetingstab.ip_0 = 192;
mysetingstab.ip_1 = 168;
mysetingstab.ip_2 = 0;
mysetingstab.ip_3 = 15;
mysetingstab.nm_0 = 255;
mysetingstab.nm_1 = 255;
mysetingstab.nm_2 = 255;
mysetingstab.nm_3 = 0;
mysetingstab.gw_0 = 192;
mysetingstab.gw_1 = 168;
mysetingstab.gw_2 = 0;
mysetingstab.gw_3 = 1;
mysetingstab.dns_p0 = 192;
mysetingstab.dns_p1 = 168;
mysetingstab.dns_p2 = 0;
mysetingstab.dns_p3 = 1;
mysetingstab.dns_s0 = 8;
mysetingstab.dns_s1 = 8;
mysetingstab.dns_s2 = 8;
mysetingstab.dns_s3 = 8;
strcpy(mysetingstab.system_login ,"abcdefghijklmnoperstwj1234567890");
strcpy(mysetingstab.system_password ,"ciekawe co sie zapisze to dlugi ciag znakow");
mysetingstab.active_time = 160;
mysetingstab.sleep_time = 300;
mysetingstab.remote_raporting = 0; // 1 == on 0 == off
mysetingstab.frequency_sec = 60;
strcpy(mysetingstab.remote_url ,"http://192.188.10.1/my_sensor_lab.php");
strcpy(mysetingstab.struct_end ,"end");
if(eep.ready()){
Serial.println("Epprom ready...");
Serial.println("Erase epprom...");
//erase epprom
for (int i = 0 ; i < eep.length() ; i++) {
uint16_t an = i;
int vb = 0 ;
eep.put(an ,vb);
// Serial.print("mem erase address: ");
//Serial.println(i);
delay(10);
} // end for
Serial.println("WAIT TIME 10 sek");
delay(10000);
Serial.println("Creating records...");
eep.put(offset_struct_start ,mysetingstab.struct_start);
eep.put(offset_wifi_ssid ,mysetingstab.wifi_ssid);
eep.put(offset_wifi_password ,mysetingstab.wifi_password);
eep.put(offset_svrport ,mysetingstab.svrport);
eep.put(offset_dhcp ,mysetingstab.dhcp);
eep.put(offset_ip_0 ,mysetingstab.ip_0);
eep.put(offset_ip_1 ,mysetingstab.ip_1);
eep.put(offset_ip_2 ,mysetingstab.ip_2);
eep.put(offset_ip_3 ,mysetingstab.ip_3);
eep.put(offset_nm_0 ,mysetingstab.nm_0);
eep.put(offset_nm_1 ,mysetingstab.nm_1);
eep.put(offset_nm_2 ,mysetingstab.nm_2);
eep.put(offset_nm_3 ,mysetingstab.nm_3 );
eep.put(offset_gw_0 ,mysetingstab.gw_0);
eep.put(offset_gw_1 ,mysetingstab.gw_1);
eep.put(offset_gw_2 ,mysetingstab.gw_2);
eep.put(offset_gw_3 ,mysetingstab.gw_3);
eep.put(offset_dns_p0 ,mysetingstab.dns_p0);
eep.put(offset_dns_p1 ,mysetingstab.dns_p1);
eep.put(offset_dns_p2 ,mysetingstab.dns_p2);
eep.put(offset_dns_p3 ,mysetingstab.dns_p3);
eep.put(offset_dns_s0 ,mysetingstab.dns_s0);
eep.put(offset_dns_s1 ,mysetingstab.dns_s1);
eep.put(offset_dns_s2 ,mysetingstab.dns_s2);
eep.put(offset_dns_s3 ,mysetingstab.dns_s3);
eep.put(offset_system_login ,mysetingstab.system_login);
eep.put(offset_system_password ,mysetingstab.system_password);
eep.put(offset_active_time ,mysetingstab.active_time);
eep.put(offset_sleep_time ,mysetingstab.sleep_time);
eep.put(offset_remote_raporting ,mysetingstab.remote_raporting);
eep.put(offset_frequency_sec ,mysetingstab.frequency_sec);
eep.put(offset_remote_url ,mysetingstab.remote_url);
eep.put(offset_struct_end ,mysetingstab.struct_end);
}
else{
Serial.println("upss - connection error");
}
Serial.println("Table isset DONE");
delay(3500);
}
void GetSetingsfromdb(){
if(eep.ready()){
Serial.println("GetSetingsfromdb");
// czyta dane
eep.fastBlockRead(offset_struct_start,&mysetingstab.struct_start ,sizeof( mysetingstab.struct_start));
eep.fastBlockRead(offset_wifi_ssid,&mysetingstab.wifi_ssid ,sizeof( mysetingstab.wifi_ssid ));
eep.fastBlockRead(offset_wifi_password ,&mysetingstab.wifi_password,sizeof( mysetingstab.wifi_password));
eep.fastBlockRead(offset_svrport,&mysetingstab.svrport,sizeof(mysetingstab.svrport));
eep.fastBlockRead(offset_dhcp,&mysetingstab.dhcp,sizeof(mysetingstab.dhcp ));
eep.fastBlockRead(offset_ip_0,&mysetingstab.ip_0,sizeof(mysetingstab.ip_0));
eep.fastBlockRead(offset_ip_1,&mysetingstab.ip_1,sizeof(mysetingstab.ip_1));
eep.fastBlockRead(offset_ip_2,&mysetingstab.ip_2,sizeof(mysetingstab.ip_2));
eep.fastBlockRead(offset_ip_3,&mysetingstab.ip_3,sizeof(mysetingstab.ip_3));
eep.fastBlockRead(offset_nm_0,&mysetingstab.nm_0,sizeof(mysetingstab.nm_0));
eep.fastBlockRead(offset_nm_1,&mysetingstab.nm_1,sizeof(mysetingstab.nm_1));
eep.fastBlockRead(offset_nm_2,&mysetingstab.nm_2,sizeof(mysetingstab.nm_2));
eep.fastBlockRead(offset_nm_3,&mysetingstab.nm_3,sizeof(mysetingstab.nm_3));
eep.fastBlockRead(offset_gw_0,&mysetingstab.gw_0,sizeof(mysetingstab.gw_0));
eep.fastBlockRead(offset_gw_1,&mysetingstab.gw_1,sizeof( mysetingstab.gw_1));
eep.fastBlockRead(offset_gw_2,&mysetingstab.gw_2,sizeof(mysetingstab.gw_2 ));
eep.fastBlockRead(offset_gw_3,&mysetingstab.gw_3,sizeof(mysetingstab.gw_3));
eep.fastBlockRead(offset_dns_p0,&mysetingstab.dns_p0,sizeof(mysetingstab.dns_p0));
eep.fastBlockRead(offset_dns_p1,&mysetingstab.dns_p1,sizeof(mysetingstab.dns_p1));
eep.fastBlockRead(offset_dns_p2,&mysetingstab.dns_p2 ,sizeof(mysetingstab.dns_p2));
eep.fastBlockRead(offset_dns_p3,&mysetingstab.dns_p3,sizeof(mysetingstab.dns_p3));
eep.fastBlockRead(offset_dns_s0,&mysetingstab.dns_s0,sizeof(mysetingstab.dns_s0));
eep.fastBlockRead(offset_dns_s1,&mysetingstab.dns_s1,sizeof(mysetingstab.dns_s1));
eep.fastBlockRead(offset_dns_s2,&mysetingstab.dns_s2,sizeof(mysetingstab.dns_s2));
eep.fastBlockRead(offset_dns_s3,&mysetingstab.dns_s3,sizeof(mysetingstab.dns_s3));
eep.fastBlockRead(offset_system_login,&mysetingstab.system_login,sizeof(mysetingstab.system_login));
eep.fastBlockRead(offset_system_password,&mysetingstab.system_password,sizeof(mysetingstab.system_password));
eep.fastBlockRead(offset_active_time,&mysetingstab.active_time,sizeof(mysetingstab.active_time));
eep.fastBlockRead(offset_sleep_time,&mysetingstab.sleep_time,sizeof(mysetingstab.sleep_time));
eep.fastBlockRead(offset_remote_raporting,&mysetingstab.remote_raporting,sizeof(mysetingstab.remote_raporting));
eep.fastBlockRead(offset_frequency_sec,&mysetingstab.frequency_sec,sizeof(mysetingstab.frequency_sec));
eep.fastBlockRead(offset_remote_url,&mysetingstab.remote_url,sizeof(mysetingstab.remote_url));
eep.fastBlockRead(offset_struct_end,&mysetingstab.struct_end ,sizeof( mysetingstab.struct_end)); // test data read end
} // end if
} //end GetSetingsfromdb()
void setup() {
//ESP.eraseConfig();
Serial.begin(9600);
delay(3000);
Wire.begin();
delay(3000);
delay(1000);
SaveDefaultSystemSettings();
GetSetingsfromdb() ;
Serial.print("remote_url: ");
Serial.println(mysetingstab.remote_url);
Serial.print("wifi_ssid: ");
Serial.println(mysetingstab.wifi_ssid);
Serial.print("wifi_password: ");
Serial.println(mysetingstab.wifi_password);
Serial.print("system_login: ");
Serial.println(mysetingstab.system_login);
Serial.print("system_password: ");
Serial.println(mysetingstab.system_password);
} // end of setup
void loop() {
// put your main code here, to run repeatedly:
}
O ile zdefiniowane pola w strukturze jest proste, to potem chcąc wykonać zapis/odczyt muszę wyliczać offset dla każdego pola.
Wolałbym użyć funkcji, zapisu w ten sposób :
Kod: save_to_db(mysetingstab.remote_raporting, value);
zamiast
Kod: eep.put(offset_remote_raporting ,mysetingstab.remote_raporting);
Niestety nie potrafię jeszcze samemu napisać funkcji, która sama wyliczy mi offset dla konkretnego pola w ramach danej struktury. Problem w tym, że offset jest wyliczany z makra i nie da się przenieść argumentów poprzez funkcję.
Czy ktoś mnie naprowadzi jak to obejść?
RE: Zapis danych do pamięci EEPROM - baza danych - JasQ - 03-02-2017
Tutaj masz bardzo elegancką bazę danych na eeprom od 24c32 do 24c1024 , sam korzystam z niej . Jest banalnie prosta w obsłudze i można zwiększyć pamięć do 3x24c512 w moim przypadku co mi wystarcza na ponad 14k zapisów licznika produkcyjnego .
http://www.arduinolibraries.info/libraries/edb
RE: Zapis danych do pamięci EEPROM - baza danych - kamil2234 - 04-02-2017
(03-02-2017, 10:45)JasQ napisał(a): Tutaj masz bardzo elegancką bazę danych na eeprom od 24c32 do 24c1024 , sam korzystam z niej . Jest banalnie prosta w obsłudze i można zwiększyć pamięć do 3x24c512 w moim przypadku co mi wystarcza na ponad 14k zapisów licznika produkcyjnego .
http://www.arduinolibraries.info/libraries/edb
Bawiłem się tą bazą, ale jakoś nie mogłem jej wtedy odpalić na ESP8266. Popatrzę na nią jutro raz jeszcze może mnie oświeci i coś z nią zrobię
W każdym razie dziś napisałem taki mechanizm pod tą bibliotekę https://github.com/CombiesGit/I2C_EEPROM.
Nie jest to ideał, ale chyba łatwiej mi się nim posługiwać. Wada jest taka, że tracę miejsce na nie wykorzystane pole w strukturze. Działa, ale dalej trudno o radość.
Kod: #include <Wire.h>
#include <I2C_EEPROM.h>
AT24C32<0x57> eep; //for RTC3231
#define offsetof(s,m) (size_t)&(((s *)NULL)->m)
struct schema {
char f_varchar[64];
int f_int;
float f_float;
double f_double;
int f_id;
};
int rec_id = 0;
void EraseEpprom(){
if(eep.ready()){
Serial.println("Epprom ready...");
Serial.println("Erase epprom...");
//erase epprom
for (int i = 0 ; i < eep.length() ; i++) {
uint16_t an = i;
int vb = 0 ;
eep.put(an ,vb);
// Serial.print("mem erase address: ");
//Serial.println(i);
delay(10);
} // end for
Serial.println("DONE -> WAIT TIME 1 sek");
delay(1000);
}
else{
Serial.println("EraseEpprom -> conection problem");
}
}
schema InitEepromValue( int rec_id ){
// Serial.print("rec_id in InitEepromValue is: ");
// Serial.println(rec_id);
schema instance;
instance.f_id = rec_id; // set record id for eeprom
strcpy(instance.f_varchar, ""); // set empty value
return(instance) ; // return structure
}
schema GetFormDB( struct schema instance){
schema odbior;
strcpy(odbior.f_varchar, "er");
odbior.f_id = 0;
odbior.f_float = 0.0;
odbior.f_double = 0.0001;
size_t offset = sizeof(schema);
offset = (offset * instance.f_id)-offset;
// Serial.println("offset is:");
// Serial.println(offset);
if(eep.ready()){
// Serial.println("Get form DB ");
eep.fastBlockRead(offset,&instance,sizeof(schema));
delay(2);
// Serial.println(instance.f_varchar);
// Serial.println(instance.f_id);
return (instance);
}
else {
Serial.println("GetFormDB -> conection problem");
return (odbior);
} // end if
} // end function GetFormDB
void SaveToDB( struct schema instance) {
//printf( "data save : %s\n", instance.f_varchar);
size_t offset = sizeof(schema);
offset = (offset * instance.f_id)-offset;
//Serial.println("offset is:");
//Serial.println(offset);
if(eep.ready()){
// Serial.println("Set to DB ");
eep.put(offset,instance);
delay(2);
}
else{
Serial.println("InsertToDB -> conection problem");
} // end if
}
void setup() {
Serial.begin(9600);
delay(3000);
Wire.begin();
delay(3000);
delay(1000);
// def
struct schema sample_instance;
struct schema login_wifi = InitEepromValue(rec_id);rec_id++;
struct schema haslo_wifi = InitEepromValue(rec_id);rec_id++;
struct schema port = InitEepromValue(rec_id);rec_id++;
struct schema last_temp = InitEepromValue(rec_id);rec_id++;
// default setings
strcpy( login_wifi.f_varchar, "admin");
strcpy( haslo_wifi.f_varchar, "Mojetajnehaslo");
port.f_int = 80;
last_temp.f_float = 23.21;
//EraseEpprom();
SaveToDB(login_wifi);
SaveToDB(haslo_wifi);
SaveToDB(last_temp);
SaveToDB(port);
login_wifi = GetFormDB(login_wifi);
haslo_wifi = GetFormDB(haslo_wifi);
last_temp = GetFormDB(last_temp);
port = GetFormDB(port);
Serial.print("haslo_wifi.f_varchar to: ");
Serial.println(haslo_wifi.f_varchar);
Serial.print("login_wifi.f_varchar to: ");
Serial.println(login_wifi.f_varchar);
Serial.print("last_temp float to: ");
Serial.println(last_temp.f_float);
Serial.print("port.int to: ");
Serial.println(port.f_int);
} // end setup
void loop() {
} // end loop
RE: Zapis danych do pamięci EEPROM - baza danych - kamil2234 - 04-02-2017
Masz może tą bibliotekę "E24C1024.h" ? nie ma w repozytoriom w https://github.com/jwhiddon/EDB. Ta czy inaczej muszę ją potem przerobić żeby pisała do pamięci AT24C32 i zmienić adres I2c na 0x57.
RE: Zapis danych do pamięci EEPROM - baza danych - kamil2234 - 05-02-2017
Odpaliłem te EDB - działa mi na ESP8266 więc teraz protestuję aktualizację rekordów na strukturze. Ciekawy jestem czy można aktualizować tylko wybrane pola struktury.
Kod: #include "Arduino.h"
#include <EDB.h>
#include <Wire.h>
#define disk 0x57
#define TABLE_SIZE 50 // 1 device bylo 131072
struct LogEvent {
int id;
int temperature;
}
logEvent;
void writer(unsigned long address, byte data)
{
Wire.beginTransmission(disk);
Wire.write((int)(address>>8));
Wire.write((int)(address & 0xFF));
Wire.write(data);
Wire.endTransmission();
delay(5);
}
byte reader(unsigned long address)
{
byte rdata = 0xFF;
Wire.beginTransmission(disk);
Wire.write((int)(address>>8));
Wire.write((int)(address & 0xFF));
Wire.endTransmission();
Wire.requestFrom(disk,1);
if(Wire.available())
rdata = Wire.read();
return rdata;
}
EDB db(&writer, &reader);
void setup() {
Serial.begin(9600);
Wire.begin();
delay(2000);
randomSeed(analogRead(0));
Serial.println("Creating db...");
// EDB_Status result = db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
//if (result != EDB_OK) printError(result);
//Serial.println("Created db...");
//createRecord(1);
Serial.println("wait check");
selectAll();
}
void loop() {
// put your main code here, to run repeatedly:
}
void createRecord(int recno)
{
Serial.println("Creating Records...");
logEvent.id = 1;
logEvent.temperature = random(1, 125);
EDB_Status result = db.insertRec(recno, EDB_REC logEvent);
if (result != EDB_OK) printError(result);
Serial.println("DONE");
}
void selectAll()
{
Serial.print("query to db: ");
for (int recno = 1; recno <= db.count(); recno++)
{
EDB_Status result = db.readRec(recno, EDB_REC logEvent);
if (result == EDB_OK)
{
Serial.print("Recno: ");
Serial.print(recno);
Serial.print(" ID: ");
Serial.print(logEvent.id);
Serial.print(" Temp: ");
Serial.println(logEvent.temperature);
}
else{
printError(result);
}
}
}
void deleteAll()
{
Serial.print("Truncating table...");
db.clear();
Serial.println("DONE");
}
void printError(EDB_Status err)
{
Serial.print("ERROR: ");
switch (err)
{
case EDB_OUT_OF_RANGE:
Serial.println("Recno out of range");
break;
case EDB_TABLE_FULL:
Serial.println("Table full");
break;
case EDB_OK:
default:
Serial.println("OK");
break;
}
}
RE: Zapis danych do pamięci EEPROM - baza danych - kamil2234 - 05-02-2017
Jak działa ten update? Zapisuje całą strukturę od nowa czy tylko zmiany? Wywołałem kod bez zdefiniowana wartości na dwóch pierwszych polach. Ale to jest chyba tożsame z tym, że jakbym do obiektu nie przypisał żadnych wartości. W efekcie uskładam takie wartości odczytu.
query to db: Recno: 1 ID: 0 Temp: 0
humi: 15
Kod: void updateOneRecord(int recno)
{
Serial.print("Updating record at recno: ");
Serial.print(recno);
Serial.print("...");
//logEvent.id = 1;
//logEvent.temperature = random(1, 125);
logEvent.humi = 15;
EDB_Status result = db.updateRec(recno, EDB_REC logEvent);
if (result != EDB_OK) printError(result);
Serial.println("DONE");
}
|