Where is my time gone? What did I do with my life?
Ok the problems described here are solved, as always it was a combination of a few causes, a wrong setting of the battery reading before starting the reading of the sensors messed up the rest of the readings.
In the fantom api you have to be careful destinguishing between the bytes read by LSREAD and the bytes read through the fantomlib SENDDIRECTCOMMANDS, also the description of the DIRECT COMMANDS in the Bluetooth Developers Kit has to be read with care, not being quite what it is....so:
fantom.nFANTOM100_iNXT_sendDirectCommand(nxtPointer, true, command, command.capacity(), response, response.length, status);
reads 4 bytes (see getBattery() in fantom lib blog )
but this is different from a reading of a sensor which starts with LSWRITE to the sensor and then used LSWRITE again to read the 21 bytes coming in...
To give an account of some of the difficulties and mistakes occuring during "research" i leave this story here......
But a nice training in detective work!
I am recording our efforts and thoughts, if something works all the roundabouts are so quickly forgotten!
we started having an idea of making a "room mapping" robot,
first we used C++ to do the job, with bluetooth, we could have mapped in OpenGL but we didn't, did that in FLASH.
(We just happen to like mixing all kind of environments:-)
then we discovered the fantom api and could get all the JAVA working on the brick and the PC
(This is fun: Lejos JAVA on the brick and fantom lib JAVA on the PC.)
so we redid the mapping idea using our homebrew lib, built on the fantom interface of E. Pirsch.
(Learning a lot about the DIRECT COMMANDS and the I2C sensors, but we had to learn more....:-(
mapping objects around the NXT worked but then it turned out the combination of 2 I2C sensors got mixed up
the sonar reading coming in during a compass reading.
(This is not the way we want it!!!! All must be neatly fit into it own objects!!!)
we started researching why, and we found this strange I2C set up procedure.
We are trying to make sense of this, and hoping to do a better job then just discarding the first 5 or 6 measurements.
The different sensors ask for different numbers of bits, and because the set up seems to be done only once, even if you use more and/or different I2C sensors.
So resuming:
Working with the fantom api we made a radar, that means the NXT mapping the distance to objects around it.
For this we used two different I2C sensors: compass and sonar.
Making a map of objects around the NXT worked but there was a problem: the distance value came in as a angle and the compass value as a distance.
The values read where coming in, but in the wrong order. Something wrong with our classes? This seemed in order...
It could be understood if we see the responses to the DIRECT COMMANDS as being read in the order they come in, and having started with the wrong reading. The instances of the objects don't "know" what they are reading, since there is no signature provided from the I2C response. Another reason could be that the setup order must be followed in the reading order, this makes sens if the bytes are "waiting" to be read, and cannot be skipped, neither recognized.
This was confirmed using three I2C sensor measurements (from different sensors). The values were still coming in, but all shifted into the "wrong instance" of the I2C sensor.
In the end we considered the setup of the I2C sensor:
This is what we got: (coming in)
recording the preparation of the I2C mode: (reading bytes with LSREAD 21 at a time)
reading a byte at a time, but getting this value in by 21 at the time: I2Cprep 14 0 1 20 0 2 16 0 1 -1 0 0 0 0 0 0 I2Cprep 0 2 14 0 1 20 0 2 16 0 1 2 -1 0 0 0 I2Cprep 14 0 1 4 0 2 14 0 1 20 0 0 2 16 0 1 I2Cprep 14 0 1 4 0 2 14 0 1 4 0 0 2 14 0 1 I2Cprep 0 2 14 0 1 4 0 2 14 0 1 2 4 0 2 14 I2Cprep 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 after this came a "normal" reading: normal measurement (byte[3] is the value) 16 0 1 46 0 0 0 0 0 0 0 0 0 0 0 0 |
trying to make sense of this: (taking the 14 for LSGETSTATUS signature)
14 0 1 20 0 2 = LSGETSTATUS (?) 16 0 1 46 0 0 0 0 0 0 0 2 this seems like a normal measurement? - 1 14 0 1 20 0 2 LSGETSTATUS (?) 16 0 1 2 46 0 0 0 this seems like starting a normal measurement? - 2 14 0 1 4 0 2 LSGETSTATUS (?) 14 0 1 20 0 0 2 LSGETSTATUS (?) 16 0 1 this seems like starting a normal measurement? - 3 14 0 1 4 0 2 LSGETSTATUS (?) 14 0 1 4 0 0 2 LSGETSTATUS (?) 14 0 1 0 2 LSGETSTATUS (?) 14 0 1 4 0 2 LSGETSTATUS (?) 14 0 1 2 4 0 2 LSGETSTATUS (?) 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 later on from calling LSGETSTATUS intead of readbytes, this 14 could be seen as: "number of bytes in waiting, ready to be read" |
provoking these bytes were 6 reading of the I2c sensor.
In the C++ Anders lib we find for the I2C compass sensor three reading in preparation:
| from the Anders lib:(with his comment) int Compass::setup(){ sensor.sensor_type(LOWSPEED); Sleep(500); degree(); degree(); degree();//Otherwise the first measurement fails return 1; } |
//degree is reading two bytes at a time, so six bytes are read? No, because the LSGETSTATUS gives the number of bytes ready, but the reading is always in 21 bytes, the 3 and 4 being the value. This difference between bytes ready and bytes read does not make life easier.
Another things we saw is that even if there are 2 I2C sensors attached to the ports that the preparation takes the same number of bytes, the second sensor, on another port, is also ready.
There is no difference in the bytes coming in using LOWSPEED or LOWSPEED_9V as sensor mode.
The problem is that is takes six measurements to "clear" the I2C sensor communication, but an uneven number to get the right order in the readings. So in case of two sensors should we also introduce a dummy measurement?
We tried building a method in the our I2C class reading the 14 bytes, but then we have to provide the portnumber, and the address to read from in the sensor (which differs, sonar 0x41, clock 0x00 for instance) so this solution could not be considered very cool, giving the different sensors.
Experimenting around with different kinds of set ups did not improve the result, the sonar sensor, which reads one byte, and the compass sensor, which reads two, both need three readings before behaving "normal".
to be continued...
A probable solution could be changing the address of the compass sensor. We tried this. It failed!
We re-used the Robot-C format found in the blog of
Done something wrong?
Ok, in C++ then, the lib of Anders, hm, no method to change the address found here.
We made a method for the compass, it failed!
But making a I2C sensor array of clock, distance, and compass in a C++ setup did work without problems, only the reading came in at a speed of (this three together) around 2 seconds.....a bit slow, but no shifted readings.....
so if we dont put I2C sensors on the same port, we dont have to change the I2C address?
0 comments:
Post a Comment