Go Down

Topic: Lack of SRAM memory (Read 1 time) previous topic - next topic

blastboot

Apr 22, 2013, 04:54 pm Last Edit: Apr 22, 2013, 04:56 pm by blastboot Reason: 1
Hello, I've finished to write and compile my program, but when it start running the arduino runs out of memory and it gives strange characters to serial.
I need some help to optimize my code... to make more SRAM available (Flash memory is good: 31.030 bytes).

Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
#include <VirtualWire.h>
#include <Wire.h>
#include "SdFatUtil.h"

//VARIÁVEIS PARA O RTC (DS1307)
//SCL      <--> Analog Input 5
//SDA      <--> Analog Input 4
#define DS1307_I2C_Endereco 0x68  // This is the I2C address
#define I2C_Write Wire.write
#define I2C_Read Wire.read
byte segundo, minuto, hora, diaSemana, dia, mes, ano;

//CONVERSÃO DE BCD PARA DECIMAL
byte bcdToDec(byte val)
{
 return ( (val/16*10) + (val%16) );
}

char* noMes[] = {
 "","Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"};

//DECLARAÇÃO DOS PINOS
const byte ledInfo = 2;
const byte ledRececao = 3;
const byte pinoRececao = 8;
const byte BUFSIZ = 128;

//DECLARAÇÃO DAS VARIÁVEIS GLOBAIS
char mensagem[6];
unsigned int dadosAgua = 0;
float dadosBat = 0.0;
float percentagem = 0;
unsigned long litros = 0;
boolean Log = false;
int altAgua = 0;

//CONFIG ETHERNET SHIELD
byte mac[] = {
 0x80, 0xA2, 0xDA, 0x00, 0xEA, 0x8C };
byte ip[] = {
 10, 50, 196, 80 };
char ficheiroIndex[] = "i.htm";
char ficheiroTanque[] = "t.jpg";
char ficheiroBorder[] = "b.jpg";
char ficheiroFavicon[] = "f.ico";
char ficheiroLog[8];
char* ficheiroLer;
EthernetServer server = EthernetServer(80);
EthernetClient client;

//PROGRAMAÇÃO DO CARTÃO SD
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

//ARMAZENA SEQUÊNCIAS DE ERRO NA MEMÓRIA FLASH PARA ECONOMIZAR RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
 PgmPrint("Erro: ");
 SerialPrintln_P(str);
 if (card.errorCode()) {
   PgmPrint("Erro cart.SD: ");
   Serial.print(card.errorCode(), HEX);
   Serial.print(',');
   Serial.println(card.errorData(), HEX);
 }
 digitalWrite(ledInfo, HIGH);
 while(1);
}

void setup() {

 Serial.begin(9600);
 delay(100);

 pinMode(ledInfo, OUTPUT);
 pinMode(ledRececao, OUTPUT);
 pinMode(10, OUTPUT);

 //INICIA A COMUNICAÇÃO I2C
 Wire.begin();

 //LIGA E DESLIGA OS 2 LEDS PARA INDICAR QUE ESTÃO OPERACIONAIS
 digitalWrite(ledInfo, HIGH);
 digitalWrite(ledRececao, HIGH);
 digitalWrite(10, HIGH);
 delay(1000);
 digitalWrite(ledInfo, LOW);
 digitalWrite(ledRececao, LOW);

 PgmPrint("RAM: ");
 Serial.println(FreeRam());

 //INICIALIZA O CARTÃO SD EM "FULL SPEED", MÁXIMO DESEMPENHO. (PARA EVITAR ERROS COM LIGAÇÃO À BREADBOARD DEVE ESTAR EM "HALF SPEED")
 if (!card.init(SPI_FULL_SPEED, 4)) error("Erro Init cart.SD!");

 //INICIALIZA O VOLUME FAT
 if (!volume.init(&card)) error("Erro vol cart.SD!");

 //LISTA NA SÉRIE OS FICHEIROS QUE ESTÃO NA RAIZ DO CARTÃO SD, COM DATA E TAMANHO
 if (!root.openRoot(&volume)) error("Erro root cart.SD!");

 //INICIA O SERVIDOR
 Ethernet.begin(mac, ip);
 server.begin();
 delay(100);

 //CONFIGURA E INICIA O RECEPTOR
 vw_set_rx_pin(pinoRececao);
 vw_setup(2000);
 vw_rx_start();

 //LED PISCA 3 VEZES A INDICAR TODA A CONFIGURAÇÂO CONCLUÍDA COM SUCESSO
 for (int i = 0; i<3; i++) {
   digitalWrite(ledInfo, HIGH);
   delay(250);
   digitalWrite(ledInfo, LOW);
   delay(250);
 }
 Serial.println(F("Config concl"));
}

void loop() {

 altAgua++;
 rececaoRF();
 clienteLigado();
 delay(500);
}

//RECEPÇÃO DOS DADOS POR RF 433MHz
void rececaoRF() {

 byte buf[VW_MAX_MESSAGE_LEN];
 byte buflen = VW_MAX_MESSAGE_LEN;

 if (vw_get_message(buf, &buflen)) {
   digitalWrite(ledRececao, HIGH);
   for (int j = 0; j<buflen; j++) {
     mensagem[j] = buf[j];
   }
   if (mensagem[0] == 'R') {
     dadosAgua = atoi(&mensagem[1]);
   }
   else if (mensagem[0] == 'B') {
     dadosBat = atof(&mensagem[1]);
     Serial.print(F("Volt Bat: "));
     Serial.println(dadosBat);
   }
   Serial.print(F("Msg Receb: "));
   Serial.println(mensagem);
   memset(&buf, 0, sizeof(buf));
   memset(&mensagem, 0, sizeof(mensagem));
   calcAgua();
   gravarDados();
   digitalWrite(ledRececao, LOW);
 }
}

CONTINUES...

blastboot

Code: [Select]
void calcAgua() {
 percentagem = ((465-dadosAgua)*100)/465;
 litros = ((465-dadosAgua)*600000)/465;
}

void gravarDados() {

 //FAZ O STACK POINTER IR PARA O INÍCIO
 Wire.beginTransmission(DS1307_I2C_Endereco);
 I2C_Write(0x00);
 Wire.endTransmission();
 Wire.requestFrom(DS1307_I2C_Endereco, 7);

 segundo = bcdToDec(I2C_Read() & 0x7f); //MASCARA PQ É BIT DE CONTROLE
 minuto  = bcdToDec(I2C_Read());
 hora    = bcdToDec(I2C_Read() & 0x3f); //MÁSCARA PQ É BIT DE CONTROLE
 dia     = bcdToDec(I2C_Read());
 mes     = bcdToDec(I2C_Read());
 ano     = bcdToDec(I2C_Read());

 sprintf(ficheiroLog,"%s%s", noMes[mes], ".csv");

 Log = file.open(&root, ficheiroLog, O_WRITE | O_APPEND);
 if (Log){
   //HORA
   file.print(dia, DEC);
   file.print(" ");
   file.print(noMes[mes]);
   file.print(" ");
   file.print("20");
   if (ano < 10) {
     file.print("0");
   }
   file.print(ano, DEC);
   file.print(" , ");
   if (hora < 10) {
     file.print("0");
   }
   file.print(hora, DEC);
   file.print(":");
   if (minuto < 10) {
     file.print("0");
   }
   file.print(minuto, DEC);
   file.print(":");
   if (segundo < 10) {
     file.print("0");
   }
   file.print(segundo, DEC);
   //DADOS    
   file.print(" , ");
   file.print(percentagem, 1);
   file.print(" , ");
   file.println(litros);
   file.close();
   Log = false;
 }
 else {
   Serial.println(F("ERRO grav LOG!"));
 }
}

void clienteLigado() {
 char clientline[BUFSIZ];
 int index = 0;
 client = server.available();
 if (client) {
   digitalWrite(ledInfo, HIGH);
   delay(1);
   digitalWrite(ledInfo, LOW);
   index = 0;
   while (client.connected()) {
     if (client.available()) {
       char c = client.read();
       if (c != '\n' && c != '\r') {
         clientline[index] = c;
         index++;
         if (index >= BUFSIZ)
           index = BUFSIZ - 1;
         continue;

       }
       clientline[index] = 0;
       Serial.println(clientline);
       digitalWrite(ledInfo, HIGH);
       delay(1);
       digitalWrite(ledInfo, LOW);        

       if (strstr(clientline, "GET / ") != 0) {
         headerRespostaHttp();
         conTypeTxt();
         ficheiroLer = ficheiroIndex;
         lerFicheiroCartao();

       }
       else if (strstr(clientline, "GET /tqe") != 0) {
         headerRespostaHttp();
         conTypeImg();
         ficheiroLer = ficheiroTanque;
         lerFicheiroCartao();
       }
       else if (strstr(clientline, "GET /bdr") != 0) {
         headerRespostaHttp();
         conTypeImg();
         ficheiroLer = ficheiroBorder;
         lerFicheiroCartao();
       }
       else if (strstr(clientline, "GET /fin") != 0) {
         headerRespostaHttp();
         client.println(F("Content-Type: image/x-icon"));
         client.println();
         ficheiroLer = ficheiroFavicon;
         lerFicheiroCartao();
       }
       else if (strstr(clientline, "GET /&dadosagua") != 0) {
         headerRespostaHttp();
         conTypeTxt();
         client.print(altAgua);
         client.println(F("px"));
         Serial.println(altAgua);
       }
       else if (strstr(clientline, "GET /&logg") != 0) {
         headerRespostaHttp();
         char carMes = clientline[10];
         switch (carMes) {
         case '1':
           sprintf(ficheiroLer,"%s%s", noMes[1], ".csv");
           //ficheiroLer = "Jan.csv";
           break;
         case '2':
           sprintf(ficheiroLer,"%s%s", noMes[2], ".csv");
           //ficheiroLer = "Fev.csv";
           break;
         case '3':
           sprintf(ficheiroLer,"%s%s", noMes[3], ".csv");
           //ficheiroLer = "Mar.csv";
           break;
         case '4':
           sprintf(ficheiroLer,"%s%s", noMes[4], ".csv");
           //ficheiroLer = "Abr.csv";
           break;
         case '5':
           sprintf(ficheiroLer,"%s%s", noMes[5], ".csv");
           //ficheiroLer = "Mai.csv";
           break;
         case '6':
           sprintf(ficheiroLer,"%s%s", noMes[6], ".csv");
           //ficheiroLer = "Jun.csv";
           break;
         case '7':
           sprintf(ficheiroLer,"%s%s", noMes[7], ".csv");
           //ficheiroLer = "Jul.csv";
           break;
         case '8':
           sprintf(ficheiroLer,"%s%s", noMes[8], ".csv");
           //ficheiroLer = "Ago.csv";
           break;
         case '9':
           sprintf(ficheiroLer,"%s%s", noMes[9], ".csv");
           //ficheiroLer = "Set.csv";
           break;
         case 'o':
           sprintf(ficheiroLer,"%s%s", noMes[10], ".csv");
           //ficheiroLer = "Out.csv";
           break;
         case 'n':
           sprintf(ficheiroLer,"%s%s", noMes[11], ".csv");
           //ficheiroLer = "Nov.csv";
           break;
         case 'd':
           sprintf(ficheiroLer,"%s%s", noMes[12], ".csv");
           //ficheiroLer = "Dez.csv";
           break;
         }
         client.print(F("Content-Disposition: attachment; filename=\"LOG_"));
         client.print(ficheiroLer);
         client.println(F("\""));
         client.println();
         lerFicheiroCartao();
       }
       else {
         client.println(F("HTTP/1.1 404 Not Found"));
         conTypeTxt();
         client.println(F("<h2>Erro 404</h2>"));
         client.println(F("<s2>Caminho/ficheiro nao existe.<s2>"));
         client.println(F(""));
       }
       break;
     }
   }
   delay(1);
   client.stop();
 }
}

void headerRespostaHttp() {
 client.println(F("HTTP/1.1 200 OK"));
}

void conTypeTxt() {
 client.println(F("Content-Type: text/html"));
 client.println();
}

void conTypeImg() {
 client.println(F("Content-Type: image/jpeg"));
 client.println();
}

void lerFicheiroCartao() {
 boolean ficheiro = false;
 ficheiro = file.open(&root, ficheiroLer, O_READ);
 if (ficheiro) {
   byte clientBuf[64];
   int clientCount = 0;

   while(file.available()) {
     clientBuf[clientCount] = file.read();
     clientCount++;
     if (clientCount > 63) {
       client.write(clientBuf, 64);
       clientCount = 0;
     }
   }
   if (clientCount > 0) {
     client.write(clientBuf, clientCount);
   }
   file.close();
   memset(&ficheiroLer, 0, sizeof(ficheiroLer));
 }
}


Thanks in advance!

AWOL

Code: [Select]
case '1':
            sprintf(ficheiroLer,"%s%s", noMes[1], ".csv");
            //ficheiroLer = "Jan.csv";
            break;
          case '2':
            sprintf(ficheiroLer,"%s%s", noMes[2], ".csv");
            //ficheiroLer = "Fev.csv";
            break;


Code: [Select]

            sprintf(ficheiroLer,"%s%s", noMes[carmes - '0' + 1], ".csv");
or similar.
Looks like a few of your GETs could live in PROGMEM too.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

blastboot

Thanks for answering!
Quote
sprintf(ficheiroLer,"%s%s", noMes[carmes - '0' + 1], ".csv");

I couldn't understand what does this do in this format. Can you give me a simple explanation?

The progmem is a good idea. I will look for it to know how to use it.

AWOL

Assume "carmes" is an ASCII decimal digit.
Subtracting '0' turns it into its actual decimal value.
Use that to form your array subscript.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up