After spending two hours working on the changelog for the upcoming release of my driver suite, I thought I’d go play with something that was a bit more fun.
I’m part of the ROBOTC for Arduino test group, which has been a lot of fun. The Arduino build does not have I2C support in the firmware yet, so I was wondering how hard it would be to implement a bit-banged I2C master. Turns out to be a lot easier than I thought. The code even worked first time I ran it! You can imagine my surprise. I haven’t tested the reading part yet, though, so there’s still room for hours of frustration and despair. The sensor I used is a Mindsensors Magic Wand.
The demo is nothing fancy, just a little running light. You can view the code below the video, as you can see it’s nothing to write home about. You can download the code here: [LINK]
#pragma config(CircuitBoardType, typeCktBoardDuemilanove) #pragma config(Sensor, dgtl2, SDATA, sensorDigitalOut) #pragma config(Sensor, dgtl3, SCLK, sensorDigitalOut) //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// /** file BitBangedI2CMaster.c * brief Bit Banged I2C master * * BitBangedI2CMaster.c provides a very simple bit banged I2C master. * * Changelog: * - 0.1: Initial release * * License: You may use this code as you wish, provided you give credit where its due. * * Credit: Adapted from http://www.keil.com/download/docs/64.asp * * author Xander Soldaat * date 20 February 2011 * version 0.1 */ const ubyte LOW = 0; const ubyte HIGH = 1; void i2c_start (); // Sends I2C Start void i2c_stop (); // Sends I2C Stop void i2c_write (ubyte output_data); // Writes data over the I2C bus ubyte i2c_read (); // Reads data from the I2C bus void PCF8574write(ubyte data); task main () { while (true) { for (int i = 0; i < 8; i++) { PCF8574write(~(1<<i)); wait1Msec(50); } } } void PCF8574write(ubyte data) { i2c_start(); i2c_write(0x70); // address i2c_write(data); // value i2c_stop(); } /** * I2C Functions - Bit Banged */ /** * Sends I2C Start Transfer */ void i2c_start () { SensorType[SDATA] = sensorDigitalOut; SensorValue[SDATA] = HIGH; // Set data line high SensorValue[SCLK] = HIGH; // Set clock line high SensorValue[SDATA] = LOW; // Set data line low (START SIGNAL) SensorValue[SCLK] = LOW; // Set clock line low } /** * Sends I2C Stop Transfer */ void i2c_stop () { SensorType[SDATA] = sensorDigitalOut; SensorValue[SCLK] = LOW; // Set clock line low SensorValue[SDATA] = LOW; // Set data line low SensorValue[SCLK] = HIGH; // Set clock line high SensorValue[SDATA] = HIGH; // Set data line high (STOP SIGNAL) SensorType[SDATA] = sensorDigitalIn; // Put port pin into HiZ } /** * Write data over the I2C bus * * @param output byte data to be written to the slave */ void i2c_write (ubyte output_data) { SensorType[SDATA] = sensorDigitalOut; for(int i = 0; i < 8; i++) // Send 8 bits to the I2C Bus { // Output the data bit to the I2C Bus SensorValue[SDATA] = ((output_data & 0x80) ? HIGH : LOW); output_data <<= 1; // Shift the byte by one bit SensorValue[SCLK] = HIGH; // Clock the data into the I2C Bus SensorValue[SCLK] = LOW; } SensorType[SDATA] = sensorDigitalIn; // Put data pin into read mode SensorValue[SCLK] = HIGH; // Clock the ACK from the I2C Bus SensorValue[SCLK] = LOW; } /** * Read data from the I2C bus * * @return data read from slave */ ubyte i2c_read () { unsigned char index, input_data; SensorType[SDATA] = sensorDigitalIn;// Put data pin into read mode input_data = 0x00; for(index = 0; index < 8; index++) // Send 8 bits to the I2C Bus { input_data <<= 1; // Shift the byte by one bit SensorValue[SCLK] = HIGH; // Clock the data into the I2C Bus input_data |= SensorValue[SDATA]; // Input the data from the I2C Bus SensorValue[SCLK] = LOW; } return input_data; }
Wow, that is really cool. What is the speed? I noticed you don’t have any wait functions in the code to slow it down. Thanks for sharing. BTW, is the RobotC Arduino FW able to do multitasking (like the NXT can)? I know that with the normal programming stuff (Arduino environment and bootloader), you can’t do multitasking (at least it isn’t supported).
Matthew I haven’t done any speed tests, to be honest. The ROBOTC for Arduino FW can run up to 4 tasks at once, that includes the main task, of course.
I am now working on the master read code which is almost working, I’m using a Mindsensors Dist-NX.
Ok, REALLY COOL! Thanks a lot. The main thing I like about programming the NXT more than Arduino, is the ability to multitask, but now all I need to do is get ROBOTC for Arduino, cool.
Matthew, ROBOTC for Arduino isn’t officially out yet, it’s still in alpha stage. I am not 100% sure what the release date for it is.
Ok, well it sounds like it will be a nice piece of software. Now, if only they made it for PICAXE as well…
They do, just it’s not RobotC, and it’s not the Picaxe :). Get a straight Pic and a good compiler… I’d actually go with AVR, they’re cheaper and WinAVR seems pretty good.
[…] There is still support for the Mindstorms NXT, VEX Cortex and PIC. Support for Arduino will be added at a later date. I have played with an early Arduino version of ROBOTC several months ago and wrote about it here: [LINK] and here: [LINK] […]
Where i am find RobotC for Arduino? I have RobotC for IFI (Vex y NXT) but I need program in Arduino. Thanks
It doesn’t officially exist yet. This was a test version.
Xander, Just purchased Robotc for Arduino, Has Robotc included I2C in the firmware? In watching the video, How do you have the NXT interface wired to the Arduino? Are the pins mapped directly to the Arduino or are you using a PCF8574 as the function in the code appears to use?
Cheers
Joe
I2C hasn’t been added to the Arduino FW yet, but it’s planned, but I have firm ETA yet, a little birdy tells me sometime in January, but don’t pin me down on that. As for the pins; I just used two digital IO pins and connected them to pins 5 and 6 on the NXT connector. The PCF8574 is simply an I2C IO multiplexer, so I can control LEDs and things like that. It is one of the simplest I2C devices that I have, so I used it for testing.
= Xander
[…] http://botbench.com/blog/2011/02/20/bit-banged-i2c-master-on-robotc-for-arduino/#comment-2674 […]