Storing read files in objects

Hello everyone !

I'm not an arduino expert, actually I'm working on my first project ! Hence, a lot of obstacles ahead :smiley: ,I could overcome few of them, but sometimes I get stuck. So.... I'm reading a file in a SD card, which contains variables of interest such as Date,Time,Hour,Section etc etc. I need to save all of this variables in attribute objects... Creating Classes and objects in Arduino seems scary to me. Do I need to create a sort of library ? As I told before, i just need objects to store my variables..these objects will not have methods. Any help please? Thanks in advance.

which contains variables of interest

No, it does NOT. You can not store variables in a file. You store data in a file. That data MIGHT include VALUES that you want to store in variables.

Creating Classes and objects in Arduino seems scary to me.

So, don't do it.

Do I need to create a sort of library ?

What you create will either be a library or not. There are no "sort of" libraries.

i just need objects to store my variables

Nonsense.

It would help if you explained what your project is intended to do. I suspect that some of the words that you are using do not mean what you seem to think they do.

UKHeliBob:
It would help if you explained what your project is intended to do. I suspect that some of the words that you are using do not mean what you seem to think they do.

Well, I'll try to be more specific then, thanks for your interest. I have a file in the SD Card, within its data there're some values which I need to store(I will compare them with the RTC time in order to make decisions with solenoids control) , I'm intending to store them as atributes of an object. But as I told you, it is my first time with arduino... I don't know how to do it yet, it seems to be more complex than in Java for example. I'll be glad to expose more details if its needed, thanks again.

rezik:
Well, I'll try to be more specific then, thanks for your interestI don't know how to do it yet, it seems to be more complex than in Java for example. I'll be glad to expose more details if its needed, thanks again.

c++ and java are virtually identical in almost every way....

Regards,
Ray L.

How is the data stored? As text (e.g. separated by commas) or in binary format?

Does the file contain one record or multiple records (e.g. a time to switch a light on and a time to switch a light off as two different records)?

sterretje:
How is the data stored? As text (e.g. separated by commas) or in binary format?

Does the file contain one record or multiple records (e.g. a time to switch a light on and a time to switch a light off as two different records)?

Hello sterretje, the data is stored as txt. Here is an example :

{"Identificação":1002,"Programa":"PRG VRO","Agendamentos":[{"Dia":3,"Hora":"05:00:00","Eventos":[{"Setor":2,"Duração":1500,"Sequencial":3,"Receita":"REC01","Água":1.5,"Fertilizantes":[{"Silo":"Silo 1","Fertilizante":"Potássio","Volume":2.3}]}]}

I made few functions to read chacarters like : " . , so I could skip unecessary data and move foward to the values of interest, they are shown in red. This values will determine which action I must give to solenoids and I'll also need to compare them to RTC values. Any other relevant info ?! Thank you

to the values of interest

When you encounter a value of interest, like 3, how do you know what to do with it? It seems to me that throwing away Dia is not a good thing.

Still can't see your code.

void EncontraDiaHora () { 
    int i, dia, hora, minutos,segundos;
    
    LeDoisPontos();
    LeDoisPontos();
    
    dia = ((arquivo.read()-48));
    Serial.println(dia);
    
    LeDoisPontos();
    LeAspaDupla();
    
    hora= ((arquivo.read()-48)*10);
    hora= hora +((arquivo.read() - 48));
    Serial.println(hora);
    
    LeDoisPontos();
    
    minutos = ((arquivo.read()-48)*10);
    minutos = minutos + ((arquivo.read() - 48));
    Serial.println(minutos);
    
    LeDoisPontos();
    
    segundos = ((arquivo.read()-48)*10);
    segundos = segundos + ((arquivo.read() - 48));
    Serial.println(segundos);
       
}

void LeDoisPontos () {  //function that reads the characters of the file until you find ': ' (colon) that separates its parameters.
  char caracter;
  while(arquivo.available()){
    caracter=arquivo.read();
    if (caracter==':') break;
  }
}

void LeAspaDupla () { // function that reads the file until you find the string ' "' (quotation marks) that separates its parameters.
  char caracter;
  while(arquivo.available()){
    caracter = arquivo.read() ;
   if (caracter=='"') break;
  }
}

This is only a part of the code since you exampled "Dia" value I'm showing you how I reach this value and what happens to it next, basically its a function to find Day,Hour,Minutes,Seconds in the byte chain , I convert them to decimal according to ASCII table reference and simply print it to serial for verification matters. If the whole code is needed, let me know.

So, the value 3 following the name Dia is stored in a variable called dia.

What is the problem, then?

Please, post all of your code. Or at least all the relevant parts..

You are using the wrong terms causing confusion to the people trying to help you. You should start at the Arduino Reference to understand the correct terminology.

And finally you are reading the file in a strange way. Reading a file from the SD card is pretty much the same as reading Serial data, so you should start reading Serial Input Basics.

You should be reading the file a line at a time, or until an end mark (on your example it could be the ','), but I would try to break it into lines for readability.

Here is an example on how to read a file one line at a time.

void sd_card() {
  byte days = 0;
  long position = 0;
  byte attempts = 0;
  char data[64] = {};
  char filename[12] = {};
  SdFile file("log.txt", O_CREAT | O_RDWR);
  file.getFilename(filename);
  if (file.isOpen()) {
    file.seekSet(position);
    while (file.available()) {
      position = file.curPosition();
      file.fgets(data, sizeof(data), "\n");
      if (strstr(data, "Dia")) {
        sscanf(data, "Dia=%02hhd", &days);
        Serial.println(days);
        file.seekSet(position);
        break;
      }
      memset(data, 0, sizeof(data));
    }
    file.close();
  }
  else Serial.println(F("Failed to open the file."));
}

*Kinda off topic (in portuguese):
Não sei qual é o tamanho do seu projeto, mas se você está pensando em pedir ajuda aqui no fórum mais vezes seria bom utilizar o nome das variáveis em inglês, porque se as pessoas não entenderem nem as suas variáveis fica bem mais difícil de ajudar e muitos vão simplesmente passar batido.

Ok so here's the code which has the function to read the files from SD, find values of interest. I'm intending to store them within objects as atributes in order to compare them with the RTC and after this comparison i will make decisions with solenoids.

CODE 1 : (read,find values of interest)

#include <SD.h>
#include <Wire.h>
#include <SPI.h>
#include <libAC.h>

File arquivo;
void setup() 
{
  Serial.begin(9600);
  pinMode(53,OUTPUT);
  if(!SD.begin(53)){
    Serial.println("O cartão falhou ao iniciar ou não está presente"); // Trocar "Serial.printl" por "Registrador:error" após os testes.
    return;
  }
  Serial.println("Cartão iniciado !");
  OpenReadArquivo();
  LeVirgula;
}
    else{
      Serial.println("O arquivo já terminou de ser lido");
      }
}


void OpenReadArquivo()
{ 
  int setor,sequencial,i,k,j,n;
  float volumeAgua = 0 ;
  float volumeFert = 0; 
  float duracao;
  char c, d, s,f, v;
 
  arquivo = SD.open("Ferti.cal");
  if (arquivo) 
  {
    Serial.println("Ferti.cal:");
    LeVirgula();
    LeVirgula();
    EncontraDiaHora();
    LeDoisPontos();
    LeDoisPontos();
    setor = ((arquivo.read()-48));
    Serial.println(setor);
    LeDoisPontos();
//--------------------------------------------------------------//    
    d = arquivo.read();
    duracao = 0;
    while(d != ','){
      duracao = duracao * 10 + ((d -48));
      d = arquivo.read();
    }
    Serial.println(duracao);
//--------------------------------------------------------------//    
    LeDoisPontos();
    sequencial = ((arquivo.read()-48));
    Serial.println(sequencial);
//--------------------------------------------------------------//
    LeDoisPontos();
    LeDoisPontos();
//--------------------------------------------------------------//    
    c = arquivo.read();
    i=1;
    while(c != '.'){
      volumeAgua = volumeAgua * 10 + (c - 48);
      c = arquivo.read();
    }
 c = arquivo.read();
      while(c != ','){
      volumeAgua = volumeAgua + (c-48)*(pow(10,-i));
      i++;
      c=arquivo.read();
      }
     Serial.println(volumeAgua);
//--------------------------------------------------------------//   
     LeDoisPontos();
     LeDoisPontos();
//--------------------------------------------------------------//
    k=0; s=0;
    s = arquivo.read();
    while(s!=','){
      Serial.print(s);
      s = arquivo.read();
     k++;
     if (s==','){
      break;
      }
    }

   
//--------------------------------------------------------------//    
    LeDoisPontos();
    LeDoisPontos();
//--------------------------------------------------------------//
  
v = arquivo.read();

    j=1;i=1;
    while(v != '.'){
      volumeFert = volumeFert * 10 + (v - 48);
      v = arquivo.read();
    }
v = arquivo.read();
     while(v != '}'){
      volumeFert = volumeFert + (v-48)*(pow(10,-i));
      j++;
      v=arquivo.read();
      }
     Serial.println();
     Serial.println(volumeFert);
     
    arquivo.close();
  } else 
  {
        Serial.println("Erro ao abrir o Ferti.cal");
  }
}



void LeVirgula (){  // função que lê os caracteres do arquivo até encontrar ',' (virgula) que separa seus parâmetros.
  char caracter;
  while(arquivo.available())
  {
    caracter = arquivo.read();
    if(caracter==',') break;
  }
}
  
  
void EncontraDiaHora () { 
    int i, dia, hora, minutos,segundos;
    
    LeDoisPontos();
    LeDoisPontos();
    
    dia = ((arquivo.read()-48));
    Serial.println(dia);
    
    LeDoisPontos();
    LeAspaDupla();
    
    hora= ((arquivo.read()-48)*10);
    hora= hora +((arquivo.read() - 48));
    Serial.println(hora);
    
    LeDoisPontos();
    
    minutos = ((arquivo.read()-48)*10);
    minutos = minutos + ((arquivo.read() - 48));
    Serial.println(minutos);
    
    LeDoisPontos();
    
    segundos = ((arquivo.read()-48)*10);
    segundos = segundos + ((arquivo.read() - 48));
    Serial.println(segundos);
       
}

void LeDoisPontos () {  //function that reads the characters of the file until you find ': ' (colon) that separates its parameters.
  char caracter;
  while(arquivo.available()){
    caracter=arquivo.read();
    if (caracter==':') break;
  }
}

void LeAspaDupla () { // function that reads the file until you find the string ' "' (quotation marks) that separates its parameters.
  char caracter;
  while(arquivo.available()){
    caracter = arquivo.read() ;
   if (caracter=='"') break;
  }
}

If you take this byte chain :

{"Identificação":1002,"Programa":"PRG VRO","Agendamentos":[{"Dia":3,"Hora":"05:00:00","Eventos":[{"Setor":2,"Duração":1500,"Sequencial":3,"Receita":"REC01","Água":1.5,"Fertilizantes":[{"Silo":"Silo 1","Fertilizante":"Potássio","Volume":2.3}]}]}

CODE 1 will return all the values of interest

Alright that's what I have so far, sorry if this is not the most optimized way to achieve my goals, but as I told you before, I'm beginner in Arduino. Since you all know the procedement to find the values of interest here's the code which provides DATE,time. I will compare those values of interest of CODE 1 with the provided time of this CODE 2.

CODE 2 (RTC)

#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);

    }


void loop(){
  printDate();
  delay(1000);
}

byte bcdToDec(byte val)  {
// Converte BCD para numeros decimais em sua forma normal 
  return ( (val/16*10) + (val%16) );
}

void printDate(){

  // Reset apontador registrador
  Wire.beginTransmission(DS1307_ADDRESS);

  byte zero = 0x00;
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //formato 24h por dia
  int weekDay = bcdToDec(Wire.read()); //0-6 -> domingo - Sabado
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

 
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

}

This is huge right now and I apologize. I would appreciate all fellow's time to understand the situation and show me some light in the dark ahead. Again, thanks

You should Google strtok. For parsing strings, it is very well worth the time to learn to use it.

Regards,
Ray L.

Can you have multiple Agendamentos in one record? Can you have multiple Eventos in one Agendamentos? Can you have multiple Fertilizantes in one Eventos?

You can store the data in a couple of structures. The below could be the basics and reflects basically the structure of your data

struct FERTILIZANTES
{
  char SILO[8];
  char Fertilizante[16];
  float Volume;
};

struct EVENTOS
{
  int Setor;
  int Duracao;
  int Sequencial;
  char Receita[8];
  float aqua;
  FERTILIZANTES Fertilizantes;  // this might have to be an array or a pointer
};

struct AGENDAMENTOS
{
  int Dia;
  char Hours;
  char Minutes;
  char Seconds;
  EVENTOS Eventos;  // this might have to be an array or a pointer
};

struct DATA
{
  int Identificacao;
  char Programa[16];
  AGENDAMENTOS Agendamentos;  // this might have to be an array or a pointer
};

If the answer to the questions in the beginning of this post is 'no', you can simplify the above to one struct. Note that you need to adjust the array sizes so the can hold the longest string plus the terminating nul character ('\0').

The below will show how it can be used and populates (part of it) with the data that you showed.

void setup()
{
  DATA record;

  record.Identificacao = 1002;
  strcpy(record.Programa, "PRG VRO");
  record.Agendamentos.Dia = 3;
  record.Agendamentos.Hours = 5;
  record.Agendamentos.Minutes = 0;
  record.Agendamentos.Seconds = 0;
  record.Agendamentos.Eventos.Setor = 2;
  ...
  ...
}

I'm not sure if classes will offer benefits (I'm not much of a C++ programmer).

Is the data that you showed one line? What is the maximum length of a line (the one you showed is 244 characters).

Can you have multiple Agendamentos in one record? Can you have multiple Eventos in one Agendamentos? Can you have multiple Fertilizantes in one Eventos?

Thanks sterretje for your interest. Well the answer is yes. But the data comes as byte chains, so as an example :

{"Identificação":1002,"Programa":"PRG VRO","Agendamentos":[{"Dia":3,"Hora":"05:00:00","Eventos":[{"Setor":2,"Duração":1500,"Sequencial":3,"Receita":"REC01","Água":1.5,"Fertilizantes":[{"Silo":"Silo 1","Fertilizante":"Potássio","Volume":2.3}]}]},{"Dia":3,"Hora":"07:00:00","Eventos":[{"Setor":2,"Duração":1500,"Sequencial":3,"Receita":"REC01","Água":1.5,"Fertilizantes":[{"Silo":"Silo 1","Fertilizante":"Potássio","Volume":2.3}]}]},{"Dia":6,"Hora":"05:00:00","Eventos":[{"Setor":2,"Duração":1300,"Sequencial":2,"Receita":"REC01","Água":4.5,"Fertilizantes":[{"Silo":"Silo 3","Fertilizante":"Potássio","Volume":4.3}]}]}]}

Your question served as a warning to me, I think with the present code I'm using I'm not able to read all of the chain... it ends in the orange commas and starts a new one. I guess there's a command i can use to solve this while (arquivo.available()) {OpenReadArquivo();} ... I'm be able to test this idea in few hours.

it ends in the orange commas

I couldn't see them when they were green, either.

RayLivingston:
You should Google strtok. For parsing strings, it is very well worth the time to learn to use it.

Regards,
Ray L.

Does this library Arduino/hardware/arduino/avr/cores/arduino/WString.h at ide-1.5.x · arduino/Arduino · GitHub allow me to use strok, strcpy or strncpy ?

Does this library Arduino/hardware/arduino/avr/cores/arduino/WString.h at ide-1.5.x · arduino/Arduino · GitHub allow me to use strok, strcpy or strncpy ?

No. Do NOT use Strings at all.

Why ? Instead of creating objects to store the values I can make structs

rezik:
Why ? Instead of creating objects to store the values I can make structs

You have used the word "object" many times in this thread but I cannot make sense of what you want to do. Can you please explain what an object means to you ?