go_away

Author Topic: Trying to understand i2c but am lost...  (Read 1100 times)

0 Members and 1 Guest are viewing this topic.

Offline jzaunTopic starter

  • Jr. Member
  • **
  • Posts: 18
  • Helpful? 0
Trying to understand i2c but am lost...
« on: April 10, 2012, 07:14:53 PM »
I've got an i2c device froms sparkfun, 9 Degrees of Freedom - Sensor Stick. I'm trying to get it to do something. Things are complicated as I can't use webbotlib. So I'm trying to use as much of the old axon code as I can. Issues arise as I'm using newer gcc versions than other people are. At any rate, I've got the following i2c code:

Code: [Select]
/*************************************************************************
 * Title:    I2C master library using hardware TWI interface
 * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
 * Target:   any AVR device with hardware TWI
 * Usage:    API compatible with I2C Software Library i2cmaster.h
 **************************************************************************/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/twi.h>
#include <stdio.h>

#include "i2c.h"
#include "util.h"

// Standard I2C bit rates are:
// 100KHz for slow speed
// 400KHz for high speed

#define I2C_DEBUG

// I2C state and address variables
static volatile eI2cStateType I2cState;
static uint8_t I2cDeviceAddrRW;

// send/transmit buffer (outgoing data)
static uint8_t I2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
static uint8_t I2cSendDataIndex;
static uint8_t I2cSendDataLength;

// receive buffer (incoming data)
static uint8_t I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
static uint8_t I2cReceiveDataIndex;
static uint8_t I2cReceiveDataLength;

// function pointer to i2c receive routine
//! I2cSlaveReceive is called when this processor
// is addressed as a slave for writing
static void (*i2cSlaveReceive)(uint8_t receiveDataLength, uint8_t* recieveData);
//! I2cSlaveTransmit is called when this processor
// is addressed as a slave for reading
static uint8_t (*i2cSlaveTransmit)(uint8_t transmitDataLengthMax, uint8_t* transmitData);

// functions
void i2cInit(void)
{
#ifdef I2C_DEBUG
    printf("I2C: INIT\r\n");
#endif
   
// set pull-up resistors on I2C bus pins
PORTD |= _BV(0); // i2c SCL on 640
PORTD |= _BV(1); // i2c SDA on 640
   
    cli();
// clear SlaveReceive and SlaveTransmit handler to null
i2cSlaveReceive = 0;
i2cSlaveTransmit = 0;
// set i2c bit rate to 100KHz
i2cSetBitrate(100);
// enable TWI (two-wire interface)
TWCR |= _BV(TWEN);
// set state
I2cState = I2C_IDLE;
// enable TWI interrupt and slave address ACK
    TWCR |= (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWIE);
TWCR |= _BV(TWEA);
    //TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
// enable interrupts
sei();
}

void i2cSetBitrate(uint16_t bitrateKHz)
{
uint8_t bitrate_div;
// set i2c bitrate
// SCL freq = F_CPU/(16+2*TWBR))
#ifdef TWPS0
    // for processors with additional bitrate division (mega128)
    // SCL freq = F_CPU/(16+2*TWBR*4^TWPS)
    // set TWPS to zero
    TWSR &= ~(BV(TWPS0));
    TWSR &= ~(BV(TWPS1));
#endif
// calculate bitrate division
bitrate_div = ((F_CPU/1000l)/bitrateKHz);
if(bitrate_div >= 16)
bitrate_div = (bitrate_div-16)/2;
TWBR = bitrate_div;
}

void i2cSetLocalDeviceAddr(uint8_t deviceAddr, uint8_t genCallEn)
{
// set local device address (used in slave mode only)
TWAR = ((deviceAddr&0xFE) | (genCallEn?1:0));
}

void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(uint8_t receiveDataLength, uint8_t* recieveData))
{
i2cSlaveReceive = i2cSlaveRx_func;
}

void i2cSetSlaveTransmitHandler(uint8_t (*i2cSlaveTx_func)(uint8_t transmitDataLengthMax, uint8_t* transmitData))
{
i2cSlaveTransmit = i2cSlaveTx_func;
}

void i2cSendStart(void)
{
//WRITE_sda();
// send start condition
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
}

void i2cSendStop(void)
{
// transmit stop condition
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

void i2cWaitForComplete(void)
{
// wait for i2c interface to complete operation
    while( !(TWCR & _BV(TWINT)) );
}

void i2cSendByte(unsigned char data)
{
   
//WRITE_sda();
// save data to the TWDR
TWDR = data;
// begin send
TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT);
}

inline void i2cReceiveByte(uint8_t ackFlag)
{
// begin receive over i2c
if(ackFlag)
{
// ackFlag = TRUE: ACK the recevied data
TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWEA);
}
else
{
// ackFlag = FALSE: NACK the recevied data
TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT);
}
}


inline uint8_t i2cGetReceivedByte(void)
{
// retieve received data byte from i2c TWDR
return TWDR;
}

inline uint8_t i2cGetStatus(void)
{
// retieve current i2c status from i2c TWSR
return TWSR;
}

void i2cMasterSend(uint8_t deviceAddr, uint8_t length, uint8_t* data)
{
uint8_t i;
// wait for interface to be ready
while(I2cState);
// set state
I2cState = I2C_MASTER_TX;
// save data
I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation
for(i=0; i<length; i++)
I2cSendData[i] = *data++;
I2cSendDataIndex = 0;
I2cSendDataLength = length;
// send start condition
i2cSendStart();
}

void i2cMasterReceive(uint8_t deviceAddr, uint8_t length, uint8_t* data)
{
uint8_t i;
// wait for interface to be ready
while(I2cState);
// set state
I2cState = I2C_MASTER_RX;
// save data
I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation
I2cReceiveDataIndex = 0;
I2cReceiveDataLength = length;
// send start condition
i2cSendStart();
// wait for data
while(I2cState);
// return data
for(i=0; i<length; i++)
*data++ = I2cReceiveData[i];
}

uint8_t i2cMasterSendNI(uint8_t deviceAddr, uint8_t length, uint8_t* data)
{
uint8_t retval = I2C_OK;
   
// disable TWI interrupt
TWCR &= ~(BV(TWIE));
   
// send start condition
i2cSendStart();
i2cWaitForComplete();
   
// send device address with write
i2cSendByte( deviceAddr & 0xFE );
i2cWaitForComplete();
   
// check if device is present and live
if(TWSR == TW_MT_SLA_ACK)
{
// send data
while(length)
{
i2cSendByte( *data++ );
i2cWaitForComplete();
length--;
}
}
else
{
// device did not ACK it's address,
// data will not be transferred
// return error
retval = I2C_ERROR_NODEV;
}
   
// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
while(!(TWCR & _BV(TWSTO)));
   
// enable TWI interrupt
TWCR |= _BV(TWIE);
   
return retval;
}

uint8_t i2cMasterReceiveNI(uint8_t deviceAddr, uint8_t length, uint8_t *data)
{
uint8_t retval = I2C_OK;
   
// disable TWI interrupt
    TWCR &= ~(BV(TWIE));
   
// send start condition
i2cSendStart();
i2cWaitForComplete();
   
// send device address with read
i2cSendByte( deviceAddr | 0x01 );
i2cWaitForComplete();
   
// check if device is present and live
if(TWSR == TW_MR_SLA_ACK)
{
// accept receive data and ack it
while(length > 1)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
*data++ = i2cGetReceivedByte();
// decrement length
length--;
}
       
// accept receive data and nack it (last-byte signal)
i2cReceiveByte(FALSE);
i2cWaitForComplete();
*data++ = i2cGetReceivedByte();
}
else
{
// device did not ACK it's address,
// data will not be transferred
// return error
retval = I2C_ERROR_NODEV;
}
   
// transmit stop condition
// leave with TWEA on for slave receiving
i2cSendStop();
   
// enable TWI interrupt
TWCR |= _BV(TWIE);
   
return retval;
}

//! I2C (TWI) interrupt service routine
SIGNAL(TWI_vect)
{
// read status bits
uint8_t status = TWSR & TWSR_STATUS_MASK;
   
switch(status)
{
            // Master General
        case TW_START: // 0x08: Sent start condition
        case TW_REP_START: // 0x10: Sent repeated start condition
#ifdef I2C_DEBUG
            printf("I2C: M->START\r\n");
#endif
            // send device address
            i2cSendByte(I2cDeviceAddrRW);
            break;
           
            // Master Transmitter & Receiver status codes
        case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged
        case TW_MT_DATA_ACK: // 0x28: Data acknowledged
#ifdef I2C_DEBUG
            printf("I2C: MT->SLA_ACK or DATA_ACK\r\n");
#endif
            if(I2cSendDataIndex < I2cSendDataLength)
            {
                // send data
                i2cSendByte( I2cSendData[I2cSendDataIndex++] );
            }
            else
            {
                // transmit stop condition, enable SLA ACK
                i2cSendStop();
                // set state
                I2cState = I2C_IDLE;
            }
            break;
        case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued
#ifdef I2C_DEBUG
            printf("I2C: MR->DATA_NACK\r\n");
#endif
            // store final received data byte
            I2cReceiveData[I2cReceiveDataIndex++] = TWDR;
            // continue to transmit STOP condition
        case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged
        case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged
        case TW_MT_DATA_NACK: // 0x30: Data not acknowledged
#ifdef I2C_DEBUG
            printf("I2C: MTR->SLA_NACK or MT->DATA_NACK\r\n");
#endif
            // transmit stop condition, enable SLA ACK
            i2cSendStop();
            // set state
            I2cState = I2C_IDLE;
            break;
        case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost
            //case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost
#ifdef I2C_DEBUG
            printf("I2C: MT->ARB_LOST\r\n");
#endif
            // release bus
            TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT);
            // set state
            I2cState = I2C_IDLE;
            // release bus and transmit start when bus is free
            //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
            break;
        case TW_MR_DATA_ACK: // 0x50: Data acknowledged
#ifdef I2C_DEBUG
            printf("I2C: MR->DATA_ACK\r\n");
#endif
            // store received data byte
            I2cReceiveData[I2cReceiveDataIndex++] = TWDR;
            // fall-through to see if more bytes will be received
        case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged
#ifdef I2C_DEBUG
            printf("I2C: MR->SLA_ACK\r\n");
#endif
            if(I2cReceiveDataIndex < (I2cReceiveDataLength-1))
                // data byte will be received, reply with ACK (more bytes in transfer)
                i2cReceiveByte(TRUE);
            else
                // data byte will be received, reply with NACK (final byte in transfer)
                i2cReceiveByte(FALSE);
            break;
           
            // Slave Receiver status codes
        case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned
        case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned
        case TW_SR_GCALL_ACK: // 0x70:     GCA+W has been received, ACK has been returned
        case TW_SR_ARB_LOST_GCALL_ACK: // 0x78:     GCA+W has been received, ACK has been returned
#ifdef I2C_DEBUG
            printf("I2C: SR->SLA_ACK\r\n");
#endif
            // we are being addressed as slave for writing (data will be received from master)
            // set state
            I2cState = I2C_SLAVE_RX;
            // prepare buffer
            I2cReceiveDataIndex = 0;
            // receive data byte and return ACK
            TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWEA);
            break;
        case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned
        case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned
#ifdef I2C_DEBUG
            printf("I2C: SR->DATA_ACK\r\n");
#endif
            // get previously received data byte
            I2cReceiveData[I2cReceiveDataIndex++] = TWDR;
            // check receive buffer status
            if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE)
            {
                // receive data byte and return ACK
                i2cReceiveByte(TRUE);
                //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
            }
            else
            {
                // receive data byte and return NACK
                i2cReceiveByte(FALSE);
                //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
            }
            break;
        case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned
        case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned
#ifdef I2C_DEBUG
            printf("I2C: SR->DATA_NACK\r\n");
#endif
            // receive data byte and return NACK
            i2cReceiveByte(FALSE);
            //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
            break;
        case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave
#ifdef I2C_DEBUG
            printf("I2C: SR->SR_STOP\r\n");
#endif
            // switch to SR mode with SLA ACK
            TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWEA);
            // i2c receive is complete, call i2cSlaveReceive
            if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData);
            // set state
            I2cState = I2C_IDLE;
            break;
           
            // Slave Transmitter
        case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned
        case TW_ST_ARB_LOST_SLA_ACK: // 0xB0:     GCA+R has been received, ACK has been returned
#ifdef I2C_DEBUG
            printf("I2C: ST->SLA_ACK\r\n");
#endif
            // we are being addressed as slave for reading (data must be transmitted back to master)
            // set state
            I2cState = I2C_SLAVE_TX;
            // request data from application
            if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData);
            // reset data index
            I2cSendDataIndex = 0;
            // fall-through to transmit first data byte
        case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received
#ifdef I2C_DEBUG
            printf("I2C: ST->DATA_ACK\r\n");
#endif
            // transmit data byte
            TWDR = I2cSendData[I2cSendDataIndex++];
            if(I2cSendDataIndex < I2cSendDataLength)
                // expect ACK to data byte
                TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWEA);
            else
                // expect NACK to data byte
                TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT);
            break;
        case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received
        case TW_ST_LAST_DATA: // 0xC8:
#ifdef I2C_DEBUG
            printf("I2C: ST->DATA_NACK or LAST_DATA\r\n");
#endif
            // all done
            // switch to open slave
            TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWEA);
            // set state
            I2cState = I2C_IDLE;
            break;
           
            // Misc
        case TW_NO_INFO: // 0xF8: No relevant state information
            // do nothing
#ifdef I2C_DEBUG
            printf("I2C: NO_INFO\r\n");
#endif
            break;
        case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition
#ifdef I2C_DEBUG
            printf("I2C: BUS_ERROR\r\n");
#endif
            // reset internal hardware and release bus
            TWCR = (TWCR & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWSTO) | _BV(TWEA);
            // set state
            I2cState = I2C_IDLE;
            break;
}
}

eI2cStateType i2cGetState(void)
{
return I2cState;
}

For my device I've got:

Code: [Select]
#include <stdio.h>
#include "adxl345.h"
#include "util.h"
#include "i2c.h"

uint16_t x_accel(void)
{
//0xA6 for a write
//0xA7 for a read

uint8_t dummy, xh, xl;
uint16_t xo;

//0x32 data registers
i2cSendStart();
i2cWaitForComplete();
i2cSendByte(0xA6);    //write to ADXL
i2cWaitForComplete();
i2cSendByte(0x32);    //X0 data register
i2cWaitForComplete();

i2cSendStop(); //repeat start
i2cSendStart();
   
i2cWaitForComplete();
i2cSendByte(0xA7);    //read from ADXL
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
xl = i2cGetReceivedByte(); //x low byte
i2cWaitForComplete();
i2cReceiveByte(FALSE);
i2cWaitForComplete();
dummy = i2cGetReceivedByte(); //must do a multiple byte read?
i2cWaitForComplete();
i2cSendStop();

//0x33 data registers
i2cSendStart();
i2cWaitForComplete();
i2cSendByte(0xA6);    //write to ADXL
i2cWaitForComplete();
i2cSendByte(0x33);    //X1 data register
i2cWaitForComplete();

i2cSendStop(); //repeat start
i2cSendStart();
   
i2cWaitForComplete();
i2cSendByte(0xA7);    //read from ADXL
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
xh = i2cGetReceivedByte(); //x high byte
i2cWaitForComplete();
i2cReceiveByte(FALSE);
i2cWaitForComplete();
dummy = i2cGetReceivedByte(); //must do a multiple byte read?
i2cWaitForComplete();
i2cSendStop();
xo = xl|(xh << 8);
return xo;
}

uint16_t y_accel(void)
{
//0xA6 for a write
//0xA7 for a read

uint8_t dummy, yh, yl;
uint16_t yo;

//0x34 data registers
i2cSendStart();
i2cWaitForComplete();
i2cSendByte(0xA6);    //write to ADXL
i2cWaitForComplete();
i2cSendByte(0x34);    //Y0 data register
i2cWaitForComplete();

i2cSendStop(); //repeat start
i2cSendStart();
   
i2cWaitForComplete();
i2cSendByte(0xA7);    //read from ADXL
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
yl = i2cGetReceivedByte(); //x low byte
i2cWaitForComplete();
i2cReceiveByte(FALSE);
i2cWaitForComplete();
dummy = i2cGetReceivedByte(); //must do a multiple byte read?
i2cWaitForComplete();
i2cSendStop();

//0x35 data registers
i2cSendStart();
i2cWaitForComplete();
i2cSendByte(0xA6);    //write to ADXL
i2cWaitForComplete();
i2cSendByte(0x35);    //Y1 data register
i2cWaitForComplete();

i2cSendStop(); //repeat start
i2cSendStart();
   
i2cWaitForComplete();
i2cSendByte(0xA7);    //read from ADXL
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
yh = i2cGetReceivedByte(); //y high byte
i2cWaitForComplete();
i2cReceiveByte(FALSE);
i2cWaitForComplete();
dummy = i2cGetReceivedByte(); //must do a multiple byte read?
i2cWaitForComplete();
i2cSendStop();
yo = yl|(yh << 8);
return yo;
}

uint16_t z_accel(void)
{
//0xA6 for a write
//0xA7 for a read

uint8_t dummy, zh, zl;
uint16_t zo;

//0x36 data registers
i2cSendStart();
i2cWaitForComplete();
i2cSendByte(0xA6);    //write to ADXL
i2cWaitForComplete();
i2cSendByte(0x36);    //Z0 data register
i2cWaitForComplete();

i2cSendStop(); //repeat start
i2cSendStart();
   
i2cWaitForComplete();
i2cSendByte(0xA7);    //read from ADXL
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
zl = i2cGetReceivedByte(); //z low byte
i2cWaitForComplete();
i2cReceiveByte(FALSE);
i2cWaitForComplete();
dummy = i2cGetReceivedByte(); //must do a multiple byte read?
i2cWaitForComplete();
i2cSendStop();

//0x37 data registers
i2cSendStart();
i2cWaitForComplete();
i2cSendByte(0xA6);    //write to ADXL
i2cWaitForComplete();
i2cSendByte(0x37);    //Z1 data register
i2cWaitForComplete();

i2cSendStop(); //repeat start
i2cSendStart();
   
i2cWaitForComplete();
i2cSendByte(0xA7);    //read from ADXL
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
zh = i2cGetReceivedByte(); //z high byte
i2cWaitForComplete();
i2cReceiveByte(FALSE);
i2cWaitForComplete();
dummy = i2cGetReceivedByte(); //must do a multiple byte read?
i2cWaitForComplete();
i2cSendStop();
zo = zl|(zh << 8);
return zo;
}

and my main I've got:

Code: [Select]
#define UART_USB UART2

int main(void) {
delay_ms(200);

    uartInit(UART_USB, 9600);
    uartSetStandardOut(UART_USB);
   
    printf("\n\n--=[ Start of Execution ]=--\n");
   
i2cInit();
delay_ms(200);

    uint16_t accelX = -1;
    uint16_t accelY = -1;
    uint16_t accelZ = -1;
    printf("Accel (x, y, z): (%u, %u, %u)\n\n", accelX, accelY, accelZ);

while(1)
{
        accelX = x_accel();
        accelY = y_accel();
        accelZ = z_accel();
        printf("Accel (x, y, z): (%d, %d, %d)\n", accelX, accelY, accelZ);
delay_ms(1000);
}

}

All I get for output is:

Code: [Select]
--=[ Start of Execution ]=--
I2C: INIT
Accel (x, y, z): (65535, 65535, 65535)

Accel (x, y, z): (0, 0, 0)
Accel (x, y, z): (0, 0, 0)
Accel (x, y, z): (0, 0, 0)
Accel (x, y, z): (0, 0, 0)
Accel (x, y, z): (0, 0, 0)
Accel (x, y, z): (0, 0, 0)


I assume I should be getting more i2c debug messages as I turned them on. When I move the sparkfun board around, its all stay 0 so something isn't working. Is there something I'm missing. I've been googling for a week and can't get anything other than my uart code to work.
« Last Edit: April 10, 2012, 07:21:48 PM by jzaun »

Offline joe61

  • Supreme Robot
  • *****
  • Posts: 417
  • Helpful? 16
Re: Trying to understand i2c but am lost...
« Reply #1 on: April 10, 2012, 09:23:50 PM »
Are you using external pull-up resistors on the data and clock lines? I don't think the internal pullups will work except at low speeds. The data sheet recommends external pull-ups. 4.7K is good.

Joe

Offline jzaunTopic starter

  • Jr. Member
  • **
  • Posts: 18
  • Helpful? 0
Re: Trying to understand i2c but am lost...
« Reply #2 on: April 10, 2012, 09:29:49 PM »
No, I has assumed the internal pullups would work, or why have em :)

I'll have to try external pullups I guess.

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,150
  • Helpful? 110
Re: Trying to understand i2c but am lost...
« Reply #3 on: April 16, 2012, 02:03:45 PM »
As part of WebbotLib Studio I have compiled an up-to-date version of avr-gcc etc (4.7.0). Am busy fixing the errors they show. So hopefully this problem will go away
Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

 


Get Your Ad Here

data_list