I wanted to add the Devantech 2D compass (CMPS01 - Rev 7), best used in the I2C two-wire interface mode, to my robomagellan project. With the aid of Peter Fleury’s delightfully comprehensive I2C code it was quickly running. Then, the compass module died.
The code should be useful to others, so I added an example to read/write the 24LC256 EEPROM, which has 32K bytes of space.
Peter’s site has much useful AVR code and can be found at homepage.hispeed.ch/peterfleury/ … tware.html
I’ve extracted the relevant parts of Peter’s I2C code, which take advantage of the TWI hardware module, with microscopic adaptions for the Baby O.
It works flawlessly! A .zip file of the collected routines for WinAVR can be found at uoxray.uoregon.edu/orangutan/i2c.zip
To demonstrate what I2C communications entail, the main code is pasted in below. In my project the Baby O communicates with a PC using the RS232 interface, via the Pololu USB-to-serial adapter. For more information (such as it is), see
uoxray.uoregon.edu/orangutan
If anyone encounters difficulties with these routines, let me know.
Cheers, Jim
/*
Baby Orangutan I2C example--read/write 24LC256 EEPROM
This program utilizes Peter Fleury's I2Master routines to communicate with an EEPROM chip
See I2C routines and other examples at Peter's site: [jump.to/fleury](http://jump.to/fleury)
Note: Peter's routines implement both hardware and "bit-bang" I2C routines.
I followed the example code, buried within the comments to i2cmaster.h, testing the
software features using the 24C02 EEPROM.
This version uses the "TWI" (two wire interface=I2C) hardware on the atmega168.
Connections required between 24LC256 and Baby O
Baby O -> 24LC256
+5 (Vdd) -> Pin 8
PC4 (SDA) -> Pin 5 Don't forget pullup resistors to +5V on each of SDA and SCL! I used 4.7 K
PC5 (SCL) -> Pin 6
Gnd (Vss) -> Pin 4,3,2,1 and 7 (WP=A0=A1=A2=low)
CPU Clock speed is 20 MHz, I2C clock=100 kHz max.
Changes to I2C code by Peter Fleury (minimal):
Set clock (F_CPU), I2C clock (100 kHz) and check that TWI clock prescaler = 1 is appropriate.
RS232 routines are used to communicate between Hyperterm on a PC, via Pololu USB to serial converter
For more information, see [uoxray.uoregon.edu/orangutan](http://www.uoxray.uoregon.edu/orangutan)
Jim Remington, sjames_remington at yahoo dot com
*/
#define F_CPU 20000000UL
/* UART baud rate */
#define UART_BAUD 9600
#include <stdio.h>
#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>
#include <uart.h>
#include <i2cmaster.h>
// setup serial routines to become stdio
extern int uart_putchar(char c, FILE *stream);
extern int uart_getchar(FILE *stream);
FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
#include "uart.c"
#include "i2cmaster.c"
int main(void)
{
unsigned char lowbyte;
uart_init(); //initialize UART hardware
i2c_init(); // initialize I2C interface
stdout = stdin = &uart_str; //setup stdio = RS232 port
puts("Test I2C routines with 24lc256 EEprom"); //chip address lines A0,1,2 are wired to ground.
// debugging: use calls similar to the following to help debug the interface with new device
// if (i2c_write(0)==1) puts("write 0 failed");
// if (i2c_rep_start(0xA0+I2C_READ)==1) puts ("rep_start failed"); //set read mode
// 24LC256 device address is 0xA0 plus the values set by connections to external pins A0,A1,A2 (see data sheet)
i2c_start_wait(0xA0+I2C_WRITE); // set device address and write mode
i2c_write(0x00); // high byte of write address 0x05
i2c_write(0x05); // low byte of write address 0x05
i2c_write(0x75); // write value 0x75 to EEPROM address 0x05
i2c_stop(); // set stop conditon = release bus
// read previously written value back from EEPROM address 0x05
i2c_start_wait(0xA0+I2C_WRITE); // set device address and write mode
i2c_write(0x00); // high byte address = 05
i2c_write(0x05); // low byte address = 05
if(i2c_rep_start(0xA0+I2C_READ)==1) puts("rep_start failed"); // set device address and read mode
lowbyte = i2c_readNak(); // read one byte from EEPROM
i2c_stop(); //stop I2C bus
printf("Byte read = %u\n",lowbyte); //should be 117 decimal
return 0;
}