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

ARC Pro is your passport to a world of endless possibilities in robot programming, waiting for you to explore.

#1  

The V4 (like the V3) can only send serial on the digital pins... You'll need to use the V4's UART port for bi-directional serial transfer... I hope DJ puts up a tutorial soon on how to use the UART port...

#2  

I thought it would be read through on of V4 EZB's digital ports. I thought this because we send serial commands through the signal pin of a digital. Then Toymaker said it should read serial feedback from the i2c port. Now you say the UART port. confused I guess I need to get this cleared up.

#3  

Rich also mentioned using i2c... We all hoped for basic serial (send and receive) through the digital pins of the V4... To my knowledge you can still only send... DJ instead provided the v4 with UART ports... UART is what we can use for bi-directional serial data transfer... I myself am not quite sure how to use the UART port but devices like the iRobot Create and I am guessing the Kangaroo too should work with 2 way serial communication using this port... DJ said that tutorials on how to use the port are coming soon...

#4  

Looking in the "Learn" section in the Data Sheet for V4 I see the UART port. It shows a RX & TX connection along with a 3.3v and Gr. Looks like you may be right. Like you I'm unsure how to use this port. I guess I'll muck around in the script commands to see if I can come up with something.

Good thing the Kangaroo doesn't need power as the V3 only supplies 3.3 and not the 5v it will get from the Sabertooth.

User-inserted image

#5  

That's the port Dave (Black port on the lower right of the board)... I am sure it will be straight forward to use... After all... It is made by EZ Robot, right?...:P We (I am) are probably over thinking things here anyway...

#6  

Here's something else that confuses me. In the specs EZ Robot states:

3 x i2c Port and 3 x High Speed UART Ports. I see the i2c ports. Where are the UARTs? They must be hard coded and be accessed through that mystery connection I'm looking for. confused

#7  

@Dave - UART 1and 2 -

User-inserted image

Hope this helps.

United Kingdom
#8  

There are script commands for the UART port; UARTInt UARTAvailable UARTRead UARTWrite

Examples and help are in the EZ-Script manual to the right of the script dialogue. There is also a sample project in the examples folder of ARC which shows how to use it.

#9  

OK, Now we're getting somewhere. :)

From what I'm reading in @Steve1DH's post above UART 1 is D5 & D6 (Tx, RX respectively) and D18 & D19 are UART 2 (Tx, RX respectively). That must make the black physical header pin UART 3?

I don't know how I missed that. I thought I read through the whole data sheet. Thanks Steve!

Also thanks @Rich for pointing me to the script commands. I knew there were there and was reviewing them as you were posting. However I had forgotten about the sample project. That will be a big help. :)

#10  

Steve, Gotta give this one to you. You answered my "whole" question. :P

United Kingdom
#11  

The black UART is UART0 :)

#12  

Ahh, that makes a huge difference. I forgot these circuit jockey's like to start at naming at 0. ;)

#13  

As soon as I get my V4, I am going to experiment using the UART to see if I can read sensor data from my iRobot Create....

PRO
Canada
#14  

Sorry guys I was a little late to see this thread, thanks all for pitching in and figuring it out.

Just to confirm for you:

Uart0 is the black 4-pin 0.1" pitch female header at the top of the EZ-B

Uart1 is pins D5 & D6 (D5 is also the Dynamixel port)

Uart2 is D18 & D19

These UART ports are great for serial displays, communication to a PC, and just as @Richard R has mentioned they are for Roomba's as well!

And as @Rich mentioned there is a code example in ARC to help you on your way.

Thanks guys!

PRO
Synthiam
#15  

As Skater said, that's right about what ports are UART compatible. However, I would not recommend wasting an input capable UART on serial displays. All Digital Pins have the ability to output serial ttl data and displays only require output.

I have put a great amount of effort into EZ-Script manual and example projects. If you're stumped on something, I would recommend calmly following these steps...

  1. Search the EZ-B datasheet for port descriptions, voltages

  2. For connection or Wi-Fi questions, visit the Learn section and consult the tutorial videos

  3. Search the EZ-B manual for words referencing your trouble. In this case, UART. The EZ-Script manual explains each UART command with example syntax and the available UART ports.

  4. Search both Examples folders within ARC for the keyword. In this case, you would search UART and find a UART project example.

And of course, if those don't help - ask on here so I can see how to address it :)

#16  

Actually, Rich constantly reminds me (us) to RTFM and explore the examples that you have provided.... I really need to listen more... :)

United Kingdom
#17  

Here's a huge secret, DJ's method above is how I manage to look like I know what I'm doing 99% of the time! :D

#18  

Rich you're too modest... I would say more like 99.9% ;)

#19  

@ Dave - Thank You for the credit.

#20  

:P @DJ, your a scream!; "calmly following these steps". "Calmly" is my middle name. ;)

Your right though. I could have probably found the answer to this question if I had just slowed down and re-read the spec sheet. I do get in a hurry at times. It usually results in a flash and smoke. eek

Also this is not for displays. I'm trying to set up a two way serial connection between EZB V4 and a Kangaroo / Sabertooth. I need the Roo to tell me where it is after I send a serial command to move to a set position.

PRO
Synthiam
#21  

Lol you indeed are one of the most patient people I've ever met. I write for the masses, knowing that future readers will stumble across my posts. Never think I'm directing anything at any specific someone. It's always generic.

Much like how I explain where the learn button is. Of course you all know. But someone new may not know... So I be specific for the future :)

United Kingdom
#22  

Dave, I referred to I2C port as I am still using a V3 so my PIC does the conversion from I2C to bi-directional comms to the serial port of the Kangaroo, hope this helps.

#23  

@Tony, each time you post it always a huge help. Thanks, the confusion was my fault not yours. When I thought it through I came to that conclusion.

#24  

Ok... I can't find any example using uart method, neither in local examples nor in the cloud... is it me or they all disappeared?

Some basic quesitons :

I'm trying to TX buffer values (between 0 and 640) from an arduino (running a code to read motors' encoders) to EZB UART0. I hooked arduino's tx to EZB's rx and arduino's rx to tx (although I only need to receive data from arduino, but in the doubt... not sure if they both need to be connected).

I tried these codes so far, without success :


UARTInit( 1, 0, 9600 )

$available = UARTAvailable( 1, 0 )

print($available)

UARTRead(0, 0,$available)

UARTReadBinary(0, 0, $available, $variab)

print($variab)

sleep(200)

halt() 

here is what I get :



Start
1: UARTInit( 1, 0, 9600 )
3: $available = UARTAvailable( 1, 0 )
5: print($available)
> 0
7: UARTRead(0, 0,$available)
9: UARTReadBinary(0, 0, $available, $variab)
11: print($variab)
> Error on line 11: Variable is an array: $variab
Done (00:00:00.1605282)

FYI if you type what the Script Help says about UartReadBinary() you get an error message :


UARTReadBinary(0, 0, UARTAvailable(0, 1), $variable)


here is what it returns :


16: UARTReadBinary(1, 0, UARTAvailable(0, 1), $variable)
> Error on line 16: Missing ) in Expression
Done (00:00:00.4367821)

that's why I used a variable for the UartAvailable() function, above. 


I'm desperately trying to get data returned. It works in the terminal EZB, I receive the counts from the encoders connected to the arduino. So, here is my real question (and since I couldn't find any example using UART keyword in the examples despite what was said earlier in this thread) :

How do I get to read what comes from this arduino the same way they are read and displayed in the serial terminal?

Thanks in advance

#25  

Ok, one step at a time:) I see the variable's value in the variable watch... so now need to figure out how to script with these values as a variable condition...

PRO
Synthiam
#26  

The cloud doesn't have any example projects. They ship with ARC. Look here: https://synthiam.com/Tutorials/Lesson/22?courseId=6

I'm not at home and on my phone so I can't give you code. But that link will help you find examples that do what you need :)

#27  

Thank you very much Dj! And enjoy your evening! I hope she's worth it! :D

PRO
Synthiam
#28  

Thanks! I'll write something if you're still spinning wheels later this evening

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


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 :


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 :

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

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

PRO
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?

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

PRO
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?

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