Page 1 of 2

C++, Fantom API: I2C Sensors

Posted: 10 Mar 2011, 19:12
by lizard381
After going through the documentation, I understand that I need to use the LSGETSTATUS, LSWRITE, and LSREAD direct commands to read data from the I2C sensors. I've gotten this to work in c++ but I don't understand why I had to do what I had to do. Basically, for an ultrasonic sensor, I have:

Code: Select all

LSWRITE (here I send 0x02 0x41 0x01 for the single shot mode)
do{
LSWRITE (here I send 0x02 0x42 for the read measurement byte 0)
bytesRead=LSGETSTATUS
}while(bytesRead<1)
LSREAD
My question is, 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.

Thanks,
Kami

Re: C++, Fantom API: I2C Sensors

Posted: 10 Mar 2011, 22:09
by aswin0
Hi,

The first lswrite Is to make a setting, there is no reply from this command.
After that you have to query for a reply. As the NXT is a slave it cannot send a message on its own, it has to be queried for a reply. If you want a second reading you will have to query for it again. This is called half duplex. Only if you have full duplex communication the slave is able to send a message on its own initiative. The NXT firmware does only support half duplex communication. The firmware that comes with robotc supports full duplex communication.

Re: C++, Fantom API: I2C Sensors

Posted: 10 Mar 2011, 22:17
by ricardocrl
Does RobotC have full-duplex?

Does it mean that a slave can spontaneously sent messages to a master, even being a laptop?

Where can I find more specific information about the differences between the firmwares?

Many thanks for the info.
Ricardo

Re: C++, Fantom API: I2C Sensors

Posted: 11 Mar 2011, 00:36
by aswin0
ricardocrl wrote:Does RobotC have full-duplex?

Does it mean that a slave can spontaneously sent messages to a master, even being a laptop?

Where can I find more specific information about the differences between the firmwares?

Many thanks for the info.
Ricardo
Yes it does. It's BlueTooth is very fast as well. I have a program that allowes you te send data over BT to excel. The NXT can transfer a message every 4-6 msec. (search for NXT2excel on my blog to get it). The downside is that robotc only supports a single slave, unlike the standard firmware that allowes for 3 slaves simultaniously.

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)

Re: C++, Fantom API: I2C Sensors

Posted: 11 Mar 2011, 02:00
by mattallen37
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.

Re: C++, Fantom API: I2C Sensors

Posted: 12 Mar 2011, 00:01
by lizard381
aswin0 wrote:Hi,

The first lswrite Is to make a setting, there is no reply from this command.
After that you have to query for a reply. As the NXT is a slave it cannot send a message on its own, it has to be queried for a reply. If you want a second reading you will have to query for it again. This is called half duplex. Only if you have full duplex communication the slave is able to send a message on its own initiative. The NXT firmware does only support half duplex communication. The firmware that comes with robotc supports full duplex communication.
Thanks! That helped a lot.

Re: C++, Fantom API: I2C Sensors

Posted: 12 Mar 2011, 00:25
by bullestock
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.

Re: C++, Fantom API: I2C Sensors

Posted: 23 Mar 2011, 22:49
by lizard381
This isn't just specific to I2C Sensors, but I didn't want to start a new thread. I seem to be having a problem where I can set the sensor type and sensor mode but I can't reset it within the same program [for instance, I first set the color sensor to colorfull/raw, then i want to set it to colorred/pctfullscale]. Similarly, I can read from each sensor once, but after that when I try to query the sensor it writes 0 bytes to the response buffer. If I restart the program I'm fine but this doesn't seem right. Is there some sort of buffer flushing I should be doing that I'm not doing?

Cheers,
Kami

Re: C++, Fantom API: I2C Sensors

Posted: 24 Mar 2011, 05:21
by afanofosc
aswin0 wrote: As the NXT is a slave it cannot send a message on its own, it has to be queried for a reply. If you want a second reading you will have to query for it again. This is called half duplex. Only if you have full duplex communication the slave is able to send a message on its own initiative. The NXT firmware does only support half duplex communication. The firmware that comes with robotc supports full duplex communication.
This doesn't make any sense to me.

http://www.interfacebus.com/I2C_Interfa ... ndard.html
I2C, due to its two-wire nature (one clock, one data) can only communicate half-duplex.
Also, from a PDF comparing 3 popular serial buses, JTAG, SPI, and I2c:
since there is only one data line full-duplex cannot be supported.
I2C is master/slave. This means nothing comes from the slave unless the master requests it. The NXT is the master and the I2C devices you attach to the NXT are the slaves. The RobotC firmware does not somehow magically enable something that the 2-wire I2C serial bus hardware simply cannot support.

See also

http://wiki.answers.com/Q/What_is_the_d ... 2c_and_spi
http://www.actel.com/documents/SPI_I2C_Interface_AN.pdf
http://www.allinterview.com/viewpost/348233.html

plus lots more.

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.

I ran an NXC version of Xander's i2c speed test program (see http://mightor.wordpress.com/2009/11/05 ... for-speed/). With its special fast mode the RobotC firmware is definitely faster but here are the numbers for the standard firmware:

Code: Select all

Read Size	Time taken	Bytes/s	Transaction time	Transactions/s
1	7000	143	7.00	143
2	8000	250	8.00	125
3	9000	333	9.00	111
4	10000	400	10.00	100
5	11000	455	11.00	91
6	12000	500	12.00	83
7	13000	538	13.00	77
8	13000	615	13.00	77
9	14000	643	14.00	71
10	15000	667	15.00	67
11	16000	688	16.00	63
12	17000	706	17.00	59
13	18000	722	18.00	56
14	18792	745	18.79	53
15	19000	789	19.00	53
16	20000	800	20.00	50
The NXC code, if you are interested (requires the enhanced NBC/NXC firmware to compile due to FormatNum usage):

Code: Select all

#define I2C_ADDR  0x02
#define I2C_REG   0x00

#define MAXREADS  1000

#define DO_I2C_REQUEST \
  asm { \
    syscall 21, __CLSWArgs0 \
    doloopWhilePending2: \
    syscall 23, __CLSCSArgs0 \
    brcmp EQ, doloopWhilePending2, __CLSCSArgs0.Result, 32 \
    syscall 22, __CLSRArgs0 \
  }

#define DO_I2C_REQUEST_WITH_YIELD \
  asm { \
    syscall 21, __CLSWArgs0 \
    doloopWhilePending2: \
    wait2 0, NA \
    syscall 23, __CLSCSArgs0 \
    brcmp EQ, doloopWhilePending2, __CLSCSArgs0.Result, 32 \
    syscall 22, __CLSRArgs0 \
  }

int time_taken[16];

int getbtn() {
  int result = -1;
  if (ButtonPressed(BTN1, false))
    result = BTN1;
  else if (ButtonPressed(BTN2, false))
    result = BTN2;
  else if (ButtonPressed(BTN3, false))
    result = BTN3;
  else if (ButtonPressed(BTN4, false))
    result = BTN4;
  return result;
}

void debounce() {
  while(getbtn() != -1) {
     Wait(MS_10);
  }
}

void displayStats(int index) {
  TextOut(0, LCD_LINE1, FormatNum("Size:    %4d B", index + 1), true);
	TextOut(0, LCD_LINE8, FormatNum("Time:    %4d ms", time_taken[index]));
}

task main() {
  SetSleepTime(30);
  SetSensorLowspeed(S1);
  byte I2CRequest[] = {I2C_ADDR, I2C_REG};
  byte I2CReply[];
  int index = 0;

  TextOut(0, LCD_LINE1, "NXC");
  TextOut(0, LCD_LINE2, "I2C Test");

	for (int readsize = 1; readsize <= 16; readsize++) {
	  TextOut(0, LCD_LINE5, FormatNum("Read Size: %2d", readsize));
/*
    asm {
  	  set __CLSCSArgs0.Port, 0
     	set __CLSWArgs0.Port, 0
     	set __CLSRArgs0.Port, 0
     	mov __CLSWArgs0.ReturnLen, readsize
     	mov __CLSRArgs0.BufferLen, readsize
     	mov __CLSWArgs0.Buffer, I2CRequest
  	}
*/
	  unsigned long tick = CurrentTick();
	  repeat(1000) {
//	  for (int readings = 0; readings < MAXREADS; readings++) {

//      DO_I2C_REQUEST
//      DO_I2C_REQUEST_WITH_YIELD

	  	while (LowspeedCheckStatus(S1) == STAT_COMM_PENDING);           // Wait for I2C bus to be ready
      I2CWrite(S1, readsize, I2CRequest); // Send the message
	  	while (LowspeedCheckStatus(S1) == STAT_COMM_PENDING);           // Wait for I2C bus to be ready
	  	I2CRead(S1, readsize, I2CReply);

	  }
	  time_taken[readsize-1] = CurrentTick()-tick;
	  PlaySound(SOUND_CLICK);
	}

	displayStats(index);
	while (true) {
    int nNxtButtonPressed = getbtn();
		if (nNxtButtonPressed == BTNRIGHT) {
			if (index < 15)
			  index++;
			else
			  index = 0;
		} else if(nNxtButtonPressed == BTNLEFT) {
				if (index > 0)
			    index--;
			  else
			    index = 15;
    }
	  debounce();
	  displayStats(index);
  }
}
John Hansen

Re: C++, Fantom API: I2C Sensors

Posted: 24 Mar 2011, 05:33
by afanofosc
lizard381 wrote:I seem to be having a problem where I can set the sensor type and sensor mode but I can't reset it within the same program [for instance, I first set the color sensor to colorfull/raw, then i want to set it to colorred/pctfullscale]. Similarly, I can read from each sensor once, but after that when I try to query the sensor it writes 0 bytes to the response buffer. If I restart the program I'm fine but this doesn't seem right. Is there some sort of buffer flushing I should be doing that I'm not doing?
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: https://sourceforge.net/apps/phpbb/mind ... ?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?

John Hansen