Page 1 of 1

SysCommHSWrite question

Posted: 20 Feb 2013, 03:09
by tabbycatrobots
I'm building a robot with 2 NXTs and want to use the port 4 HS communications. I've made up some simple test
programs, so I can understand what code is required, before I use it in the full program with motor control, BT, etc.

My programs using SysCommHSRead and SysCommHSWrite aren't working. I've included listings below, so
if anyone can offer ideas, thank you.

The physical connection is okay, because I have sent data both ways using
SetHSOutputBuffer(0, mlen, msg);
SetHSOutputBufferOutPtr(0);
SetHSOutputBufferInPtr(mlen);
SetHSState(HS_SEND_DATA);
SetHSFlags(HS_UPDATE); //send it
and
GetHSInputBuffer(0, inPtr, buffer);
based on ideas in Daniele Benedettelli's book.

I'm running firmware: FW NBC/NXC 1.31 and BricxCC Build 3.3.8.8.

I want to investigate HS port 4 more to better understand what will work best in my program, so wrote the
following programs. Actually for this post, I've just listed the programs up to the point where they appear to
be failing.

Code: Select all

//  WYPR_01_SC_Master.nxc
//  Created by: hdrake      2013Feb18


task main()
{
    unsigned long   data_tbs;

    byte            port_4_speed;

    byte            port_4_state;

    byte            snd_msg_type;
    byte            snd_data_hi;
    byte            snd_data_lo;
    byte            snd_msg_id;

    byte            ack_msg_type;
    byte            ack_data_hi;
    byte            ack_data_lo;
    byte            ack_msg_id;

    byte            exc_msg_type;
    byte            exc_data_hi;
    byte            exc_data_lo;
    byte            exc_msg_id;

    bool            receive_ok;

    string          data_as_string;
    string          ack_nack;

    CommHSCheckStatusType   hs_status;
    CommHSControlType       hs_control_args;
    CommHSReadWriteType     hs_write_args;
    CommHSReadWriteType     hs_read_ack_args;
    CommHSReadWriteType     hs_read_exc_args;

    SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);  //  Do I need this?

    hs_control_args.Command = HS_CTRL_INIT;
    hs_control_args.BaudRate = HS_BAUD_921600;
    hs_control_args.Mode = HS_MODE_8N1;
    SysCommHSControl(hs_control_args);

//  Not sure if I need the following?
    hs_control_args.Command = HS_CTRL_INIT;
    SysCommHSControl(hs_control_args);

    TextOut(0, LCD_LINE1, "HS Cmd Result = ", DRAW_OPT_CLEAR_WHOLE_SCREEN);
    NumOut(0, LCD_LINE2, hs_control_args.Result);  //  = 5 ?
    until(ButtonPressed(BTNCENTER, TRUE));
    Wait(2000);


    data_tbs = 0xfedcba98;
    data_as_string = NumToStr(data_tbs);

    TextOut(0, LCD_LINE1, "data_tbs = ", DRAW_OPT_CLEAR_WHOLE_SCREEN);
    NumOut(0, LCD_LINE2, data_tbs);

//    TextOut(0, LCD_LINE3, "data_as_str = ");
//    TextOut(0, LCD_LINE4, data_as_string);

    until(ButtonPressed(BTNCENTER, TRUE));
    Wait(2000);

    snd_msg_type = 0xfe;
    snd_data_hi = 0xdc;
    snd_data_lo = 0xba;
    snd_msg_id = 0x98;

    ArrayBuild(hs_write_args.Buffer,
               snd_msg_type, snd_data_hi, snd_data_lo, snd_msg_id);

//  Send the command.
    SysCommHSWrite(hs_write_args);
    Wait(2);
    if (hs_write_args.Status != NO_ERR)
    {
        TextOut(0, LCD_LINE3, "error on write =");
        NumOut(0, LCD_LINE4, hs_write_args.Status);  //  = 3 ?
        until(ButtonPressed(BTNCENTER, TRUE));
        Wait(2000);
    }

Code: Select all

//  WHYY_01_SC_Slave.nxc
//  Created by: hdrake      2013Feb18

//  This program tries to receive a 32 bit (unsigned long) value on the
//  HS RS485 port 4.  It uses the SysCommHS* Syscall functions.



////////////////////////////////////////////////////////////////////////////////
//                                  MAIN
////////////////////////////////////////////////////////////////////////////////
task main()
{
    unsigned long   data_tbs;
    unsigned long   incoming_cmd;
    unsigned long   cmd_rcvd_ok;
    unsigned long   cmd_completed;
    unsigned long   cmd_rcv_error;

    byte            port_4_speed;

    byte            cmd_msg_type;
    byte            cmd_data_hi;
    byte            cmd_data_lo;
    byte            cmd_msg_id;

    byte            ack_msg_type;
    byte            ack_data_hi;
    byte            ack_data_lo;
    byte            ack_msg_id;

    byte            exc_msg_type;
    byte            exc_data_hi;
    byte            exc_data_lo;
    byte            exc_msg_id;

    bool            receive_ok;

    string          data_as_string;
    string          ack_nack;

    CommHSCheckStatusType   hs_status;
    CommHSControlType       hs_control_args;
    CommHSReadWriteType     hs_read_cmd_args;
//    CommHSReadWriteType     hs_write_ack_args;
//    CommHSReadWriteType     hs_write_exc_args;
    CommHSReadWriteType     hs_write_args;


    SetSensorType(IN_4, SENSOR_TYPE_HIGHSPEED);

    hs_control_args.Command = HS_CTRL_INIT;
    hs_control_args.BaudRate = HS_BAUD_921600;
    hs_control_args.Mode = HS_MODE_8N1;

    SysCommHSControl(hs_control_args);

    hs_control_args.Command = HS_CTRL_INIT;

    SysCommHSControl(hs_control_args);

    if (hs_control_args.Result)
    {
        TextOut(0, LCD_LINE1, "hi-speed initialized");  //  Nothing 
//  appears after this.
    }



//  Check for Command message.
    do
    {
        SysCommHSCheckStatus(hs_status);
    } until(hs_status.DataAvailable)

    Wait(1);

//  Read command message.
    SysCommHSRead(hs_read_cmd_args);

    cmd_msg_type = hs_read_cmd_args.Buffer[0];
    cmd_data_hi = hs_read_cmd_args.Buffer[1];
    cmd_data_lo = hs_read_cmd_args.Buffer[2];
    cmd_msg_id = hs_read_cmd_args.Buffer[3];

    TextOut(0, LCD_LINE5, "cmd data = ");
    NumOut(4, LCD_LINE6, cmd_msg_type);
    NumOut(8, LCD_LINE6, cmd_data_hi);
    NumOut(12, LCD_LINE6, cmd_data_lo);
    NumOut(16, LCD_LINE6, cmd_msg_id);


It appears that the slave is doing a read and nothing is being received. The master, who is doing the write shows
hs_write_args.Status = 3. I'm lost at this point as to what is failing.

Any ideas, corrections, suggestions are appreciated.
Thanks.
Howard

Re: SysCommHSWrite question

Posted: 20 Feb 2013, 20:48
by afanofosc
I would first update to the NBC/NXC enhanced firmware version 1.32 and grab the BricxCC test release of 3.3.8.10. It is possible that there were API header bugs in 3.3.8.8 that affect these functions.

You can't use RS485 on the NXT unless you set the sensor type on port 4 to SENSOR_TYPE_HIGHSPEED. I recommend that you use UseRS485() instead. You also need to call RS485Enable();

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();
}

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
    RS485ReadEx(buffer, cnt);
//    RS485Read(buffer);
    // send out ACK
    RS485Write(ACK);
    WaitForMessageToBeSent();
    // display message
    TextOut(0, LCD_LINE1, buffer);
  }
}
John Hansen

Re: SysCommHSWrite question

Posted: 21 Feb 2013, 00:44
by tabbycatrobots
Thank you. I'll update the FW and BricxCC before trying any more experiments. Reading through your code,
I see the line
// RS485Initialize();
in both the sender and receiver programs. Why is it commented out? Does some other command negate
the need for it?

On a different level, is there a reliable-transmission or speed or other reason that you recommend using
the RS485* commands rather than the SetHS* commands or the SysCommHS* commands?

Thanks again for the help.

Howard

Edit to above post:
Please disregard my comment:
I see the line
// RS485Initialize();
in both the sender and receiver programs. Why is it commented out? Does some other command negate
the need for it?

I overlooked your comment:
(this is equivalent to RS485Initialize)
I apologize.

Howard