• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Zapis danych do pamięci EEPROM - baza danych
#1
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ść?
 
Odpowiedź
#2
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
Ważne aby robić co się lubi albo lubić co się robi .
Arduino UNO, TINY, PRO MINI
Pomoc nagradzamy punktami reputacji Wink
 
Odpowiedź
#3
(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ę Smile

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
 
Odpowiedź
#4
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.
 
Odpowiedź
#5
Odpaliłem te EDB  Shy  - 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;
 }
}
 
Odpowiedź
#6
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");
}
 
Odpowiedź
  


Skocz do:


Przeglądający: 2 gości