NXC: RS-458

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
Post Reply
webstorms
Posts: 38
Joined: 10 Mar 2011, 15:27

NXC: RS-458

Post by webstorms »

Hello Forum,
I'm close to crying. I'm eager to get my two NXTs communicating with each other through the RS-485 port. I'm trying to establish the communication with NXC. Yet unsuccessful. I'm using the latest version of the nbc compiler available for mac.

On my mac (running: 10.6.6) I get a few errors when compiling John Hansen's example: ex_RS485Receive.nxc (http://bricxcc.sourceforge.net/nbc/nxcd ... le.html#a0)

Here are the first three (it kinda goes on like this…):
#Error: Undefined Identifier RS485Enable File[…] ; line 8
# RS485Enable(
#----------------------
#Error: ";" expected File […] ; line 8
# RS485Enable()
#----------------------
#Error: Unmatched close parenthesis File […] ; line 8
# RS485Enable();

On my mom's mac (running: 10.5.8) I get this error:
#Error: Preprocessor macro function does not match instance (#asm{__UseRS485() })

Now why would the errors change when using the same compiler? And why won't the example code compile successfully? Please help me, I need to get this running real real real soon for my Science Fair Project! I will be your biggest fan if you can help me out. Do I need to include a file perhaps?

Thanks in advanced
webstorms
Posts: 38
Joined: 10 Mar 2011, 15:27

Re: NXC: RS-458

Post by webstorms »

Has anybody else been able to compile this example?
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC: RS-458

Post by mattallen37 »

That example compiled perfectly fine for me. I am running Win 7 64-bit, with BCC 3.3.8.10, and NBC 1.2.1.r4.

I don't think I have tried running the examples, but I have successfully used my own RS-485 programs.

Edit: I am running 1.31 EFW.
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
webstorms
Posts: 38
Joined: 10 Mar 2011, 15:27

Re: NXC: RS-458

Post by webstorms »

Could you share your code? Could you try compile the example? That would help me a lot.

Thanks though. :)
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC: RS-458

Post by mattallen37 »

Well, it is certainly not in a "share" type setup. I used these for debugging the lib I was writing. Here is the lib:

Code: Select all

/*
My RS485 protocol data specs:

Sending byte array looks like this:
  Senders address, Target address, Commands(flags), Data1, Data2, ..., Data n

Sending Ping looks like this:
  Senders address, Target address, Ping Flag Value
  
Acknowledgement looks like this:
  Senders address, Target address, Acknowledgement Flag Value

Returned values
-2 timeout
-1 something went wrong, probably not right address
0  not acknowledged
Command = success
*/

#define Master485Address 0x00 //The address of this NXT
#define Slave1485Address 0x01 //Slave number 1's address

//Master to slave flags
#define PingValue       0x08   //Return an Acknowledgement
#define WriteValue      0x10   //Write registers
#define ReadBackValue   0x20   //Return Values

//Slave to master flags
#define Acknowledge     0x01   //Result returned from a ping or write-only command

void SendRS485ByteArray (byte SenderAddress, byte TargetAddress, byte Command, byte SendData[]){
  byte SendCompleteData[];
  byte SendCompleteDataLength=ArrayLen(SendData)+3;
  ArrayInit(SendCompleteData, 0, SendCompleteDataLength);
  SendCompleteData[0]=SenderAddress;
  SendCompleteData[1]=TargetAddress;
  SendCompleteData[2]=Command;
  byte i=0;
  repeat(ArrayLen(SendData)){
    SendCompleteData[i+3]=SendData[i];
    i++;
  }
  string StringSendData = FlattenVar(SendCompleteData);         //Flatten it into a string
  SendRS485String(StringSendData);                              //Send the string
  until(HSOutputBufferOutPtr() == StrLen(StringSendData)+1);    //Wait until the string has been sent
}

int MasterReadRS485ByteArray (byte My485Address, byte BytesToReceive, int TimeOut, byte & InArray[]){
  bool TimedOut=false;
  byte TimePassed=0;                                                              //Reset the timeout counter
  byte cnt;
  string InString;
  byte RawInArray[];
  byte RawInArraySize=BytesToReceive+3;
  ArrayInit(RawInArray, 0, RawInArraySize);

  until (HSInputBufferInPtr() >= (BytesToReceive+4) || TimedOut){ //Until whole string is received
    Wait(1);                                            //Wait 1 ms
    if (TimeOut==0){                          //If TimeOut equals 0, then don't time out.
      TimedOut=false;
    }
    else{
      TimePassed++;                                     //increase the timer
      if (TimePassed>=TimeOut){
        TimedOut=true;
      }
    }
  }
  if (TimedOut){                            //If the timeout took place
    return -2;
  }
  else{                                     //If the timeout did not take place
    cnt=HSInputBufferInPtr();
    GetHSInputBuffer(0, cnt, InString);                 //Read the buffer
    SetHSInputBufferInPtr(0);
    UnflattenVar(InString, RawInArray);                 //Unflatten the string into an array
    byte SendersAddress=RawInArray[0];
    byte TargetsAddress=RawInArray[1];
    byte Command       =RawInArray[2];
    if (TargetsAddress==My485Address)                   //If the RdataC[0] contains this NXT's address, read the rest
    {
      ArraySubset(InArray, RawInArray, 3, NA);
      return Command;
    }
  }
  return -1;
}

void MasterSendPing(byte My485Address, byte TargetAddress){
  byte PingData[3];
  ArrayBuild(PingData, My485Address, TargetAddress, PingValue); //Build the array to send
  string StringPingData = FlattenVar(PingData);                 //Flatten it into a string
  SendRS485String(StringPingData);                              //Send the string
  until(HSOutputBufferOutPtr() == StrLen(StringPingData)+1);    //Wait until the string has been sent
}

int MasterCheckAcknowledgement(byte My485Address, int TimeOut){
  bool TimedOut=false;
  byte TimePassed=0;                                                              //Reset the timeout counter
  string InString;
  byte RawInArray[];
  ArrayInit(RawInArray, 0, 3);

  until (HSInputBufferInPtr() == 4 || TimedOut){   //Until whole string is received
    Wait(1);                                                   //Wait 1 ms
    if (TimeOut==0){                     //If TimeOut equals 0, then don't time out.
      TimedOut=false;
    }
    else{
      TimePassed++;                      //increase the timer
      if (TimePassed>=TimeOut){
        TimedOut=true;
      }
    }
  }
  if (TimedOut){                         //If the timeout took place
    return -2;
  }
  else{                                  //If the timeout did not take place
    GetHSInputBuffer(0, 4, InString);                          //Read the buffer
    SetHSInputBufferInPtr(0);
    UnflattenVar(InString, RawInArray);                        //Unflatten the string into an array
    byte SendersAddress=RawInArray[0];
    byte TargetsAddress=RawInArray[1];
    byte Command       =RawInArray[2];
    if (TargetsAddress==My485Address)                          //If the TargetsAddress contains this NXT's address, read the rest
    {
      return Command;
    }
  }
  return -1;
}

int MasterPing(byte My485Address, byte TargetAddress, int TimeOut){
  MasterSendPing(My485Address, TargetAddress);
  return MasterCheckAcknowledgement(My485Address, TimeOut);
}

void SlaveAcknowledge(byte My485Address, byte TargetAddress){
  byte AcknowledgeData[3];
  ArrayBuild(AcknowledgeData, My485Address, TargetAddress, Acknowledge); //Build the array to send
  string StringAcknowledgeData = FlattenVar(AcknowledgeData);        //Flatten it into a string
  SendRS485String(StringAcknowledgeData);                                //Send the string
  until(HSOutputBufferOutPtr() == StrLen(StringAcknowledgeData)+1);      //Wait until the string has been sent
}

int SlaveReadAndRespondRS485ByteArray (byte My485Address, byte BytesToReceive, int TimeOut, byte SendValues[], byte & InArray[]){
  byte GoOn=0;
  int TimePassed=0;                                                              //Reset the timeout counter
  byte cnt;
  string InString;
  byte RawInArray[];

  until (HSInputBufferInPtr() >= (BytesToReceive+4) || GoOn!=0){   //Until whole string is received
    Wait(1);
    if(HSInputBufferInPtr()==4){                                   //If only a ping
      Wait(3);
      if(HSInputBufferInPtr()==4){                                 //Confirm only a ping
        GoOn=1;
      }
    }
    if (TimeOut!=0){                     //If TimeOut equals 0, then don't time out.
      TimePassed++;                      //increase the timer
      if (TimePassed>=TimeOut){
        GoOn=2;
      }
    }
  }
  
  if (GoOn==2){                          //If TimedOut
    return -2;                           // Return -2
  }

  else{                                  //If it didn't time out
    if (GoOn==0){
      byte RawInArraySize=BytesToReceive+3;
      ArrayInit(RawInArray, 0, RawInArraySize);
      cnt=HSInputBufferInPtr();
      GetHSInputBuffer(0, cnt, InString);  //Read the buffer
      SetHSInputBufferInPtr(0);
      UnflattenVar(InString, RawInArray);  //Unflatten the string into an array
      byte SendersAddress=RawInArray[0];
      byte TargetsAddress=RawInArray[1];
      byte Command       =RawInArray[2];
      if (TargetsAddress==My485Address)
      {
        if (ReadBackValue==(Command&ReadBackValue)){
          SendRS485ByteArray (My485Address, SendersAddress, Command, SendValues);
        }
        if (WriteValue==(Command&WriteValue)){
          ArraySubset(InArray, RawInArray, 3, NA);
        }
        return Command;
      }
    }
    if (GoOn==1){
      ArrayInit(RawInArray, 0, 3);
      cnt=HSInputBufferInPtr();
      GetHSInputBuffer(0, cnt, InString);  //Read the buffer
      SetHSInputBufferInPtr(0);
      UnflattenVar(InString, RawInArray);  //Unflatten the string into an array
      byte SendersAddress=RawInArray[0];
      byte TargetsAddress=RawInArray[1];
      byte Command       =RawInArray[2];
      if (TargetsAddress==My485Address)
      {
        if (PingValue==(Command&PingValue)){
          SlaveAcknowledge(My485Address, SendersAddress);
          return Command;
        }
      }
    }
  }
  return -1;
}
Master program:

Code: Select all

/*
Returned values
-2 timeout
-1 something went wrong, probably not right address
0  not acknowledged
Command = success
*/
#include "MyRS485 lib.nxc" //Note, the main library

#define My485Address     0x00 //The address of this NXT
#define Master485Address 0x00 //The address of the master
#define Slave1485Address 0x01 //Slave number 1's address

//Master to slave flags
#define PingValue       0x08   //Return an Acknowledgement
#define WriteValue      0x10   //Write registers
#define ReadBackValue   0x20   //Return Values

//Slave to master flags
#define Acknowledge 0x01   //Result returned from a ping or write-only command

#define BytesToReceive 10
#define TimeOut        15

byte Sdata[];           //Array to send data

byte Rdata[BytesToReceive];

byte Svar0,Svar1,Svar2,Svar3,Svar4,Svar5,Svar6,Svar7,Svar8,Svar9;

int result;

task display()          //Display the results
{
  while(true)
  {
    ClearScreen();
    NumOut(0, LCD_LINE1,Rdata[0]);
    NumOut(0, LCD_LINE2,Rdata[1]);
    NumOut(0, LCD_LINE3,Rdata[2]);
    NumOut(0, LCD_LINE4,Rdata[3]);
    NumOut(0, LCD_LINE5,Rdata[4]);

    NumOut(50, LCD_LINE1,Rdata[5]);
    NumOut(50, LCD_LINE2,Rdata[6]);
    NumOut(50, LCD_LINE3,Rdata[7]);
    NumOut(50, LCD_LINE4,Rdata[8]);
    NumOut(50, LCD_LINE5,Rdata[9]);

    NumOut(0, LCD_LINE8,result);

    Wait(50);
  }
}

task RS()
{
  while (true)
  {
    Svar0=Random();
    Svar1=Random();
    Svar2=Random();
    Svar3=Random();
    Svar4=Random();
    Svar5=Random();
    Svar6=Random();
    Svar7=Random();
    Svar8=Random();
    Svar9=Random();
    ArrayBuild(Sdata, Svar0,Svar1,Svar2,Svar3,Svar4,Svar5,Svar6,Svar7,Svar8,Svar9);

    SendRS485ByteArray (My485Address, Slave1485Address, (WriteValue|ReadBackValue), Sdata);
    result=MasterReadRS485ByteArray (My485Address, BytesToReceive, TimeOut, Rdata);

    //result=MasterPing(My485Address, Slave1485Address, TimeOut);
    
    if (result==-1){
      PlayToneEx(500,100,3,0);
    }
    if (result==-2){
      PlayToneEx(1000,10,1,0);
    }
    Wait(500);
  }
}

task main()
{
  SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);   //Set up for RS485
  SetHSState(HS_INITIALISE);                    //      ''
  SetHSFlags(HS_UPDATE);                        //      ''
  SetHSSpeed(HS_BAUD_921600);
  SetHSInputBufferInPtr(0);
  SetHSInputBufferOutPtr(0);
  start display;
  start RS;
}
Slave program:

Code: Select all

/*
My RS485 protocol data specs:

Sending byte array looks like this:
  Senders address, Target address, Commands/flags, Data1, Data2, ..., Data n

Sending Ping looks like this:
  Senders address, Target address, Ping Flag Value

Acknowledgement looks like this:
  Senders address, Target address, Acknowledgement Flag Value

Returned values
-2 timeout
-1 something went wrong
0  not acknowledged
Command = success
*/
#include "MyRS485 lib.nxc" //Note, the main library

#define My485Address     0x01 //The address of this NXT
#define Master485Address 0x00 //The address of the master
#define Slave1485Address 0x01 //Slave number 1's address

//Master to slave flags
#define PingValue       0x08   //Return an Acknowledgement
#define WriteValue      0x10   //Write registers
#define ReadBackValue   0x20   //Return Values

//Slave to master flags
#define Acknowledge 0x01   //Result returned from a ping or write-only command

#define BytesToReceive 10
#define TimeOut        500

byte Sdata[];

byte Rdata[BytesToReceive];

byte Svar0,Svar1,Svar2,Svar3,Svar4,Svar5,Svar6,Svar7,Svar8,Svar9;


int result;

task display()
{
  while(true)
  {
    ClearScreen();
    NumOut(0, LCD_LINE1,Rdata[0]);
    NumOut(0, LCD_LINE2,Rdata[1]);
    NumOut(0, LCD_LINE3,Rdata[2]);
    NumOut(0, LCD_LINE4,Rdata[3]);
    NumOut(0, LCD_LINE5,Rdata[4]);

    NumOut(50, LCD_LINE1,Rdata[5]);
    NumOut(50, LCD_LINE2,Rdata[6]);
    NumOut(50, LCD_LINE3,Rdata[7]);
    NumOut(50, LCD_LINE4,Rdata[8]);
    NumOut(50, LCD_LINE5,Rdata[9]);

    NumOut(0, LCD_LINE8,result);
    Wait(75);
  }
}


task RS()
{
  while (true)
  {
    Svar0=Random();
    Svar1=Random();
    Svar2=Random();
    Svar3=Random();
    Svar4=Random();
    Svar5=Random();
    Svar6=Random();
    Svar7=Random();
    Svar8=Random();
    Svar9=Random();
    ArrayBuild(Sdata, Svar0,Svar1,Svar2,Svar3,Svar4,Svar5,Svar6,Svar7,Svar8,Svar9);

    result=SlaveReadAndRespondRS485ByteArray (My485Address, BytesToReceive, TimeOut, Sdata, Rdata);
    if (result==-1){
      PlayToneEx(500,100,3,0);
    }
    if (result==-2){
      PlayToneEx(1000,10,1,0);
    } 
  }
}

task main()
{
  SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);
  SetHSState(HS_INITIALISE);
  SetHSFlags(HS_UPDATE);
  SetHSSpeed(HS_BAUD_921600);
  SetHSInputBufferInPtr(0);
  SetHSInputBufferOutPtr(0);
  start display;
  start RS;
}
I just ran a test, exactly as they are, and it worked fine. The master sends 10 numbers (random) to the slave, and the slave responds with 10 numbers (random). I really don't think I can explain it very well, as it was quite a while ago that I wrote them. I do know however, that the lib does not do any error checking (no CRC or checksum).

Hopefully you will be able to get something out of it.
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: NXC: RS-458

Post by afanofosc »

webstorms wrote:Hello Forum,
Here are the first three (it kinda goes on like this…):
#Error: Undefined Identifier RS485Enable File[…] ; line 8
# RS485Enable(
#----------------------
#Error: ";" expected File […] ; line 8
# RS485Enable()
#----------------------
#Error: Unmatched close parenthesis File […] ; line 8
# RS485Enable();
These kind of errors suggest that you are not telling the compiler to target the enhanced NBC/NXC firmware, which these API functions require. Make sure that you pass -EF on the command line. Also make sure that you have the latest enhanced NBC/NXC firmware on your brick. I am fairly sure that adding -EF to your command line will fix the problem. Are you using nxtcc or the nbc command line compiler? If you are using nxtcc then I think you can set the compiler command line options via a preferences dialog - but I can't recall for sure what I have implemented in that tool at this point.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
webstorms
Posts: 38
Joined: 10 Mar 2011, 15:27

Re: NXC: RS-458

Post by webstorms »

Thank you so much John! It compiles. :D and thanks for the source code matt.
Post Reply

Who is online

Users browsing this forum: No registered users and 44 guests