Welcome to Synthiam!

Program robots using technologies created from industry experts. ARC is our free-to-use robot programming software that makes features like vision recognition, navigation and artificial intelligence easy.
Get Started

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. :)

AI Support Bot
Related Content
Synthiam
#29  
ok, if anyone else is arround, here is what I'm now facing : don't seem to be able to get ASCII strings...

here is the error message I get using this code plagiarized from ARC examples :

the code first :

Code:


UARTInit( 1, 0, 9600 )

:loop

$available = UARTAvailable( 1, 0 )

print("Bytes in buffer: " + $available)

$read = UARTRead(1, 0,$available)

print("Received: " + $read)

sleep(1000)

goto(loop)



And now the error message I get :

Code:


Start
1: UARTInit( 1, 0, 9600 )
3: :loop
5: $available = UARTAvailable( 1, 0 )
7: print("Bytes in buffer: " + $available)
> Bytes in buffer: 0
9: $read = UARTRead(1, 0,$available)
11: print("Received: " + $read)
> Received:
13: sleep(1000)
15: goto(loop)
3: :loop
5: $available = UARTAvailable( 1, 0 )
7: print("Bytes in buffer: " + $available)
> Bytes in buffer: 16
9: $read = UARTRead(1, 0,$available)
11: print("Received: " + $read)
> Error on line 11: Missing String Quotes or Invalid Expression at index 15: "A
Done (00:00:01.1545633)



It's supposed to read these values :

"A="
then a number between 0 and 640
"B="
then a number between 0 and 640.

It seems that it can't read ASCII string values... maybe it's the "=" ?

** update : it is not... even after changing the code in arduino to only return numbers... I get this :

Code:

Start
1: UARTInit( 1, 0, 9600 )
3: :loop
5: $available = UARTAvailable( 1, 0 )
7: print("Bytes in buffer: " + $available)
> Bytes in buffer: 0
9: $read = UARTRead(1, 0,$available)
11: print("Received: " + $read)
> Received:
13: sleep(1000)
15: goto(loop)
3: :loop
5: $available = UARTAvailable( 1, 0 )
7: print("Bytes in buffer: " + $available)
> Bytes in buffer: 6
9: $read = UARTRead(1, 0,$available)
11: print("Received: " + $read)
> Error on line 11: Missing String Quotes or Invalid Expression at index 15: "
Done (00:00:01.5197188)
Synthiam
#30  
the question is missing some info. Is the arduino sending an unsigned 16 bit int? Signed 16 bit int? Or a string of characters?

Because it can't be an 8 bit unsigned int cause that only goes to 255.

What is the arduino sending?
#32  
it was initially sending a string of charaters AND a int (it seems int is by default signed in arduino).

Arduino int stores a 16-bit (2-byte) value by default.

I took out the string of characters but I still get this error message :

15: goto(loop)
3: :loop
5: $x = UartAvailable(1, 0)
7: print("Bytes in buffer: " + $x)
> Bytes in buffer: 7
9: $y = UARTRead(1, 0, $x)
11: print("Received: " + $y)

> Error on line 11: Missing String Quotes or Invalid Expression at index 15: "
Done (00:00:02.4873538)
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.

Code:


# 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.
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 :

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...

Code:

# 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:

Code:

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!:)
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()
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:

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() > 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

Code:


uartinit(0, 0, 9600)

:loop

# Send a request for data to the arduino
uartwrite(0, 0, "a")

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

$dataAvail = UartAvailable(0, 0)

IF ($dataAvail != 2)

print("The arduino didn't send us anything. Exiting")

halt()

ELSE

UartReadBinary(0, 0, 2, $encoders)

print("Encoder A: " + $encoders[0])
print("Encoder B: " + $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.
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
Synthiam
#41  
You can't connect the terminal and the ezb and the arduino together at the same time.
#42  
almost there, almost there... indeed, terminal must not be running for it opens the port.

Now... The only reading I get back in EZB is 97... which is char "a"...

What am I missing?
Synthiam
#43  
sounds like the ezb is writing to itself. check the wiring...

- EZB UART 1 TX connected to ARDUINO RX
- EZB UART 1 RX connected to ARDUINO TX
#44  
I triple Check that part. Tomorrow thursday il be able to work on It but only remotely. I'll check again just to make sure.

There's a loop back happening somewhere indeed.

But, really, thank you so much. I knew all the operations and functions but really I'm not yet trained enough to think of them when I'd need them, although I started thinking of serial write right before I read ur advice in that matter which is a start of a beginning of understanding. Let's stay positive! Haha.

Cheers.
Synthiam
#45  
Yeah - it must be a wiring issue.

The Arduino and ARC code are both solid. The arduino loops for ever until it receives the command 'a' from ARC. Once it receives the command, it transmits the A and B trigger values and resets the counter.

It's an incredibly simple process - so the wiring will be the focus.

Resetting the counter after each query is the right way to monitor encoders. This is because it allows you to see which wheel is rotating quicker/slower since the last query. And if your sample time is ever 1,000 ms, then you can correct the speed with pwm.

If you wish to know the distance traveled, simply keep a running total in ARC of both encoder values.
#46  
Arduino has a separate power source. Maybe I should give both (EZB and Arduino) a common ground?
Synthiam
#47  
Oh most definitely yes and yes! Always always common ground :). Apologies for not mentioning that before as I assumed they were the same power source.

Always need a common ground. First rule!:)
#48  
that was the issue. Needed a common ground...:) It seems to work now.

thanks a lot Dj!

Now, it took me so long to figure this out thanks to your help that this thread should be referred as a great tutorial for future users who would wish to establish similar com.

Best,
Elfège.