Need some help on creating a RS485 library on NXC

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
knutselman
Posts: 4
Joined: 30 Jun 2011, 20:35

Need some help on creating a RS485 library on NXC

Post by knutselman »

Hi,
For a next robot build, I'd like to use RS485 connection, but I can't get it to work. I have never used RS485 before, so it seemed me the best to make a library so I can use it very often and easy.

Here's my Lib I created:

Code: Select all

// Lego NXT RS-485 Library
// Made by Robbe D

void WaitForMessageToBeSent()            //Wait till the message arrives
{
  while(HSOutputBufferOutPtr() < HSOutputBufferInPtr())
    Wait(1);
}

void SendBoolRS485(const bool value)
{
 SendRS485Bool(value);
 WaitForMessageToBeSent();
}

void SendNumberRS485(const int value)
{
 SendRS485Number(value);
 WaitForMessageToBeSent();
}

void SendStringRS485(const string value)
{
 SendRS485String(value);
 WaitForMessageToBeSent();
}

string GetStringRS485()
{
  byte mlen;
  string buffer;
  // wait for a message to arrive.
  mlen = 0;
  while (mlen == 0)
    mlen = HSInputBufferInPtr();
  // read it.
  GetHSInputBuffer(0, mlen, buffer);
  // clear the incoming buffer
  SetHSInputBufferInPtr(0);
  return buffer;
}

int GetNumberRS485()
{
  byte mlen;
  int buffer;
  // wait for a message to arrive.
  mlen = 0;
  while (mlen == 0)
    mlen = HSInputBufferInPtr();
  // read it.
  GetHSInputBuffer(0, mlen, buffer);
  // clear the incoming buffer
  SetHSInputBufferInPtr(0);
  return buffer;
}

bool GetBoolRS485()
{
  byte mlen;
  bool buffer;
  // wait for a message to arrive.
  mlen = 0;
  while (mlen == 0)
    mlen = HSInputBufferInPtr();
  // read it.
  GetHSInputBuffer(0, mlen, buffer);
  // clear the incoming buffer
  SetHSInputBufferInPtr(0);
  return buffer;
}

sub SetupRS485()
{
  SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);
  SetHSState(HS_INITIALISE);
  SetHSFlags(HS_UPDATE);
  SetHSInputBufferInPtr(0);
  SetHSInputBufferOutPtr(0);
}
When I try it out with my test programs, nothing happens.
Master code:

Code: Select all

#include "RS485Lib.nxc"

task main()
{
 int num;
 string str;
 bool boolean;
 SetupRS485();
 SendNumberRS485(1);
 num = GetNumberRS485();
 if (num == 1)
 {OnFwd(OUT_A, 50);}
 Wait(2000);
 SendStringRS485("test");
 str = GetStringRS485();
 if (str == "test")
 {OnFwd(OUT_A, -50);}
 Wait(2000);
 SendBoolRS485(true);
 boolean = GetBoolRS485();
 if (boolean == true)
 {OnFwd(OUT_A, 50);}
 Wait(2000);
}
Slave code:

Code: Select all

#include "RS485Lib.h"

task main()
{
 int num;
 string str;
 bool boolean;
 SetupRS485();
 num = GetNumberRS485();
 SendNumberRS485(num);
 str = GetStringRS485();
 SendStringRS485(str);
 boolean = GetBoolRS485();
 SendBoolRS485(boolean);
}
It should turn motor A, but it doesn't do anything!!!
Does somebody know my mistake(s)?

Thanks,
Robbe
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: Need some help on creating a RS485 library on NXC

Post by afanofosc »

Why don't people start with the RS485 routines documented in the NXC help system?

Here are two programs that work:

http://bricxcc.sourceforge.net/nbc/nxcd ... le.html#a2

http://bricxcc.sourceforge.net/nbc/nxcd ... e.html#a11

John Hanse
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
hassenplug
Posts: 346
Joined: 27 Sep 2010, 03:05
Contact:

Re: Need some help on creating a RS485 library on NXC

Post by hassenplug »

John,

I'm just about to attempt to create a network of NXTs using rs485. Thanks for pointing out these files.

Steve
---> Link to lots of MINDSTORMS stuff under my picture --->
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: Need some help on creating a RS485 library on NXC

Post by HaWe »

Steve,
if you wish, tell me if I can help / assist / test anything!
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: Need some help on creating a RS485 library on NXC

Post by afanofosc »

Sadly, I must announce here that my enhanced firmware changes to allow user control over the RS485 port baud rate have been tested recently and proven to not work very well at all. Is there anyone out there who would be willing to help me sort out where the problem lies? I would need someone who can scope the output to see if it shows the correct timing for the specified baud rate and whether all the bytes are transmitted.

According to Andrew Milluzzi,
I noticed it keeps dropping bytes as I get lower and after hooking it up to a scope, it appears that it is not sending them all.
I am not entirely sure what is going wrong. I think the baud rate calculation is okay and I can't see where or why characters would be dropped from the output buffer at slower baud rates. The receiving side does have a timeout (RTOR) but I am setting it to a larger value for slower baud rates. The default is 2400 and I am scaling that up to ~65535 (the maximum receiver timeout value) at the slowest baud rate setting (1200). I guess I need to dig around and see if there is some kind of transmit timeout that would explain the problem. I have spent many hours over the last couple weeks trying to get this to work right but so far I have had no luck.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
ronmcrae
Posts: 33
Joined: 28 Sep 2010, 14:56

Re: Need some help on creating a RS485 library on NXC

Post by ronmcrae »

afanofosc wrote: I can't see where or why characters would be dropped from the output buffer at slower baud rates.
Are the dropped characters random within the buffer? Or the last character? Over the years I've seen issues with switching off the RS485 transmitter too soon, usually at the end of the message. This causes the last character in a string to get garbled and/or not be received. At lower baud rates this effect will be more pronounced, because the transmitter definitely needs to stay enabled longer to ensure that the last character has cleared the UART. Is there perhaps some way that the transmitter is getting switched off, even during the transmitted message? That could lose a character.

I'd be happy to get involved in troubleshooting, but only after I'm done with a couple weeks vacation.

Ron.
milluzaj
Posts: 31
Joined: 28 Sep 2010, 22:15

Re: Need some help on creating a RS485 library on NXC

Post by milluzaj »

Hey,

So I have dug through this and so have several others helping test the NXTBee block.

The issue seems to be is that as the speed slows, we lose data. At full speed everything is fine and dandy. When you slow down to a baud rate of 9600, I can get at best 2 bytes at a time.

Now if I understand the code correctly, every 1 ms it refreshes the buffer and attempts to resend. Since a bug of 9600 means that it is sending a bit every 104 micro seconds, that means that 10 bits would be over a millisecond. I am guessing that speed is simply too slow to send data in one chunk. (Which would mean that it is not necessary a bug, but a know limitation.) So the question becomes (and this is where my knowledge of the firmware stops), does the FW overwrite the bits after that 1 ms mark? I have tried to make it wait (even really long periods of time) between sends and the issue persists. I have also tried to make it intelligently wait and that seems to also not work.

That is what I know. Seems to be just what others have observed as well. I can make my code work in 2 byte chunks, but the overhead would suck.
Blog: 08milluz.wordpress.com
LMS Shuttle: facebook.com/lmsshuttle
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: Need some help on creating a RS485 library on NXC

Post by mattallen37 »

Just curious, why would you want low speeds such as 9600? I guess that if you are interfacing with a uC you might want slowish speeds... but anything less than 9600? I have always used 921,600 (except for the occasional test).
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: Need some help on creating a RS485 library on NXC

Post by afanofosc »

milluzaj wrote:Now if I understand the code correctly, every 1 ms it refreshes the buffer and attempts to resend. Since a bug of 9600 means that it is sending a bit every 104 micro seconds, that means that 10 bits would be over a millisecond. I am guessing that speed is simply too slow to send data in one chunk. (Which would mean that it is not necessary a bug, but a know limitation.) So the question becomes (and this is where my knowledge of the firmware stops), does the FW overwrite the bits after that 1 ms mark? I have tried to make it wait (even really long periods of time) between sends and the issue persists. I have also tried to make it intelligently wait and that seems to also not work.
Can you show me where the firmware code sends HS data out in 1ms buffer refresh resend attempts?

I was under the impression that when the Comm module got its chance to execute (once every millisecond) that it would copy all the bytes from the HsOutBuf to the VarsComm.HsOutBuf then pass a pointer to that buffer to this function:

Code: Select all

void dHiSpeedSendData(UBYTE *OutputBuffer, UBYTE BytesToSend)
{
  HIGHSPEEDSendDmaData(OutputBuffer,BytesToSend);
}
And in HIGHSPEEDSendDmaData it checks to see if the previous send has completed (*AT81C_US0_TNCR == 0) and if so it copies the data from the VarsComm.HsOutBuf to another buffer called OutDma and then it sets *AT91C_US0_TNPR equal to the the address of the OutDma buffer and it sets *AT91C_US0_TNCR equal to the number of bytes you want to send (based on the Comm module's HsOutBuf.OutPtr - HsOutBuf.InPtr).

So if your program writes up to 128 bytes to the HS output buffer and then sets the InPtr to however many bytes you wrote to the output buffer and then sets the HsState to HS_SEND_DATA and the HsFlags to HS_UPDATE what should happen is that the next cycle through the Comm module's Ctrl routine should send all those bytes out the RS485 port. At least, that is the impression I have from looking over this code once or twice. I could be wrong. It is certain that I do not fully understand what the AT91SAM7 does once you set TNPR to a buffer containing data and set TNCR to the number of bytes you want to send. It seems to me like it ought to start sending the data and keep on sending it until TNCR counts down to zero. Anyone here know for sure?

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
mightor
Site Admin
Posts: 1079
Joined: 25 Sep 2010, 15:02
Location: Rotterdam, Netherlands
Contact:

Re: Need some help on creating a RS485 library on NXC

Post by mightor »

mattallen37 wrote:Just curious, why would you want low speeds such as 9600? I guess that if you are interfacing with a uC you might want slowish speeds... but anything less than 9600? I have always used 921,600 (except for the occasional test).
Most, if not all, devices other than the NXT use a fall-back speed of 9600. To configure them for higher baud rates, you need to initially be able to speak to them at the lower rates :)

- Xander
| My Blog: I'd Rather Be Building Robots (http://botbench.com)
| RobotC 3rd Party Driver Suite: (http://rdpartyrobotcdr.sourceforge.net)
| Some people, when confronted with a problem, think, "I know, I'll use threads,"
| and then two they hav erpoblesms. (@nedbat)
Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests