This sketch implements a COSM remote sensor, that measures temperature and VCC. The board sleeps during the idle period and is woken up by the watch dog.
#include <avr/wdt.h>
#include <avr/sleep.h>
#include "HardwareRadio.h"
static volatile uint8_t adcfinished = 0;
static int8_t adc_offset = 0;
static inline void wdt_timersetup(uint8_t timeout)
{
WDTCSR = (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIF) | (1 << WDIE) |
(timeout & 0x08 ? _WD_PS3_MASK : 0x00) | (timeout & 0x07);
}
ISR(WDT_vect, ISR_NOBLOCK)
{
}
ISR(ADC_vect, ISR_BLOCK)
{
adcfinished = 1;
}
static inline int16_t adc_measure(void)
{
set_sleep_mode(SLEEP_MODE_ADC);
adcfinished = 0;
do
{
sleep_mode();
} while (0 == adcfinished);
return ADC ;
}
float measure_tmcu(void)
{
int32_t val = 0;
uint8_t nbavg = 5;
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
ADCSRB = (1 << MUX5);
ADMUX = (1 << REFS1) | (1 << REFS0) | (1 << MUX3) | (1 << MUX0);
_delay_us(200);
ADCSRA |= (1 << ADIF);
ADCSRA |= (1 << ADIE);
adc_measure();
_delay_us(100);
for(uint8_t i=0;i<nbavg;i++){
val += adc_measure() - adc_offset;
}
ADCSRA &= ~((1 << ADEN) | (1 << ADIE));
return (1.13 * val / (float)nbavg - 272.8);
}
int8_t measure_adc_offset(void)
{
uint16_t val;
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
ADCSRB = 0;
ADMUX = (1 << REFS1) | (1 << REFS0) | (1 << MUX3);
_delay_us(200);
ADCSRA |= (1 << ADIF);
ADCSRA |= (1 << ADIE);
adc_measure();
_delay_us(100);
val = adc_measure();
ADCSRA &= ~((1 << ADEN) | (1 << ADIE));
return (val);
}
float measure_vmcu(void)
{
uint16_t v;
uint8_t vth;
for(vth=0;vth<32;vth++){
BATMON = vth & 0x1F;
BATMON = vth & 0x1F;
if(0 == (BATMON & (1<<BATMON_OK))){
break;
}
}
if(vth & 0x10){
v = 2550 + 75*(vth&0x0F);
}else{
v = 1700 + 50*(vth&0x0F);
}
return v / 1000.0;
}
void setup()
{
DDRB = 0x00;
PORTB = 0xFF;
DDRD = 0x00;
PORTD = 0xFF;
DDRE = 0x00;
PORTE = 0xFF;
DDRF = 0x00;
PORTF = 0xFF;
DDRG = 0x00;
PORTG = 0xFF;
DIDR0 = 0xFF;
adc_offset = measure_adc_offset();
wdt_timersetup(WDTO_8S);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
void loop()
{
float tmcu, vmcu;
tmcu = measure_tmcu();
vmcu = measure_vmcu();
Radio.print("ADDR=");
Radio.print(", T=");
Radio.print(tmcu);
Radio.print(", V=");
Radio.print(vmcu);
Radio.print('\n');
while(Radio.
tx_in_progress);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
}