Serial Input (Byte ->>> Int)

I have a compiled code, “working” except the last part. I could really use help with this.

  1. I am using RoboRealm to send the Webcam X mouse location (0-640) through Serial to my Uno. (It’s a 640x480 resolution, only using X)

  2. Once received it was coming through in strange, so I used atoi to make it into a solid integer. When I write back to RoboRealm using Serial.print, it shows exactly what RoboRealm sent (i.e. 640 far right side, 0 far left side for cursor location) So this is great.

  3. My problem is, I don’t think the int “isa” is really the value it’s showing. The reason is the LED portion doesn’t work. And even if I change that to print to the serial it always say’s I am below 300.

Below is the code, I am a noob so sorry for needing help with something probably simple! :slight_smile:

int incomingByte = 0;   
char bytes[4] = { 0, 0, 0, 0 };
int i = 0;
int isa;

void setup() {
  
        Serial.begin(9600); 
        pinMode(5, OUTPUT);
        
}

void loop() {

        if (Serial.available() > 0) {
                
           while(i < 4) {
             
                bytes[i] = Serial.read();
                i++;    
                       }

                isa = atoi(bytes);  // isa variable              
                     
                Serial.print(isa); // When it prints back to 3rd party program 
                                   // over serial, it shows correct value. 
                
                // THIS PORTION NOT WORKING - EVEN TESTED PRINTING TO SERIAL, ALWAYS SHOWS < 300
                // I DONT THINK "isa" IS REALLY THE VALUE IT PRINTS TO SERIAL. 
                  
                if (isa > 300) {
                digitalWrite(5, HIGH);
                               }
                
                else {
                digitalWrite(5, LOW);
                }               
        }
            
            i = 0;
}

When you read Serial.available(), your code assumes that the buffer is holding 4 bytes (e.g., while (i < 4)) of data. You say the device will only be sending 3 digit characters. When your code tries to read the 4th byte, Serial.read() should return -1 because the buffer is empty. I don’t even know how atoi() handles the characters ‘6’, ‘4’, ‘0’, -1. I’d do a little work on the while loop and make sure the bytes[] array is null terminated after the read buffer is empty. This may not solve the problem, but it’s worth checking.

Thanks for the advice, but no dice :expressionless:

I made a change, char bytes[3] = { 0, 0, 0 }; as you mentioned.

It still works the same, it’s like the int “isa” isn’t really the true value. For instance, I hold my mouse over 590 and it prints to the serial 590, my 3rd party program, great. But in that case, why isn’t the LED switching on? No clue. Like I mentioned, I have also tried printing to serial “on” or “off” just to rule out any other issues. The if statement just isn’t executing period.

I didn’t state myself clearly. Examine the following code and see what I meant:

int incomingByte = 0;   
char bytes[4] = { 
  0, 0, 0, 0 };
int i = 0;
int isa;

void setup() {

  Serial.begin(9600); 
  pinMode(5, OUTPUT);

}

void loop() {
  int bufferBytes;
  char val;

  i = 0;
  if (Serial.available() > 0) {
    delay(100);
    bufferBytes = Serial.available();
    Serial.print("bufferBytes: "); // When it prints back to 3rd party program 
    Serial.println(bufferBytes); // When it prints back to 3rd party program 
    while (bufferBytes--) {
      bytes[i] = Serial.read();
      i++;  
    }  
  }
  bytes[i] = '\0';    // Make it a string
  isa = atoi(bytes);  // isa variable              

  Serial.print("Isa: "); // When it prints back to 3rd party program 
  Serial.println(isa); // When it prints back to 3rd party program 
  // over serial, it shows correct value. 

  // THIS PORTION NOT WORKING - EVEN TESTED PRINTING TO SERIAL, ALWAYS SHOWS < 300
  // I DONT THINK "isa" IS REALLY THE VALUE IT PRINTS TO SERIAL. 

  if (isa > 300) {
    Serial.print("Isa > 300: Isa: "); // When it prints back to 3rd party program 
    Serial.println(isa); // When it prints back to 3rd party program 
    digitalWrite(5, HIGH);
  } 
  else {
    Serial.print("Isa <= 300: Isa: "); // When it prints back to 3rd party program 
    Serial.println(isa); // When it prints back to 3rd party program 
    digitalWrite(5, LOW);
  }               
  delay(5000);
}

While the delay() call is messy, it shows what’s going on…

Thank you. This worked somewhat. I will try and improve upon it, it's still very glitchy but at least somewhat processing the if statements.

So I can learn from this, is it possible you can explain what is going on in some of the code? Thank you again! (questions below)

    while (bufferBytes--) { // What are you decrementing right here?
      bytes[i] = Serial.read();
      i++;  
    }  
  }
  bytes[i] = '\0';    // I have never seen this, should I always do this with arrays?
  i = 0;
  if (Serial.available() > 0) {
    delay(100);
    bufferBytes = Serial.available();
    Serial.print("bufferBytes: "); // When it prints back to 3rd party program 
    Serial.println(bufferBytes); // When it prints back to 3rd party program 
    while (bufferBytes--) {
      bytes[i] = Serial.read();
      i++;  
    }  
  }
  bytes[i] = '\0';    // Make it a string

What if more than 3 bytes arrive?

This is not a good way of doing serial. Adding a delay "so stuff will arrive" is fraught with peril.

http://www.gammon.com.au/serial

What end of line sequence is roborealm sending? I think you are first seeing the number and the turning off the led when you get the end of line chars.

Mark

In the code fragment:

  i = 0;
  if (Serial.available() > 0) {                          // Is there something in the serial buffer?
    bufferBytes = Serial.available();                // How many bytes are there?
    Serial.print("bufferBytes: ");                    // Debug code
    Serial.println(bufferBytes); 
    while (bufferBytes--) {                            // Copy buffer contents
      bytes[i] = Serial.read();
      i++;  
    }  
  }
  bytes[i] = '\0';    // Make it a string
  isa = atoi(bytes);  // isa variable

The second call to Serial.available() returns the number of bytes received in the serial buffer. The while loop simply copies bufferBytes characters into the bytes[] array. In C, strings are null terminated, which means you need to add a null termination character ('\0') after the input data is received. Now you have a string in the bytes[] array that atoi() can digest properly. See Nick's link for a better way to do this.

Nick: I know the use of delay() is not good (which is why I said using delay() "is messy") and that I didn't provide for buffer overflow. I was just trying to keep it as simple as possible so he could see what was happening.