Constant byte array changes value during run time

Hi folks,
I am trying to communicate with a solar inverter that expects a query string[14] like this:

The sketch below starts normally (altough not yet receiving any correct answer) but I was surprised to notice it appears to start sending a different string after a while. Follows part of the Serial Monitor log as an image to prevent non-readable codes interference:

At 14:40:14.328 it sent the query message OK as shown in Hexa and ASCII in following line. It got no answer at all and imediately printed the five values supposedly calculated with the unreceived answer.
About five seconds after Tmp print it queried again at 14:40:19.375 in Hex and some millis after in ASCII acompanied by two repetitions of query wich I don’t know how they appeared. Anyway, the query message is still ok.
Some 100 ms later it seems to get an answer (wrong again) and the five computed values.
Then, at 14:40:24.546 I was surprised by a modified “constant” message! The four initial bytes are correct but from fifth on they got corrupted. Can a variable declared as a constant change its value? Prior versions of the sketch used just a byte array, I changed to a const byte array precisely to avoid any change.
Of course there are other issues yet wit my code, but if I can’t keep at least the query message fix I’ll be in deep trouble.
I’d greatly appreciate any help, follows my sketch.

  Inicializa duas portas seriais, a do monitor e a do HC-12 nas linhas 2(RX) e  3(TX);
  A cada 10 segundos envia a mensagem F2 FE 12 12 D6 E9 1B 00 00 40 00 08 CF 65 pelo
  monitor junto com minha assinatura, em seguida manda a mesma mensagem pelo HC-12
  e aguarda resposta durante 20 mseg.

#include <SoftwareSerial.h>
SoftwareSerial HC12Serial(2, 3); //RX, TX

void setup()
  // initialize both serial ports:
  Serial.begin(9600);         //monitor
  HC12Serial.begin(9600);     //HC12

void loop()  //  <------sent msg echo------->
{            //  F2FE1212D6E91B0000400008CF65<-------received data------>
  byte rcvd[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 28 bytes
  word data[7];//                            0E01597402B7406B000008F414B4     7 16-bit words
  bool flag = false;//                       Vdc,Vac,Adc,<-Wx10-->Wac,Tmp
  int i;
  const byte message[] = {0xF2, 0xFE, 0x12, 0x12, 0xD6, 0xE9, 0x1B, 0x00, 0x00, 0x40, 0x00, 0x08, 0xCF, 0x65};
  for (i = 0; i < 14; i++)  {Serial.print(message[i], HEX); Serial.print(" ");}; Serial.println();
  Serial.write(message, sizeof(message)); Serial.println();
  HC12Serial.write(message, sizeof(message));
//delay(100);  //delay to allow host procesing
  if (HC12Serial.available()) 
    for (i = 0; i < 28; i++)  {Serial.print(rcvd[i], HEX); Serial.print(" ");};
    for(i=14; i<28; i=i+2) {data[i]=256*rcvd[i]+rcvd[i+1]; Serial.print(data[i]); Serial.print(" ");};
    float Vdc=1.0*data[0]/100;
    float Vac=1.0*data[1]/100;
    float Adc=1.0*data[2]/100;
    float Wh =10.0*data[3];
    float Wac=1.0*data[5]/10;
    float Tmp=data[6]/100;
    float Aac=Wac/Vac;
    float Wdc=Vdc*Adc;
    float Eff=100*Wac/Wdc; 
    Serial.print("Vdc="); Serial.println(Vdc);
    Serial.print("Vac="); Serial.println(Vac);
    Serial.print("Adc="); Serial.println(Adc);
    Serial.print("Eff="); Serial.println(Eff);
    Serial.print("Tmp="); Serial.println(Tmp);
    for (i = 14; i < 28; i = i + 2) {
      data[i] = 256 * rcvd[i] + rcvd[i + 1];
      Serial.print(" ");

You are exceeding the bounds of both the data and rcvd arrays.

< edit >
Looking at it a bit longer, you are staying within bound of the rcvd array, but the out of bounds write to data is likely what is corrupting the message array (all depends on exactly where the compiler is storing the variables).


I would set the timeout higher, like 10 milliseconds instead of 1 millisecond. One millisecond is barely enough time to receive a single character at 9600.

if (HC12Serial.available())
You could wait for 28 characters to arrive before reading:
if (HC12Serial.available(28))

  float Vdc = 1.0 * data[0] / 100;
  float Vac = 1.0 * data[1] / 100;
  float Adc = 1.0 * data[2] / 100;
  float Wh = 10.0 * data[3];
  float Wac = 1.0 * data[5] / 10;
  float Tmp = data[6] / 100;

You don’t need to multiply by 1.0 to get your ‘word’ upgraded to a ‘float’. You can do it in the divide:

  float Vdc = data[0] / 100.0;
  float Vac = data[1] / 100.0;
  float Adc = data[2] / 100.0;
  float Wh  = data[3] * 10.0;
  float Wac = data[5] / 10.0;
  float Tmp = data[6] / 100.0;

Wow, @jonhwasser, your clues are very much appreciated! Thanks a lot! I’ll implement them immediately, but I still am worried by that “constant” changing its value.

Oh, yes. Definitely change that to:

     data[(i-14)/2] = 256 * rcvd[i] + rcvd[i + 1];


for (int w = 0; w < 7; w++) {
      data[w] = 256 * rcvd[w*2+14] + rcvd[w*2+15];
      Serial.print(" ");


I thought using (1000) would set it to 1000 milliseconds (default value), am I wrong?

and then next line should iterate (i=0; i<14; i++) right?

I also could read the whole answer to check echo against message, that is, IF message keeps constant…

Oh, yes. Definitely change that to:

     data[(i-14)/2] = 256 * rcvd[i] + rcvd[i + 1];


for (int w = 0; w < 7; w++) {
      data[w] = 256 * rcvd[w*2+14] + rcvd[w*2+15];
      Serial.print(" ");

Geee… that was a VERY dumb mistake, thanks for pointing it @david_2018

I beg your pardon for my not so clear code formatting. I’ll try to adopt a more standard style.

It seems you hit the bull’s eye. I was the culprit. After correcting my gross error the message kept its original value forever. Thank you so much!

Unfortunately today the Sun is about to set and the inverted has gone asleep. Tomorrow I’ll try to found remaining errors. Thank you both again,

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