There comes a time in the life of any semi autonomous robot when the study of the classics occurs. For Terry, the BeagleBone Black driven Actobotics construction, short of visiting the Globe the answer would seem to be at current "To Beep".
Terry is now run by a RoboClaw 2x5A controller board with two 1024 pulse per revolution shaft encoders attached to an 8:1 ratio gearing on the wheel. This gives an overall of about 13 bits of precision from the shaft encoders relative to the wheel. In the future I can use this magnificent 4 inch alloy gear wheel as a torque multiplier by moving the motor to its own tooth pinion gear. Terry now also has an IR distance sensor out front, and given the 512mb of RAM on the BeagleBone some fairly interesting mapping can be built up by just driving around and storing readings. Distance + accurate shaft encoders for the win?
To use the RoboClaw from the BeagleBone Black I created a little nodejs class. It's not fully complete yet, but it is already somewhat useful. I found creating the nodejs interesting because when coding for MCUs one gets quite used to the low level style of sending bytes and stalling until the reply comes in. For nodejs such a style doesn't implement well. Normally one would see something like
doMagic( 7, rabbits, function() {
console.log("got them rabbitses, we did");
});
Where the callback function is performed when the task of pulling the number of rabbits from the hat is complete. For using the RoboClaw you might have something like
claw.getVersion( function( v ) {
console.log("version:" + v.value );
});
claw.setQPPS( 1024 );
Which all seems fairly innocent. The call to getVersion will send the VERSION command to the roboclaw with a given address (you can have many claws on the same bus). The claw should then give back a version string and a checksum byte. The checksum can be stripped off and verified by the nodejs.
The trouble is that the second call, to set of the quadratic decoder pulses per second, will start to happen before the RoboClaw got a chance to service the getVersion call. Trying to write a second command before you have the full reply from the first is a recipe for disaster. So the nodejs RoboClaw class maintains a queue of requests. The setQPPS() is not run right away, but enqueued for later. Once the bytes come back over the UART in response to the getVersion() then the callback is run and the RoboClaw nodejs class then picks the next command (setQPPS) and sends that to the RoboClaw. This way you get the strict ordered serial IO that the RoboClaw hardware is needing, but the nodejs can execute many commands without any stalling. Each command is handled in the order it is written in the nodejs source code, it just doesn't execute right away.
Next up is trying to tune the PID controller variables for the robot. One might expect a command such as "move 1 wheel circumference forward" to work fairly exactly if the quality of the shaft encoders is good. Though for the wheel size and QPPS I get a little bit of overshoot currently. I suspect the current D is not sufficient to pull it up in time. It may be a non issue when the wheels are down and friction helps the slow down process.
Terry now also has an IMU onboard. I created a small class to read from the TWI HMC5883 magneto. You'll have to figure your declination and I have a small hack on about line 100 to alter the heading so that a 0 degree reading means that physically Terry is facing North. I should bring that parameter out of the class so that its easier to adjust for other robots that might mount their IMU in a different physically orientation than what I happened to use.
C++, Linux, libferris and embedded development. Yet another blog from yet another NARG.
Monday, May 26, 2014
Saturday, May 10, 2014
Going from Arduino TWI to BeagleBone Black Bonescript
It's handy for a robot to know what orientation it is holding, and for that a Magnetometer can give you where north is at relative to the chip orientation. For this I used the HMC5883. I started out with a cut down minimal version of code running on Arduino and then started porting that over to Bonescript for the BeagleBone Black to execute.
The HMC5883 only needs power (3v3), ground, and the two wires of a TWI.
One of the larger API changes of the port is the Arduino line:
Wire.requestFrom( HMC5883_ADDRESS_MAG, 6 );
Which takes the TWI address of the chip you want 6 bytes from. It has to be prefixed by another TWI transmission to set the read byte address to start from where you would like, in this case HMC5883_REGISTER_MAG_OUT_X_H_M = 0x03.
On the Bonescript side this becomes the following. The TWI address isn't used because the wire object already knows that, but you pass the register address to start reading from directly to the request to read bytes:
The HMC5883 only needs power (3v3), ground, and the two wires of a TWI.
One of the larger API changes of the port is the Arduino line:
Wire.requestFrom( HMC5883_ADDRESS_MAG, 6 );
Which takes the TWI address of the chip you want 6 bytes from. It has to be prefixed by another TWI transmission to set the read byte address to start from where you would like, in this case HMC5883_REGISTER_MAG_OUT_X_H_M = 0x03.
On the Bonescript side this becomes the following. The TWI address isn't used because the wire object already knows that, but you pass the register address to start reading from directly to the request to read bytes:
self.wire.readBytes( HMC5883_REGISTER_MAG_OUT_X_H_M,
BUFFER_SIZE,
function(err, res) { ... });
I pushed the code up to github bbbMagnetometerHMC5883. Note that getting "north" requires both a proper declination angle for your location and also some modification to allow for how your magneto chip is physically oriented on your robot. Actual use of the chip is really easy with the async style of nodejs.
I pushed the code up to github bbbMagnetometerHMC5883. Note that getting "north" requires both a proper declination angle for your location and also some modification to allow for how your magneto chip is physically oriented on your robot. Actual use of the chip is really easy with the async style of nodejs.
Subscribe to:
Posts (Atom)