├── .gitignore ├── ._.gitignore ├── Readme.md ├── I2C_Master_DSS_Lib ├── LeakSensors.h ├── I2C_Master_DSS_Lib.ino └── LeakSensors.cpp ├── I2C_Slave └── I2C_Slave.ino ├── I2C_Master_DSS_struct └── I2C_Master_DSS_struct.ino ├── I2C_Master └── I2C_Master.ino ├── I2C_Master_DSS └── I2C_Master_DSS.ino └── I2C_Slave_struct └── I2C_Slave_struct.ino /.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | ._Readme.md -------------------------------------------------------------------------------- /._.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott216/I2C-Examples/HEAD/._.gitignore -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | I2C Testing between two Arduinos. 2 | 3 | The slave sends 14 bytes of data. It sends a several different data types: bets, integer, long integer, and float 4 | 5 | I2C_Slave.ino is the sketch for the slave arduino that sends the data to the master when requested. 6 | 7 | I2C_Master.ino uses the wire.h library to request data from the slave. 8 | 9 | I2C_Master_DSS.ino uses a different library (https://github.com/rambo/I2C) for I2C communication. I wanted to try it because it uses less RAM then wire.h. 10 | 11 | I2C_Slave_struct.ino uses a union and typedef struct to convert the I2C data to a byte array 12 | 13 | I2C_Master_DSS_struct.ino uses the I2C.h library (not wire.h) and convert data from I2C back to variables using union and struct 14 | 15 | When wiring two Arduinos that are both 5 volts, I2C lines both use a 1.5k pull-up resistor to +5v. When using one 5 volt arduino and one 3.3 volt, use 4.7k pull-up resistors to +3.3v line. 16 | 17 | More info on the i2c.h library is can be found here: http://dsscircuits.com/articles/arduino-i2c-master-library.html 18 | 19 | -------------------------------------------------------------------------------- /I2C_Master_DSS_Lib/LeakSensors.h: -------------------------------------------------------------------------------- 1 | /* 2 | This libray makes getting the sensor data simpler by creating simple function calls you use to specify which 3 | sensor you want data from and what data you want. 4 | */ 5 | 6 | #include "Arduino.h" 7 | 8 | class Leaksensor 9 | { 10 | public: 11 | Leaksensor(); // constructor 12 | byte SensorStatus(byte SensorID); // Sensor status: 0 if online, 1 wireless sensor is offline, 2 I2C error 13 | bool isWet(byte SensorID); // Returns true if water is detected 14 | float remoteBattVolts(byte SensorID); // Battery voltage of wireless sensor in millivolts 15 | uint16_t RemoteTemperature(byte SensorID); // Temperature of wireless sensor 16 | byte RemoteSignalStrength(byte SensorID); // Wireless signal strength of wireless sensor 0-100 17 | byte SensorType(byte SensorID); // Sensor type: 1 = wired, 2 = wireless 18 | 19 | private: 20 | int getData(uint8_t sensorID); 21 | 22 | typedef struct sensorData_t { 23 | byte stat; 24 | byte sensorId; 25 | byte sensortype; 26 | byte isWet; 27 | uint16_t temp; 28 | float volts; 29 | byte signal; 30 | }; 31 | 32 | typedef union I2C_Packet_t { 33 | sensorData_t sensor; 34 | byte I2CPacket[sizeof(sensorData_t)]; 35 | }; 36 | 37 | I2C_Packet_t leakinfo; 38 | }; 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /I2C_Master_DSS_Lib/I2C_Master_DSS_Lib.ino: -------------------------------------------------------------------------------- 1 | /* 2 | I2C Test - Master 3 | I2C communication between two Arduinos. Use this with I2C_Slave_struct.ino 4 | This version creates a library to make the main sketch simpler 5 | 6 | Uses DSS's I2C.h library, not the Wire.h library. 7 | Uses union and typedef struct to convert byte array from I2C back to usable varible 8 | 9 | */ 10 | 11 | #include "LeakSensors.h" 12 | #include // https://github.com/rambo/I2C 13 | 14 | Leaksensor sensorInfo; // initialize Leaksensor class 15 | 16 | void setup () 17 | { 18 | Serial.begin(9600); 19 | Serial.println(F("Initialize library for I2C Master Test")); 20 | } // end setup() 21 | 22 | 23 | void loop() 24 | { 25 | static byte sID; 26 | 27 | // Alternate between sensors 28 | if (sID == 22) 29 | { sID = 23;} 30 | else 31 | { sID = 22;} 32 | 33 | byte stat = sensorInfo.SensorStatus(sID); 34 | if (stat == 0 ) 35 | { 36 | Serial.print(sID); 37 | Serial.print(F("\t")); 38 | Serial.print(sensorInfo.SensorStatus(sID)); 39 | Serial.print(F("\t")); 40 | Serial.print(sensorInfo.SensorType(sID)); 41 | Serial.print(F("\t")); 42 | Serial.print(sensorInfo.isWet(sID) ); 43 | Serial.print(F("\t")); 44 | Serial.print(sensorInfo.RemoteTemperature(sID)); 45 | Serial.print(F("\t")); 46 | Serial.print(sensorInfo.remoteBattVolts(sID)); 47 | Serial.print(F("\t")); 48 | Serial.println(sensorInfo.RemoteSignalStrength(sID)); 49 | } 50 | else 51 | { 52 | Serial.print(F("Error getting sensor data. Err: ")); 53 | Serial.print(stat); 54 | Serial.print(F(" for sensor # ")); 55 | Serial.println(sID); 56 | } 57 | delay(2000); 58 | 59 | } // end loop() 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /I2C_Slave/I2C_Slave.ino: -------------------------------------------------------------------------------- 1 | /* 2 | I2C Test - this is the slave 3 | Use with I2C_Master.ino or I2C_Master_DSS.ino 4 | Sends 14 bytes to Master. Has a mix of data formats 5 | 6 | */ 7 | 8 | #include // http://arduino.cc/it/Reference/Wire 9 | #define PACKET_SIZE 14 10 | 11 | // convert float to byte array source: http://mbed.org/forum/helloworld/topic/2053/ 12 | typedef union float2bytes_t // union consists of one variable represented in a number of different ways 13 | { 14 | float f; 15 | byte b[sizeof(float)]; 16 | }; 17 | 18 | const byte addrSlaveI2C = 21; // I2C Slave address of this device 19 | byte I2C_Packet[PACKET_SIZE]; // Array to hold data sent over I2C to main Arduino 20 | bool printDataflag = false; 21 | 22 | void setup() 23 | { 24 | Serial.begin(9600); 25 | Serial.println(F("Initialize wire library for slave I2C")); 26 | Wire.begin(addrSlaveI2C); // Initiate the Wire library and join the I2C bus 27 | Wire.onRequest(wireRequestEvent); // Register a function to be called when a master requests data from this slave device. 28 | } 29 | 30 | 31 | void loop() 32 | { 33 | uint32_t mS = millis(); 34 | uint16_t mV = 3000; 35 | uint16_t temp = 75; 36 | 37 | I2C_Packet[0] = addrSlaveI2C; 38 | I2C_Packet[1] = 2; // command ID 39 | 40 | I2C_Packet[2] = mV >> 8 & 0xff; ; // millivolts 41 | I2C_Packet[3] = mV & 0xff; 42 | 43 | I2C_Packet[4] = temp >> 8 & 0xff; // Temperature 44 | I2C_Packet[5] = temp & 0xff; 45 | 46 | // Convert float to 4-byte array 47 | float2bytes_t f2b; 48 | f2b.f = 1234.567; 49 | I2C_Packet[6] = f2b.b[0]; 50 | I2C_Packet[7] = f2b.b[1]; 51 | I2C_Packet[8] = f2b.b[2]; 52 | I2C_Packet[9] = f2b.b[3]; 53 | 54 | // convert from an unsigned long int to a 4-byte array 55 | I2C_Packet[10] = (int)((mS >> 24) & 0xFF) ; 56 | I2C_Packet[11] = (int)((mS >> 16) & 0xFF) ; 57 | I2C_Packet[12] = (int)((mS >> 8) & 0XFF); 58 | I2C_Packet[13] = (int)((mS & 0XFF)); 59 | 60 | // Print out data every time the Master makes a request 61 | if (printDataflag) 62 | { 63 | PrintData(I2C_Packet[0], I2C_Packet[1], mV, temp, f2b.f, mS); 64 | printDataflag = false; 65 | } 66 | 67 | } 68 | 69 | // Send data to Master. This is an interrupt driven event 70 | void wireRequestEvent() 71 | { 72 | // Send byte array from panStamp. Main Arduino will decode bytes 73 | Wire.write(I2C_Packet, PACKET_SIZE); 74 | printDataflag = true; 75 | 76 | } 77 | 78 | // Print out data that will be sent to the master 79 | void PrintData(byte sID, byte cID, uint16_t mV, uint16_t temp, float somefloat, uint32_t mS) 80 | { 81 | Serial.print(sID); 82 | Serial.print("\t"); 83 | Serial.print(cID); 84 | Serial.print("\t"); 85 | Serial.print(mV); 86 | Serial.print("\t"); 87 | Serial.print(temp); 88 | Serial.print("\t"); 89 | Serial.print(somefloat); 90 | Serial.print(" "); 91 | Serial.println(mS); 92 | } 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /I2C_Master_DSS_struct/I2C_Master_DSS_struct.ino: -------------------------------------------------------------------------------- 1 | /* 2 | I2C Test - Master 3 | I2C communication between two Arduinos. Use this with I2C_Slave_struct.ino 4 | 5 | Uses DSS's I2C.h library, not the Wire.h library. 6 | Uses union and typedef struct to convert byte array from I2C back to usable varible 7 | 8 | */ 9 | 10 | 11 | typedef struct sensorData_t { 12 | byte stat; 13 | byte sensorId; 14 | byte sensortype; 15 | byte isWet; 16 | uint16_t temp; 17 | float volts; 18 | byte signal; 19 | }; 20 | 21 | typedef union I2C_Packet_t { 22 | sensorData_t sensor; 23 | byte I2CPacket[sizeof(sensorData_t)]; 24 | }; 25 | 26 | #include // https://github.com/rambo/I2C 27 | 28 | #define PACKET_SIZE sizeof(sensorData_t) 29 | I2C_Packet_t leakinfo; 30 | const uint8_t addrSlaveI2C = 21; // ID of I2C slave. Don't use #define 31 | 32 | // Function prototype 33 | int getData(); 34 | 35 | void setup () 36 | { 37 | Serial.begin(9600); 38 | Serial.println(F("Initialize library for I2C Master Test")); 39 | I2c.begin(); // enables the I2C hardware 40 | I2c.timeOut(10000); 41 | Serial.println(F("Finished setup")); 42 | 43 | } // end setup() 44 | 45 | 46 | void loop() 47 | { 48 | static byte getSensorID; 49 | 50 | // Alternate between sensors 51 | if (getSensorID == 22) 52 | { getSensorID = 23;} 53 | else 54 | { getSensorID = 22;} 55 | 56 | 57 | int i2cStatus = getData(getSensorID); // get data for sensor # 22 58 | if( i2cStatus == 0) 59 | { 60 | Serial.print(leakinfo.sensor.stat); 61 | Serial.print("\t"); 62 | Serial.print(leakinfo.sensor.sensorId); 63 | Serial.print("\t"); 64 | Serial.print(leakinfo.sensor.sensortype); 65 | Serial.print("\t"); 66 | Serial.print(leakinfo.sensor.isWet ); 67 | Serial.print("\t"); 68 | Serial.print(leakinfo.sensor.temp); 69 | Serial.print("\t"); 70 | Serial.print(leakinfo.sensor.volts); 71 | Serial.print("\t"); 72 | Serial.println(leakinfo.sensor.signal); 73 | } 74 | else 75 | { 76 | Serial.print(F("No packet received, error: ")); 77 | Serial.println(i2cStatus); 78 | } 79 | 80 | delay(2000); 81 | } // end loop() 82 | 83 | 84 | // I2C Request data from slave 85 | int getData(uint8_t sensorID) 86 | { 87 | // Tell slave which sensor we want data for 88 | I2c.write(addrSlaveI2C, sensorID); 89 | 90 | //get data for sensor defined above in I2c.write() and store in byteArray array 91 | byte byteArray[PACKET_SIZE]; 92 | int readstatus = I2c.read(addrSlaveI2C, PACKET_SIZE, byteArray ); 93 | // If we got an I2C packet, we can copy the values into the union leakinfo 94 | if(readstatus == 0) 95 | { 96 | for (int k=0; k < PACKET_SIZE; k++) 97 | { 98 | leakinfo.I2CPacket[k] = byteArray[k]; 99 | } 100 | return 0; 101 | } // end got packet 102 | else 103 | { return readstatus; } // No Packet received 104 | 105 | } // end getData() 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /I2C_Master_DSS_Lib/LeakSensors.cpp: -------------------------------------------------------------------------------- 1 | #include "LeakSensors.h" 2 | #include // https://github.com/rambo/I2C 3 | 4 | #define PACKET_SIZE sizeof(sensorData_t) 5 | 6 | uint8_t addrSlaveI2C = 21; // ID of I2C slave. Don't use #define 7 | 8 | static byte prevSensorID = 0; // sensor ID of previous request 9 | static uint32_t lastRequestTime = 0; // millis of last request. Used to prevent calling slave too often 10 | const uint32_t requestDelay = 1000; 11 | 12 | Leaksensor::Leaksensor() // Constructor 13 | { 14 | // Initialize I2C 15 | I2c.begin(); // enables the I2C hardware 16 | I2c.timeOut(10000); 17 | } 18 | 19 | byte Leaksensor::SensorStatus(byte SensorID) // Sensor status 20 | { 21 | // If requesting a different sensor, or some time has passed since last request, call slave to get fresh data 22 | if (SensorID != prevSensorID && (long)(millis() - lastRequestTime) > requestDelay ) 23 | { 24 | int i2cStat = Leaksensor::getData(SensorID); // Refresh sensor data 25 | } 26 | return leakinfo.sensor.stat; 27 | } 28 | 29 | bool Leaksensor::isWet(byte SensorID) 30 | { 31 | // If requesting a different sensor, or some time has passed since last request, call slave to get fresh data 32 | if (SensorID != prevSensorID && (long)(millis() - lastRequestTime) > requestDelay ) 33 | { 34 | int i2cStat = Leaksensor::getData(SensorID); // Refresh sensor data 35 | } 36 | return leakinfo.sensor.isWet; 37 | } 38 | 39 | float Leaksensor::remoteBattVolts(byte SensorID) // Battery voltage of wireless sensor in millivolts 40 | { 41 | // If requesting a different sensor, or some time has passed since last request, call slave to get fresh data 42 | if (SensorID != prevSensorID && (long)(millis() - lastRequestTime) > requestDelay ) 43 | { 44 | int i2cStat = Leaksensor::getData(SensorID); // Refresh sensor data 45 | } 46 | return leakinfo.sensor.volts; 47 | } 48 | 49 | uint16_t Leaksensor::RemoteTemperature(byte SensorID) // Temperature of wireless sensor 50 | { 51 | // If requesting a different sensor, or some time has passed since last request, call slave to get fresh data 52 | if (SensorID != prevSensorID && (long)(millis() - lastRequestTime) > requestDelay ) 53 | { 54 | int i2cStat = Leaksensor::getData(SensorID); // Refresh sensor data 55 | } 56 | return leakinfo.sensor.temp; 57 | } 58 | 59 | byte Leaksensor::RemoteSignalStrength(byte SensorID) // Wireless signal strength of wireless sensor 0-100 60 | { 61 | // If requesting a different sensor, or some time has passed since last request, call slave to get fresh data 62 | if (SensorID != prevSensorID && (long)(millis() - lastRequestTime) > requestDelay ) 63 | { 64 | int i2cStat = Leaksensor::getData(SensorID); // Refresh sensor data 65 | } 66 | return leakinfo.sensor.signal; 67 | } 68 | 69 | byte Leaksensor::SensorType(byte SensorID) // Sensor type: 1 = wired, 2 = wireless 70 | { 71 | // If requesting a different sensor, or some time has passed since last request, call slave to get fresh data 72 | if (SensorID != prevSensorID && (long)(millis() - lastRequestTime) > requestDelay ) 73 | { 74 | int i2cStat = Leaksensor::getData(SensorID); // Refresh sensor data 75 | } 76 | return leakinfo.sensor.sensortype; 77 | } 78 | 79 | // I2C Request data from slave 80 | int Leaksensor::getData(uint8_t sensorID) 81 | { 82 | // Tell slave which sensor we want data for 83 | I2c.write(addrSlaveI2C, sensorID); 84 | 85 | //get data for sensor defined above in I2c.write() and store in byteArray array 86 | byte byteArray[PACKET_SIZE]; 87 | int readstatus = I2c.read(addrSlaveI2C, PACKET_SIZE, byteArray ); 88 | // If we got an I2C packet, we can copy the values into the union leakinfo 89 | if(readstatus == 0) 90 | { 91 | for (int k=0; k < PACKET_SIZE; k++) 92 | { 93 | leakinfo.I2CPacket[k] = byteArray[k]; 94 | } 95 | lastRequestTime = millis(); 96 | prevSensorID = sensorID; 97 | return 0; 98 | } // end got packet 99 | else 100 | { 101 | leakinfo.sensor.stat = 2; // I2C Error 102 | return readstatus; 103 | } // No Packet received 104 | 105 | } // end getData() 106 | 107 | -------------------------------------------------------------------------------- /I2C_Master/I2C_Master.ino: -------------------------------------------------------------------------------- 1 | /* 2 | I2C Test - Master 3 | Use with I2C_Slave.ino 4 | 5 | I2C communication between two Arduinos. The master will make a request from the slave. The slave will respond. 6 | In this example, the slave will send 14 bytes of data. I have a combination of bytes, integer, long unsigned integer and float data 7 | 8 | */ 9 | 10 | typedef struct { 11 | byte slaveID; 12 | byte cmdID; 13 | uint16_t mV; 14 | uint16_t temp; 15 | float myFloat; // some float number 16 | uint32_t mS; // millis() from slave 17 | } RemoteSensorData_t; 18 | 19 | typedef union float2bytes_t // union consists of one variable represented in a number of different ways 20 | { 21 | float f; 22 | char b[sizeof(float)]; 23 | }; 24 | 25 | #include // For I2C communication with panStamp, http://www.arduino.cc/en/Reference/Wire 26 | #define PACKET_SIZE 14 // I2C packet size, slave will send 14 bytes to master 27 | #define addrSlaveI2C 21 // ID of i@C slave 28 | 29 | // Function prototype 30 | bool getData(RemoteSensorData_t* sensorInfo); 31 | 32 | void setup () 33 | { 34 | Serial.begin(9600); 35 | delay(2000); 36 | Serial.print("RAM = "); 37 | Serial.println(freeRam()); 38 | Serial.println(F("Initialize library for I2C Master Test")); 39 | Wire.begin(); // Initialiae wire library for I2C communication 40 | Serial.println(F("Finished setup")); 41 | Serial.print("RAM = "); 42 | Serial.println(freeRam()); 43 | 44 | } // end setup() 45 | 46 | 47 | void loop() 48 | { 49 | RemoteSensorData_t sensor1; 50 | if( getData( &sensor1 )) 51 | { 52 | Serial.print(sensor1.slaveID); 53 | Serial.print("\t"); 54 | Serial.print(sensor1.cmdID); 55 | Serial.print("\t"); 56 | Serial.print(sensor1.mV); 57 | Serial.print("\t"); 58 | Serial.print(sensor1.temp); 59 | Serial.print("\t"); 60 | Serial.print(sensor1.myFloat); 61 | Serial.print(" "); 62 | Serial.print(sensor1.mS); 63 | Serial.print(" RAM:"); 64 | Serial.print(freeRam()); 65 | Serial.println(); 66 | } 67 | else 68 | { 69 | Serial.println(F("No packet received")); 70 | } 71 | 72 | delay(2000); 73 | } // end loop() 74 | 75 | 76 | // I2C Request data from slave 77 | bool getData(RemoteSensorData_t* sensorInfo) 78 | { 79 | float2bytes_t b2f; 80 | bool gotI2CPacket = false; 81 | byte i=0; 82 | byte i2CData[PACKET_SIZE]; // don't use char data type 83 | 84 | Wire.requestFrom(addrSlaveI2C, PACKET_SIZE); // request data from I2C slave 85 | 86 | while(Wire.available()) // Wire.available() will return the number of bytes available to read 87 | { 88 | i2CData[i++] = Wire.read(); // receive a byte of data 89 | gotI2CPacket = true; // Flag to indicate sketch received I2C packet 90 | } 91 | 92 | // If we got an I2C packet, we can extract the values 93 | if(gotI2CPacket) 94 | { 95 | gotI2CPacket = false; // Reset flag 96 | 97 | sensorInfo->slaveID = i2CData[0]; // Slave address 98 | sensorInfo->cmdID = i2CData[1]; // some sort of command ID 99 | 100 | sensorInfo->mV = i2CData[2] << 8; 101 | sensorInfo->mV |= i2CData[3]; 102 | sensorInfo->temp = i2CData[4] << 8; 103 | sensorInfo->temp |= i2CData[5]; 104 | 105 | // Get floating point number 106 | b2f.b[0] = i2CData[6]; 107 | b2f.b[1] = i2CData[7]; 108 | b2f.b[2] = i2CData[8]; 109 | b2f.b[3] = i2CData[9]; 110 | sensorInfo->myFloat = b2f.f; 111 | 112 | // Get long integer - milliseconds 113 | sensorInfo->mS = ( ((unsigned long)i2CData[10] << 24) 114 | + ((unsigned long)i2CData[11] << 16) 115 | + ((unsigned long)i2CData[12] << 8) 116 | + ((unsigned long)i2CData[13] ) ); 117 | 118 | return true; 119 | } // end got packet 120 | else 121 | { return false; } // No Packet received 122 | 123 | } // end getData 124 | 125 | 126 | 127 | //==================================================================================================== 128 | // Displays the amount of freem SRAM 129 | //==================================================================================================== 130 | int freeRam () { 131 | extern int __heap_start, *__brkval; 132 | int v; 133 | return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 134 | } 135 | 136 | -------------------------------------------------------------------------------- /I2C_Master_DSS/I2C_Master_DSS.ino: -------------------------------------------------------------------------------- 1 | /* 2 | I2C Test - Master 3 | Use with I2C_Slave.ino 4 | I2C communication between two Arduinos. The master will make a request from the slave. The slave will respond. 5 | In this example, the slave will send 14 bytes of data. I have a combination of bytes, integer, long unisgned integer and float data 6 | 7 | Testing library from DSS circuits http://github.com/rambo/I2C to see if it uses less RAM then wire.h library, and it does. 168 fewer bytes 8 | Slave arduino still needs to run wire.h library. DSS library doesn't support slave communication (as of 4/6/13) 9 | 10 | Reference: http://dsscircuits.com/articles/arduino-i2c-master-library.html 11 | 12 | */ 13 | 14 | typedef struct { 15 | byte slaveID; 16 | byte cmdID; 17 | uint16_t mV; 18 | uint16_t temp; 19 | float myFloat; // some float number 20 | uint32_t mS; // millis() from slave 21 | } RemoteSensorData_t; 22 | 23 | typedef union float2bytes_t // union consists of one variable represented in a number of different ways 24 | { 25 | float f; 26 | char b[sizeof(float)]; 27 | }; 28 | 29 | #include // https://github.com/rambo/I2C 30 | #define PACKET_SIZE 14 // I2C packet size, slave will send 14 bytes to master 31 | #define addrSlaveI2C 21 // ID of i@C slave 32 | 33 | // Function prototype 34 | int getData(RemoteSensorData_t* sensorInfo); 35 | 36 | void setup () 37 | { 38 | Serial.begin(9600); 39 | delay(2000); 40 | Serial.print("RAM = "); 41 | Serial.println(freeRam()); 42 | Serial.println(F("Initialize library for I2C Master Test")); 43 | I2c.begin(); 44 | I2c.timeOut(30000); 45 | Serial.println(F("Finished setup")); 46 | Serial.print("RAM = "); 47 | Serial.println(freeRam()); 48 | 49 | } // end setup() 50 | 51 | 52 | void loop() 53 | { 54 | RemoteSensorData_t sensor1; 55 | 56 | int i2cStatus = getData( &sensor1 ); 57 | if( i2cStatus == 0) 58 | { 59 | Serial.print(sensor1.slaveID); 60 | Serial.print("\t"); 61 | Serial.print(sensor1.cmdID); 62 | Serial.print("\t"); 63 | Serial.print(sensor1.mV); 64 | Serial.print("\t"); 65 | Serial.print(sensor1.temp); 66 | Serial.print("\t"); 67 | Serial.print(sensor1.myFloat); 68 | Serial.print(" "); 69 | Serial.print(sensor1.mS); 70 | 71 | Serial.print(" RAM:"); 72 | Serial.print(freeRam()); 73 | Serial.println(); 74 | } 75 | else 76 | { 77 | Serial.print(F("No packet received, error: ")); 78 | Serial.println(i2cStatus); 79 | } 80 | 81 | delay(2000); 82 | } // end loop() 83 | 84 | 85 | // I2C Request data from slave 86 | int getData(RemoteSensorData_t* sensorInfo) 87 | { 88 | float2bytes_t b2f; 89 | byte i2CData[PACKET_SIZE]; 90 | 91 | int readstatus = I2c.read(addrSlaveI2C, PACKET_SIZE , i2CData); //request data and store directly to i2CData array 92 | 93 | // If we got an I2C packet, we can extact the values 94 | if(readstatus == 0) 95 | { 96 | sensorInfo->slaveID = i2CData[0]; // Slave address 97 | sensorInfo->cmdID = i2CData[1]; // some sort of command ID 98 | 99 | sensorInfo->mV = i2CData[2] << 8; 100 | sensorInfo->mV |= i2CData[3]; 101 | sensorInfo->temp = i2CData[4] << 8; 102 | sensorInfo->temp |= i2CData[5]; 103 | 104 | // Get floating point number 105 | b2f.b[0] = i2CData[6]; 106 | b2f.b[1] = i2CData[7]; 107 | b2f.b[2] = i2CData[8]; 108 | b2f.b[3] = i2CData[9]; 109 | sensorInfo->myFloat = b2f.f; 110 | 111 | // Get long integer - milliseconds 112 | sensorInfo->mS = ( ((unsigned long)i2CData[10] << 24) 113 | + ((unsigned long)i2CData[11] << 16) 114 | + ((unsigned long)i2CData[12] << 8) 115 | + ((unsigned long)i2CData[13] ) ); 116 | 117 | return 0; 118 | } // end got packet 119 | else 120 | { return readstatus; } // No Packet received 121 | 122 | } // end getData 123 | 124 | 125 | 126 | //==================================================================================================== 127 | // Displays the amount of freem SRAM 128 | //==================================================================================================== 129 | int freeRam () { 130 | extern int __heap_start, *__brkval; 131 | int v; 132 | return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 133 | } 134 | 135 | -------------------------------------------------------------------------------- /I2C_Slave_struct/I2C_Slave_struct.ino: -------------------------------------------------------------------------------- 1 | /* 2 | I2C Test - this is the slave 3 | I2C communication between two Arduinos. Use this with I2C_Master_DSS_struct.ino 4 | 5 | Sends 14 bytes to Master. Put register map in a typedef struct and use a union to put in a byte array 6 | 7 | Scenario for register map - Connected to the slave arduino are some wireless water detectors and wired water detector. 8 | Both have a wet/dry status. But the wireless also have temperature, voltage of wireless Tx battery, and wireless signal strength 9 | 10 | Register Map: 11 | byte Desc 12 | 0 status (slave status) 13 | 1 sensor Id 14 | 2 sensor type: 0=wireless, 1=wired 15 | 3 Wet/Dry Status 16 | 4 temperature (unisgned int), (wireless only) 17 | 5 temperature 18 | 6 volts (float) (wireless only) 19 | 7 volts 20 | 8 volts 21 | 9 volts 22 | 10 Signal Strengh (wireless only) 23 | 24 | */ 25 | 26 | #include // http://arduino.cc/it/Reference/Wire 27 | 28 | typedef struct sensorData_t{ 29 | byte stat; 30 | byte sensorId; 31 | byte sensortype; 32 | byte isWet; 33 | uint16_t temp; 34 | float volts; 35 | byte signal; 36 | }; 37 | 38 | typedef union I2C_Packet_t{ 39 | sensorData_t sensor; 40 | byte I2CPacket[sizeof(sensorData_t)]; 41 | }; 42 | 43 | #define PACKET_SIZE sizeof(sensorData_t) 44 | #define MAX_SENT_BYTES 2 // max bytes master can send 45 | #define ID 0 46 | 47 | I2C_Packet_t leakinfo; 48 | 49 | byte receivedCommands[2]; // Commands sent from master. Only need one of the two bytes for now 50 | 51 | const byte addrSlaveI2C = 21; // I2C Slave address of this device 52 | bool printDataflag = false; 53 | 54 | void setup() 55 | { 56 | Serial.begin(9600); 57 | Serial.println(F("Initialize wire library for slave I2C")); 58 | Wire.begin(addrSlaveI2C); // Initiate the Wire library and join the I2C bus 59 | Wire.onRequest(wireRequestEvent); // Register a function to be called when a master requests data from this slave device. 60 | Wire.onReceive(wireReceiveEvent); // Function to be called when master sends commands to slave 61 | } 62 | 63 | 64 | void loop() 65 | { 66 | 67 | switch (receivedCommands[ID]) 68 | { 69 | case 22: 70 | leakinfo.sensor.stat = 0; 71 | leakinfo.sensor.sensorId = receivedCommands[ID]; 72 | leakinfo.sensor.sensortype = 0; 73 | leakinfo.sensor.isWet = 0; 74 | leakinfo.sensor.temp = 75; 75 | leakinfo.sensor.volts = 3141 / 1000.0; 76 | leakinfo.sensor.signal = 88; 77 | break; 78 | case 23: 79 | leakinfo.sensor.stat = 0; 80 | leakinfo.sensor.sensorId = receivedCommands[ID]; 81 | leakinfo.sensor.sensortype = 1; 82 | leakinfo.sensor.isWet = 1; 83 | leakinfo.sensor.temp = 60; 84 | leakinfo.sensor.volts = 216 / 100.0; 85 | leakinfo.sensor.signal = 79; 86 | break; 87 | default: 88 | leakinfo.sensor.stat = 1; 89 | leakinfo.sensor.sensorId = receivedCommands[ID]; 90 | leakinfo.sensor.sensortype = 0; 91 | leakinfo.sensor.isWet = 0; 92 | leakinfo.sensor.temp = 0; 93 | leakinfo.sensor.volts = 0; 94 | leakinfo.sensor.signal = 0; 95 | break; 96 | } // send switch 97 | 98 | 99 | // Print out data every time the Master makes a request 100 | if (printDataflag) 101 | { 102 | PrintI2CByteArray(); 103 | printDataflag = false; 104 | } 105 | 106 | } // end loop() 107 | 108 | // Send data to Master. This is an interrupt driven event 109 | void wireRequestEvent() 110 | { 111 | // Send byte array from panStamp. Main Arduino will decode bytes 112 | Wire.write(leakinfo.I2CPacket, PACKET_SIZE); 113 | printDataflag = true; 114 | 115 | } // end wireRequestEvent() 116 | 117 | // Master is sending data to slave. Data tells slave what to send back when it 118 | // gets a wireRequestEvent 119 | void wireReceiveEvent(int bytesReceived) 120 | { 121 | for (int a = 0; a < bytesReceived; a++) 122 | { 123 | if ( a < MAX_SENT_BYTES ) 124 | { receivedCommands[a] = Wire.read(); } 125 | else 126 | { Wire.read(); } // if we receive more data then allowed just throw it away 127 | } 128 | } // end wireReceiveEvent() 129 | 130 | 131 | // Print out data that will be sent to the master 132 | void PrintSensorData() 133 | { 134 | Serial.print(leakinfo.sensor.stat); 135 | Serial.print("\t"); 136 | Serial.print(leakinfo.sensor.sensorId); 137 | Serial.print("\t"); 138 | Serial.print(leakinfo.sensor.sensortype); 139 | Serial.print("\t"); 140 | Serial.print(leakinfo.sensor.isWet ); 141 | Serial.print("\t"); 142 | Serial.print(leakinfo.sensor.temp); 143 | Serial.print("\t"); 144 | Serial.print(leakinfo.sensor.volts); 145 | Serial.print("\t"); 146 | Serial.println(leakinfo.sensor.signal); 147 | } // end PrintSensorData() 148 | 149 | // Print the byt array going out I2C 150 | void PrintI2CByteArray() 151 | { 152 | for(int i=0; i