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:
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)
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)
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.
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.
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:
#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?