You can control all the functions of the NXT using the direct commands, and the JAVA and C++ and C# libs using the bluetooth/COMPort are built on these commands.
Using the different libraries which are available, the Direct Commands are hidden in the objects for instance the sonar is based on the I2C class, which uses Direct Commands.
So in the Bram Fokke, the Anders and the Lejos libraries, the ones I studied, because they are free, the Direct Commands are hidden in the classes. (The fantom lib found later allowed us to built our own library.)
But then you encounter a sensor which was not there in the time they wrote their classes and this sensor just doesn't behave like the sensor types they have provided for. Then suddenly you have to study the Direct Commands.
In principle not very difficult and there is the documentation of the Bluetooth Developers Kit of Lego: http://mindstorms.lego.com/Overview/NXTreme.aspx
In principle you can find your way with these docs.
I was especially interested in the control of the I2C clock sensor.
The only reference about these sensors I eventually found on the web is:
http://hsrc.static.net/Research/NXT%20I2C%20Communication/
Details:
- the first two bits are sometimes included sometimes hidden (length of command)
- the LSREAD in the mindstorm pdf has a mistake: it is 21 bytes long (or 24), the rx length from 4-21, Anders lib 24 bytes.
- what comes back can be status included, or not (fantom lib)
- the setup of a sensor (I2C) produces a lot of bytes which should be discarded
- the commands responses must be all taken care of! One byte in between, not read will mesh everything up!
But even the last doc of the links was not really clear to me, missing the two first Bytes to write!
So here some examples, building on this page:
As written above these three commands are used:
LSWRITE is used for both reading registers and writing commands from the NXT.
(so the second byte is always 0! In some libes these 2 bytes are integrated differently!)
Then you can follow this last doclink:
send(&command[0],7); replaces LSWRITE
sensor.read() does the LSREAD
sensor.wait_ans(nr) waits for nr bytes, using the LSGETSTATUS and a timer
(to be found in the Lib of Anders)
for instance: play a tone: (C++ lib of Anders)
char command[10];
//---------------------------------------------playtone
command[0]=0x06;//length LSB
command[1]=0x00;//length MSB
command[2]=0x00;//do not bother to send anything back (0x80 when something is expected back)
command[3]=0x03;//play tone
int freq = 4000;
command[4]=freq;
command[5]=freq >>8;
int time = 100;
command[6]=time;
command[7]=time>>8;
command[8]=0;
comport->send(&command[0],8);
//----------------------------------------------------end playtone----
example 2: set output state of a sensor:
command[0]=5;//total length
command[1]=0x00;//second byte of the length
command[2]=0x80; //0x00 would block the measurements because sending something
command[3]=0x05;//setinputmode command
command[4]=0x00;//port of the sensor on the brick NXT
command[5]=0x0A;//constant for type of sensor
command[6]=0x00;//sensormode
comport->send(&command[0],7);
}
if(sensor.wait_ans(4)){
answer=sensor.read();
}
//---------end set output state
example 3 reading a register of an I2C sensor
char command[9];
command[0]=7;//total length
command[1]=0x00;//total length
command[2]=0x80;//expect something back
command[3]=0x0F;//LSWRITE
command[4]=0x00; //port
command[5]=2;//lenght of bytes to send
command[6]=1;//length of bytes to receive
command[7]=CLOCK_ADDRESS; //i2c address of the clock
command[8]=reg_adr;
comport->send(&command[0],9);
char *answer;
if(sensor.wait_ans(1)){ //and wait for the one byte back
answer=sensor.read();
return answer[1] ; //reading this was using not the answer[0], but this depends on the sensor
}
//------------------------end reading a register
example 4: writing to e register, that is copy the last one, but add one register after this commandList:
char command[10];
command[0]=8;
command[1]=0x00;
command[2]=0x80;
command[3]=0x0F;//LSWRITE
command[4]=0x00; //port
command[5]=3;//lenght of bytes to send
command[6]=1;//length of bytes to receive
command[7]=CLOCK_ADDRESS; //i2c address
command[8]=reg_adr;
command[9]=val; //thus giving the value you want to give this register
comport->send(&command[0],10);
char *answer;
if(sensor.wait_ans(1)){
answer=sensor.read();
return answer[1] ; //again, the reading back of the response has to be looked at, depending on sensor
}
//end ----------------------------------------------------reading a register
With these direct commands, the Dev - Cpp classes for the clock sensor were built.
See the blog: I2C setup to see more details (and problems), using the fantom lib
Limits: using DIRECT COMMANDS from the PC, you cannot set registers on sensors, due to the master slave relation, see master slave blog.
1 comments:
Hey there, I'm the Author of hsrc.static.net and it's great to see people taking my work and making it better!
I spent much time like you looking for answers to get my XT under control.
-Keep up the good work
-Paul Taylor black69@tpg.com.au
Post a Comment