Issue with indexing within Array

Hi All,

Having a really bizzarre issue with indexing an array. I've got an application where i'm writing to a BM71 bluetooth module over UART. This is my code:

for(int i=0; i<20; i++){
    info_data[i] = Serial1.read();
    Serial.print(info_data[i],HEX);
    Serial.print(" ");
  }
  Serial.println();
  
  for(int j=0; j<3 ; j++){
    Serial.print(info_data[j],HEX);
    Serial.print(" ");
  }

And the output is:

20:1:27.950 -> AA 0 E 80 1 0 1 6 1 1 45 73 21 10 8A 60 1 94 FF FF
20:1:27.950 -> 35 23 0 

Why does my code not correctly print the first three values in the array?

Because the code you posted cannot possibly compile?

Hi,
What is the format e lengh of the array info_data[i] ? Char, int, .........etc.

The above assumes that data are available to be read, which is not necessarily the case.

This does not explain your other problem(s).

This is a small snippet of the code. it complies fine hence the output!

"Why doesn't it work?" is a bad question because we can't see what you mean.

Issues may be that there are stray characters in the buffer from the bootup, incorrectly interpreting CR/LF from the serial monitor, etc.

You should post the entire program (a stripped down version that focuses on the error if the program is large), what you expected to get, and what you got instead. You are only showing us what you got and asking why it isn't right. That's like calling a mechanic that doesn't know you and asking him "what's wrong with my car?".

That's OK - I only posted a snippet of my answer.

bytes... I'll post full code for context


void setup() {
  // put your setup code here, to run once
  Serial1.begin(9600);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  byte info_req[] = {0xAA,0x00,0x01,0x01,0xFE};

  Serial1.write(info_req, sizeof(info_req)); 
  
  byte info_data[0];
  int msg_len = 0;

  for(int i=0; i<20; i++){
    info_data[i] = Serial1.read();
    Serial.print(info_data[i],HEX);
    Serial.print(" ");
  }
  Serial.println();

  for(int a = 0; a < 3 ; a++){
    Serial.print(info_data[a],HEX);
    Serial.print(" ");
  }

  Serial.println();
  delay(200);
}

Oops

Same problem. Read data only when Serial1.available() says that data are actually available.

Hi JaBa,

So my code does what I want it to do (for now) as i'm just trying to confirm comms over UART with my bluetooth module.

The message format back from the module is perfect and what im expecting according to the user manual so no errors there. The bytes in position 1 and 2 (0 and E) determine the length of the message. I just want to pull that information out so then i can read the messages back at the exact length, without those extra bytes on the end (the two FF at the end).

Different commands have different length messages, so i'd like to only read the desired amount of infomation, based on bytes 1 and 2.

I guess im confused as to why the values printed in the 2nd for loop are different, even though my code doesnt update any of the values in the info_data array!

Hope that clears things up :smile:

See reply #9

Ok that works, how do i go about making sure that array size changes dependent on the length of the messages coming through? Or how do i initialise it without giving it a fixed size?

Where to begin? There's too much going wrong here to even know where to begin.
It would appear to me that you are overflowing the info_data variable and just asking for everything to crash down around you.
I don't see HOW it's working. Unless you are starting the Arduino program and then triggering the device to send. Typically, one asks the Serial if there is anything to be read before one begins to read. if(Serial.available())
If you want to interpret the first two bytes as being a length, you could use something like:
int msgLen = (Serial.read()) * 256) + Serial.read()
or intmsglen = Serial.read() <<8+Serial.read().
It looks to me that because you don't ensure a specific starting point the entire content is shifted. You state that 0 and E are the first two bytes but in the output you listed they are the second and third. Or?

What works?

How long are the messages?

Answer: you don't! The array size is declared by you when you write the program and will absolutely NEVER change while that program runs.
What you MUST do is declare a receiving array (buffer) that is at least one byte larger than whatever you think you may ever receive. Typically, a 0 indicates "there is no more to read". Of course, that doesn't work for you if a zero really could be part of the received message.

Assuming that you will receive messages similar to what you have used so far, you would define your buffer as byte info_data[25];
Read all of the characters into that buffer, including the first two bytes that state how long the message truly is. Using that info, you can loop through the rest of the message and know where to stop because the message told you how long it was. Just remember that the first character of the message is in [2] because the lengh is in [0] and [1].

So you need to read the first three bytes of the message to find out how big to make the buffer.

  byte header[3];
  for (int i=0; i<3; i++) {
    // WARNING: assumes the data bytes have 
    // already arrived and are waiting in the buffer.
    header[i] = Serial1.read();
  }
  int length = header[1];
  length <<= 8;
  length += header[2];

  byte info_data[length];
  for (int i=0; i<length; i++) {
    // WARNING: assumes the data bytes have 
    // already arrived and are waiting in the buffer.
    info_data[i] = Serial1.read();
  }

Note: This assumes that the 'length' field does NOT include the length of the header.

Well, I'll be. I supposedly passed my Alzheimer test (negative) but I don't think I ever knew that you could dynamically create an array in Arduino like that. To be clear though, that array can't be resized unless it goes out of scope (dies) first, right?
Ok, maybe I should have failed. Now that I think about it, I have done that in a function before - declare an array based on a passed parameter. This age thing is getting the best of me!

You can't define the same name twice in the same scope. You could create a separate scope within the function and declare a separate array of a different size with the same name but that wouldn't be 'resizing' an array, it would be creating a separate array.

I have been told it is not part of the ISO C++ standard, but gcc supports it.