Asked — Edited
Resolved Resolved by Steve1DH!

V4 Two Way Serial Communication - Where Do I Connect To Read?

Hi all,

I'm trying to get serial feedback from a device. Does anyone know where on the V4 I should attach to read back serial information from device? I know I send a serial command to through one of V4's digital signal pins but where do I read it back from?

I thought it would be read from the same digital pin I sent the command. However @Toymaker made a comment in another thread that it may have to be read through one of the i2c ports.

Any insight is welcomed. :)


ARC Pro

Upgrade to ARC Pro

Unleash your creativity with the power of easy robot programming using Synthiam ARC Pro

PRO
Synthiam
#33  

So based on the error, i have to assume the Arduino is sending two bytes to make an int. You will really have to check the arduino code to ensure this is true, otherwise everything i am writing is a waste of effort:).

The data being read is binary, not ascii. So you cannot "print" a non ascii value because it has no corresponding character.

For example, you can look at an ASCII CHART to see what values map to readable characters...

User-inserted image

In your code, the ASCII value may be 0, which is a null. You can't print a null. You can't print anything that you can't read with your eyeballs.

Also, attempting to read more than one unreadable byte value into a string will not work. You can't have a string equal ESCAPE and NULL and BELL etc etc...

*Note: Doesn't look like you've been using the Variable Watcher. I would recommend using it to view the values of the variables for debugging.

You will need to use Binary Read to read the data into an array of values. Then combine the 2 values to get a 16 bit integer.


# initialize the uart
UARTInit(0, 0, 9600)

:Loop

# get how much data is available to be read in the input buffer
$available = UARTAvailable(0, 0)

# Do we have enough data? We need at least 2 bytes 
if ($available >= 2)

  # get 2 bytes from the buffer into the input array
  UARTReadBinary(0, 0, 2, $inArray)

  # convert 2 bytes into a 16 bit int (uncomment only one that works)
  #$realValue = ($inArray[0] << 8) + $inArray[1]
  #$realValue = ($inArray[1] << 8) + $inArray[0]

  print("The returned value is: " + $realValue)

else

  print("No data yet...")

endif

Sleep(100)

goto(Loop)

*Disclaimer: i have no idea what is high or low byte from the ardiuno to convert the 2 bytes to a 16 bit int. You have to choose one that works.

PRO
Synthiam
#34  

I should also add that it sounds like the Arduino code is missing something very important to communication. There's no way to know when the first byte is transmitted and what to parse. It's like walking into a room and starting a sentence from the middle to a group of people.

This will never work because you don't know where the first byte is to parse.

Chances are, if this is the Arduino code that you're using, it was written poorly and will not work at all... ever

Some poorly written code that merely transmits data carelessly will be impossible to parse.

#35  

Thank you so much for your help Dj. I improved a little in that sense that I got that the data I'm getting from the arduino are decimals that I can convert back into char using a simple "$value - 48" which gives me the number in char value... but as you said it yourself, I need the real value... and, well... honestly, I do not grasp your code. I tried it but it returns odd results. The best is that I show you 1) Arduino C code (poor code, as you suggested, but mine so I like it anymay:) ) 2) my script and what I attempted to do so far and 3) the debug.

Arduino code :

// just reading the encoder, nothing else.

//defining Pins names for the code

int pwm = 13; int forward = 10; int reverse = 11;

int MaxCountValue = 640;

int encoderValue_A = 0;int encoderValue_B = 0; void count(void);

void setup()

{

  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), countA, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), countB, FALLING);
  encoderValue_A = 0;
  encoderValue_B = 0;
}

void loop()
{
  int encoderValue_ADIV = encoderValue_A / 10;
  int encoderValue_BDIV = encoderValue_B / 10;

  //Serial.println("encoder_value_A");
  Serial.println(encoderValue_ADIV);
  //Serial.println("encoder_value_B");
  Serial.println(encoderValue_BDIV);

  if (encoderValue_A >= MaxCountValue)
  {
    encoderValue_A = 0;
  }
  else if (encoderValue_B >= MaxCountValue)
  {
    encoderValue_B = 0;
  }
  
  delay(500);

}

void countA()

{

  encoderValue_A++;
  
}

void countB()

{

  encoderValue_B++;
  
}

EZB script from your script and some adaptation, including char conversion. It seems there's no equivalent to the C++ char function in EZB...

# initialize the uart
UARTInit(0, 0, 9600)

:Loop

# get how much data is available to be read in the input buffer
$available = UARTAvailable(1, 0)

print($available)

# Do we have enough data? We need at least 2 bytes
if ($available >= 4)

  # get 2 bytes from the buffer into the input array
  UARTReadBinary(1, 0, $available, $inArray)

#encoder A
print($inArray[0])
print($inArray[1])
# convert dec to char
$valEncoderA1 = $inArray[0] - 48
$valEncoderA2 = $inArray[1] - 48
print($valEncoderA1)
print($valEncoderA2)

# convert 2 bytes into a 16 bit int (uncomment only one that works)
  $realValue = ($inArray[0] << 8) + $inArray[1]
  print($realValue)
  $realValue = ($inArray[1] << 8) + $inArray[0]
  
  print($realValue)

# encoder B
print($inArray[2])
print($inArray[3])
# convert dec to char
$valEncoderB1 = $inArray[2] - 48
$valEncoderB2 = $inArray[3] - 48
print($valEncoderB1)
print($valEncoderB2)

#$ValEncoderA  = print($valEncoderA1 + $valEncoderA2)

#print(($valEncoderA1) +  ($valEncoderA2))

else 

 print("no data yet...")
endif 

sleep(1000)

goto(Loop)

and finally, the console debug result:

Start
2: UARTInit(0, 0, 9600)
4: :Loop
7: $available = UARTAvailable(1, 0)
9: print($available)
> 8
12: if ($available >= 4)
15: UARTReadBinary(1, 0, $available, $inArray)
19: print($inArray[0])
> 50
20: print($inArray[1])
> 52
22: $valEncoderA1 = $inArray[0] - 48
23: $valEncoderA2 = $inArray[1] - 48
24: print($valEncoderA1)
> 2
25: print($valEncoderA2)
> 4
28: $realValue = ($inArray[0] << 8) + $inArray[1]
29: print($realValue)
> 12852
30: $realValue = ($inArray[1] << 8) + $inArray[0]
32: print($realValue)
> 13362
35: print($inArray[2])
> 13
36: print($inArray[3])
> 10
38: $valEncoderB1 = $inArray[2] - 48
39: $valEncoderB2 = $inArray[3] - 48
40: print($valEncoderB1)
> -35
41: print($valEncoderB2)
> -38
51: endif
54: sleep(1000)
56: goto(Loop)
4: :Loop
7: $available = UARTAvailable(1, 0)
9: print($available)
> 0
12: if ($available >= 4)
48: else
50: print("no data yet...")
> no data yet...
51: endif
54: sleep(1000)
56: goto(Loop)
4: :Loop
7: $available = UARTAvailable(1, 0)
9: print($available)
> 8
12: if ($available >= 4)
15: UARTReadBinary(1, 0, $available, $inArray)
19: print($inArray[0])
> 50
20: print($inArray[1])
> 52
22: $valEncoderA1 = $inArray[0] - 48
23: $valEncoderA2 = $inArray[1] - 48
24: print($valEncoderA1)
> 2
25: print($valEncoderA2)
> 4
28: $realValue = ($inArray[0] << 8) + $inArray[1]
29: print($realValue)
> 12852
30: $realValue = ($inArray[1] << 8) + $inArray[0]
32: print($realValue)
> 13362
35: print($inArray[2])
> 13
36: print($inArray[3])
> 10
38: $valEncoderB1 = $inArray[2] - 48
39: $valEncoderB2 = $inArray[3] - 48
40: print($valEncoderB1)
> -35
41: print($valEncoderB2)
> -38
51: endif
54: sleep(1000)
56: goto(Loop)
4: :Loop
7: $available = UARTAvailable(1, 0)
9: print($available)
> 0
Done (00:00:03.7055186)

Dunno if any body will have the will to help further on this... feels like I'm asking too much.

I do not understand, mainly, the << operator here... I know what it does, but don't see how it can help me convert dec results into the real values... The funny part is that if Arduino's debug returns the value 24, EZB terminal does to and shows on the right the equivalence in char table... but I can't get the char value (except with this "minus 48" as you can see). I'd need to merge the two results for $valEncoderB1 and $valEncoderB2 so I could get the int real number again... which is not optimal. Best is indeed to convert binary into dec, and that's where I'm lost.

Thanks again, even if you can't take the time for so much trouble!:)

PRO
Synthiam
#36  

That code will never work. First, look at the Serial.println() arduino command: https://www.arduino.cc/en/Serial/Println

It means PRINT LINE, which appends an ascii character to the end.

Second, it's for ascii, and you're not sending ascii.

the << is a bit shift because you claim the data being sent is a 16bit int which is 2 bytes. But, after reviewing the ARduino code, none of it will work.

Use SERIAL.WRITE()

PRO
Synthiam
#37  

Here, this is the proper way to do it.

  1. Connect EZB UART 0 TX to ARDUINO RX
  2. Connect EZB UART 0 RX to ARDUINO TX

Arduino Code:


// just reading the encoder, nothing else.

int encoderValue_A = 0;
int encoderValue_B = 0; 

void setup() {

  Serial.begin(9600);

  pinMode(2, INPUT);
  pinMode(3, INPUT);

  attachInterrupt(digitalPinToInterrupt(2), countA, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), countB, FALLING);
}

void loop() {

  // if there is data to read, read it
  if (Serial.available() &gt; 0) {

    // read the incoming data from the ezb
    int incomingByte = Serial.read();

    // command 'a' means transmit the current values and reset the counters
    if (incomingByte == 'a') {

      // send the values
      Serial.write(encoderValue_A);
      Serial.write(encoderValue_B);

      // reset the values
      encoderValue_A = 0;
      encoderValue_B = 0;
    }
}

void countA() {

  encoderValue_A++;  
}

void countB() {

  encoderValue_B++;  
}

EZB Code


uartinit(0, 0, 9600)

:loop

# Send a request for data to the arduino
uartwrite(0, 0, &quot;a&quot;)

# wait a bit for the data to be transmitted
sleep(50)

$dataAvail = UartAvailable(0, 0)

IF ($dataAvail != 2)

  print(&quot;The arduino didn't send us anything. Exiting&quot;)

  halt()

ELSE

  UartReadBinary(0, 0, 2, $encoders)

  print(&quot;Encoder A: &quot; + $encoders[0])
  print(&quot;Encoder B: &quot; + $encoders[1])

ENDIF

sleep(100)

goto(loop)
#38  

Damn! Thank you Dj! I'm all moved by this kindness! Really! I'm going to try this right now. Awesome.

PRO
Synthiam
#39  

No prob!

That way will work great. The idea of resetting the encoder value on each read is smart. This is because it gives you the ability on each read to see how much each encoder is different from the other. So if you expect to go straight, and one encoder is off by a large number from the other, you can correct it with pwm.

Having the ezb actually request the read is smart. That's a bidirectional communication model. Which means the Arduino does it's thing, and the ezb occasionally checks up on it.

ezb: "Hey Arduino, send me your encoder tick count and start counting from zero again" arduino: "Here you go ezb"

#40  

yes, but for now it doesn't seem to work on my side. It's like arduino isn't receiving anything. Serial Terminal reads "a" in ARC but for some reason the condition doesn't work in arduino or more precisely it seems that it doesn't receive the "a" value. Tried in char format (97) just in case, nothing.

EZB's Terminal stops reading "a" if I disconnect Arduino Tx to EZB Rx wire...

AND... Well it was just that I forgot to define the board index properly in UartAvailable(1, 0):D