Class Notes

Assignment

design and build a wired &/or wireless network connecting at least two processors

Due to lack of time I have been working on my final project, which will include a I2C network of modules controlled by a master.

I will be updating this page with the networking related sections once I’m able to make progress on the final project.

23rd May

I researched TWI / I2C slave libraries which were implemented in software and did not require the TWI hardware available in some of the higher end AVRs.

I found TinyWire, which is a CPP library that calls into the USI-TWI library written by Donald Blake.

The other option is to tweak Neil’s i2c_master code to work for slaves.

First, I’m going to try TinyWire.

I found some sample code here to test out the I2C interaction. However, when I hooked up the Arduino module and the slave board, the slave MCU got extremely hot and I had to disconnect it.

As a next step I’m trying some simpler code to send data from the master to slave only:

This is the master:


//Code for the Arduino Uno
#include <Wire.h>
 
void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
}
 
byte x = 0;

void loop() {
  Wire.beginTransmission(0x4);
  Wire.write(++x % 2);        
  Wire.endTransmission();    

  delay(1000);
}

This is the slave:



#define output(directions, pin) (directions |= (1 << pin)) // set port direction for output
#define input(directions, pin) (directions &= (~(1 << pin))) // set port direction for input
#define set(port, pin) (port |= (1 << pin)) // set port pin
#define clear(port, pin) (port &= (~(1 << pin))) // clear port pin

#define LED_PIN PB3

#define I2C_SLAVE_ADDRESS 0x4 // Address of the slave
 
#include <TinyWireS.h>
 
void setup()
{
    output(DDRB, LED_PIN);
    clear(PORTB, LED_PIN);
    
    TinyWireS.begin(I2C_SLAVE_ADDRESS); // join i2c network
}
 
void loop()
{
  byte recd = 1;
  if(TinyWireS.available()) {
      recd = TinyWireS.receive();
      if(recd == 1) {
          clear(PORTB, LED_PIN);
      } else {
          set(PORTB, LED_PIN);
      }
  }
}


This worked fine, the slave blinked the LED every 1 sec.

Next step is to get the slave to send back some data to the master.

Here is the master code I tried:


#include <Wire.h>

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600); // start serial for output
}

void loop() {
  Serial.println("requesting");
  Wire.requestFrom(4, 1); // request 1 byte from slave device address 4

  while (Wire.available()) // slave may send less than requested
  {
    int i = Wire.read(); // receive a byte as character
    Serial.println(i); // print the character
  }

  delay(50);
}

Here is the slave code:


// Code for the ATtiny85
#define I2C_SLAVE_ADDRESS 0x4 // Address of the slave

#include <TinyWireS.h>

int i=0;

void setup()
{
    TinyWireS.begin(I2C_SLAVE_ADDRESS); // join i2c network
    //TinyWireS.onReceive(receiveEvent); // not using this
    TinyWireS.onRequest(requestEvent);
    
    // Turn on LED when program starts
    pinMode(1, OUTPUT);
    digitalWrite(1, HIGH);
}

void loop()
{
    // This needs to be here
    TinyWireS_stop_check();
}

// Gets called when the ATtiny receives an i2c request
void requestEvent()
{
    TinyWireS.send(i);
    i++;
}

I uploaded the slave code with the internal clock set to 8mhz. This worked perfectly well! The master was outputting incrementing numbers from the slave.

I tried reproducing the scenario where the slave board was heating up, but couldn’t - it seemed to work fine with all the changes I tried 1) changing internal clock to 1mhz 2) using VCC & GND from the Arduino

Anyhow its great to have a working I2C slave implementation.

Original Files