Save Data from Arduino to SD card

Hi, My friend,
I want to save data from Arduino to SD card,
I've used EDB master library but I have a lot of problems.
For example :
if I updated one value, its changed in all tables
please, what's the best way to save data in SD card without problems?
Thanks :slight_smile:

Let's see an example of your code that causes the problem. What are these tables to which you refer ?

Hi, my friends,
what's the best way to save the values to SD card?
Thanks :slight_smile:

Have you got any SD libraries installed ?
Have you looked at the examples in the IDE ?

What sort of data do you want to save ?

UKHeliBob:
Have you got any SD libraries installed ?
Have you looked at the examples in the IDE ?
What sort of data do you want to save ?

#include "Arduino.h"
#include <EDB.h>

// Use the external SPI SD card as storage
#include <SPI.h>
#include <SD.h>

#define SD_PIN 10  // SD Card CS pin
#define TABLE_SIZE 8192

// The number of demo records that should be created.  This should be less
// than (TABLE_SIZE - sizeof(EDB_Header)) / sizeof(LogEvent).  If it is higher,
// operations will return EDB_OUT_OF_RANGE for all records outside the usable range.
#define RECORDS_TO_CREATE 10

char* db_name = "/db/edb_test.db";
File dbFile;

// Arbitrary record definition for this table.
// This should be modified to reflect your record needs.
struct LogEvent {
    int id;
    int temperature;
}
logEvent;

// The read and write handlers for using the SD Library
// Also blinks the led while writing/reading
void writer (unsigned long address, byte data) {
    digitalWrite(13, HIGH);
    dbFile.seek(address);
    dbFile.write(data);
    dbFile.flush();
    digitalWrite(13, LOW);
}

byte reader (unsigned long address) {
    digitalWrite(13, HIGH);
    dbFile.seek(address);
    byte b = dbFile.read();
    digitalWrite(13, LOW);
    return b;
}

// Create an EDB object with the appropriate write and read handlers
EDB db(&writer, &reader);

// Run the demo
void setup()
{
    pinMode(13, OUTPUT);
    digitalWrite(13, LOW);

    Serial.begin(9600);
    Serial.println(" Extended Database Library + External SD CARD storage demo");
    Serial.println();

    randomSeed(analogRead(0));

    if (!SD.begin(SD_PIN)) {
        Serial.println("No SD-card.");
        return;
    }

    // Check dir for db files
    if (!SD.exists("/db")) {
        Serial.println("Dir for Db files does not exist, creating...");
        SD.mkdir("/db");
    }

    if (SD.exists(db_name)) {

        dbFile = SD.open(db_name, FILE_WRITE);

        // Sometimes it wont open at first attempt, espessialy after cold start
        // Let's try one more time
        if (!dbFile) {
            dbFile = SD.open(db_name, FILE_WRITE);
        }

        if (dbFile) {
            Serial.print("Openning current table... ");
            EDB_Status result = db.open(0);
            if (result == EDB_OK) {
                Serial.println("DONE");
            } else {
                Serial.println("ERROR");
                Serial.println("Did not find database in the file " + String(db_name));
                Serial.print("Creating new table... ");
                db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
                Serial.println("DONE");
                return;
            }
        } else {
            Serial.println("Could not open file " + String(db_name));
            return;
        }
    } else {
        Serial.print("Creating table... ");
        // create table at with starting address 0
        dbFile = SD.open(db_name, FILE_WRITE);
        db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
        Serial.println("DONE");
    }

    recordLimit();
    countRecords();
    createRecords(RECORDS_TO_CREATE);
    countRecords();
    selectAll();
    deleteOneRecord(RECORDS_TO_CREATE / 2);
    countRecords();
    selectAll();
    appendOneRecord(RECORDS_TO_CREATE + 1);
    countRecords();
    selectAll();
    insertOneRecord(RECORDS_TO_CREATE / 2);
    countRecords();
    selectAll();
    updateOneRecord(RECORDS_TO_CREATE);
    selectAll();
    countRecords();
    deleteAll();
    Serial.println("Use insertRec() and deleteRec() carefully, they can be slow");
    countRecords();
    for (int i = 1; i <= 20; i++) insertOneRecord(1);  // inserting from the beginning gets slower and slower
    countRecords();
    for (int i = 1; i <= 20; i++) deleteOneRecord(1);  // deleting records from the beginning is slower than from the end
    countRecords();

    dbFile.close();
}

void loop()
{
}

// utility functions

void recordLimit()
{
    Serial.print("Record Limit: ");
    Serial.println(db.limit());
}

void deleteOneRecord(int recno)
{
    Serial.print("Deleting recno: ");
    Serial.println(recno);
    db.deleteRec(recno);
}

void deleteAll()
{
    Serial.print("Truncating table... ");
    db.clear();
    Serial.println("DONE");
}

void countRecords()
{
    Serial.print("Record Count: ");
    Serial.println(db.count());
}

void createRecords(int num_recs)
{
    Serial.print("Creating Records... ");
    for (int recno = 1; recno <= num_recs; recno++)
    {
        logEvent.id = recno;
        logEvent.temperature = random(1, 125);
        EDB_Status result = db.appendRec(EDB_REC logEvent);
        if (result != EDB_OK) printError(result);
    }
    Serial.println("DONE");
}

void selectAll()
{
    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 updateOneRecord(int recno)
{
    Serial.print("Updating record at recno: ");
    Serial.print(recno);
    Serial.print("... ");
    logEvent.id = 1234;
    logEvent.temperature = 4321;
    EDB_Status result = db.updateRec(recno, EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
    Serial.println("DONE");
}

void insertOneRecord(int recno)
{
    Serial.print("Inserting record at recno: ");
    Serial.print(recno);
    Serial.print("... ");
    logEvent.id = recno;
    logEvent.temperature = random(1, 125);
    EDB_Status result = db.insertRec(recno, EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
    Serial.println("DONE");
}

void appendOneRecord(int id)
{
    Serial.print("Appending record... ");
    logEvent.id = id;
    logEvent.temperature = random(1, 125);
    EDB_Status result = db.appendRec(EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
    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;
    }
}

I used this code but I can't save data in two table ??

Hi My friends
I use this library EDB master
I want to save my data into 3 different tables
what's the best way to do this?

#include "Arduino.h"
#include <EDB.h>

// Use the external SPI SD card as storage
#include <SPI.h>
#include <SD.h>

#define SD_PIN 10  // SD Card CS pin
#define TABLE_SIZE 8192

// The number of demo records that should be created.  This should be less
// than (TABLE_SIZE - sizeof(EDB_Header)) / sizeof(LogEvent).  If it is higher,
// operations will return EDB_OUT_OF_RANGE for all records outside the usable range.
#define RECORDS_TO_CREATE 10

char* db_name = "/db/edb_test.db";
File dbFile;

// Arbitrary record definition for this table.
// This should be modified to reflect your record needs.
struct LogEvent {
    int id;
    int temperature;
}
logEvent;

// The read and write handlers for using the SD Library
// Also blinks the led while writing/reading
void writer (unsigned long address, byte data) {
    digitalWrite(13, HIGH);
    dbFile.seek(address);
    dbFile.write(data);
    dbFile.flush();
    digitalWrite(13, LOW);
}

byte reader (unsigned long address) {
    digitalWrite(13, HIGH);
    dbFile.seek(address);
    byte b = dbFile.read();
    digitalWrite(13, LOW);
    return b;
}

// Create an EDB object with the appropriate write and read handlers
EDB db(&writer, &reader);

// Run the demo
void setup()
{
    pinMode(13, OUTPUT);
    digitalWrite(13, LOW);

    Serial.begin(9600);
    Serial.println(" Extended Database Library + External SD CARD storage demo");
    Serial.println();

    randomSeed(analogRead(0));

    if (!SD.begin(SD_PIN)) {
        Serial.println("No SD-card.");
        return;
    }

    // Check dir for db files
    if (!SD.exists("/db")) {
        Serial.println("Dir for Db files does not exist, creating...");
        SD.mkdir("/db");
    }

    if (SD.exists(db_name)) {

        dbFile = SD.open(db_name, FILE_WRITE);

        // Sometimes it wont open at first attempt, espessialy after cold start
        // Let's try one more time
        if (!dbFile) {
            dbFile = SD.open(db_name, FILE_WRITE);
        }

        if (dbFile) {
            Serial.print("Openning current table... ");
            EDB_Status result = db.open(0);
            if (result == EDB_OK) {
                Serial.println("DONE");
            } else {
                Serial.println("ERROR");
                Serial.println("Did not find database in the file " + String(db_name));
                Serial.print("Creating new table... ");
                db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
                Serial.println("DONE");
                return;
            }
        } else {
            Serial.println("Could not open file " + String(db_name));
            return;
        }
    } else {
        Serial.print("Creating table... ");
        // create table at with starting address 0
        dbFile = SD.open(db_name, FILE_WRITE);
        db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
        Serial.println("DONE");
    }

    recordLimit();
    countRecords();
    createRecords(RECORDS_TO_CREATE);
    countRecords();
    selectAll();
    deleteOneRecord(RECORDS_TO_CREATE / 2);
    countRecords();
    selectAll();
    appendOneRecord(RECORDS_TO_CREATE + 1);
    countRecords();
    selectAll();
    insertOneRecord(RECORDS_TO_CREATE / 2);
    countRecords();
    selectAll();
    updateOneRecord(RECORDS_TO_CREATE);
    selectAll();
    countRecords();
    deleteAll();
    Serial.println("Use insertRec() and deleteRec() carefully, they can be slow");
    countRecords();
    for (int i = 1; i <= 20; i++) insertOneRecord(1);  // inserting from the beginning gets slower and slower
    countRecords();
    for (int i = 1; i <= 20; i++) deleteOneRecord(1);  // deleting records from the beginning is slower than from the end
    countRecords();

    dbFile.close();
}

void loop()
{
}

// utility functions

void recordLimit()
{
    Serial.print("Record Limit: ");
    Serial.println(db.limit());
}

void deleteOneRecord(int recno)
{
    Serial.print("Deleting recno: ");
    Serial.println(recno);
    db.deleteRec(recno);
}

void deleteAll()
{
    Serial.print("Truncating table... ");
    db.clear();
    Serial.println("DONE");
}

void countRecords()
{
    Serial.print("Record Count: ");
    Serial.println(db.count());
}

void createRecords(int num_recs)
{
    Serial.print("Creating Records... ");
    for (int recno = 1; recno <= num_recs; recno++)
    {
        logEvent.id = recno;
        logEvent.temperature = random(1, 125);
        EDB_Status result = db.appendRec(EDB_REC logEvent);
        if (result != EDB_OK) printError(result);
    }
    Serial.println("DONE");
}

void selectAll()
{
    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 updateOneRecord(int recno)
{
    Serial.print("Updating record at recno: ");
    Serial.print(recno);
    Serial.print("... ");
    logEvent.id = 1234;
    logEvent.temperature = 4321;
    EDB_Status result = db.updateRec(recno, EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
    Serial.println("DONE");
}

void insertOneRecord(int recno)
{
    Serial.print("Inserting record at recno: ");
    Serial.print(recno);
    Serial.print("... ");
    logEvent.id = recno;
    logEvent.temperature = random(1, 125);
    EDB_Status result = db.insertRec(recno, EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
    Serial.println("DONE");
}

void appendOneRecord(int id)
{
    Serial.print("Appending record... ");
    logEvent.id = id;
    logEvent.temperature = random(1, 125);
    EDB_Status result = db.appendRec(EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
    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;
    }
}

Thanks !!

I can't save data in two table ??

What happens when you try ?
What should happen ?

If you want 3 different tables, you will most likely need 3 different filenames on you SD card and 3 different EDB objects and, if the records are different, 3 different sets of reader/writer handlers.

What have you tried so far? It looks like you just posted the demo code without modification.

blh64:
If you want 3 different tables, you will most likely need 3 different filenames on you SD card and 3 different EDB objects and, if the records are different, 3 different sets of reader/writer handlers.

What have you tried so far? It looks like you just posted the demo code without modification.

I added new EDB and New Table

like this

db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
db.create(1, TABLE_SIZE, (unsigned int)sizeof(logEvent2));

UKHeliBob:
What happens when you try ?
What should happen ?

when I update the value in table 1 it will update in table 2

I want to separate table 1 and table 2

when I update the value in table 1 it will update in table 2

I want to separate table 1 and table 2

Are you sure that you can have more than one table each database file ?

The create method doesn't create a database, it writes the header, you call it once for any given EDB object
from what I see - look at the source code of the library (its not very well commented alas)...

You need to declare 3 EDB objects, each with separate writers and readers using 3 different files.

On the Uno there is not enough RAM to open 3 files at once on an SDcard I fear though...

MarkT:
The create method doesn't create a database, it writes the header, you call it once for any given EDB object
from what I see - look at the source code of the library (its not very well commented alas)...

You need to declare 3 EDB objects, each with separate writers and readers using 3 different files.

On the Uno there is not enough RAM to open 3 files at once on an SDcard I fear though...

do u know another way to save data?

do u know another way to save data?

Do you need all 3 files to be open at once ?

Can you please summarise what you are trying to do ?