This low power Arduino clone on a breadboard is sampling the temperature every three seconds and transmitting it to a Raspberry Pi which is acting as a hub. This is done using Nordic nrf24l01+ transceivers. They're dead cheap so ideal for this. The low power and therefore long battery life (not tested how long the batteries last yet) is due to a combination of removing most unneeded components and the use of a MCP1700-3302E/TO power regulator and power saving software from Jeelabs. More info to follow...
The RF24 library for Arduino
The RF24 library ported to Raspberry Pi
#The Raspberry Pi Code: #include <cstdlib> #include <iostream> #include "../RF24.h" #include <time.h> #include <stdio.h> using namespace std; // spi device, spi speed, ce gpio pin RF24 radio("/dev/spidev0.0",8000000,25); void setup(void) { // init radio for reading radio.begin(); radio.enableDynamicPayloads(); radio.setAutoAck(1); radio.setRetries(15,15); radio.setDataRate(RF24_2MBPS); radio.setPALevel(RF24_PA_LOW); radio.setCRCLength(RF24_CRC_16); radio.openReadingPipe(1,0xF0F0F0F0E4LL); radio.powerUp(); radio.startListening(); } int main(int argc, char** argv) { int count = 0; int timeout = 5; int returncode = 0; time_t starttime; time_t currtime; double difftime = 0; time(&starttime); setup(); char receivePayload[11] = ""; while ( (count < 1) && (difftime < timeout) ){ if ( radio.available() ) { // Dump the payloads until we've gotten everything bool done = false; while (!done) { // Fetch the payload, and see if this was the last one. uint8_t len = radio.getDynamicPayloadSize(); done = radio.read(receivePayload, len); count++; printf("%s\n",receivePayload); } } time(&currtime); difftime=((double)currtime - (double)starttime); } if(difftime > timeout - 1){ printf("timeout after %.f seconds\n",difftime); returncode = 1; } return returncode; } #-----------------------
#-----------------------
#Arduino Code:
// Voltage divider used for this circuit : Vin 4.8v (3 x AA batteries) and 2 x 10k Ohm resistors
// connected to analog 0. The input voltage from the voltage regulator is 3.3v
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port D3 on the Arduino
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device address
DeviceAddress insideThermometer;
//power stuff
//#include <avr/sleep.h>
#include <JeeLib.h> // Include library containing low power functions
ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Setup for low power waiting
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
RF24 radio(8,7); // (CE, CSN)
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(__FILE__);
Serial.println("ready...");
sensors.begin();
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
sensors.setResolution(insideThermometer, 12);
printf_begin();
radio.begin();
//radio.setChannel(0x6c);
radio.setAutoAck(1);
radio.setRetries(15,15);
radio.setPayloadSize(11);
radio.setDataRate(RF24_2MBPS);
radio.openWritingPipe(0xF0F0F0F0E4LL); //3LL for nona, 2LL for nano, 1LL for UNO
radio.setPALevel(RF24_PA_MAX);
radio.enableDynamicPayloads();
//radio.printDetails();
// analogReference(INTERNAL);
}
void loop()
{
//voltage
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 3.3V):
float voltage = sensorValue * (3.3 / 1023.0);
float undivided = (voltage * 20000)/10000;
//----------------
sensors.requestTemperatures(); // Send the command to get temperatures
float tempC = sensors.getTempC(insideThermometer);
radio.stopListening();
char outBuffer[11]= "";
char temp[8]="";
char hum[8]="09.0";
int volt = readVcc();
ftoa(temp,tempC,2);
ftoa(hum, undivided,2);
sprintf(outBuffer,"%s,%s",temp,hum);
//Serial.println(outBuffer);
radio.powerUp();
radio.write(outBuffer, strlen(outBuffer));
radio.powerDown();
Sleepy::loseSomeTime(3000); // SLEEP (DEEP) for 3 seconds
}
//===============================================================================
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
//===============================================================================
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}
//==========================================================================================
char *ftoa(char *a, double f, int precision)
{
long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
char *ret = a;
long heiltal = (long)f;
itoa(heiltal, a, 10);
while (*a != '\0') a++;
*a++ = '.';
long desimal = abs((long)((f - heiltal) * p[precision]));
itoa(desimal, a, 10);
return ret;
}
//===============================================================================
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}
#-----------------------
code here #-----------------------
#-----------------------
code here #-----------------------
#-----------------------
code here #-----------------------