Hardware
The ElectricImp's WiFi connection and programming is wonderfully simple but price, power requirements, and its closed source aspect made me not invest more time here. Instead I tried an old-school RF pair to transmit Temperature data between two Arduinos.Transmitter
Since I'd like to keep using 3.3v sensors such as the TMP102, I got a low power 3.3v 8MHz Arduino Mini Pro to read the sensor and transmit the data to the RF Link Transmitter. This way I don't have to translate the signals between 5v and 3.3v as i would have had to do with a regular 5v Arduino. The soldering was a quick and dirty job where I connected the power and I2C link directly to the Arduino:As you can see above I simply hardwired a signal line from the Arduino over to the RF transmitter using a white cable. The connection to the TMP102 sensor is done over I2C using A4/A5 with connectors protruding from the back of the Arduino and looping back over the the sensor.
The main focus is the transmitter since the receiver will most likely be a single AC powered device. Therefore I dug out my old Uno and a ProtoShield to hack together the receiver side. I really just wanted to print the information on the screen but I also had to experiment with some error checking code in the end. RF transmissions are NOT reliable as I found out.
Receiver
The final receiver unit ended up using not much more than the Uno, a ProtoShield, and an RF Link Receiver:
The code uses the VirtualWire Arduino library and was amazingly simple to use and setup. With no antenna to speak of, I ended up with about a 100ft range which is not bad since I was feeding the transmitter a paltry 3.3v. The RF Link specsheet says a range of 1.5 to 12v so I was planning to do some range experimentation, figuring out how supply voltage would affect range but ended up moving on to the next project that uses XBee radios instead.
Software
The code below is for both the receiver and transmitter with a simple #ifdef statements redirecting the Arduino compiler to build each sketch. The LED usage made it easy to debug and do some manual range checking by just watching for blinks every second a GOOD reading was received. Removing the checksum code allows you to see the corrupted messages as distance and interference increased.
Fun little project but I won't be going in this direction since I don't want to deal with cross talk interference with 10+ sensor nodes and the re-transmission protocols required. I was also not happy with having to add an Arduino Pro Mini to each node even at $10 per node although eBay sells them for $6 now which is getting very tempting...
#include <Wire.h>
#include <VirtualWire.h>
static int tmp102Address = 0x48;
static byte kID = 0;
byte gCounter = 0;
void encode(byte ioBuffer[8], byte inTemp1, byte inTemp2)
{
ioBuffer[0] = 't';
ioBuffer[1] = 'e';
ioBuffer[2] = 'm';
ioBuffer[3] = 'p';
ioBuffer[4] = gCounter++;
ioBuffer[5] = kID;;
ioBuffer[6] = inTemp1;
ioBuffer[7] = inTemp2;
}
bool decode(byte ioBuffer[8], byte outTemp[2])
{
Serial.print((char)ioBuffer[0]);
Serial.print((char)ioBuffer[1]);
Serial.print((char)ioBuffer[2]);
Serial.print((char)ioBuffer[3]);
Serial.print(" #");
Serial.print((int)ioBuffer[4]);
Serial.print(" id-");
Serial.print((int)ioBuffer[5]);
Serial.print(" [");
Serial.print((int)ioBuffer[6]);
Serial.print(',');
Serial.print((int)ioBuffer[7]);
Serial.print("] ");
outTemp[0] = ioBuffer[6];
outTemp[1] = ioBuffer[7];
return ioBuffer[0] == 't' && ioBuffer[1] == 'e' && ioBuffer[2] == 'm' && ioBuffer[3] == 'p';
}
#define transmitter
#ifdef transmitter
void setup()
{
Serial.begin(9600);
Serial.println("Transmitter");
Wire.begin();
// Initialise the IO and ISR
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000); // Bits per sec
vw_set_tx_pin(3);
}
void loop()
{
byte message[8];
Wire.requestFrom(tmp102Address, 2);
encode(message, Wire.read(), Wire.read());
digitalWrite(13, true); // Flash a light to show transmitting
vw_send(message, 8);
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13, false);
Serial.println(gCounter);
delay(1000); // Send a temperature sample every second
}
#else // receiver
void setup()
{
Serial.begin(9600);
Serial.println("Receiver");
// Initialize the IO and ISR
vw_set_ptt_inverted(true);
vw_set_rx_pin(3);
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
digitalWrite(13, true); // Flash a light to show received good message
byte id;
byte counter;
byte temp[2];
decode(buf, temp);
// 12bit int so using two's compliment for negative
int TemperatureSum = ((temp[0] << 8) | temp[1]) >> 4;
float celsius = TemperatureSum * 0.0625;
Serial.print(celsius);
Serial.print("C ");
Serial.print(celsius * 9 / 5 + 32);
Serial.println("F");
delay(100);
digitalWrite(13, false);
}
}
#endif
Fun little project but I won't be going in this direction since I don't want to deal with cross talk interference with 10+ sensor nodes and the re-transmission protocols required. I was also not happy with having to add an Arduino Pro Mini to each node even at $10 per node although eBay sells them for $6 now which is getting very tempting...
#include <Wire.h>
#include <VirtualWire.h>
static int tmp102Address = 0x48;
static byte kID = 0;
byte gCounter = 0;
void encode(byte ioBuffer[8], byte inTemp1, byte inTemp2)
{
ioBuffer[0] = 't';
ioBuffer[1] = 'e';
ioBuffer[2] = 'm';
ioBuffer[3] = 'p';
ioBuffer[4] = gCounter++;
ioBuffer[5] = kID;;
ioBuffer[6] = inTemp1;
ioBuffer[7] = inTemp2;
}
bool decode(byte ioBuffer[8], byte outTemp[2])
{
Serial.print((char)ioBuffer[0]);
Serial.print((char)ioBuffer[1]);
Serial.print((char)ioBuffer[2]);
Serial.print((char)ioBuffer[3]);
Serial.print(" #");
Serial.print((int)ioBuffer[4]);
Serial.print(" id-");
Serial.print((int)ioBuffer[5]);
Serial.print(" [");
Serial.print((int)ioBuffer[6]);
Serial.print(',');
Serial.print((int)ioBuffer[7]);
Serial.print("] ");
outTemp[0] = ioBuffer[6];
outTemp[1] = ioBuffer[7];
return ioBuffer[0] == 't' && ioBuffer[1] == 'e' && ioBuffer[2] == 'm' && ioBuffer[3] == 'p';
}
#define transmitter
#ifdef transmitter
void setup()
{
Serial.begin(9600);
Serial.println("Transmitter");
Wire.begin();
// Initialise the IO and ISR
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000); // Bits per sec
vw_set_tx_pin(3);
}
void loop()
{
byte message[8];
Wire.requestFrom(tmp102Address, 2);
encode(message, Wire.read(), Wire.read());
digitalWrite(13, true); // Flash a light to show transmitting
vw_send(message, 8);
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13, false);
Serial.println(gCounter);
delay(1000); // Send a temperature sample every second
}
#else // receiver
void setup()
{
Serial.begin(9600);
Serial.println("Receiver");
// Initialize the IO and ISR
vw_set_ptt_inverted(true);
vw_set_rx_pin(3);
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
digitalWrite(13, true); // Flash a light to show received good message
byte id;
byte counter;
byte temp[2];
decode(buf, temp);
// 12bit int so using two's compliment for negative
int TemperatureSum = ((temp[0] << 8) | temp[1]) >> 4;
float celsius = TemperatureSum * 0.0625;
Serial.print(celsius);
Serial.print("C ");
Serial.print(celsius * 9 / 5 + 32);
Serial.println("F");
delay(100);
digitalWrite(13, false);
}
}
#endif