Need some help on creating a RS485 library on NXC

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
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 »

~ Ron, it sounds like your program is similar to mine.

My programs wait until the right number of bytes are available, by waiting until(HSInputBufferInPtr()>=BytesToReceive); Actually, I think I usually say BytesToReceive+1 (I think there is a null in there or something like that).

I just changed the setup speed from HS_BAUD_921600 to HS_BAUD_4800, and got no errors. I was sending 14 bytes each way. It also tested successfully at 9600 Baud. I tried HS_BAUD_1200 and HS_BAUD_2400, but those gave me problems (could have been that my user-code has issues).
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
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 »

nxtreme wrote:...I just purchased some RS485 converter chips and once they arrive (and when I finish some other projects that need finishing...) I'm going to see if I can get my NXT talking to my computer. Since I mainly want to use speeds around 4800 baud, your findings really come in handy. Thanks again!
I am eagerly awaiting your results.

Since your 20X2(s) is too old to work with I2C slave for the NXT, maybe you could get them talking with UART. Now, don't tell me the 20X2 version is too old for that ;) Or... did you get a new 20X2 with the order?
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
nxtreme
Posts: 246
Joined: 29 Sep 2010, 03:53
Location: 192.168.1.2

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

Post by nxtreme »

mattallen37 wrote:I am eagerly awaiting your results.

Since your 20X2(s) is too old to work with I2C slave for the NXT, maybe you could get them talking with UART. Now, don't tell me the 20X2 version is too old for that ;) Or... did you get a new 20X2 with the order?
So am I :). Well, I'm still not 100% sure it's the firmware version on my Picaxe 20X2, but that's what I'll blame it on for now. No, I still need to order some more Picaxe chips but I was thinking more along the lines of an PC>FDTI>RS485 Converter>NXT. At least, that's how I'd test it out for now. Eliminates the problem of code on the Picaxe side being messed up. Anyways, sorry to take this topic OT!
One King to rule them all, One King to find them,
One King to bring them all and in the darkness bind them
On Earth where Shadows lie.
milluzaj
Posts: 31
Joined: 28 Sep 2010, 22:15

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

Post by milluzaj »

So John, I presume you look at the inbuffinptr and the inbuffoutptr on the receiver and looking the the outbuffoutptr and outbuffinptr to confirm it actually sent? Do those registers actually retrun the correct values as it is sent? That is how I wait for sending in the block and it appears to still have the issue.

Thought?
Blog: 08milluz.wordpress.com
LMS Shuttle: facebook.com/lmsshuttle
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 »

The latest version of the enhanced firmware has changed how the HsOutBuf.OutPtr and HsOutBuf.InPtr fields are updated. The original firmware writes the data out like this:

Code: Select all

void cCommSendHiSpeedData(void)
{
  VarsComm.HsModuleOutBuf.OutPtr = 0;
  for (VarsComm.HsModuleOutBuf.InPtr = 0; VarsComm.HsModuleOutBuf.InPtr < IOMapComm.HsOutBuf.InPtr; VarsComm.HsModuleOutBuf.InPtr++)
  {
    VarsComm.HsModuleOutBuf.Buf[VarsComm.HsModuleOutBuf.InPtr] = IOMapComm.HsOutBuf.Buf[IOMapComm.HsOutBuf.OutPtr];
    IOMapComm.HsOutBuf.OutPtr++;
  }
  dHiSpeedSendData(VarsComm.HsModuleOutBuf.Buf, (VarsComm.HsModuleOutBuf.InPtr - VarsComm.HsModuleOutBuf.OutPtr));
}
Notice that if you are comparing the HsOutBuf.OutPtr and the HsOutBuf.InPtr that they will have been updated before the data is completely sent - since the sending doesn't even start to occur until you call dHiSpeedSendData and it isn't actually completed for some number of milliseconds later at slower baud rates. In the enhanced firmware I originally left this function unchanged but currently it looks like this:

Code: Select all

void cCommSendHiSpeedData(void)
{
  VarsComm.HsModuleOutBuf.OutPtr = 0;
  memcpy(VarsComm.HsModuleOutBuf.Buf, IOMapComm.HsOutBuf.Buf, IOMapComm.HsOutBuf.InPtr);
  VarsComm.HsModuleOutBuf.InPtr = IOMapComm.HsOutBuf.InPtr;
  dHiSpeedSendData(VarsComm.HsModuleOutBuf.Buf, VarsComm.HsModuleOutBuf.InPtr);
//  IOMapComm.HsOutBuf.OutPtr = IOMapComm.HsOutBuf.InPtr;
}
As you can see, I have changed the code to not update the HsOutBuf.OutPtr. The latest code leaves this field unchanged until in cCommCtrl the function dHiSpeedBytesToSend returns zero:

Code: Select all

  // update the HsState if there are bytes remaining to be sent
  if (IOMapComm.HsState >= HS_BYTES_REMAINING)
  {
    UWORD bts = 0;
    dHiSpeedBytesToSend(&bts);
    if (bts == 0)
    {
      IOMapComm.HsState = HS_DEFAULT;
      IOMapComm.HsOutBuf.OutPtr = IOMapComm.HsOutBuf.InPtr;
    }
    else
      IOMapComm.HsState = HS_BYTES_REMAINING + bts;
  }
You can see that the IOMapComm.HsState field is now dual-purposed to hold a state value (HS_INITIALISE = 1, HS_INIT_RECEIVER, HS_SEND_DATA, HS_DISABLE, HS_ENABLE, HS_DEFAULT, HS_BYTES_REMAINING = 0x10) as well as the number of bytes remaining to be sent. Just subtract HS_BYTES_REMAINING from HsState if it is >= HS_BYTES_REMAINING.

The proper way to wait for bytes to be sent is to wait until HsState is reset back to HS_DEFAULT but with the latest enhanced firmware you should be able to wait until HsOutBuf.OutPtr is equal to HsOutBuf.InPtr.

The output buffer is always used with HsOutBuf.OutPtr starting at zero which means you write your output data to the first byte in HsOutBuf.Buf and then HsOutBuf.InPtr is set to the number of bytes you are writing. This, however, is not at all how the HsInBuf and its two pointers work. The input buffer is a circular 128 byte buffer. The next incoming byte is written to HsInBuf.Buf at the current value of HsInBuf.InPtr after which InPtr is incremented. This repeats until InPtr reaches 128 and it is reset back to zero.

Code: Select all

      for (Tmp = 0; Tmp < NumberOfBytes; Tmp++)
      {
        IOMapComm.HsInBuf.Buf[IOMapComm.HsInBuf.InPtr] = VarsComm.HsModuleInBuf.Buf[Tmp];
        IOMapComm.HsInBuf.InPtr++;
        if (IOMapComm.HsInBuf.InPtr > (SIZE_OF_HSBUF - 1))
        {
          IOMapComm.HsInBuf.InPtr = 0;
        }
        VarsComm.HsModuleInBuf.Buf[Tmp] = 0;
      }
HsInBuf.OutPtr is unchanged as data comes in. It should be updated in a user program to equal InPtr when you have finished reading the data from the circular input buffer. In a compiler that can call new system call functions and you have the enhanced NBC/NXC firmware on your brick then you would just use CommHSRead which will update the HsInBuf.OutPtr field for you but that function does not work right in the standard firmware. So you have to do it yourself. The CommHSRead function also copies the data correctly from the circular buffer which you have to do on your own if you can't use the enhanced NBC/NXC firmware's CommHSRead function.

In any case, I think you've got something fouled up in your code.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
milluzaj
Posts: 31
Joined: 28 Sep 2010, 22:15

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

Post by milluzaj »

Okay, I think I am off by 1 when updating the inbuffoutptr. Let me try that tonight and see.
Blog: 08milluz.wordpress.com
LMS Shuttle: facebook.com/lmsshuttle
Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests