
paulbearne04

Hi i am having problems using the Uart 0 with the sdk c# on my ez-b v4
i am writing a standalone app as well as a plugin for my inmoov bot, as i only have one ez-b v4 (limited funds) i am using an stm32F429 discovery board i had lying around to operate the additional servos and neopixel ring. The F429 disco board is working fine and i can send a simple command from the ez-b the protocol is just 4 bytes [0xFE][command byte][servonum byte][value byte] and works fine at 115200 F429 recieves the commands without any problems but i then send back either the same 4 bytes to acknowledge a set command or with a changed value byte if requesting a value from the F429
i have the following code set up in C# to wait for the response but it always returns the same value of 239 0xef in both my standalone version and the plugin version the F429 is sending correctly as i have connected it to an arduino , Nulceo stm32F746 and Nucleo stm32F401 and they all receive the 4 bytes correctly. i suspect i am doing something wrong as the _ezb.Uart.UARTExpansionAvailableBytes always seems to return 4086 once i send it data from the F429 I have been struggling with this for a couple of days now so any help would be appreciated am i using the right command to read the data?
private byte[] waitforresponse(int port)
{
// start timeout timer
timeoutTimer.Enabled = true;
TimedOut = false;
// here to debug uart rx problem
// bytes = 0 first time though the loop
int bytes = _ezb.Uart.UARTExpansionAvailableBytes(port);
while ((_ezb.Uart.UARTExpansionAvailableBytes(port) < 4) && (TimedOut == false))
{
Application.DoEvents();
}
timeoutTimer.Enabled = false;
// here to debug uart rx problem
// bytes = 0 first time though the loop
bytes = _ezb.Uart.UARTExpansionAvailableBytes(port);
if (TimedOut == false)
{
// original code return 4 bytes all with 239 0xEF
//byte[] data = _ezb.Uart.UARTExpansionRead(port, 4);
// added this for debug
// reads 4086 bytes all of the same value 239 0xEF
byte[] data = _ezb.Uart.UARTExpansionReadAvailable(port);
return data;
}
else
{
return null;
}
}
if you have a remote device connected (uart) sending bytes, EZ-B will process the bytes from the UART FIFO and will keep it in a fixed buffer .
buffer size = 5000 bytes
https://www.ez-robot.com/Community/Forum/Thread?threadId=5403
If you don't execute UARTExpansionRead or UARTExpansionReadAvailable the data will accumulate in the buffer, and then buffer will overflow (losing old data or not keeping up with the new data).
Can you check the remote side logic if is not generating the data, while waiting for an ACK (your software logic) from the EZB side ?
Can you post the Arduino/STM32 code ?
That's what i put the 4086 bytes available down to but the code is break pointed at remote and in VS so could only ever send once , my thoughts also as the number it shows its buffer full of it 0xEF and my remote which is nibbles reversed of the sof character sent at the start of the data packet 0xFE which i think may just be a red heron also when i collect the data and look at it using UARTExpansionReadAvailable it is just full of 0xEF. I can see on the lcd the command is received only once thats not to say that MBED code is not messed up lower down but the keil debugger stops the code when a breakpoint is hit so i'm pretty certain it only gets there once. while typeing i realised i haven't tried just sending a byte from the remote so will try that later
code for remote
is pretty simple
Serial device(PC_10,PC_11);
void ParseCommand()
{
uint8_t Text[30];
uint8_t txbuf[4] = {buf[0],buf[1],buf[2],buf[3]};
int i;
lcd.ClearStringLine(LINE(currentCommandLine));
led1 = !led1;
switch (buf[1]) {
case 0x00:
break;
case 0x01:
sprintf((char*)&Text,"Move servo %d to %d",(int)buf[2],(int)buf[3]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
moveServo(buf[2],buf[3]);
break;
case 0x02:
sprintf((char*)&Text,"Set servo %d Min to %d",(int)buf[2],(int)buf[3]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
servomins[buf[2]] = buf[3];
break;
case 0x03:
sprintf((char*)&Text,"Set servo %d Max to %d",(int)buf[2],(int)buf[3]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
servomaxs[buf[2]] = buf[3];
break;
case 0x04:
sprintf((char*)&Text,"Set servo %d speed to %d",(int)buf[2],(int)buf[3]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
servospeeds[buf[2]] = buf[3];
break;
case 0x05:
break;
case 0x06:
sprintf((char*)&Text,"Set servo %d steps to %d",(int)buf[2],(int)buf[3]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
servosteps[buf[2]] = buf[3];
break;
case 0x07: // is moving command
sprintf((char*)&Text,"Get servo %d moving state",(int)buf[2]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
if (servomoving[buf[2]] == true){
txbuf[3] = 0x01;
} else {
txbuf[3] = 0x00;
}
break;
case 0x08: // get current position
sprintf((char*)&Text,"Get servo %d Position",(int)buf[2]);
lcd.DisplayStringAt(0, LINE(currentCommandLine++), (uint8_t *)Text,
CENTER_MODE);
txbuf[3] = currentservopos[buf[2]];
break;
case 0x09:
break;
case 0x10 :
break;
}
if (currentCommandLine > 9)
{
currentCommandLine = 6;
}
// send response
for(i=0;i<4 ; i++)
{
device.putc(txbuf[i]);
}
}
// serial uart Rx ISR
void callback()
{
uint8_t inchar;
// while the fifo has data loop collecting it
while(device.readable()) {
// read the first character this will also clear the interupt
inchar = device.getc();
// see if we have sof character
if( inchar == 0xfe) {
buf[0] = 0xfe;
startbyte = true;
bufcount = 1;
} else {
if (startbyte) {
// received a sof so start getting command and data
buf[bufcount++] = inchar;
if (bufcount >= 4) {
bufcount=0;
// we have full command packet so act on it
ParseCommand();
// reset sof received flag ready for next command
startbyte = false;
}
}
}
}
}
Use code tags e.g. [ code ] and [ /code ] to format the code:
I added some code to help the troubleshooting:
Code:
Let's check simple things in sequence:
1) 3 wires to connect both devices: rx, tx, gnd
2) you have somewhere serial format & baud:
device.format(8, Serial::None, 1);
device.baud(115200);
Try to change to a slow speed e.g. 9600
3) Somewhere in your c# code you have:
UARTExpansionInit(0, 115200);
4) Your c# code does the following:
connects to the EZB
wait a few seconds (or connect event)
executes UARTExpansionInit (... )
executes UARTExpansionReadAvailable (...)
5) if you call UARTExpansionAvailableBytes(...) what is the return value ?
6) do you get any feedback in the LCD after the above points?
7) Send a command or dummy command, does the LCD reports the command ?
8) if you execute UARTExpansionAvailableBytes (...) do you get 4 bytes reported ?
i have tried 1 2 and 3 , 4 i use onconnect but do init later when i'm using the comms 5 it reads 0 on first call then 4086 after that. 7 lcd does report the command being received one the functions in c# code is to send servo config min max speed and step which get reported correctly on the lcd so i dont think its a timing issue. i'll check 8 as at the moment it will come out of the loop on timeout or any number of characters as long as its above 4.
two questions:
1) Board model connected to the EZB
2) Can you post the Serial pinout initialization code:
e.g.
Serial device(D10, D2);
I created a sample mbed program to test the serial communication between a STM32F01 and EZB v4.
the message protocol is simple and you can use ARC's Serial Terminal to test the interaction.
Code:
the code is simple, no bullet proof neither is rocket science
Code:
2) Do not ever ever ever use Application.DoEvents. Your code may be using a System.Windows.Forms.Timer instead of System.Timers.Timer.
Use the System.Timers.Timer, which will run in a separate thread. However, beware that you will need to use an Invoke for a System.Timers.Timer thread to modify any GUI Application thread objects