Global variable stuck in IF statement

Hello,
I use a Nodemcu and program it with the Aeduino IDE.
I have two global variables that I use in two IF statements. I can print the value of the variables in the IF statement, but not outside the IF statement.

Deze variabelen zijn global

type or paste code here

long mEAV = 0 ; //Actual use from grid	
long mEAT = 0 ; //Actual grid injection   	
//********LOOP********
void loop() 
{
 long tl = 0;                            // for reading values comming from smart meter
long tld =0;
if (Serial.available())                // if date from smart meter available
   {
      digitalWrite(LedTest,LOW);
      input = Serial.read();
      // --- 7 bits instelling ---       
      input &= ~(1 << 7);                                       
      buffer[bufpos] = input&127;          // Fill buffer up to and including a new line (\n)
      bufpos++;
      if (input == '\n')                            // We received a new line (data up to \n)
         {                                                               
            // 1-0:1.7.0 = Elektra actueel verbruik (DSMR v4.0)
            if (sscanf(buffer,"1-0:1.7.0(%ld.%ld*s" , &tl , &tld) >0 ) 
            {
                mEAV = tl * 1000 + tld;
                lcd.setCursor(0,2);
                lcd.print("mEAV = ");
                lcd.setCursor(8,2);
                lcd.print(mEAV);	//Here mEAV can be printed on LCD
             }              
            // 1-0:2.7.0 = Actual generated electricity (DSMR v4.0)
            // 1-0:2.7.0 = Elektra actueel teruglevering (DSMR v4.0)
            if (sscanf(buffer,"1-0:2.7.0(%ld.%ld*s" , &tl , &tld) >0  ) 
            {
                mEAT = tl * 1000 + tld ;
                lcd.setCursor(0,3);
                lcd.print("mEAT = ");
                lcd.setCursor(8,3);
                lcd.print(mEAT);	//Here mEAT can be printed on LCD 
                if (mEAT > 0)
                    {
                        digitalWrite (LedTeruglevering,LOW);
                    }
                else
                    {
                        digitalWrite (LedTeruglevering,HIGH);
                    }
            } 
            bufpos = 0;     
          }         // end of if input = 'n'
            
      digitalWrite(LedTest,HIGH);
      lcd.setCursor(0,0);
      lcd.print(mEAT);	//Here mEAT can NOT be printed on LCD
      lcd.setCursor(10,0);
      lcd.print(mEAV); 	//Here mEAV can NOT be printed on LCD 
   }           // end of (Serial.available())

//Apparently  mEAT and mEAV can only be printed in the "if (sscanf ....." statement, not //outside, although
//mEAT and mEAV are global variables, not local

That doesn't look possible, does it?

Interesting.

Now please post the entire sketch OR reduce that huge sketch you don't wanna publish to the barest minimum that illustrates this problem.

It's hard to be sure those code lines even execute. Have you tried throwing a few Serial.print statement ps in there to see the values of key variables and confirm the logical,flow through the sketch that they inform?

a7

It looks like an array out of bounds. Show all code please

Hello,
I left out the preceeding 140 lines (defining all the other variables and the Setup part) and only uploaded the "stubborn" part. The mEAT and mEAV values are printed on the LCD in the IF statements, but not outside. Therefore I can not use the values further in the program.

OK, here comes the whole load:

#include <ESP8266WiFi.h>
  #include <espnow.h>
  #include <LiquidCrystal_I2C.h>
  #include <Wire.h>                                     // Library for I2C communication
  #include <Ethernet.h>
  LiquidCrystal_I2C lcd(0x27, 20, 4);                   // set the LCD address to 0x27 for a 20 chars and 4 line display
  IPAddress ip(192,168,4,7);
  IPAddress server(192,168,4,4);
  EthernetClient client;
             // REPLACE WITH RECEIVER MAC Address
  uint8_t broadcastAddress1[] = {0x5C, 0xCF, 0x7F, 0x0F, 0x98, 0x6B};//mac adres ontvanger 1
  uint8_t broadcastAddress2[] = {0x5C, 0xCF, 0x7F, 0x10, 0x2F, 0xA4};//mac adres ontvanger 2
  char input;  // incoming serial data (byte)                                                        // incoming serial data (byte)
  #define BUFSIZE 200       // was 75 and not working
  char buffer[BUFSIZE];  //Buffer for serial data to find \n .                                              //Buffer for serial data to find \n .
  int LedTeruglevering = D0;                        // Led to indicate that PV generates surplus power GPIO 16 =D0 (near User button)
  int LedTest = D4;                        // Led to indicate that PV generates surplus power GPIO 2 =D4 (near D0 pin)
  int bufpos = 0;
  long I1 = 0; //Current fase R
  long I2 = 0; //Current fase S
  long I3 = 0; //Current fase T
  long mEAV = 0 ; //Actual use from grid
  long mEAT = 0 ; //Actual grid injection         
  long V = 0;  //Actual use from grid
  long T = 0;  //Actual grid injection
  
  int increaseLowThreshold = 130;                   // threshold to increase selfuse with small steps (120W)
  int increaseHighThreshold = 200;                  // threshold to increase selfuse with large steps (200W)
  int decreaseHighThreshold = 90;                   // threshold to decrease selfuse with small steps (decrease steps are larger than increase steps) (90W)
  int decreaseLowThreshold = 30;                    // threshold to quickly decrease selfuse (30W)
  int increaseSmallStep = 1;                        // 1% van 2000W = 20W >130-20=110
  int increaseLargeStep = 5;                        // 5% van 2000W = 100W > 210-100=110
  int decreaseLargeStep = -4;                       // 4% van 2000W = 80W >30+80=110
  int decreaseSmallStep = -1;                       // 1% van 2000W = 20W >90+20=110
  int Q1 = 0;                                       // procentual power for user Q1
  int Q2 = 0;                                       // procentual power for user Q2
  int Q3 = 0;                                       // procentual power for user Q3
  int Q4 = 0;                                       // for toekomstig gebruik
  int Step = 0 ;
  char Str1 [20];                                   // can send up to 20 characters to receivers ( intended for 4*20 LCD)
           // Structure example to send data
           // Must match the receiver structure
  typedef struct test_struct 
    {
      int Q1 ;                                      // procentual load of user 1
      int Q2 ;                                      // procentual load of user 2
      int Q3 ;                                      // procentual load of user 3
      int Q4 ;                                      // procentual load of user 4
      int mEAV ;                                    // value of electric consumption
      int mEAT ;                                    // value of electric injection
      int Step ;                                    // step up-down value
      //char Str1 [20]=("P1 Reader sending");         // can send up to 20 characters to receivers ( intended for 4*20 LCD)
     } test_struct;
 
// Create a struct_message called test to store variables to be sent****************************
  test_struct myData;
  unsigned long lastTime = 0;  
  unsigned long timerDelay = 500;  // send readings timer
//**********************************************************************************************
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) 
  {
     
      char macStr[18];
      //Serial.println("Packet to:");
      snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
            mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
      //Serial.println(macStr);
      //Serial.println(" send status: ");
      if (sendStatus == 0)
        {
            //Serial.println("Delivery success");
        }
      else
        {
            //Serial.println("Delivery fail");
        }
       
   }
 //***************SETUP******************************************************************
void setup() 
{
    Serial.begin(115200);
    // Set device as a Wi-Fi Station
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
   
    //Serial.print("nodemcu one to many :sender 4 ");
    //Serial.println("Sender MAC 5C CF 7F AC 73 FE");
    // Init ESP-NOW
    if (esp_now_init() != 0)
      {
        Serial.println("Error initializing ESP-NOW");
        return;
      }
    esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  
        // Once ESPNow is successfully Init, we will register for Send CB to
        // get the status of Transmitted packet
    esp_now_register_send_cb(OnDataSent);
  
  // Register peer
    esp_now_add_peer(broadcastAddress1, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
    esp_now_add_peer(broadcastAddress2, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
    lcd.init();                                                     // initialize the lcd
    lcd.backlight();                                                // turn on the backlight
    //Ethernet.begin(mac, ip);
    //delay(1000);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Nodemcu one to many");
    lcd.setCursor(0, 1);
    lcd.print("Sender P1 Reader 1");
    lcd.setCursor(0, 2);
    lcd.print("  04/04/2023  ");
    delay(2000);
    //lcd.clear();
    //lcd.setCursor(0, 0);
    //lcd.print("My IP address: ");
    //lcd.setCursor(0, 1 );
    //lcd.print(Ethernet.localIP());
                                                     // seriële verbinding over D7 en D8
    delay(1000);
    pinMode(LedTeruglevering, OUTPUT);
    pinMode(LedTest, OUTPUT);
    digitalWrite(LedTest,HIGH);
    digitalWrite (LedTeruglevering,HIGH);
    delay(1000);
    lcd.clear();
    ESP.wdtEnable(5000);
    //digitalWrite(LedTest,LOW);
    delay(1000);
}
 //******************************LOOP**********************************************************************************

void loop() 
{
   //digitalWrite(LedTest,(digitalRead(D9)));
 /* actualTime1 = millis();
  if(actualTime1 - PastTime > 500)
  {
    digitalWrite(LedTest,HIGH);
    if(actualTime1 - PastTime > 5000)
    {
      digitalWrite(LedTest,LOW);
      PastTime = millis();
    }
    
  }
  */
  //Serial.print("nodemcu one to many sender P1 Reader ");
  //Serial.println("Sender MAC 5C CF 7F AC 73 FE");

  
  //if ((millis() - lastTime) > timerDelay) 
  //{
   
    //lastTime = millis();
   //*********************************************************************************
   // reading values from smart meter
          
  long tl = 0;                                                    // for reading values comming from smart meter
  long tld =0;
  if (Serial.available())                                         // if date from smart meter available
     {
        digitalWrite(LedTest,LOW);
        input = Serial.read();
        // --- 7 bits instelling ---       
        input &= ~(1 << 7);                                        // --- 7 bits setting --- nu 8
        // Vul buffer tot en met een nieuwe lijn (\n)                                                                  
        buffer[bufpos] = input&127;                                 // Fill buffer up to and including a new line (\n)
        bufpos++;
        if (input == '\n')                                            // We received a new line (data up to \n)
           {                                                               
              // 1-0:1.7.0 = Elektra actueel verbruik (DSMR v4.0)
              if (sscanf(buffer,"1-0:1.7.0(%ld.%ld*s" , &tl , &tld) >0 ) 
              {
                  mEAV = tl * 1000 + tld;
                  //lcd.setCursor(0,2);
                  //lcd.print("mEAV = ");
                  //lcd.setCursor(8,2);
                  //lcd.print(mEAV);
                  //lcd.setCursor(8,3);
                  //lcd.print("     ");
              }                                                            // 1-0:2.7.0 = Actual generated electricity (DSMR v4.0)
              // 1-0:2.7.0 = Elektra actueel teruglevering (DSMR v4.0)
              if (sscanf(buffer,"1-0:2.7.0(%ld.%ld*s" , &tl , &tld) >0  ) 
              {
                  mEAT = tl * 1000 + tld ;
                  //lcd.setCursor(8,2);
                  //lcd.print("     ");
                  //lcd.setCursor(0,3);
                  //lcd.print("mEAT = ");
                  //lcd.setCursor(8,3);
                 // lcd.print(mEAT);
                  if (mEAT > 0)
                      {
                          digitalWrite (LedTeruglevering,LOW);
                      }
                  else
                      {
                          digitalWrite (LedTeruglevering,HIGH);
                      }
              } 
              bufpos = 0;     
            }         // end of if input = 'n'
              
        digitalWrite(LedTest,HIGH);
        lcd.setCursor(0,0);
        lcd.print(mEAT);
        lcd.setCursor(10,0);
        lcd.print(mEAV);     
     }           // end of (Serial.available())
     
/*                 
// controlling power of users  ********************************************
// 1 determin Step ****************************************************
  Step=0;
  if (mEAT < decreaseLowThreshold)
      { 
        Step =decreaseLargeStep;
      }
  if (mEAT < decreaseHighThreshold)
      { 
        Step =decreaseSmallStep;
      }
  if (mEAT > increaseLowThreshold)
      { 
        Step =increaseSmallStep;
      }
  if (mEAT > increaseHighThreshold)
      { 
        Step =increaseLargeStep;
      }
  if (mEAT <= 0)
      {
        Step = -30;
      }
// 2 Determin percentages for the outputs                  
   if (Q2 <=0)
      {
         Q1=Q1+Step;
         Q2=0;
         Q3=0;
         Q4=0;
       }
             
    if (Q1>=100&& Q3<=0)
       {
          Q1=100;
          Q2=Q2+Step;
          Q3=0;
          Q4=0;
        }
    if (Q2>=100 && Q4<=0)
        {
           Q1=100;
           Q2=100;
           Q3=Q3+Step;
           Q4=0;
         }
    if (Q3>=100)
         {
            Q1=100;
            Q2=100;
            Q3=100;
            Q4=Q4+Step;
          }
    if (Q4>= 100)
          {
             Q4=100;
          }
    if(Q1<=0)
          {
             Q1=0;
             Q2=0;
             Q3=0;
             Q4=0;
           }
// Send out the information to te loads        
   esp_now_send(0, (uint8_t *) &myData, sizeof(myData));          // Send message via ESP-NOW    
   myData.Q1 = Q1;
   myData.Q2 = Q2;
   myData.Q3 = Q3;
   myData.Q4 = Q4;
   myData.mEAV = mEAV;
   myData.mEAT = mEAT;
   myData.Step = Step;
    //myData.Str1[20] = Str1[20];
   
       
  if (mEAV > 5)       // comment for use              
     {
        lcd.setCursor(0, 0);
        lcd.print ("                   ");
        lcd.setCursor(0, 0);
        lcd.print ("Verbruik = ");
        lcd.setCursor(11,0);
        lcd.print (mEAV);
        //lcd.setCursor(19, 0);
        //lcd.print ("W");
     }
       // Levering aan net > 10W
  if (mEAT > 5 ) 
     {
        lcd.setCursor(0, 0);
        lcd.print ("                   ");
        lcd.setCursor(0, 0);
        lcd.print ("Injeksie = ");
        lcd.setCursor(14,0);
        lcd.print (mEAT);
        //lcd.setCursor(19, 0);
        //lcd.print ("W");
     }
  if (mEAT < 5 && mEAV < 5) 
     {
        lcd.setCursor(0, 0);
        lcd.print ("                   ");
        lcd.setCursor(0, 0);
        lcd.print (" Energie Neutraal");
                  
      }

  if (mEAT >5)                                                    //10 for use, 100 for debugging
      {
         digitalWrite(LedTeruglevering, LOW); 
      }
  else 
      {
         digitalWrite(LedTeruglevering, HIGH); 
      }

          // lijn 1
          /*lcd.setCursor(0, 1);
          lcd.print ("                   ");
          lcd.setCursor(0,1);                                                 
          lcd.print("Step"); 
          lcd.setCursor(5,1);
          lcd.print(Step);
          lcd.setCursor(8,1); 
          lcd.print("%");
          lcd.setCursor(9,1);
          */ //lijn2
          /*lcd.setCursor(0, 2);
          lcd.print ("                   ");
          lcd.setCursor(0,2);                                               
          lcd.print("USR1");
          lcd.setCursor(5,2);                                                
          lcd.print(Q1);
          lcd.setCursor(8,2);                                               
          lcd.print("%");
          lcd.setCursor(10,2);                                               
          lcd.print("USR2");
          lcd.setCursor(15,2);                                                
          lcd.print(Q2);
          lcd.setCursor(18,2);                                               
          lcd.print("%");
          //lijn3
          lcd.setCursor(0, 3);
          lcd.print ("                   ");
          lcd.setCursor(0,3);                                               
          lcd.print("USR3");
          lcd.setCursor(5,3);                                                
          lcd.print(Q3);
          lcd.setCursor(8,3);                                               
          lcd.print("%");
          lcd.setCursor(10,3);                                               
          lcd.print("USR4");
          lcd.setCursor(15,3);                                                
          lcd.print(Q4);
          lcd.setCursor(18,3);                                               
          lcd.print("%");
   */
}   // einde Loop    

The ONLY thing keeping you from writing past the end of buffer is the number of characters you receive from the serial port before receiving a '\n'. Once you overwrite the end of the buffer you may see all kinds of weirdness.

You might have just cut out the commented stuff, never mind.

On a tiny window just now but here

I suggest you to add like this

        buffer[bufpos] = input&127;                                 // Fill buffer up to and including a new line (\n)
        bufpos++;
        buffer[bufpos] = '\0';

so that buffer is always a well terminated string of characters.

It may have nothing to do with anything. Peephole stuff.

a7

And he should explicitly CHECK bufpos, to ensure it does not get incremented past the end of the buffer...

1 Like

What is the purpose of buffer[bufpos] = '\0'; ?
In the original software, the buffer was only 75 long, causing the program to "fall over":
the Nodemcu cut out and started anew, probably because data from the buffer overan program memory. I experimented with several lenghts and 200 is ok. At 125, it falls over.
I'll give your suggestion a try.

C string terminator
Are you not known about it?

@Brunovlaanderen
may be my library is of help:

https://werner.rothschopf.net/microcontroller/202112_noiasca_smartmeter.htm

Adding buffer[bufpos] = '\0' did not solve the problem.
Expierienced another strange problem:
In this form, lines 2 and 3 are printed on the LCD, but if I uncomment the code to print on line 0, nothing appears on the LCD!

   if (sscanf(buffer,"1-0:1.7.0(%ld.%ld*s" , &tl , &tld) >0 ) 
              {
                  mEAV = tl * 1000 + tld;
                  lcd.setCursor(0,2);
                  lcd.print("mEAV = ");
                  lcd.setCursor(8,2);
                  lcd.print(mEAV);
                  //lcd.setCursor(8,3);
                  //lcd.print("     ");
              }                                                            // 1-0:2.7.0 = Actual generated electricity (DSMR v4.0)
              // 1-0:2.7.0 = Elektra actueel teruglevering (DSMR v4.0)
              if (sscanf(buffer,"1-0:2.7.0(%ld.%ld*s" , &tl , &tld) >0  ) 
              {
                  mEAT = tl * 1000 + tld ;
                  //lcd.setCursor(8,2);
                  //lcd.print("     ");
                  lcd.setCursor(0,3);
                  lcd.print("mEAT = ");
                  lcd.setCursor(8,3);
                  lcd.print(mEAT);
                  if (mEAT > 0)
                      {
                          digitalWrite (LedTeruglevering,LOW);
                      }
                  else
                      {
                          digitalWrite (LedTeruglevering,HIGH);
                      }
              } 
              bufpos = 0;     
            }         // end of if input = 'n'
              
        digitalWrite(LedTest,HIGH);
        //lcd.setCursor(0,0);
        //lcd.print(mEAT);
        //lcd.setCursor(10,0);
        //lcd.print(mEAV);     

Hello,
After multiple changes to the code without result, I picked another P1 reader software as the base for my project. Thanks for your responses.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.