Arduino Forum

Using Arduino => Programming Questions => Topic started by: jim-yang on Sep 18, 2018, 09:49 pm

Title: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 09:49 pm
I was looking at Robin2's Serial input basics and trying to run the same tests he did, but I can't seem to get this code working. I made some slight modifications, but I don't think the modifications I made would affect it. If I uncomment my disptest function, it prints every element in the array(0-7) properly. In the Uno TX side, when writing the serial HEX is used in the Serial.print section, but shouldn't the monitor already know that due to the 0x prefix?

His test uses an Uno and a Mega to communicate, whereas I'm only using a UNO. I'm also using Visual Studio instead of the Arduino IDE.
I created an array to make sure I was displaying the contents within the array properly and it works fine.

Are my assumptions correct?

1. There should not be an issue with me using a Uno instead of a Mega to receive the data using the code from the example.

Since the RX is the Mega, but I am using the Uno instead. In the getting started section, the instructions both reference using the Arduino IDE and in both sections they use the same example, so I don't have to worry about the code not working because I'm using different devices right. I saw in a previous post that someone had issues because they were using Python 3 and the code was written for Python 2.7. Since they were using they are using two different devices to communicate, the code on one device was incorrect affected the other. Since I'm using only 1 device and the Serial Monitor, there shouldn't be an issue.

2. The Uno didn't run through the setup correctly.

I upload the code onto the Uno, and open the serial monitor. All that is displayed is Opening port and Port Open. Since it hasn't printed "Arduino is ready", this should mean that the setup function hasn't actually successfully ran yet? The only thing that happened is the serial communication is established via the 9600 baud rate.

3. Since the setup isn't finished, the data being entered is not being read.

I open the Serial monitor and enter my array into the Serial and press enter {0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}. The RX pin Blinks every time I press enter, but no output occurs. The Uno is receiving data from the serial monitor, but because of 2 and "Arduino is ready" isn't being printed it's not actually reading the data but just acknowledging it received data?

4. 2,3 are incorrect. Since the disptest function is displaying the values in the array of each element, and VS said the upload process has finished, everything is loaded properly.

If I uncomment the disptest function, the Serial Monitor output constantly shows me the values of the test array. which means that the setup did run successfully. Since the function is constantly printing the values of the test array, the loop is running perfectly fine. If I enter numbers into the Serial Monitor and press enter the RX lights up, but since it's not being read properly, the data isn't being stored correctly.

5. I'm not entering the array properly.
Currently I'm trying to enter the array as {0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}. This might not be the right way to enter the array? It's how the data is written in the code so I assumed it should be right. I've tried using [] and <> and ().

6. Edit and nothing happens.
I modified the code so that it only displays my test array if the newData is false, but by default it is and therefore will be displaying, but even if I enter data, newData is not changing to true so this means that recBytesWithStartEndMarkers is not working properly. The RX is still lighting up when I enter numbers into the Serial Monitor.

Code: [Select]
void loop()
{
recvBytesWithStartEndMarkers();
showNewData();
disparraycond();
}
void disparraycond()
{
while (newData == false)
{
disptest();
}
}


I looked at the recvBytesWithStartEndMarkers function, and I think it should work fine, but I'm not sure why it wouldn't.


Code: [Select]

const byte numBytes = 8;
byte test[numBytes] = { 1,2,3,4,5,6,7,8};
byte receivedBytes[numBytes]; //Entered into the Serial Monitor: {0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}
byte numReceived = 0;
boolean newData = false;


// The setup() function runs once each time the micro-controller starts
void setup()
{
Serial.begin(9600);
Serial.println("<Arduino is ready>");
}

// Add the main program code into the continuous loop() function
void loop()
{
recvBytesWithStartEndMarkers();
showNewData();
//disptest();
}
void disptest()
{
for (byte i = 0; i <= 7; i++)
{
Serial.print("Byte: "); Serial.println(i);
Serial.print("Value: "); Serial.println(receivedBytes[i], DEC);
}
}
void recvBytesWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
byte startMarker = 0x80;
byte endMarker = 0x40;
byte rb;


while (Serial.available() > 0 && newData == false) {
rb = Serial.read();

if (recvInProgress == true)
{
if (rb != endMarker)
{
receivedBytes[ndx] = rb;
ndx++;
if (ndx >= numBytes)
{
ndx = numBytes - 1;
}
}
else {
receivedBytes[ndx] = '\0'; // terminate the string
recvInProgress = false;
numReceived = ndx;  // save the number for use when printing
ndx = 0;
newData = true;
}
}

else if (rb == startMarker)
{
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
Serial.print("This just in ... ");
for (byte n = 0; n < numReceived; n++) {
Serial.print(receivedBytes[n], HEX);
Serial.print(' ');
}
Serial.println();
showGroupsOfBytes();
newData = false;
}
}

void showGroupsOfBytes() {
for (byte n = 0; n < numReceived; n++) {
Serial.print(receivedBytes[n], HEX);
Serial.print(' ');
if ((n + 1) % 5 == 0) {
Serial.println();
}
}
Serial.println();
}
Title: Re: Array entered not being read
Post by: AWOL on Sep 18, 2018, 09:58 pm
Quote
2. The Uno didn't run through the setup correctly.
How do you know this?
You don't wait for the string to be sent before calling loop()

Quote
//Entered into the Serial Monitor: {0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}
Are you saying you're sending nearly 50 bytes?
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 10:11 pm
2. My assumption is due to the fact that
Code: [Select]
Serial.println("Arduino is Ready"); is not is not displaying "Arduino is ready" in all the other tests, this string is always printed upon opening the Serial Monitor. So since it's not showing this time, I assume isn't properly set up.

When I run other examples, the Serial monitor always displays "Arduino is Ready" when I upload the code and open the serial Monitor. Wouldn't I want the string to be displayed before the loop, since it's only being initialized once. This way the string is displayed and then the loop is running and I can enter the array.

4. Unless I'm interpreting it wrong, I'm sending 8 hexadecimal elements? Each element is a byte, so the sum is 64 bytes, but it's only reading 8 bytes at a time?
Title: Re: Array entered not being read
Post by: AWOL on Sep 18, 2018, 10:19 pm
What are you actually typing into the serial monitor?
Is it the sequence of ASCII characters "{0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}"

That doesn't contain the start marker 0x80 (which doesn't have an ASCII representation, because ASCII only encodes 0 to 127 decimal or 0x00 to 0x7F), or the end marker 0x40 (which is the ASCII character '@')
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 10:22 pm
I was typing "{0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}" into the Monitor and pressing enter.
Ah I didn't notice, I thought 11111111 was 80 not 7F.
If I used decimal instead of hexadecimal it shouldn't have the same marker issue should it?
Isn't it just storing the element entered into a binary stream.
If I use {127,1,2,3,4,5,6,0}, I just need to change the start and end markers. that way 11111111 and 00000000 are the markers.
Title: Re: Array entered not being read
Post by: AWOL on Sep 18, 2018, 10:26 pm
Why not use '{' as the start marker, and '}' as the end?

Be aware that such a long string will not fit into eight bytes
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 10:34 pm
Why not use '{' as the start marker, and '}' as the end?

That's a really good point, I was trying to make the demo work. I was just trying to get the markers matched.

[
Be aware that such a long string will not fit into eight bytes
Am I misunderstanding, but I thought the elements in the array would be binary and not strings. Are you saying what I input into the Serial Monitor are actually strings?
Title: Re: Array entered not being read
Post by: AWOL on Sep 18, 2018, 10:39 pm
Not strings in the C sense of a null-terminated array, and yes, what is sent is binary (because that's all there is), but you are sending a '{' character, a '0' character, a 'x' character, '8' character, and so on.

There is no magical translation happening for you.
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 10:42 pm
I see, When I changed the markers it worked.
When I entered, {0x7B ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x7D}
The resultant display was
This just in ... 30 78 37 42 20 2C 30
30 78 37 42 20
2C 30



Code: [Select]
const byte numBytes = 8;
byte test[numBytes] = { 1,2,3,4,5,6,7,8};
byte receivedBytes[numBytes]; //Entered into the Serial Monitor: {0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}
byte numReceived = 0;
boolean newData = false;


// The setup() function runs once each time the micro-controller starts
void setup()
{
Serial.begin(9600);
Serial.println("<Arduino is ready>");
}


// Add the main program code into the continuous loop() function
void loop()
{
recvBytesWithStartEndMarkers();
showNewData();
//disparraycond();
}
void disparraycond()
{
while (newData == false)
{
disptest();
}
}
void disptest()
{
for (byte i = 0; i <= 7; i++)
{
Serial.print("Byte: "); Serial.println(i);
Serial.print("Value: "); Serial.println(test[i], DEC);
}
}
void recvBytesWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
byte startMarker = 0x7B;
byte endMarker = 0x7D;
byte rb;


while (Serial.available() > 0 && newData == false) {
rb = Serial.read();

if (recvInProgress == true)
{
if (rb != endMarker)
{
receivedBytes[ndx] = rb;
ndx++;
if (ndx >= numBytes)
{
ndx = numBytes - 1;
}
}
else {
receivedBytes[ndx] = '\0'; // terminate the string
recvInProgress = false;
numReceived = ndx;  // save the number for use when printing
ndx = 0;
newData = true;
}
}

else if (rb == startMarker)
{
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
Serial.print("This just in ... ");
for (byte n = 0; n < numReceived; n++) {
Serial.print(receivedBytes[n], HEX);
Serial.print(' ');
}
Serial.println();
showGroupsOfBytes();
newData = false;
}
}

void showGroupsOfBytes() {
for (byte n = 0; n < numReceived; n++) {
Serial.print(receivedBytes[n], HEX);
Serial.print(' ');
if ((n + 1) % 5 == 0) {
Serial.println();
}
}
Serial.println();
}
Title: Re: Array entered not being read
Post by: DKWatson on Sep 18, 2018, 10:44 pm
0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040
is not what you think it is. That is a stream of 47 bytes. The serial monitor is an ASCII terminal program dealing with characters. If, from within Arduino for example, you performed Serial.write(0x40) it would output the single byte.

Also, as bookmarks you're using one printable and one non-printable character. Make up your mind. If you're going to generate a data stream from a smart source capable of transmitting bytes instead of characters, use the ASCII codes for STX(2) and ETX(3) as does everybody else. If not, of course use anything you want, but they should both be printable, i.e. <= 0x7F.

WRT to your setup, 9600 baud is very slow, about 1ms per character, so your initial print takes about 16ms to complete. That's eons when compared to what you are doing next. Without testing, just throw a delay(15) in after the print statement to allow that function to complete.
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 11:12 pm
0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040
is not what you think it is. That is a stream of 47 bytes. The serial monitor is an ASCII terminal program dealing with characters. If, from within Arduino for example, you performed Serial.write(0x40) it would output the single byte.

Also, as bookmarks you're using one printable and one non-printable character. Make up your mind. If you're going to generate a data stream from a smart source capable of transmitting bytes instead of characters, use the ASCII codes for STX(2) and ETX(3) as does everybody else. If not, of course use anything you want, but they should both be printable, i.e. <= 0x7F.

WRT to your setup, 9600 baud is very slow, about 1ms per character, so your initial print takes about 16ms to complete. That's eons when compared to what you are doing next. Without testing, just throw a delay(15) in after the print statement to allow that function to complete.
So when you say that it's an ASCII terminal program dealing with characters, when I enter
{0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040}
it's reading

{doesn't exist, STX,2,RS,STX, LF,@, ( }

not (in decimal)

{128,2,80,48,2,32,16,64)

Cause this would technically be 9 bytes since 128 is 2 bytes since it overflows right?


Is this just a property of the Serial Monitor? Even if I use DEC instead of HEX, it'll always be reading them as characters? If I use a Visual Studio Form App to send a byte array of numeric values so that they come in as
{122, 30, 31, 32, 33, 34, 35, 65}  (DEC)
It'll still be read as
{Z, 0, 1, 2, 3, 4, 5, A} (HEX) and not the decimal or even binary

{0111 1010, 0001 1110, 0001 1111, 0001 0000, 0001 0001, 0001 0010, 0001 0011, 100 0001}

I remember reading about the delay but wasn't exactly sure how it affects the program. If I'm not actually printing something I don't need to worry about the delay?
HEX:DEC:BIN
80:128: 1 0000 0000
2: 2: 0000 0010
50: 80: 0101 0000
30:48: 0011 0000
2: 2: 0000 0010
20: 32: 00100000
10:16: 0001 0000
40:64:0100 0000
Title: Re: Array entered not being read
Post by: AWOL on Sep 18, 2018, 11:16 pm
Does this (http://www.asciitable.com/) make things clearer?
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 11:35 pm
Kind of? I understand the ASCII table, and what the numbers correspond to. What I wasn't aware of was that the Serial Monitor would read the inputs as ASCII Characters. What I'm not 100% clear of is

for example the same code with slight modifications

Code: [Select]

void recvBytesWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
byte startMarker = 65;
byte endMarker = 90;
byte rb;
byte comp;

while (Serial.available() > 0 && newData == false)
{
rb = Serial.read();
if (recvInProgress == true)
{
if (rb != endMarker)
{
receivedBytes[ndx] = rb;
ndx++;
if (ndx >= numBytes)
{
ndx = numBytes - 1;
}
}
else
{
recvInProgress = false;
numReceived = ndx;  // save the number for use when printing
ndx = 0;
newData = true;
}
}

else if (rb == startMarker)
{
recvInProgress = true;
}

for (byte x = 0; x <= 7; x++)
{
Serial.print("In Byte: ");
Serial.println(x);
Serial.print("Value: ");
Serial.println( receivedBytes[x],DEC);
}
Serial.println("///////////////////////////////////////////////");

}
}


If I input { 65, 50, 50, 50, 50, 50, 50, 90} into the serial monitor, is it reading
A. {A, 2, 2, 2, 2, 2, 2, Z}
or
B. { 65, 50, 50, 50, 50, 50, 50, 90}

Cause from what I understand now, It's reading it as A

Can I make it read actual integer like it reading { 65, 50, 50, 50, 50, 50, 50, 90} so example, receivedBytes[3] = 50 and not receivedBytes[3] = '2'

Title: Re: Array entered not being read
Post by: AWOL on Sep 18, 2018, 11:41 pm
Code: [Select]
byte startMarker = 65;
byte endMarker = 90;

I know that 65 is 0x41 is 'A', and 90 is 0x5A, so that should be 'Z' (?)

So - WHY NOT WRITE IT LIKE THAT?

Code: [Select]
byte startMarker = 'A';
byte endMarker = 'Z';


Anyway, I thought we'd agreed that start and end should be '{' and '}' ?
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 11:46 pm
Ah yes I forgot we agreed that it makes sense to make the markers {}

I was really just confused about the whole Serial Monitor being ASCII characters I forgot about that  :)

 Apologies

Since I really care about the other elements being actual numeric values I overlooked the Markers.
Code: [Select]
Title: Re: Array entered not being read
Post by: jim-yang on Sep 18, 2018, 11:54 pm
If I make {} my start and end markers, does that mean I have to type { {,2,3,4,5,6,}} into the Serial Monitor to set the End markers  as
Code: [Select]

byte startMarker = '{';
byte endMarker = '}'

Do I need to clear the array at the end of receiving? When I run this code, it gives me an odd display. Isn't the program just supposed to overwrite previous save instances?

input into the serial monitor: (A, 5, 6,7, 5, 3, 1, Z} [Enter]

Output:This just in ... 44 32 53 44 32 54 44

Input: (A, 4, 2, 6, 4, 2, 7, Z} [Enter]
Output: This just in ... 44 32 52 44 32 50 44




Code: [Select]
void recvBytesWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
byte startMarker = 'A';
byte endMarker = 'Z';
byte rb;
byte comp;

while (Serial.available() > 0 && newData == false)
{
rb = Serial.read();
if (recvInProgress == true)
{
if (rb != endMarker)
{
receivedBytes[ndx] = rb;
ndx++;
if (ndx >= numBytes)
{
ndx = numBytes - 1;
}
}
else
{
recvInProgress = false;
numReceived = ndx;  // save the number for use when printing
ndx = 0;
newData = true;
}
}

else if (rb == startMarker)
{
recvInProgress = true;
}



}
}
void showNewData() {
if (newData == true) {
Serial.print("This just in ... ");
for (byte n = 0; n < numReceived; n++) {
Serial.print(receivedBytes[n], DEC);
Serial.print(' ');
}
Serial.println();
newData = false;
}
}
Title: Re: Array entered not being read
Post by: jim-yang on Sep 19, 2018, 07:59 pm
0x80 ,0x02 ,0x50 ,0x30 ,0x02 ,0x20 ,0x10 ,0x040
is not what you think it is. That is a stream of 47 bytes. The serial monitor is an ASCII terminal program dealing with characters. If, from within Arduino for example, you performed Serial.write(0x40) it would output the single byte.
I think I see what you mean now. If I type in the Serial Monitor: A [enter] 1 [enter] 1 [enter] 1 [enter] 1 [enter] 1 [enter] 1 [enter] 1 [enter] Z [enter]. The output results in the ASCIII DEC and the resultant output is [49 49 49 49 49 49 49]. If I enter 2, it becomes 50.

What I'm confused about now is, if what you described applies to all serial communication. I think this is the issue I've ran into. In my windows form is the whole array like I was initially.

If I use serial communication to send the whole array over, the stream will still be very large and give me issues compared to me sending 1 byte at a time right?
Title: Re: Array entered not being read
Post by: DKWatson on Sep 20, 2018, 05:27 am
The serial link transmits (typically) 8-bit bytes. The link itself doesn't care what is in those bytes. It's up to the applications at either end to configure the stream such that what the transmitter sends is understood by the receiver. This is what is referred to as a protocol. As you are in control of both ends, you can devise any protocol you want. Bear in mind that hitting the <enter> key simply results in sending ASCII 10 (newline) or ASCII 13 (return) or some combination of the two. This does not have to be transmitted by you unless you choose. By convention, these codes are often used to signal the end of a transmission but can be replaced by any other 'marker' you wish. What is important is that both ends are on the same page (in terms of understanding each other).

What most often is done, as the characters are received one byte/character at a time, they are added to a receive buffer and tested at the same time to see if an end-of-line or end-of-text 'marker' has been received. If that's the case, as flag is raised signalling the buffer-handling segment of your code that it is now safe to extract the contents of the receive buffer and do some thing with it. You can use an array or a circular (ring) buffer to collect the incoming bytes.