C++, Fantom API: I2C Sensors

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
aswin0
Posts: 201
Joined: 29 Sep 2010, 06:58

Re: C++, Fantom API: I2C Sensors

Post by aswin0 »

John,

When I stated robotC has full duplex communication I was not referring to communication from the NXT to a sensor. I meant communication (over Bluetooth) between a NXT and a pc. Remember we were talking about direct commands, and not about I2C commands.

From the robotC help:
The ROBOTC BT messaging has been optimized for a single slave connection on the master. This allows for significantly less latency on the BT message link. Slaves can immediately transmit messages without having to wait for a polling request from the master. ROBOTC also allows for multiple slave support, but a description of this is beyond the scope of this tutorial. This optimization gives a performance improvement of three to 20 times over other architecture that support – at a significantly reduced performance level – multiple simultaneous slaves.
My blog: nxttime.wordpress.com
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: C++, Fantom API: I2C Sensors

Post by afanofosc »

The OP may have been talking about direct commands via the Fantom API but nowhere does he mention Bluetooth. He was asking about how to read I2C sensor values from the NXT (via Fantom) and why he could not read a US value with LSRead after writing to 0x41.
why do I need that extra LSWRITE to send the read measurement byte 0 command? I thought that this should work without it but I get sent in an infinite loop without it.
Not only was the OP not talking about Bluetooth but where in the text of your response that I quoted do you mention Bluetooth?

The way the direct command protocol works over Bluetooth or USB has nothing at all to do with why you can't read the US sensor value with LSRead after writing to 0x41 with LSWrite. And I'm under the impression that the direct command protocol works pretty much exactly the same in the RobotC firmware as it does in the standard firmware. There's no "full duplex" option when communicating with an NXT via the Fantom drivers with direct commands.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
aswin0
Posts: 201
Joined: 29 Sep 2010, 06:58

Re: C++, Fantom API: I2C Sensors

Post by aswin0 »

I see your point. I assumed he had a client server setup as I only ever used direct commands in a client server configuration. But, and there you are right again, even then you'll only benefit from full duplex when sending messages to mailboxes between two programs.
I do not know whether you can benefit from full duplex when using the fantom API, I never tried that. But I know you can when using a serial port to communicate between a program on the NXT and one on a PC.
My blog: nxttime.wordpress.com
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: C++, Fantom API: I2C Sensors

Post by afanofosc »

I may not understand what you are saying about full-duplex vs half-duplex wrt Bluetooth communication in the standard NXT firmware vs the RobotC firmware. It is certain that the standard firmware is fully capable of writing from a slave to a master on connection 0 whenever it wants to. That is precisely what happens when a direct command comes into the Comm module from a PC. The slave NXT creates a packet of data and it writes it to the Bluetooth output buffer for connection 0 and sends the response to the PC.

I just had a browse through the source code in c_cmd.c and c_comm.c and as far as I can see there is absolutely nothing there that would stop a program running on a slave from writing a message via Bluetooth over connection 0 to its master. The system call CommBTWrite takes a connection number from 0 to 3.

Code: Select all

//cCmdWrapCommBTWrite
//ArgV[0]: (return) Status byte, SBYTE
//ArgV[1]: Connection index, 0-3
//ArgV[2]: Buffer
//
NXT_STATUS cCmdWrapCommBTWrite(UBYTE * ArgV[])
{
  SBYTE * pReturnVal =  (SBYTE*)(ArgV[0]);
  UBYTE Connection   = *(ArgV[1]);
  UBYTE * pBuf;
  UWORD BufLength;
  DV_INDEX DVIndex;

  //Resolve array arguments
  DVIndex = *(DV_INDEX *)(ArgV[2]);
  pBuf = cCmdDVPtr(DVIndex);

  BufLength = DV_ARRAY[DVIndex].Count;

  //If there's an old error code hanging around, clear it before proceeding.
  if (VarsCmd.CommStat < 0)
    VarsCmd.CommStat = SUCCESS;

  //!!! Only first 256 bytes could possibly make it through! Should return error on longer input?
  //!!! Not requesting a wait-for-response because only known use doesn't read responses.
  pMapComm->pFunc(SENDDATA, (UBYTE)BufLength, Connection, FALSE, pBuf, (UWORD*)&(VarsCmd.CommStat));

  //!!! Reasonable to wrap below code in cCmdCommBTCheckStatus?
  //INPROGRESS means our request was accepted by His Funkiness of pFunc
  if (VarsCmd.CommStat == (SWORD)INPROGRESS)
  {
    *pReturnVal = STAT_COMM_PENDING;

    //Set DirtyComm flag so stream is reset after program ends
    VarsCmd.DirtyComm = TRUE;
  }
  //Translate BTBUSY to ERR_COMM_CHAN_NOT_READY
  else if (VarsCmd.CommStat == (SWORD)BTBUSY)
  {
    *pReturnVal = ERR_COMM_CHAN_NOT_READY;
  }
  else
  {
    *pReturnVal = UNPACK_STATUS(VarsCmd.CommStat);
  }

  return (NO_ERR);
}
It passes the connection number and the outbound buffer data to the Comm module's SENDDATA function. Here's the relevant code from c_comm.c:

Code: Select all

      case SENDDATA:
      {

        /* Param2 indicates the port that the data should be */
        /* be sent on - param1 indicates the number of data  */
        /* to be sent. pName is the pointer to the data      */
        if (Param1 <= sizeof(VarsComm.BtModuleOutBuf.Buf))
        {
          if ('\0' != IOMapComm.BtConnectTable[Param2].Name[0])
          {
            VarsComm.BtCmdData.ParamOne   = Param1;
            VarsComm.BtCmdData.ParamTwo   = Param2;
            VarsComm.BtCmdData.ParamThree = Param3;
            memcpy((VarsComm.BtModuleOutBuf.Buf), pName, Param1);
            VarsComm.ActiveUpdate = UPD_SENDDATA;
          }
          else
          {
            ReturnVal  = (UWORD)ERR_COMM_CHAN_NOT_READY;
            ReturnVal |= 0x8000;
          }
        }
        else
        {
          ReturnVal  = (UWORD)ERR_COMM_BUFFER_FULL;
          ReturnVal |= 0x8000;
        }
      }
      break;
In the case for handling UPD_SENDDATA it calls dBtSendMsg once the stream is open (which it may already be). This function is exactly the same routine that the firmware calls to send out the response message to any direct or system command that the firmware automatically handles under the hood.

Again, I could be wrong, but to the best of my knowledge the only "half-duplex" thing in the standard firmware related to Bluetooth messaging is the design of the standard NXT firmware's mailbox system and its associated protocol for sending mailbox messages between two NXTs. In the standard firmware's design of the mailbox system a slave NXT never sends a message directly to a mailbox on the master NXT. Instead it writes to a local response mailbox and the master NXT has to poll a slave NXT for a message. This is the kind of behavior that you were describing in your original response on this thread. But - again to my knowledge - that is strictly limited to the mailbox system and not to Bluetooth communication in general.

One thing that the RobotC firmware may do better/differently than the standard NXT firmware is optimize how and when it switches the Bluetooth subsystem (which is exactly the same for both firmwares) between command mode and data mode. Since switching back and forth is time-consuming the better you manage this state the more optimal you can communicate via Bluetooth. In the standard NXT firmware, though, this normally only becomes an issue when you have multiple connections that you need to send data over. To switch from one connection to another you have to close and reopen a stream to the new connection and that requires switching from data mode to command mode and then back to data mode again. I believe that is one of the reasons why the RobotC firmware (from what I have gathered) only allows one slave at a time.

A Bluetooth connection with an active stream is, to my knowledge, a bi-direction (aka full-duplex) serial port. Here's a quote from http://wiresareobsolete.com/wordpress/2 ... th-rfcomm/ that seems to back me up:
RFCOMM is a layer of the Bluetooth Protocol Stack that provides serial data transfer services (via “sockets”). It is the base of many of the common profiles such as Dialup Networking (DUN) and Serial Port Profile (SPP). In essence, though, it is a way for developers to create a full duplex serial data stream between two points.
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
lizard381
Posts: 44
Joined: 16 Nov 2010, 19:57

Re: C++, Fantom API: I2C Sensors

Post by lizard381 »

Sorry I took so long to get back to this.
afanofosc wrote:You'd have to post your code before anyone could say definitively what, if anything, you are doing wrong. Are you using your special direct command replacement function that we discussed here: viewtopic.php?f=3&t=487? If so then it may be a problem with the way you are draining the response. Are you getting back non-zero status values?
I can't exactly post my code, but I did check the status values, and I am getting non-zero status values. I'm actually getting a NI-VISA status code, 0xBFFF003E, VI_ERROR_IO, "Could not perform operation because of I/O error". I've checked online, and a fair amount of people seemed to have gotten this error when using visa libraries and communicating over usb or serial, and I'm using usb. The proposed solution is to set the buffer size before using the write command, which I will try and report back if this is successful (or if it isn't!).
afanofosc wrote:The OP may have been talking about direct commands via the Fantom API but nowhere does he mention Bluetooth. He was asking about how to read I2C sensor values from the NXT (via Fantom) and why he could not read a US value with LSRead after writing to 0x41.
You're correct, as I mentioned above, I'm not using bluetooth, I'm using USB, and the other poster (myself) is not a he, I'm a she :) .
I haven't grown past my playing with Legos stage and I don't think I want to :)
Blog: http://nuhlikklebickle.blogspot.com
Kami
bullestock
Posts: 27
Joined: 29 Sep 2010, 19:34
Location: Denmark
Contact:

Re: C++, Fantom API: I2C Sensors

Post by bullestock »

afanofosc wrote:The RobotC firmware simply supports a special fast I2C mode that does not exist in the standard NXT firmware and is not always supported by third-party NXT I2C device manufacturers like HiTechnic.
As does the LeJOS firmware.
bullestock
Posts: 27
Joined: 29 Sep 2010, 19:34
Location: Denmark
Contact:

Re: C++, Fantom API: I2C Sensors

Post by bullestock »

bullestock wrote:
mattallen37 wrote:
aswin0 wrote:...A few years ago someone made a table comparing all different languages/firmwares. I do not have the link but i'm sure you can find it. The table needs an update however. (this could well be a joined effort on this forum)
This is probably what you are talking about.

I agree, it could use an update.
Incidentally, a few days ago I sent some benchmark data for LeJOS to Steve Hassenplug, and he does intend to update the page.
As the page has not been updated yet, let me share my findings:

LeJOS NXJ version: 0.85

Loop counts:

With display 54177
Without display 70543

Size of compiled file: 6256 bytes.
Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests