Networking

This week's assignment is to communicate between two processors


I decided to communicate between two of my circuits that i have already made. So i am sing for this week two of the circuits that i have previously created and both use Attiny44.
I wanted to give I2c communication a go. After a short look through the attiny44 datasheet and a little search online I saw a two-wire communication mode mentioned in the dataseet. (two wire mode)

A little more search showed me that there are libraries avilable to support the communication using the Arduino IDE. one of the most famous being Tinywire

The library

There are some great examples attached for the library both with the master and slave as senders and as recievers. I am using my Master as a reciver and my slave as a sender and i intend to use potentiometer values from the slave to control a DC motor connted to the Master.
But first lets try the examples. The examples are quite straight forward. The slave sends a charchter and when the master recieves it, it indicates so by lighting an LED.
The example uses a second LEd to indicate when the there was an error (The master was not recieving the right message). I dont have a second LEd so i adjusted the code to turn the same LEd on and off when there was an error.

i am using the arduino in the corner for powering up purposes only.

Master Code

#include < TinyWire.h >

#define led_pin PA3
#define error_led_pin PA7
#define button_pin PA2

byte slave_address = 10;


void setup() {
// config led_pin as Output for driving an LED
pinMode(led_pin, OUTPUT);
// config error_led_pin as Output for driving an LED
pinMode(error_led_pin, OUTPUT);
// config button_pin als INPUT for a connected button (normally open; connects to GND)
pinMode( button_pin, INPUT_PULLUP);

// config TinyWire library for I2C master functionality
TinyWire.begin();
}

void loop() {
// check, if the button was pressed
if(digitalRead( button_pin ) == 0) {
// request 1 byte from the slave with address slave_address
// returns 0, if there was no error. (otherwise you can find the different error code definitions in TinyWire.h)
if( TinyWire.requestFrom( slave_address, 1 ) == 0 ) {
// read all bytes in buffer
while(TinyWire.available()) {
// if the read byte is an 'a', toggle the LED
if(TinyWire.read()=='a') digitalWrite(led_pin,HIGH);
delay(10000);
}
} else {
// if there was an error, turn on the error LED
digitalWrite(led_pin, HIGH);
delay(1000);
digitalWrite(led_pin, LOW);
delay(1000);
digitalWrite(led_pin, HIGH);
delay(1000);
}
delay(300);
// reset the error led after a short delay
digitalWrite( led_pin, LOW);

}
}

Slave code
#include < TinyWire.h >

byte own_address = 10;


void setup() {
// config TinyWire library for I2C slave functionality
TinyWire.begin( own_address );
// register a handler function in case of a request from a master
TinyWire.onRequest( onI2CRequest );
}

void loop()

}

// Request Event handler function
// --> Keep in mind, that this is executed in an interrupt service routine. It shouldn't take long to execute
void onI2CRequest() {
// sends one byte with content 'b' to the master, regardless how many bytes he expects
// if the buffer is empty, but the master is still requesting, the slave aborts the communication
// (so it is not blocking)
TinyWire.send('b');
}

The code is not working. i am constantly getting the error signal. I went back to the datasheet.
and sure enough there was an error in my connection! I did connect the two wires together. Just neglected tpo coinect them to VCC


I reconnected everything on a breadboard instead. I could have connected them directly but I did not have the right kind of connectors. I carried on using a different code. I installed the attinycore Linked here which allows for the usage of a special version of the wire library instead of tinywire. I went with a simple approach of using a button on the master to control an LED on the slave. I used the following code for the master sender:

#include < Wire.h >
#include
#define button PA2
void setup() {
Wire.begin();
pinMode(button, INPUT);
}
void loop() {
int data;
data = digitalRead(button);
if (data == 1)
{
Wire.beginTransmission(8);
Wire.write(1);
Wire.endTransmission();
}
else {
Wire.beginTransmission(8);
Wire.write(0);
Wire.endTransmission();
}
}

And the following code for the slave reciever:


#include < Wire.h >
#define led PA2
void setup() {
Wire.begin(8);
Wire.onReceive(receiveEvent);
pinMode(led, OUTPUT);
}
void loop() {
delay(100);
}
void receiveEvent(int howMany) {
int x = Wire.read();
if (x == 1)
{
digitalWrite(led, HIGH);
}
if (x == 0)
{
digitalWrite(led, LOW);
}
}

The idea behind the code is very simple. The master registers the press of a button and if the button is pressed it sends '1' to the slave and '0' if it isnt. The slave reads all the data recieved and turns on the LED accordingly.

The connection is not very clear in the video so here is a clear diagram of the connection. SDA and SCL pins fall on the spi header. The are the same pins as the MOSI and SCK. I used my circuit created on electronics design week and the circuit created on output devices week. Both already had spi header which I used to program them. I had to program the master and slave code first, disconnect the programmer and connect them together according to the I2C diagram.


Obviously, I2C is not the only kind of wired communicatioin between controllers. One other common kind of communication is SPI (Serial Peripheral Interface). I2C allows multiple masters and slaves on the bus. On the other hand SPI can only work with one master device controlling multiple slaves. In both I2C and SPI the master device controls the clock for all slaves, but an I2C slave device can modify the main bus clock. SPI is capable of higher data rates and requires three bus lines as opposed to the I2C where only two are needed.