Arduino code optimisation - Low memory available, stability problems may occur.

Hi
I've a sketch for 3 current sensors, and it required too much memory

Could somebody help me with code optimization?

#include "EmonLib.h"
#include <UIPEthernet.h> //https://github.com/ntruchsess/arduino_uip Arduino Uno pins:
 10 = CS, 11 = MOSI, 12 = MISO, 13 = SCK
EnergyMonitor emon0;
EnergyMonitor emon1;
EnergyMonitor emon2;   
byte mac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
EthernetClient client;
char server[] = "www.emoncms.org";  
  float Irms0;
  float Irms1;
  float Irms2;

void setup()
{ 
  Serial.begin(9600);
  Ethernet.begin(mac);
  emon0.current(0, 67);
  emon1.current(1, 67);
  emon2.current(2, 67);
  int var;
  while(var < 3){
    Irms0 = emon0.calcIrms(1480);
    Irms1 = emon1.calcIrms(1480);
    Irms2 = emon2.calcIrms(1480);
   var++;}
//  Serial.print("IP Address        : ");
//  Serial.println(Ethernet.localIP());
//  Serial.print("Subnet Mask       : ");
//  Serial.println(Ethernet.subnetMask());
//  Serial.print("Default Gateway IP: ");
//  Serial.println(Ethernet.gatewayIP());
//  Serial.print("DNS Server IP     : ");
//  Serial.println(Ethernet.dnsServerIP());
}

void loop()
{
int var=0;
float total_power_i;
float cooker_i;
float hall_i;
float total_power_a;
float cooker_a;
float hall_a;
float total_power_at;
float cooker_at;
float hall_at;
int st;
int ft;

  while(var < 15)
  {
  st = millis();

  total_power_i = (emon0.calcIrms(1480)-0.25)*230;
  cooker_i = (emon1.calcIrms(1480)-0.25)*230;
  hall_i = (emon2.calcIrms(1480)-0.25)*230;

  ft = millis();
  float t=(ft-st)/3600000;
  total_power_a=total_power_a+total_power_i*t;
  cooker_a=cooker_a+cooker_i*t;
  hall_a=hall_a+hall_i*t;

  var++;
  }
  total_power_at=total_power_at+total_power_a;
  cooker_at=cooker_at+cooker_a;
  hall_at=hall_at+hall_a;

//  Serial.println(total_power);   
//  Serial.println(cooker);
//  Serial.println(hall);  

  if (client.connect(server, 80))
  {
//   Serial.println("-> Connected");
    client.print( F("GET /input/post.json?"));
    client.print(F("node=1&apikey=c9c87cxxxxxxxxxxxxxxxxxxxxd66d21&json={"));
    client.print("total_power_i:");
    client.print( total_power_i );
    client.print(",cooker_power_i:");
    client.print( cooker_i );
    client.print(",hall_i:");
    client.print( hall_i );
    client.print(",total_power_a:");
    client.print( total_power_a );
    client.print(",cooker_a:");
    client.print( cooker_a );
    client.print(",hall_a:");
    client.print( hall_a );
    client.print(",total_power_at:");
    client.print( total_power_at );
    client.print(",cooker_at:");
    client.print( cooker_at );
    client.print(",hall_at:");
    client.print( hall_at );
    client.print("}");    

        while (client.available()){
        char line = client.read();
        if ( line=='ok'){
          total_power_a=0;
          cooker_a=0;
          hall_a=0;
          Serial.println(F("Ok"));
           }
           else {
            Serial.println(F("failed_"));
            }
        }
            client.println( " HTTP/1.1");
    client.print( "Host: " );
    client.println(server);
    client.println( F("Connection: close"));
    client.println();
    client.println();
    client.stop();
  }
  else {
   // Serial.println(F("failed"));
  }

}

 

Sketch uses 24,620 bytes (80%) of program storage space. Maximum is 30,720 bytes.
Global variables use 1,671 bytes (81%) of dynamic memory,
leaving 377 bytes for local variables.
Maximum is 2,048 bytes.
Low memory available, stability problems may occur.

 

Edit - wrapped long lines - BT

Robert Wall's picture

Re: Arduino code optimisation - Low memory available, stability problems may occur.

I can see you have used the "F(...)" macro in places, but what else have you looked at and tried?
What about a macro or a function to calculate the power (the same code appears 3 times).
Why, in setup( ), are you getting the 3 currents, storing them in 3 separate variables, and then not using them? The offset removal filters in emonLib should not now need to be run to stabilise as the latest uses a different filter that's pre-initialised. You could at worst throw the returned values away and save 12 bytes of global variables. And if the offset isn't close to half-supply, tweak it in your version of emonLib.
You might, but probably won't if the compiler is doing its stuff, save some program memory by removing everything you don't need in emonLib. The same might apply to your Ethernet library also - that's undoubtedly the memory hog.
Are you still using Serial anywhere? (Is there a dependency in the Ethernet library that I don't know about?)

mel's picture

Re: Arduino code optimisation - Low memory available, stability problems may occur.

I can see you have used the "F(...)" macro in places, but what else have you looked at and tried?

I have tried to revise data type for variables, tried to place declaration of variables in different places, remove all serial prints (temporary i need them for debugging).

What about a macro or a function to calculate the power (the same code appears 3 times).

I can assume that this measure can save a lot of memory, but i'm not so advanced in programming to make functions. If somebody can help me with function or share his sketch it would be great.

Why, in setup( ), are you getting the 3 currents, storing them in 3 separate variables, and then not using them? The offset removal filters in emonLib should not now need to be run to stabilise as the latest uses a different filter that's pre-initialised. You could at worst throw the returned values away and save 12 bytes of global variables. And if the offset isn't close to half-supply, tweak it in your version of emonLib.

It seems that I'm using the latest version of EmonLib - https://github.com/openenergymonitor/EmonLib - last update in Jan 2014 and i still have problems. In the evening I will work on this part

You might, but probably won't if the compiler is doing its stuff, save some program memory by removing everything you don't need in emonLib. The same might apply to your Ethernet library also - that's undoubtedly the memory hog.

I'm not so advanced ))

Are you still using Serial anywhere? (Is there a dependency in the Ethernet library that I don't know about?)

I'm using serial.print for debugging. In production i will remove it.

My plan is to use 6 current sensors (currently I have only 3, and I'm waiting for another 3), but I'm not sure that it will be possible without specific function for measuring power.

Could you give me some tips how to do it?

Thanks

Robert Wall's picture

Re: Arduino code optimisation - Low memory available, stability problems may occur.

You won't save a lot of memory with a macro, again if the compiler is smart, you won't save any, but any saving will be useful if you have compiler warnings.

What saving do you see when you remove Serial? - Is it enough to get rid of the warning?

I don't think I will be able to find time to rewrite your sketch, which is what I think you want. I do think you should read some tutorials on C & C++ programming, because understanding and being able to create a function is one of the fundamental skills you need.

My bible for C is of course "Kernigan & Ritchie" http://www.amazon.co.uk/C-Programming-Language-2nd/dp/0131103628/ref=sr_.... This is the standard text book. The normal place I point people at who want to move up to C++ is http://www.relisoft.com/book/index.htm and that assumes you know C. Because the Arduino environment normally uses a very small subset of the language, neither are the best place for a beginner to start, nor are many of the other on-line tutorials. I'd still suggest you have both of those, and maybe Bruce Eckel's "Thinking in C++" http://www.planetpdf.com/developer/article.asp?ContentID=6634 available for reference.

However, there is this: http://www.me.umn.edu/courses/me2011/arduino/arduinoGuide.pdf which does look to be a good starting place for a beginner. It does not go as far as classes and methods that are used here, though.

As for wanting to have 6 current inputs - I think there is a risk that you might never succeed if you also have the Ethernet library. All I know for certain is that the NanodeRF sketches, which also use an Ethernet library, broke when an updated and larger JeeLib was used.

stuart's picture

Re: Arduino code optimisation - Low memory available, stability problems may occur.

Its the dynamic memory which the compiler is reporting problems with - don't forget this is only a warning - your code may be fine.

So try and remove any global variables - can the ethernet library be tweaked or does it have some options you can disable - that will also be using a memory "buffer" - can that be shrunk?

 

 try and merge all your client.print functions together to see if that helps - ensure you use the "F" macro as mentioned by Robert.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.