Page 1 of 2

NXC: Non-responsive RS485 Receive

Posted: 01 Sep 2011, 22:26
by haydenstudios
Hello there, I have just started using RS485 in NXC for the first time, but I have had a few problems. First of all, I am using John's sample programs from his website. The Send program:

Code: Select all

// RS-485 sender program

inline void WaitForMessageToBeSent()
{
  while(RS485SendingData())
    Wait(MS_1);
}

task main()
{
  // configure the S4 port as RS485
  UseRS485();
  // make sure the RS485 system is turned on
  RS485Enable();
  // initialize the UART to default values
  // low level API function call (allows changing UART settings)
  RS485Uart(HS_BAUD_DEFAULT, HS_MODE_DEFAULT);
//  // hi level API function call
//  RS485Initialize();
  Wait(MS_1); // make sure everything gets turned on okay
  int i;
  byte buffer[];
  while (true) {
    string msg;
    msg = "goofy " + NumToStr(i);
    TextOut(0, LCD_LINE1, msg);

    // send the # of bytes (5 bytes)
    byte cnt = ArrayLen(msg);
    SendRS485Number(cnt);
    WaitForMessageToBeSent();

    // wait for ACK from recipient
    until(RS485DataAvailable());
    RS485Read(buffer);

    // now send the message
    SendRS485String(msg);
    WaitForMessageToBeSent();

    // wait for ACK from recipient
    until(RS485DataAvailable());
    RS485Read(buffer);

    i++;
  }
  // disable RS485 (not usually needed)
  RS485Disable();
}
And the receive program:

Code: Select all

                               // RS-485 receiver program
inline void WaitForMessageToBeSent()
{
  while(RS485SendingData())
    Wait(MS_1);
}

task main()
{
  byte mlen;
  string buffer;
  // configure the S4 port as RS485
  UseRS485();
  // make sure the RS485 system is turned on
  RS485Enable();
//  // initialize the UART to default values
//  RS485Initialize();
  // configure the UART (this is equivalent to RS485Initialize)
  RS485Uart(HS_BAUD_DEFAULT, HS_MODE_DEFAULT);

  Wait(MS_1); // make sure everything is turned on
  byte ACK[] = {1};
  while (true) {
    // wait for a message to arrive.

    // read the number of bytes message
    until(RS485DataAvailable() >= 5);

    // read the number of bytes
    RS485Read(buffer);
    long cnt = 0;
    UnflattenVar(buffer, cnt);

    // send out ACK
    RS485Write(ACK);
    WaitForMessageToBeSent();

    // now wait for the real message
    until(RS485DataAvailable() >= cnt);

    // now read the actual message
    RS485Read(buffer);

    // send out ACK
    RS485Write(ACK);
    WaitForMessageToBeSent();

    // display message
    TextOut(0, LCD_LINE1, buffer);
  }
}
I have the EFW v1.31 on both NXTs, have gotten the programs to compile and download, and verified that the NXTs are correctly connected to each other through sensor port 4, but I still get this problem:
The sending NXT displays its expected text, "goofy: 0" but it remains so. The receiving end just shows the "RS458Receive Running text". In other words, noting happens. I decided to see what would happen when the receiving end was off. And then, the numbers on the screen of the sending NXT started going up. I looked at the code, and understand what is supposed to happen. I have guessed that it's the receiver's fault, but I'm not entirely sure. Any light that someone could shed on this would be useful. I searched this forum for past posts, but found none that were what my problem is. Thanks in advance.

Re: NXC: Non-responsive RS485 Receive

Posted: 02 Sep 2011, 02:52
by afanofosc
I can get the symptoms you describe only when I start the sender before I start the receiver and I have previously run the programs after a power down/power up cycle. If I run the programs after powering up it works regardless of which program I start first. A second run after an abort seems to only work (and always work) if I start the receiver first.

I don't ever see the sender program counting up if the receiver program is turned off or the receiving NXT is turned off.

John Hansen

Re: NXC: Non-responsive RS485 Receive

Posted: 02 Sep 2011, 13:43
by haydenstudios
Thank you for replying Jonh. Unfortunately, I still get the same results regardless of which program I start first, and also regardless of wether I've run a program since powering the NXTs up. And It was only yesterday that I freshly installed your enhanced firmware on my NXTs. And the counter goes up when my receiving NXT is powered down. But it does not go up if the NXT is on, regardless of wether or not the receive program is running.

Re: NXC: Non-responsive RS485 Receive

Posted: 04 Sep 2011, 01:00
by haydenstudios
Update: I tried an NXT-G program using RS485, and it worked fine, regardless of which program I started first, and I also tried swapping the programs, and it still worked. So now I know that this is not a hardware problem. The program I want to make will be very sophisticated, so I don't want to have to program it in NXT-G. Might anyone be willing to point me in the direction of a different NXC RS485 example program? I'd much rather experience a working example program before writing my own. If worst comes to worst, then I will try. But I hope someone can help. Anyone? Please?

Re: NXC: Non-responsive RS485 Receive

Posted: 04 Sep 2011, 05:00
by mattallen37
haydenstudios wrote:...But I hope someone can help. Anyone? Please?
Send me a PM, and when I get home (IIR) I will get you my NXC library for RS485.

Re: NXC: Non-responsive RS485 Receive

Posted: 04 Sep 2011, 10:12
by h-g-t
Hi,

Had a look through the stuff I have downloaded and over the years and found these.

Don't know where they are from but the 'ms' in the names might mean Mindsensors.

Code: Select all

//485Sendms.nxc

void SendRS485Bool(const bool value)
{
  byte msg[];
  ArrayBuild(msg, value, 0);
  SetHSOutputBuffer(0, 2, msg);
  SetHSOutputBufferOutPtr(0);
  SetHSOutputBufferInPtr(2);
  SetHSState(HS_SEND_DATA);
  SetHSFlags(HS_UPDATE); //send it
}

void SendRS485Number(const int value)
{
  string msg = Flatten(value);
  SetHSOutputBuffer(0, 5, msg);
  SetHSOutputBufferOutPtr(0);
  SetHSOutputBufferInPtr(5);
  SetHSState(HS_SEND_DATA);
  SetHSFlags(HS_UPDATE); //send it
}

void SendRS485String(const string msg)
{
  byte mlen = ArrayLen(msg);
  SetHSOutputBuffer(0, mlen, msg);
  SetHSOutputBufferOutPtr(0);
  SetHSOutputBufferInPtr(mlen);
  SetHSState(HS_SEND_DATA);
  SetHSFlags(HS_UPDATE); //send it
}

void WaitForMessageToBeSent()
{
  while(HSOutputBufferOutPtr() < HSOutputBufferInPtr())
    Wait(1);
}

task main()
{
  SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);
  SetHSState(HS_INITIALISE);
  SetHSFlags(HS_UPDATE);

  Wait(10);
  int i;
  while (true) {
    string msg;
    msg = "goofy ";
    msg += NumToStr(i);
    SendRS485String(msg);
    WaitForMessageToBeSent();
    i++;
//    Wait(50);
  }
}



//  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// 485Recivems.nxc

task main()
{
  byte mlen;
  string buffer;
  SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);
  SetHSState(HS_INITIALISE);
  SetHSFlags(HS_UPDATE);
  // start with empty input buffer
  SetHSInputBufferInPtr(0);
  SetHSInputBufferOutPtr(0);

  Wait(10);
  while (true) {
    // 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);
    // display message
    TextOut(0, LCD_LINE1, buffer);
  }
}


Re: NXC: Non-responsive RS485 Receive

Posted: 04 Sep 2011, 16:06
by afanofosc
You should not use any of this old low level code anymore. It would be MUCH better for us to figure out what is going wrong with your NXTs and the API functions used in the samples. This can be done in a variety of ways but it is hard for me to do it for you when the code works fine with the latest version of the 1.31 enhanced NBC/NXC firmware on my two NXTs. What is the name of the firmware image you downloaded onto your NXTs and what is its timestamp? Was it the firmware image in the latest test release zip?

Have your program output some of the low level RS485 information to the LCD so you can tell what is going on with both of your NXTs. Put in NumOut or TextOut calls in loops so you can tell where your program is stuck/waiting. Or use beeps instead, if you prefer. Perhaps also check and output the return values of any function call.

John Hansen

Re: NXC: Non-responsive RS485 Receive

Posted: 04 Sep 2011, 16:44
by haydenstudios
afanofosc wrote:What is the name of the firmware image you downloaded onto your NXTs and what is its timestamp?
The file name was, "lms_arm_nbcnxc_131.rfw," and it was last modified on March 13, 2011.
afanofosc wrote:Was it the firmware image in the latest test release zip?
It was located in the BricxCC directory resulting from the installation of the file "bricxcc_setup_3389.exe," and I just checked your website, and that's the latest version.
afanofosc wrote:Have your program output some of the low level RS485 information to the LCD so you can tell what is going on with both of your NXTs. Put in NumOut or TextOut calls in loops so you can tell where your program is stuck/waiting. Or use beeps instead, if you prefer. Perhaps also check and output the return values of any function call.

John Hansen
Alright, I'll try some of that if worst comes to worst.

EDIT: It seems I should've heeded your words a bit more closely John, cause I was using the firmware from your latest official release. But I just downloaded some newer firmware, and the programs are now working. Thanks for the help guys.

Re: NXC: Non-responsive RS485 Receive (Solved!)

Posted: 07 Jun 2012, 02:26
by haydenstudios
So, due to a large collection of reasons, I think it is justifiable to bump this existing thread instead of create a new one. I'm right now making a pong game where two NXTs communicate via RS485, so it's played on two different screens. I tried starting out simple by just having the position of the tray of the master NXT sent to the slave NXT, and displayed on the screen. My setup uses two NXTs connected through sensor port 4, and an RCX rotation sensor connected to sensor port 2 of the master NXT.

The master program:

Code: Select all

inline void WaitForMessageToBeSent()
{
  while(RS485SendingData())
    Wait(1);
}

task main()
{
  SetSensor(IN_2, SENSOR_ROTATION);
  // configure the S4 port as RS485
  UseRS485();
  // make sure the RS485 system is turned on
  RS485Enable();
  // initialize the UART to default values
  // low level API function call (allows changing UART settings)
  RS485Uart(HS_BAUD_DEFAULT, HS_MODE_DEFAULT);
//  // hi level API function call
//  RS485Initialize();
  Wait(1); // make sure everything gets turned on okay
  int Position1 = 0, SensorOld, SensorNew;
  while(true)
  {
    SendRS485Number(Position1);
    WaitForMessageToBeSent();
    // Send the position of the tray
    SensorNew = SENSOR_2;
    RectOut(Position1, 0, 24, 4);
    Wait(30);
    ClearScreen();
    SensorOld = SensorNew;
    SensorNew = SENSOR_2;
    SensorNew -= SensorOld;
    Position1 += SensorNew;
    //Calculate the new position of the tray
    if(Position1 < 0)
    {
      Position1 = 0;
    }
    if(Position1 > 76)
    {
      Position1 = 76;
    }
    //Make sure the tray doesn't go too far to the side
  }
}
The slave program:

Code: Select all

inline void WaitForMessageToBeSent()
{
  while(RS485SendingData())
    Wait(1);
}

task main()
{
  UseRS485();
  // make sure the RS485 system is turned on
  RS485Enable();
  // initialize the UART to default values
  // RS485Initialize();
  // configure the UART (this is equivalent to RS485Initialize)
  RS485Uart(HS_BAUD_DEFAULT, HS_MODE_DEFAULT);
  Wait(1);
  int BallX, BallY, Position1, Position2 = 0, SensorOld, SensorNew;
  TextOut(0, LCD_LINE4, "Sanding by...");
  //Stand by until an RS485 message is received
  while(true)
  {
    until(RS485DataAvailable());
    RS485Read(Position1);
    //Wait until it receives a message, and write that number as the position
    PlayTone(500, 25);
    //Play a sond to indicate that it is indeed receiving a message
    RectOut(Position1, 0, 24, 4);
    //Display the tray at the received postition
    Wait(30);
    ClearScreen();
  }
}
The problem is, it doesn't work. The slave program stands by and waits for the master to start. And when it starts, the slave program is supposed to start displaying the master's tray. It kind of does that. As in, it simply displays it at one position and it never moves regardless of whether or not you move it on the master NXT. I tried the programs by John in the original post, and they work, but mine doesn't. So I must be doing something wrong. What am I doing wrong?

Re: NXC: Non-responsive RS485 Receive

Posted: 07 Jun 2012, 03:11
by mattallen37
I don't know that this would have any effect on the RS485 operation, but try changing the slave program to this:

Code: Select all

inline void WaitForMessageToBeSent()
{
  while(RS485SendingData())
    Wait(1);
}

task main()
{
  UseRS485();
  // make sure the RS485 system is turned on
  RS485Enable();
  // initialize the UART to default values
  // RS485Initialize();
  // configure the UART (this is equivalent to RS485Initialize)
  RS485Uart(HS_BAUD_DEFAULT, HS_MODE_DEFAULT);
  Wait(1);
  int BallX, BallY, Position1, Position2 = 0, SensorOld, SensorNew;
  TextOut(0, LCD_LINE4, "Sanding by...");
  //Stand by until an RS485 message is received
  while(true)
  {
    until(RS485DataAvailable());
    RS485Read(Position1);
    //Wait until it receives a message, and write that number as the position
    PlayTone(500, 25);
    //Play a sond to indicate that it is indeed receiving a message
    ClearScreen();
    RectOut(Position1, 0, 24, 4);
    //Display the tray at the received postition
  }
}