code optimization help-Low memory available stability problems may occur..

Hi all,
I am using UNO and ethernet shield…and using sd card facility of ethernet shield …IDE is giving warning of
low memory available stability problems may occur…i searched on internet come to know that PROGMEM
And (F()) can be used to lessen the usage of memory …can anyone help me out in my code to be optimized…i also used sdFat library instead of SD…
This is my code:

#include "SdFat.h"
SdFat SD;
#include<SPI.h>
#include<Ethernet.h>
#include <SoftwareSerial.h> // Arduino IDE <1.6.6
#include <PZEM004T.h>
PZEM004T pzem1(4,5);  // RX,TX
PZEM004T pzem2(6,7);  // RX,TX
PZEM004T pzem3(8,9);  // RX,TX
static long v1,v2,v3,i1,i2,i3,p1,p2,p3,e1,e2,e3;
IPAddress ip1(192,168,1,1);
static char outVolt[20],outCurr[20],outPow[20],outEng[20],Finalstring[200];
byte mymac[6];
byte myip[4];
byte mynm[4];
byte mygw[4];
byte mydns[4];
byte server[4];
char sID[16] = "DSSS501";
static char s[16];
EthernetClient client;
void setup() {
 Serial.begin(9600);
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
  
  delay(2000);
  if(!SD.begin(4))Serial.println("SD fail");
  else Serial.println("SD ok");
  File fh=SD.open("nw_set.txt",FILE_READ);
  char netbuffer[32];
  if (!fh)
  {Serial.println("SD open fail");
  return;}
  int chpos=0;
  int lineno=0;
  while(fh.available())
  {
    char ch=fh.read();
    if(ch=='\n'){
      chpos=0;
      switch(lineno){
        case 0:
        if (getmac(netbuffer,mymac));//Serial.println(F("mac ok"));
        break;
        case 1:
        if (getip(netbuffer,myip));//Serial.println(F("ip ok"));
        break;
         case 2:
        if (getip(netbuffer,mynm));//Serial.println(F("sm ok"));
        break;
         case 3:
        if (getip(netbuffer,mygw));//Serial.println(F("gw ok"));
        break;
         case 4:
        if (getip(netbuffer,mydns));//Serial.println(F("dns ok"));
        break;
         case 5:
        if (getip(netbuffer,server));//Serial.println(F("server is ok"));
        break;
      }
        lineno++;
        
      }
      else if (ch=='\r'){
        //do nothing
      }
      else if(chpos<31){
        netbuffer[chpos]=ch;
        chpos++;
        netbuffer[chpos]=0;
      }
    }
    fh.close();


    int x;
    Serial.print("\r\nmac");
    for(x=0;x<6;x++){
     Serial.print(mymac[x],HEX);
      if(x<5); Serial.print(":");
    }
      Serial.print("\r\nip");
      for(x=0;x<4;x++){
      Serial.print(myip[x],DEC);
      if(x<3); Serial.print(".");
    }
      Serial.print("\r\nNM");
      for(x=0;x<4;x++){
       Serial.print(mynm[x],DEC);
      if(x<3); Serial.print(".");
    }
       Serial.print("\r\ngw");
      for(x=0;x<4;x++){
       Serial.print(mygw[x],DEC);
      if(x<3); Serial.print(".");
    }
         Serial.print("\r\ndns");
      for(x=0;x<4;x++){
      Serial.print(mydns[x],DEC);
      if(x<3); Serial.print(".");
    }
      Serial.print("\r\nserver");
     for(x=0;x<4;x++){
      Serial.print(server[x],DEC);
      if(x<3); Serial.print(".");
    }
  //Serial.println("\r\nStrating ethernet");
  Ethernet.begin(mymac,myip,mydns,mygw,mynm);
  //Serial.println(Ethernet.localIP());
  byte oct1 = myip[0];
  byte oct2 = myip[1];
  byte oct3 = myip[2];
  byte oct4 = myip[3];  
  sprintf(s, "%d.%d.%d.%d", oct1, oct2, oct3, oct4);
 // Serial.println(s); 
  Serial.println("connecting...");
  delay(5000);
  if (client.connect(server, 6666)) {
    Serial.println("connected");
  } else {    
     Serial.println("connection failed");
  }   

}

void loop() {


   if (client.connected()) {
   v1 = pzem1.voltage(ip1);
  if (v1 < 0.0) v1 = 0.0;
 i1 = pzem1.current(ip1);
  if(i1 >= 0.0){  }  
 p1 = pzem1.power(ip1);
  if(p1 >= 0.0){   }  
 e1 = pzem1.energy(ip1);
  if(e1 >= 0.0){  }
  Serial.println();


 v2 = pzem2.voltage(ip1);
  if (v2 < 0.0) v2 = 0.0;
  v2=v1+v2;
  i2 = pzem2.current(ip1);
  if(i2 >= 0.0){
    i2=i1+i2; }  
 p2 = pzem2.power(ip1);
  if(p2 >= 0.0){ 
  p2=p1+p2;  }
 e2 = pzem2.energy(ip1);
  if(e2 >= 0.0){     e2=e1+e2; }

  

 Serial.print("Meter reading:");
  v3 = pzem3.voltage(ip1);
  if (v3 < 0.0) v3 = 0.0;
  v3=v3+v2;
  sprintf(outVolt, "%lu", v3 );
  i3 = pzem3.current(ip1);
  if(i3 >= 0.0){
  i3=i3+i2;  
  sprintf(outCurr, "%lu", i3 );  
   }  
  p3 = pzem3.power(ip1);
  if(p3 >= 0.0){
  p3=p3+p2;
  sprintf(outPow, "%lu", p3 );
   }
  e3 = pzem3.energy(ip1);
  if(e3 >= 0.0){
  e3=e3+e2;
  sprintf(outEng, "%lu", e3 );
  }
  sprintf(Finalstring, "DevID:%s;IP:%s;Vtg:%s;Cur:%s;Pow:%s;Eng:%s",sID,s,outVolt,outCurr,outPow,outEng);
  client.println(Finalstring);
   delay(500);
   }
}


byte getmac(char* macbuf,byte* thismac){
  byte thislen=strlen(macbuf);
  byte thisoctet=1;
  thismac[0]=strtol(&macbuf[0],NULL,16);
  for(int x=0;x<thislen;x++){
    if(macbuf[x]==':'){
      thismac[thisoctet]=strtol(&macbuf[x+1],NULL,16);
      thisoctet++;
    }
  }
  if(thisoctet==6)return(1);
  else return(0);
}
byte getip(char* ipbuf,byte* thisip){
  byte thislen=strlen(ipbuf);
  byte thisoctet=1;
  thisip[0]=atoi(&ipbuf[0]);
  for(int x=0;x<thislen;x++){
    if(ipbuf[x]=='.'){
      thisip[thisoctet]=atoi(&ipbuf[x+1]);
      thisoctet++;
    }
  }
  if (thisoctet==4)return(1);
  else return(0);
}

I don’t see spectacular savings in this code, I do see errors like this:

if(x<3); Serial.print(".");

that first ; shouldn’t be there.

I suppose you have a good reason to reserve 280 bytes for these strings:

static char outVolt[20],outCurr[20],outPow[20],outEng[20],Finalstring[200];

Furthermore: there is no penalty to using whitespace, or to place statements on their own, separate line. It does make code a lot more readable. Your indentation is often off and that’s also confusing, press CTRL-T in the IDE to automagically fix that.

sorry Now auto formatted:

#include "SdFat.h"
SdFat SD;
#include<SPI.h>
#include<Ethernet.h>
#include <SoftwareSerial.h> // Arduino IDE <1.6.6
#include <PZEM004T.h>
PZEM004T pzem1(4, 5); // RX,TX
PZEM004T pzem2(6, 7); // RX,TX
PZEM004T pzem3(8, 9); // RX,TX
static long v1, v2, v3, i1, i2, i3, p1, p2, p3, e1, e2, e3;
IPAddress ip1(192, 168, 1, 1);
static char outVolt[20], outCurr[20], outPow[20], outEng[20], Finalstring[200];
byte mymac[6];
byte myip[4];
byte mynm[4];
byte mygw[4];
byte mydns[4];
byte server[4];
char sID[16] = "DSSS501";
static char s[16];
EthernetClient client;
void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);

  delay(2000);
  if (!SD.begin(4))Serial.println("SD fail");
  else Serial.println("SD ok");
  File fh = SD.open("nw_set.txt", FILE_READ);
  char netbuffer[32];
  if (!fh)
  { Serial.println("SD open fail");
    return;
  }
  int chpos = 0;
  int lineno = 0;
  while (fh.available())
  {
    char ch = fh.read();
    if (ch == '\n') {
      chpos = 0;
      switch (lineno) {
        case 0:
          if (getmac(netbuffer, mymac)); //Serial.println(F("mac ok"));
          break;
        case 1:
          if (getip(netbuffer, myip)); //Serial.println(F("ip ok"));
          break;
        case 2:
          if (getip(netbuffer, mynm)); //Serial.println(F("sm ok"));
          break;
        case 3:
          if (getip(netbuffer, mygw)); //Serial.println(F("gw ok"));
          break;
        case 4:
          if (getip(netbuffer, mydns)); //Serial.println(F("dns ok"));
          break;
        case 5:
          if (getip(netbuffer, server)); //Serial.println(F("server is ok"));
          break;
      }
      lineno++;

    }
    else if (ch == '\r') {
      //do nothing
    }
    else if (chpos < 31) {
      netbuffer[chpos] = ch;
      chpos++;
      netbuffer[chpos] = 0;
    }
  }
  fh.close();


  int x;
  Serial.print("\r\nmac");
  for (x = 0; x < 6; x++) {
    Serial.print(mymac[x], HEX);
    if (x < 5) Serial.print(":");
  }
  Serial.print("\r\nip");
  for (x = 0; x < 4; x++) {
    Serial.print(myip[x], DEC);
    if (x < 3) Serial.print(".");
  }
  Serial.print("\r\nNM");
  for (x = 0; x < 4; x++) {
    Serial.print(mynm[x], DEC);
    if (x < 3) Serial.print(".");
  }
  Serial.print("\r\ngw");
  for (x = 0; x < 4; x++) {
    Serial.print(mygw[x], DEC);
    if (x < 3) Serial.print(".");
  }
  Serial.print("\r\ndns");
  for (x = 0; x < 4; x++) {
    Serial.print(mydns[x], DEC);
    if (x < 3) Serial.print(".");
  }
  Serial.print("\r\nserver");
  for (x = 0; x < 4; x++) {
    Serial.print(server[x], DEC);
    if (x < 3) Serial.print(".");
  }
  //Serial.println("\r\nStrating ethernet");
  Ethernet.begin(mymac, myip, mydns, mygw, mynm);
  //Serial.println(Ethernet.localIP());
  byte oct1 = myip[0];
  byte oct2 = myip[1];
  byte oct3 = myip[2];
  byte oct4 = myip[3];
  sprintf(s, "%d.%d.%d.%d", oct1, oct2, oct3, oct4);
  // Serial.println(s);
  Serial.println("connecting...");
  delay(5000);
  if (client.connect(server, 6666)) {
    Serial.println("connected");
  } else {
    Serial.println("connection failed");
  }

}

void loop() {


  if (client.connected()) {
    v1 = pzem1.voltage(ip1);
    if (v1 < 0.0) v1 = 0.0;
    i1 = pzem1.current(ip1);
    if (i1 >= 0.0) {  }
    p1 = pzem1.power(ip1);
    if (p1 >= 0.0) {   }
    e1 = pzem1.energy(ip1);
    if (e1 >= 0.0) {  }
    Serial.println();


    v2 = pzem2.voltage(ip1);
    if (v2 < 0.0) v2 = 0.0;
    v2 = v1 + v2;
    i2 = pzem2.current(ip1);
    if (i2 >= 0.0) {
      i2 = i1 + i2;
    }
    p2 = pzem2.power(ip1);
    if (p2 >= 0.0) {
      p2 = p1 + p2;
    }
    e2 = pzem2.energy(ip1);
    if (e2 >= 0.0) {
      e2 = e1 + e2;
    }



    Serial.print("Meter reading:");
    v3 = pzem3.voltage(ip1);
    if (v3 < 0.0) v3 = 0.0;
    v3 = v3 + v2;
    sprintf(outVolt, "%lu", v3 );
    i3 = pzem3.current(ip1);
    if (i3 >= 0.0) {
      i3 = i3 + i2;
      sprintf(outCurr, "%lu", i3 );
    }
    p3 = pzem3.power(ip1);
    if (p3 >= 0.0) {
      p3 = p3 + p2;
      sprintf(outPow, "%lu", p3 );
    }
    e3 = pzem3.energy(ip1);
    if (e3 >= 0.0) {
      e3 = e3 + e2;
      sprintf(outEng, "%lu", e3 );
    }
    sprintf(Finalstring, "DevID:%s;IP:%s;Vtg:%s;Cur:%s;Pow:%s;Eng:%s", sID, s, outVolt, outCurr, outPow, outEng);
    client.println(Finalstring);
    delay(500);
  }
}


byte getmac(char* macbuf, byte* thismac) {
  byte thislen = strlen(macbuf);
  byte thisoctet = 1;
  thismac[0] = strtol(&macbuf[0], NULL, 16);
  for (int x = 0; x < thislen; x++) {
    if (macbuf[x] == ':') {
      thismac[thisoctet] = strtol(&macbuf[x + 1], NULL, 16);
      thisoctet++;
    }
  }
  if (thisoctet == 6)return (1);
  else return (0);
}
byte getip(char* ipbuf, byte* thisip) {
  byte thislen = strlen(ipbuf);
  byte thisoctet = 1;
  thisip[0] = atoi(&ipbuf[0]);
  for (int x = 0; x < thislen; x++) {
    if (ipbuf[x] == '.') {
      thisip[thisoctet] = atoi(&ipbuf[x + 1]);
      thisoctet++;
    }
  }
  if (thisoctet == 4)return (1);
  else return (0);
}

yes that values should remain same throughout the code

static char outVolt[20],outCurr[20],outPow[20],outEng[20],Finalstring[200];

any help??

(4 hours after posting the question)

akshay123: any help??

I am bit impatient there, and I apologize… :(

So you have a UNO with Ethernet, SD, a sensor library and 3 softserial interfaces and your out of memory.

Why not optimise in the direction of an ATMega2560 ?

Why didn’t you start using the F macro? That saves a bunch of RAM.

The main problem is that you are composing the FinalString and then printing it all at once. Instead, just print the pieces:

    client.print( F("DevID:") ); // one piece
    client.print( sID );

       ...

    v3 = pzem3.voltage(ip1);
    if (v3 < 0.0) v3 = 0.0;
    v3 = v3 + v2;
    client.print( F(";Vtg:") );       // another...
    client.print( v3 );

    i3 = pzem3.current(ip1);
    if (i3 >= 0.0) {
      i3 = i3 + i2;
    }
    client.print( F(";Cur:") );
    client.print( i3 );

       ...

Then you won’t need the FinalString array, saving 200 bytes. BTW, it doesn’t need to be a global, because you only used it in loop. :-/

Here is your sketch, modified to use the F macro for printing “double-quoted strings”. It also uses ‘.’ for single-character prints, instead of “.” (saves one byte of RAM for each usage):

#include "SdFat.h"
SdFat SD;
#include<SPI.h>
#include<Ethernet.h>
#include <SoftwareSerial.h> // Arduino IDE <1.6.6
#include <PZEM004T.h>

PZEM004T pzem1(4, 5); // RX,TX
PZEM004T pzem2(6, 7); // RX,TX
PZEM004T pzem3(8, 9); // RX,TX

static long v1, v2, v3, i1, i2, i3, p1, p2, p3, e1, e2, e3;
IPAddress ip1(192, 168, 1, 1);
byte mymac[6];
byte myip[4];
byte mynm[4];
byte mygw[4];
byte mydns[4];
byte server[4];
const char sID[] PROGMEM = "DSSS501";
EthernetClient client;

void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);

  delay(2000);
  if (!SD.begin(4))Serial.println( F("SD fail") );
  else Serial.println( F("SD ok") );
  File fh = SD.open("nw_set.txt", FILE_READ);
  char netbuffer[32];
  if (!fh)
  { Serial.println( F("SD open fail") );
    return;
  }
  int chpos = 0;
  int lineno = 0;
  while (fh.available())
  {
    char ch = fh.read();
    if (ch == '\n') {
      chpos = 0;
      switch (lineno) {
        case 0:
          if (getmac(netbuffer, mymac)); //Serial.println(F("mac ok"));
          break;
        case 1:
          if (getip(netbuffer, myip)); //Serial.println(F("ip ok"));
          break;
        case 2:
          if (getip(netbuffer, mynm)); //Serial.println(F("sm ok"));
          break;
        case 3:
          if (getip(netbuffer, mygw)); //Serial.println(F("gw ok"));
          break;
        case 4:
          if (getip(netbuffer, mydns)); //Serial.println(F("dns ok"));
          break;
        case 5:
          if (getip(netbuffer, server)); //Serial.println(F("server is ok"));
          break;
      }
      lineno++;

    }
    else if (ch == '\r') {
      //do nothing
    }
    else if (chpos < 31) {
      netbuffer[chpos] = ch;
      chpos++;
      netbuffer[chpos] = 0;
    }
  }
  fh.close();


  int x;
  Serial.print( F("\r\nmac") );
  printArrayTo( Serial, mymac, sizeof(mymac), ':' );

  Serial.print( F("\r\nip") );
  printArrayTo( Serial, myip, sizeof(myip), '.' );

  Serial.print( F("\r\nNM") );
  printArrayTo( Serial, mynm, sizeof(mynm), '.' );

  Serial.print( F("\r\ngw") );
  printArrayTo( Serial, mygw, sizeof(mygw), '.' );

  Serial.print( F("\r\ndns") );
  printArrayTo( Serial, mydns, sizeof(mydns), '.' );

  Serial.print( F("\r\nserver") );
  printArrayTo( Serial, server, sizeof(server), '.' );

  //Serial.println( F("\r\nStrating ethernet") );
  Ethernet.begin(mymac, myip, mydns, mygw, mynm);
  //Serial.println(Ethernet.localIP());

  
  Serial.println( F("connecting...") );
  delay(5000);
  if (client.connect(server, 6666)) {
    Serial.println( F("connected") );
  } else {
    Serial.println( F("connection failed") );
  }

}

void loop() {


  if (client.connected()) {

    Serial.print( F("Meter reading:") );

    v1 = pzem1.voltage(ip1);
    if (v1 < 0.0) v1 = 0.0;
    i1 = pzem1.current(ip1);
    if (i1 >= 0.0) {  }
    p1 = pzem1.power(ip1);
    if (p1 >= 0.0) {   }
    e1 = pzem1.energy(ip1);
    if (e1 >= 0.0) {  }


    v2 = pzem2.voltage(ip1);
    if (v2 < 0.0) v2 = 0.0;
    v2 = v1 + v2;
    i2 = pzem2.current(ip1);
    if (i2 >= 0.0) {
      i2 = i1 + i2;
    }
    p2 = pzem2.power(ip1);
    if (p2 >= 0.0) {
      p2 = p1 + p2;
    }
    e2 = pzem2.energy(ip1);
    if (e2 >= 0.0) {
      e2 = e1 + e2;
    }

    Serial.println();


    client.print( F("DevID:") );
    client.print( (const __FlashStringHelper *) sID );

    client.print( F(";IP:") );
    printArrayTo( client, myip, sizeof(myip), '.' );

    v3 = pzem3.voltage(ip1);
    if (v3 < 0.0) v3 = 0.0;
    v3 = v3 + v2;
    client.print( F(";Vtg:") );
    client.print( v3 );

    i3 = pzem3.current(ip1);
    if (i3 >= 0.0) {
      i3 = i3 + i2;
    }
    client.print( F(";Cur:") );
    client.print( i3 );

    p3 = pzem3.power(ip1);
    if (p3 >= 0.0) {
      p3 = p3 + p2;
    }
    client.print( F(";Pos:") );
    client.print( p3 );

    e3 = pzem3.energy(ip1);
    if (e3 >= 0.0) {
      e3 = e3 + e2;
    }
    client.print( F(";Eng:") );
    client.println( e3 );

    delay(500);
  }
}


void printArrayTo( Stream & out, byte *array, size_t size, char delim )
{
  for (size_t i = 0; i < size; i++) {
    // print one number
    out.print( *array++ );

    // print the delimiter, but not after the last byte
    if (i < size-1)
      out.print( delim );
  }
}

byte getmac(char* macbuf, byte* thismac) {
  byte thislen = strlen(macbuf);
  byte thisoctet = 1;
  thismac[0] = strtol(&macbuf[0], NULL, 16);
  for (int x = 0; x < thislen; x++) {
    if (macbuf[x] == ':') {
      thismac[thisoctet] = strtol(&macbuf[x + 1], NULL, 16);
      thisoctet++;
    }
  }
  if (thisoctet == 6)return (1);
  else return (0);
}


byte getip(char* ipbuf, byte* thisip) {
  byte thislen = strlen(ipbuf);
  byte thisoctet = 1;
  thisip[0] = atoi(&ipbuf[0]);
  for (int x = 0; x < thislen; x++) {
    if (ipbuf[x] == '.') {
      thisip[thisoctet] = atoi(&ipbuf[x + 1]);
      thisoctet++;
    }
  }
  if (thisoctet == 4)return (1);
  else return (0);
}

Notice that it uses a common function to print IP addresses and MACs:

void printArrayTo( Stream & out, byte *array, size_t size, char delim )
{
  for (size_t i = 0; i < size; i++) {
    // print one number
    out.print( *array++ );

    // print the delimiter, but not after the last byte
    if (i < size-1)
      out.print( delim );
  }
}

To use it, you pass in the Stream it should print to (e.g., client or Serial), and the array it should print. For example:

 Serial.print( F("\r\nmac") );
  printArrayTo( Serial, mymac, sizeof(mymac), ':' );

      ... or ...

    client.print( F(";IP:") );
    printArrayTo( client, myip, sizeof(myip), '.' );

The original sketch used 28050 bytes of program space and 1713 bytes of RAM.
The modified version uses 26560 bytes of program space and 1223 bytes of RAM (not tested!).

Plenty of room.

This is perfect One...Thanks alot Sir :)