About Week 13
Networking and Communications Exercise...
This week assignment is about Networking and Communications: design and build a wired &/or wireless network connecting at least two processors.
For my exercises I started from my boards built from Satshakit design of my colleague Daniele. First of all I used I2C-bus protocol. I2C is a Master to Slave protocol in which the Master asks data to the Slave or to send data to it. The Slave could only replay to the only Master without making any query. I2C protocol works over analog pins, with the possibility to have much more digital pins. Obviously if I need more analog pins (for example for analog sensors) I2C is not the right protocol. However for my exercise I used an analog one, the analog tmp36 temperature sensor.
The I2C bus , based on two wires , does not allow the contemporary communication between Master and Slave . The data exchange have to be managed by the Master through slaves addresses (unique). The flow can be summarized as the follow:
- The Master sends on the bus a start bit
- The Master sends on the bus the address of slave which wants to communicate
- Master decide if Write or read from the device
- The slave reads or writes according to the request of the Master
As regards the code we need the Wire library that has all the functions needed to implement Master - Slave between two/more boards.
MASTER
//MASTER #includebyte x = 0; byte num = 0; void setup() { //inizialize Wire.begin(); //init serial Serial.begin(9600); //debug that code starts Serial.println("...start communication"); } void loop() { // sends a byte to the I2C device // Which it has the address value 0x01 //start transmission Wire.beginTransmission(0x01); //byte sent Wire.write(x); Serial.println(x); //end transmission Wire.endTransmission(); delayMicroseconds(500); //a byte request to the slave with address 0x01 Wire.requestFrom(0x01, 1); //waiting for datat on i2c bus while(Wire.available()) { //when data available the master reads the data num = Wire.read(); } x++; Serial.println(num); //data check if(num != x) Serial.println("ERROR"); delay(500); }
SLAVE
//SLAVE #includebyte x = 0; void setup() { //wire inizialization //slave address Wire.begin(0x01); //receive/request data event Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent); } void loop() { //do something delay(1000); } void receiveEvent(int data) { //this event is generated itf there is a data to read //read x = Wire.read(); //data elaboration x++; } void requestEvent() { //this event is generated if data is requested //send data to Master Wire.write(x); }
The schematic of the circuit I made is shown in the following figure.
After this first try I modify all the system in order to request (from Master) the measure of the temperature from slave. The scale of temperature (C or F) is requested alternatively by the the Master ( Wire.write(0), Wire.write(1)). In this case the value sent is a float and have to be sent as a set of byte. The above sketches has been modified accordingly including a new library "I2C_Anything.h"
MASTER 2
//MASTER #include#include "I2C_Anything.h" byte x = 0; volatile float fnum; void setup() { Wire.begin(); Serial.begin(9600); Serial.println("START"); } void loop() { Wire.beginTransmission(0x04); Wire.write(x); Serial.println(x); Wire.endTransmission(); delayMicroseconds(500); Wire.requestFrom(0x04, 4); while(Wire.available()) { Serial.print ("Waiting "); //read I2C_readAnything (fnum); } if(x==1) { Serial.print ("Received temp (F) = "); Serial.println (fnum); x=0; }else{ Serial.print ("Received temp (C) = "); Serial.println (fnum); x=1; } delay(500); }
SLAVE 2
//SLAVE #include#include "I2C_Anything.h" byte x = 0; int val_Adc = 0; float temp = 0; void setup() { //init seriale Serial.begin(9600); Wire.begin(0x04); Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent); } void loop() { //do something delay(1000); } void receiveEvent(int data) { x = Wire.read(); Serial.println(x); val_Adc = analogRead(0); //in C temp = ((val_Adc * 0.00488) - 0.5) / 0.01; if (x==0){ //In F temp = (temp * 9 / 5) + 32; } } void requestEvent() { Serial.println(temp); //spedisco il dato al Master I2C_singleWriteAnything(temp); }
I2C_Anything.h
// Code modified from the original one written by Nick Gammon // May 2012 #include#include template int I2C_writeAnything (const T& value) { const byte * p = (const byte*) &value; unsigned int i; for (i = 0; i < sizeof value; i++) Wire.write(*p++); return i; } // end of I2C_writeAnything template int I2C_readAnything(T& value) { byte * p = (byte*) &value; unsigned int i; for (i = 0; i < sizeof value; i++) *p++ = Wire.read(); return i; } // end of I2C_readAnything template int I2C_singleWriteAnything (const T& value) { int size = sizeof value; byte vals[size]; const byte* p = (const byte*) &value; unsigned int i; for (i = 0; i < sizeof value; i++) { vals[i] = *p++; } Wire.write(vals, size); return i; }