Microduino and ATtiny45 talking I2C.. or not

Hi,

I’m trying to get a Microduino (which is basically an Arduino Uno: www.microduino.cc) to talk to an ATtiny45 over I2C. But am getting nowhere… when i use no Pull-up resistors the Microduino does not init, when i use 10kOhm pull-ups same thing. Using 4.7kOhm pullups allows the Microduino to run its code, but the ATtiny is not responding. The RTC module which is on the same i2c bus however does work.
I’m using the TinyWireS library http://playground.arduino.cc/Code/USIi2c#.UxtAxnVdWlh to talk to the ATtiny and i re-flashed it to run at 8Mhz instead of 1Mhz…
When i probe the bus using a Beaglebone, the ATtiny does not respond. querying the ATtiny at its i2c address also turns up nothing.

Code for the ATtiny:

#include <TinyWireS.h>
#include <usiTwiSlave.h>

#define PX40_PIN 1
#define LEDpin 4
#define minValue 50
#define maxValue 200
#define I2C_SLAVE_ADDR 0x26

volatile uint8_t i2c_regs[] = {0x00 ,0x00};


const uint8_t numReadings = 10;
uint8_t readings[numReadings];
uint8_t index;
uint8_t total;
uint8_t average;


void setup(){
  pinMode(PX40_PIN, INPUT);
  pinMode(LEDpin, OUTPUT);
  TinyWireS.begin(I2C_SLAVE_ADDR); 
}

uint8_t readPX() {
  // subtract the last reading:
  total= total - readings[index];         
  // read from the sensor:  
  readings[index] =  map(analogRead(PX40_PIN),minValue,maxValue,1,100);
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array:  
  index = index + 1; 
  // if we're at the end of the array...
  if (index >= numReadings)              
    // ...wrap around to the beginning: 
    index = 0;                           
  // calculate the average:
  average = total / numReadings;         
  return average;            
}

void statusLed(boolean state){
  if (state) {
    digitalWrite(LEDpin,HIGH  );
  } else {
    digitalWrite(LEDpin,LOW);
  }
}

void i2cComm(uint8_t msg){
  statusLed(true);
  byte byteRcvd = 0;
  if (TinyWireS.available()){
    byteRcvd = TinyWireS.receive();
    TinyWireS.send(msg);
  }
  statusLed(false);
}

void loop(){
  i2c_regs[1] = readPX();
  i2cComm(i2c_regs[1]);
}

code for the master:

#include <SoftwareSerial.h>
#include <Adafruit_GPS.h>
#include <SD.h>
#include <Rtc_Pcf8563.h>
#include <Wire.h>

int PX40_i2c_address=0x26;

class PX40{
    char depth;
    public:    
    void update(){
        Wire.requestFrom(PX40_i2c_address,1);
        delay(10);
        while (Wire.available()){
            char c = Wire.read();
        }
    }
    char getDepth(){
        return depth;
    }
} px40;


Adafruit_GPS GPS(&Serial1);

Rtc_Pcf8563 rtc;
const int chipSelect = 4;

void setup(){
  Wire.begin();
  Serial.begin(9600);
  GPS.begin(38400);
  rtc.initClock();
  pinMode(10,OUTPUT);
  if (!SD.begin(chipSelect)) {
    Serial.println("SD Card Failed to Initialise!");
    return;
  }
  Serial.println("SD Card ready.");
  delay(1000);
}

void queryGPS(){
  boolean gotNMEA = false;
  while (!gotNMEA){
    char c = GPS.read();
    if (GPS.newNMEAreceived()){
      if (GPS.parse(GPS.lastNMEA())){
        gotNMEA=true;
      }
    }
  }
}

void queryRTC(){
 rtc.getDate();
 rtc.getTime();
}

void checkRTC(){
  if (GPS.year != rtc.getYear() || GPS.month != rtc.getMonth() || GPS.day != rtc.getDay() || GPS.hour != rtc.getHour() || GPS.minute != rtc.getMinute() || GPS.seconds != rtc.getSecond()){
    rtc.setDate(GPS.day,0,GPS.month,0,GPS.year);
    rtc.setTime(GPS.hour,GPS.minute,GPS.seconds);
  }
}

String getTimeStamp(){
  String timeStamp = "";
  timeStamp = String(rtc.formatDate());
  timeStamp = timeStamp + " ";
  timeStamp = timeStamp + String(rtc.formatTime());
  return timeStamp;
}

void writeLog(String logEntry) {
  File logFile = SD.open("Probe.log",FILE_WRITE);
  if (logFile){
    logFile.println(getTimeStamp() + " " + logEntry);
    logFile.close();
    Serial.println("Logged: "+ logEntry);
  } else {
    Serial.println("Error writing logEntry!");
  }
}


void loop(){
  Serial.println("Updating GPS");
  queryGPS();
  Serial.println("Updating RTC");
  queryRTC();
  Serial.println("Verifying RTC <> GPS sync");
  checkRTC();
  Serial.println("Updating PX40");
  px40.update();
  Serial.println("writing Log");
  writeLog(getTimeStamp() + px40.getDepth());
  delay(5000);
}

Now,… i’m not an electronics engineer. Just an IT guy who likes to tinker. so plz be gentle :wink:

Anyone have any ideas what i’m missing here?

Post the schematics you’re using including all wiring between the Arduino and the Tiny.

Breadboard view:

Schematic view:

I'm missing the pullups for the I2C lines. Insert 4k7 for both SDA and SCL and try again. Which ATtiny kit for the Arduino IDE are you using?

You might have to deactivate the timer interrupt on the tiny to get a fast enough responses on the I2C but that's just to increase reliability, if it's not even visible on the bus you don't have to care for this yet.

Oops, silly me.. i did put them on the real breadboard though. i just forgot to draw them here.

I adjusted the schematics.

I'm using an arduino as ISP for the ATtiny, i burned a new bootloader into it so it would run 8Mhz instead of 1. Is that what you mean with deactiviting the timer interrupt or is that another option i need to set somewhere?

Thanks for looking into this! :D

I'm using an arduino as ISP for the ATtiny, i burned a new bootloader into it so it would run 8Mhz instead of 1. Is that what you mean with deactiviting the timer interrupt or is that another option i need to set somewhere?

The Arduino IDE doesn't support the ATtiny off-the-shelf, so you must have modified it with an ATtiny support module. There are several of them, so which one did you choose?

The bootloader does not change the clock speed but if you chose the correct board in the Arduino IDE it had set the fuses correctly and that changes the clock speed (better the clock divider).

Deactivating the interrupt mean I had to change the Arduino core code. Instructions how to make it at least re-entrant are found here: https://github.com/boxtec/tinyLCD_I2C.

The Arduino IDE doesn't support the ATtiny off-the-shelf, so you must have modified it with an ATtiny support module. There are several of them, so which one did you choose?

I used the ATtiny hardware libraries linked in this how-to to set up the Arduino IDE: http://highlowtech.org/?p=1695

I'm right at the same spot as you; I have a bunch of tinywire slaves (atmel 84's and 85's) on two I2C busses, and scanning from the Beaglebone shows zip. Zilch. Nada. Except for the off the shelf slaves, those work fine (a mag/accelerometer, a ds1307 clock, etc). Also did the same clock/fuse settings for 8 Mhz int osc.

Prior tests from an Arduino (an Uno or Leo, I can't remember which) worked fine with all the slaves.

Now ... big hint: I have two older slaves, an Attiny85 running an RGB LED, and an Attiny84, both I'd built last year. They both work with the BBB! So I think I used a different / older tiny core, or a slightly different twi library. That could be the magic bullet for us.

Just curious ,are you using something like 'i2c-detect -r -y 1' on the BBB?

What pullups do you use? Do you power the Tinys with 3V3 or 5V?

I can confirm this works (now):

Beaglebone Black / Angstrom
Adafruit Logic Level Shifter http://www.adafruit.com/products/757
Attiny 84’s and 85’s - all the same bus (the ‘third’ bus, the second external). There are 6 mcu’s, each is on about 1 meter of recycled ethernet cable, all tied back to headers on stripboard.

There are NO extra pullups; the shifter has 10k resistors on it, and I think what’s happening is the BBB has internal pullups on the 3.3v side, which shows as a 5v pullup on the high side.

I can now get reliable i2cdetects, so I’m back on track…