Go Down

Topic: make code smaller (Read 2401 times) previous topic - next topic

wdvalenz

I have been working to get my weather station connected to internet.

unfortunately it seems that the sketch it too big to be transfered to the Arduino UNO.

Can a good soul  help me.

Can someone give some hints on how to make ma code smaller.

Thank you so much!!!




//incluir librerías
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SPI.h>
#include <SoftwareSerial.h>

SoftwareSerial Davis(3, 5); // RX, TX
int Min=-10;
int t[12]={-1};
int d[55];
int i=1;
char FileName[12];
SdFile myFile;
SdFat sd;

  float temp;
  int hum;
  float vel_v;
  int dir_v;
  float bar;
  float lluv;
  float lluv_ac;
  float rad;

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x41, 0xF9 };
//byte ip[] = { 192,168,0,163};
byte server[] = {190,147,203,25}; // Direccion ip del servidor
EthernetClient client;

void setup()
{
 if (!sd.begin(4, SPI_HALF_SPEED)) sd.initErrorHalt();
 pinMode(18, OUTPUT);
 pinMode(19, OUTPUT);
 Davis.begin(19200);
 //Ethernet.begin(mac, ip);
 Serial.begin(9600);
 delay(1000);
}

//////////////////////////////////////////////////////////////////////

void LeerSe()

{ digitalWrite(19, HIGH);
 Davis.println("LOOP 1");
 delay(10);
  for(i=1;i<=47;i++)// (Davis.available())
  {   d=Davis.read();
      delay(10);
  }

   i=1;
   if(d[11]*d[12]*d[13]==0){
     delay(1000);
     LeerSe();
   }

   temp=0.1*(d[12+3]*256+d[11+3]);
   temp=5*(temp-32)/9;
   hum=(d[13]);
   vel_v=0.44704*d[16];
   dir_v=d[18];
   bar=0.001*(d[10]*256+d[9]);
   lluv=0.001*(d[49]*256+d[46]);
   lluv_ac=0.001*(d[49]*256+d[46]);
   rad=0.1*(d[47]*256+d[46]);
   if(bar<0||temp<0){
   LeerSe();
   }
   else{

//   Serial.println(" DATOS LEIDOS ");
//    Serial.print("temp=");
//    Serial.println(temp);
//    Serial.print("hum=");
//    Serial.println(hum);
//    Serial.print("vel_v=");
//    Serial.println(vel_v);
//    Serial.print("dir_v=");
//    Serial.println(dir_v);
//    Serial.print("bar=");
//    Serial.println(bar);
//    Serial.print("lluv=");
//    Serial.println(lluv);
//    Serial.print("lluv_ac=");
//    Serial.println(lluv_ac);
//     Serial.print("dir_v=");
//    Serial.println(dir_v);
//    Serial.print("rad=");
//    Serial.println(rad);
   Davis.flush();
   delay(5);
   }
   digitalWrite(19, LOW);
}


//////////////////////////////////////////////////////////////////////

void LeerFH()
{digitalWrite(18, HIGH);
 Davis.println("GETTIME");
 delay(5);
  for(i=1;i<=8;i++)// (Davis.available())
   {
    t=Davis.read();
    delay(10);
   }
   Davis.flush();
  i=1; // reiniciar el contador
  t[7]=t[7]-100; //ajuste al año
  if(t[3]<0)//||t[3]>59||t[4]<0||t[4]>23||t[5]<1||t[5]>31||t[6]<1||t[6]>12||t[7]<0||t[7]>100)
  {delay(10);
  LeerFH();
   }
  else{
  Serial.print("Fecha y hora=");
//   Serial.print(t[7]+2000);
//   Serial.print("-");
//   Serial.print(t[6]);
//   Serial.print("-");
//   Serial.print(t[5]);
//   Serial.print(" ");
//   Serial.print(t[4]);
//   Serial.print(":");
//   Serial.print(t[3]);
//   Serial.print(":");
//   Serial.println(t[2]);
//   delay(10);
//   digitalWrite(18, LOW);
  }
}

//////////////////////////////////////////////////////////////////////

void Enviar() {

 if (Ethernet.begin(mac) == 0) {
   Serial.println("Failed to configure Ethernet using DHCP");
   // no point in carrying on, so do nothing forevermore:
   for(;;)
     ;
 }
 // give the Ethernet shield a second to initialize:
 delay(1000);
 Serial.println("connecting...");

 // if you get a connection, report back via serial:
 if (client.connect(server, 1830)) {
   Serial.println("connected");
   // Make a HTTP request:
   client.print("GET /logger/prueba_arduino.php?id_arduino=");
   client.print(1);
 
  client.print("&temp=");
   client.print(temp,DEC);
    client.print("&hum=");
   client.print(hum,DEC);
     client.print("&vel_v=");
   client.print(vel_v,DEC);
     client.print("&dir_v=");
   client.print(dir_v,DEC);
     client.print("&bar=");
   client.print(bar,DEC);
     client.print("&rad=");
   client.print(rad,DEC);
     client.print("&lluv=");
   client.print(lluv,DEC);
     client.print("&lluv_ac=");
   client.println(lluv_ac,DEC);
 }
 else {
   // kf you didn't get a connection to the server:
   Serial.println("connection failed");
 }

 // if there are incoming bytes available
 // from the server, read them and print them:
 int i =0;
 if (client.available()) {
   for(i=1;i<=12;i++){
     delay(5);
   char c = client.read();
   Serial.print(c);
 }
 }

 // if the server's disconnected, stop the client:
 if (!client.connected()) {
   Serial.println();
   Serial.println("disconnecting.");
   client.stop();

 }
 delay(5000);
}

//////////////////////////////////////////////////////////////////////

//Función de Guardar datos leídos
void Logger()

{sprintf(FileName, "MT%.2d%.2d%.2d.csv", t[7], t[6], t[5]); //ddmmaa
delay(5);
Serial.println(FileName);
  if (!myFile.open(FileName, O_RDWR | O_CREAT | O_AT_END)) {
   sd.errorHalt("ERROR SD");
   return;
 }

        digitalWrite(18, HIGH);
         myFile.print(t[4]);
         myFile.print(",");

         //    TEMP (°F)
            myFile.print(temp);
            myFile.print(",");
         //   HUM (%)
           myFile.print(hum);
           myFile.print(",");
         //    VELV (mph)
            myFile.print(vel_v);
            myFile.print(",");
         //    DIRV (°;N=0)
           myFile.print(dir_v);
           myFile.print(",");
         //   BAR (in)
           myFile.print(bar);
           myFile.print(",");
         //    LLUVIA
           myFile.print(lluv_ac);
           myFile.print(",");
         //    RAD (W/m^2)
           myFile.println(rad);
         //
           myFile.close();
           delay(5);
           digitalWrite(18, LOW);

}

//////////////////////////////////////////////////////////////////////

void loop(){
 LeerFH();
 delay(10);
 if(Min<t[3]){
 Min=t[3];
 LeerSe();
 Logger();
 Enviar();
}
delay(25000);
}



billroy

Juggling big libraries is always a treat.

It appears you are using DHCP to get an IP address for the Ethernet shield.  This pulls in a bunch of code to handle the DHCP transactions.

I found in a recent project that providing a fixed IP address for Ethernet.begin() dropped the DHCP code out of my sketch and saved the space I needed to make it fit.  It might work for you.

Good luck with your project,

-br


CrossRoads

If you can't shrink, you can move up to a '1284P based board, 128K flash, 16K SRAM

'ATMega1284P Duemilanova-style board.  www.crossroadsfencing.com/BobuinoRev17/
Schematic   PL for the ATMega1284P Thru PCB

Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Firstly, WDvalenz can you please edit your first post and place your code with in code tags so I can read it clearly.
You'll notice there is a smiley in your ethernet section as a result of not using code tags.

Secondly, from what I see in your function 'LeerSe()' you have in there the following;
Code: [Select]

void LeerSe() {
...
if(d[11]*d[12]*d[13]==0){
      delay(1000);
      LeerSe();
    }
...
if(bar<0||temp<0){
    LeerSe();
    }
}


To me it appears you are calling the function from within itself a few times, I don't think it is wise to do so.

Also, please think about commenting your code, it will help you and it will help us.

Paul

wdvalenz

#4
Feb 18, 2013, 08:59 pm Last Edit: Feb 18, 2013, 11:35 pm by CrossRoads Reason: 1
I made that, I am trying to use recursiveness, when the reading is not property done then I try to read once again.

I changed the code now I am not using DHCP to get the ip adress, the code is smaller now but I am having a problem as the funtion Logger seems to "stop" the process is I coment the line it works perfectly but whe I want to try adding the Logger it does nothing.
(Code tags added by moderator)
Code: [Select]


// 19-02-13
// "logger+cliente" para estación meteorológica Davis para Arduino
// con microcontrolador Atmel ATmega328

// Se usa un ethernet shield con tarjeta SD 4GB
// La estación meteorológica se conecta a los pines 3 y 5
// leds indicadores en los pines 18 y 19
// Puerto serial para revisar estado (debug)

//incluir librerías
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SPI.h>
#include <SoftwareSerial.h>

// Tarjeta SD
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile myFile;
SdFat sd;
#define error(s) error_P(PSTR(s))


SoftwareSerial Davis(3, 5); // RX, TX
int Min=-10;
int Hr=99;
int t[50]={-1};
int d[100];
int i=1;
char c[33];
char FileName[13];

  float temp;
  float hum;
  float vel_v;
  float dir_v;
  float bar;
  float lluv;
  float lluv_ac;
  float rad;

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x41, 0xF9 };
byte ip[] = { 192,168,8,162};
byte server[] = {190,147,203,25}; // Direccion ip del servidor

EthernetClient client;

void setup()
{pinMode(10, OUTPUT);
 pinMode(18, OUTPUT);
 pinMode(19, OUTPUT);
 Davis.begin(19200);
 Ethernet.begin(mac, ip);
 Serial.begin(9600);
 if (!sd.begin(4, SPI_FULL_SPEED)) sd.initErrorHalt();
 //Serial.println(" start ");
 delay(1000);
}

//////////////////////////////////////////////////////////////////////

void LeerSe()

{ digitalWrite(19, HIGH);
 Davis.println("LOOP 1");
 delay(10);
 
  for (i=1;i<=50;i++)//Davis.available())
  {   d[i]=Davis.read();
      delay(10);
  }
   Davis.flush();
   i=1;
   
   temp=0.1*(d[12+3]*256+d[11+3]);
   temp=5*(temp-32)/9;
   hum=(d[13]);
   vel_v=0.44704*d[16];
   dir_v=d[18];
   bar=0.001*(d[10]*256+d[9]);
   lluv=0.001*(d[49]*256+d[46]);
   lluv_ac=0.001*(d[49]*256+d[46]);
   rad=0.1*(d[47]*256+d[46]);
   
   //if(bar<0||temp<0||rad>1000){
  // delay(20);
   //LeerSe();
  // }
  // else{

   Serial.println(" DATOS LEIDOS ");
//Serial.print("temp=");
//Serial.println(temp,DEC);
//Serial.print("hum=");
//Serial.println(hum,DEC);
//Serial.print("vel_v=");
//Serial.println(vel_v,DEC);
//Serial.print("ve_v=");
//Serial.println(dir_v,DEC);
//Serial.print("bar=");
//Serial.println(bar,DEC);
//Serial.print("lluv=");
//Serial.println(lluv,DEC);
//Serial.print("lluv_ac=");
//Serial.println(lluv_ac,DEC);
//Serial.print("dir_v=");
//Serial.println(dir_v,DEC);
//Serial.print("rad=");
//Serial.println(rad,DEC);

   delay(50);
   //}
   
   digitalWrite(19, LOW);
}


//////////////////////////////////////////////////////////////////////

void LeerFH()
{digitalWrite(18, HIGH);
 Davis.println("GETTIME");
 delay(5);
 t[3]=0;
  for(i=1;i<=8;i++) // (Davis.available())
   {
    t[i]=Davis.read();
    delay(10);
    }
   Davis.flush();
  i=1; // reiniciar el contador
  t[7]=t[7]-100; //ajuste al año
  if(t[3]<0||t[3]>59||t[4]<0||t[4]>23||t[5]<1||t[5]>31||t[6]<1||t[6]>12||t[7]<0||t[7]>100)
  {delay(10);
  LeerFH();
   }
  else{
  Serial.print("Fecha y hora=");
  Serial.print(t[7]+2000);
  Serial.print("-");
  Serial.print(t[6]);
  Serial.print("-");
  Serial.print(t[5]);
  Serial.print(" ");
  Serial.print(t[4]);
  Serial.print(":");
  Serial.print(t[3]);
  Serial.print(":");
  Serial.println(t[2]);
  delay(10);
  digitalWrite(18, LOW);
  }
}

//////////////////////////////////////////////////////////////////////

//Función de Guardar datos leídos

void Logger()

{sprintf(FileName, "MT%.2d%.2d%.2d.csv", t[7], t[6], t[5]); //ddmmaa
delay(5);

  if (!myFile.open(FileName, O_RDWR | O_CREAT | O_AT_END)) {
   sd.errorHalt("ERROR SD");
   return;
 }

        digitalWrite(18, HIGH);
         myFile.print(t[4]);
         myFile.print(",");

         //    TEMP (°F)
            myFile.print(temp);
            myFile.print(",");
         //   HUM (%)
           myFile.print(hum);
           myFile.print(",");
         //    VELV (mph)
            myFile.print(vel_v);
            myFile.print(",");
         //    DIRV (°;N=0)
           myFile.print(dir_v);
           myFile.print(",");
         //   BAR (in)
           myFile.print(bar);
           myFile.print(",");
         //    LLUVIA
           myFile.print(lluv_ac);
           myFile.print(",");
         //    RAD (W/m^2)
           myFile.println(rad);
         //
           myFile.close();
           delay(5);
           Serial.print("almacenados en ");
           Serial.println(FileName);
           digitalWrite(18, LOW);

}

//////////////////////////////////////////////////////////////////////


void Enviar()
{
 ///////
     digitalWrite(18, HIGH);
   Ethernet.begin(mac, ip);
   Serial.println("Conectando...");
delay(100);
 if (client.connect(server, 1830)) {
    Serial.println("Conectado");
    delay(1000);
   client.print("GET /logger/prueba_arduino.php?id_arduino=");
   
   
   
   client.print(1);
   client.print("&temp=");
   client.print(temp,DEC);
    client.print("&hum=");
   client.print(hum,DEC);
     client.print("&vel_v=");
   client.print(vel_v,DEC);
     client.print("&dir_v=");
   client.print(dir_v,DEC);
     client.print("&bar=");
   client.print(bar,DEC);
     client.print("&rad=");
   client.print(rad,DEC);
     client.print("&lluv=");
   client.print(lluv,DEC);
     client.print("&lluv_ac=");
   client.println(lluv_ac,DEC);
   //client.println(" HTTP/1.0");
   //client.println("User-Agent: Arduino 1.0");
   client.println();
   delay(10);
   client.flush();
    }
 ////////
//  i=1;
//  while (client.available()) {
//    c[i] = client.read();
//    Serial.print(c[i]);
//    i++;
//  }
   if (!client.connected()) {
   Serial.println("Datos no enviados.");
   delay(2000);
   client.stop();
   Enviar();
   delay(10);
 }
 client.stop();
digitalWrite(18, LOW);
}

//////////////////////////////////////////////////////////////////////

void loop(){
 LeerFH();
 if(Min!=t[3]){
   
 Serial.println(" ! ");
 LeerSe();
 //Logger();
 Enviar();
 Min=t[3];
 t[3]=-1;
}
delay(5000);
}

#5
Feb 19, 2013, 12:17 am Last Edit: Feb 19, 2013, 12:26 am by rockwallaby Reason: 1
@CrossRoads, thanks, some people just don't seem to read  :~

Quote
wdvalenz wrote:
I made that, I am trying to use recursiveness, when the reading is not property done then I try to read once again.

If it fails it will do it again and again and again until the Arduino runs out of memory for the stack.
You will need to change how you do this. Re-code it to have a retry loop which can be specified to retry a number of times, such as 3.
If it doesn't succeed you return an error code and let the user know and put the Arduino into a specified condition.

Another thing you can do to help reduce your code it to use integer instead of floating point variables.
Then at the display output, you format your data to represent floating point by dividing by a scale factor.
For example, you declare 'float hum', and I assume this is humidity right?
Humidity can be represented as 0 to 1000 as an integer with a 0.1% resolution. Then to display it, simply divide by ten to have it scaled 0.0% to 100.0%.

The difference is that you work with it as an integer during your program and that can significantly reduce your program size and the available processor ram used in calculations. I often keep sensor data as, what is called, raw, that is raw ADC format, so 0 to 1023 and then have the function that does the displaying do the necessary scaling into what is called engineering units.

So, to summerise, try to make as much of your data munching using variables with integer format where possible.

How does the Davis weather station present its data on the serial channel, as strings or binary or key/value pairs or what?
What are the delimiters used to separate the data values from the Davis weather station? Again, more information!

Again, your commenting is lacking, it takes more work for me to understand your program, and I don't want to guess, so please comment.

Please be much more specific when you mention errors, not just
Quote
but whe I want to try adding the Logger it does nothing

That means absolutely nothing to me, and like I said before, I don't want or need to waste my time guessing all the time, please be much more accurate and specific with how you write.

Paul

Jantje

Unless you are using the due board:
Replace your
Code: [Select]
Serial.println("[Your text]");
and
Code: [Select]
Serial.print("[Your text]");
by
Code: [Select]
Serial.println(F("[Your text]"));
and
Code: [Select]
Serial.print(F("[Your text]"));

Best regards
Jantje

Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

#7
Feb 19, 2013, 11:38 am Last Edit: Feb 19, 2013, 11:55 am by rockwallaby Reason: 1
Hi Jantje,

I haven't compiled the OP's code, but I wouldn't have thought it would exceed the memory of the UNO.
If he is, then I think it just comes down to unhealthy programming practice.

P.S. still loving working in Eclipse with the plug-in you made, working right now on my project, ah such bliss  :D

Tot,
Paul

I had a similar problem... it was easily solved by getting rid of a few 'serial print' commands. Don't keep them unless SUPER necessary. 

FTL

Jantje

rockwallaby

If he is, then I think it just comes down to unhealthy programming practice.

I do not agree it is a unhealthy programming practice. I like verbose information and there is nothing unhealthy about it. If you put all those strings in flash memory you quickly fill up the memory. Then avrdude will refuse to upload the program stating it is to big.
The F() macro was introduces around 1.0 to fix this problem and since then I have been using it intensively keeping verbose feedback and "small programs".


P.S. still loving working in Eclipse with the plug-in you made, working right now on my project, ah such bliss  :D

I'm working on a 1.5.x compatible version now. If you feel like testing read this blog http://blog.baeyens.it/#post0


I had a similar problem... it was easily solved by getting rid of a few 'serial print' commands. Don't keep them unless SUPER necessary. 

Using the F macro has nearly the same effect without the loss of the Serial.print feedback.

Best regards
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Quote
Jantje wrote and quoted:
Quote
Quote from: rockwallaby on 19 February 2013, 20:38:26
If he is, then I think it just comes down to unhealthy programming practice.

Quote
I do not agree it is a unhealthy programming practice. I like verbose information and there is nothing unhealthy about it. If you put all those strings in flash memory you quickly fill up the memory. Then avrdude will refuse to upload the program stating it is to big.
The F() macro was introduces around 1.0 to fix this problem and since then I have been using it intensively keeping verbose feedback and "small programs".


Sorry Jantje, I think you misunderstood, I did not mean using flash memory instead of ram was bad, rather that the code as presented by the OP was generally constructed using 'bad programming practices'.

Look through his code for a few minutes and I think you will agree, that firstly it is difficult to read and understand and with a lack of code commenting, but more importantly, he is using recursive calls back into the same function, as I pointed out to the OP some posts back.

I too like a degree of verboseness in terms of commenting my code.

Yes, putting constant data in flash memory can help and is generally a good idea, but I doubt it will help sort out the problems with the program as presented by the OP.

So, wdvalenz, can you let us know how you are progressing with this code?

Paul

P.S. I'll take a peek at your blog today with interest.

Jantje

Paul wdvalenz
I took a look at the first lines of code and I agree there is "room for code quality improvement"
I did not look at the code enough to see how the "room for code quality improvement" relates to "smaller code size".

From a general advice point of view: In the "learning by doing" mindset of Arduino I believe the best advise for the OP is to start using the F() macro. This allows the OP to get back on the road and (s)he will improve coding skills over time by doing more sketches.
The other way around: "improving coding skills first" will reduce the "doing"; which will reduce the "interest in the platform"; which will reduce the chances of "growing the Arduino community".

Best regards
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Nick_Pyner


I have been working to get my weather station connected to internet.

unfortunately it seems that the sketch it too big to be transfered to the Arduino UNO.

//incluir librerías
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SPI.h>
#include <SoftwareSerial.h>

  Davis.println("GETTIME");



You could be dead right, it is too big, that's the way it is, and the real answer is to move to a Mega.

I don't understand a word of your code but, fundamentally, it's the libraries that will put you over the edge.

Good luck with your project.

Go Up