sonde/main.c

294 lines
5 KiB
C

#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include "debug.h"
#include "analog.h"
//#include "dht11.h"
#include "rf24.h"
#include "lib/Hamming.h"
#include "crc8.h"
#include "onewire.h"
#define EE_Num 0
uint8_t ADDR[5]={0xE7,0xE7,0xE7,0xE7,0xE7}; //{0xE7,0xE7,0xE7,0xE7,0xE7}; //
#define PKTLEN 24
#define CMD_DATA 0x20
#define CMD_BIN 0x30
#ifdef DEBUG
char debugbuf[32];
uint16_t totaltime;
#endif
char buffer[18];
char* text = buffer +4;
uint8_t sendbuffer[24];
uint8_t id;
uint8_t pid=0;
volatile bool wdt_flag=false;
volatile bool pcint_flag=false;
ISR(WATCHDOG_vect){
wdt_flag=true;
}
ISR(PCINT0_vect){
pcint_flag = true;
}
// Put in sleep mode until next ISR
void sleep(){
#ifdef DEBUG
uint16_t time = TCNT1;
totaltime +=time;
//debughex(&time,2);
#endif
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_enable();
//sleep_bod_disable();
sei();
sleep_cpu();
sleep_disable();
#ifdef DEBUG
TCCR1A =0;
TCCR1C =0;
TCNT1 = 0;
TCCR1B = 2;
#endif
}
// Sleep for c*8s + 0-6s
void wait_for_next(int c){
int cnt=c;
#ifdef DEBUG
cnt=2;
#endif
while (cnt--){
wdt_enable(WDTO_8S);
WDTCSR |= _BV(WDIE);
sleep();
}
cnt = rand()%6;
while (cnt--){
wdt_enable(WDTO_1S);
WDTCSR |= _BV(WDIE);
sleep();
}
#ifdef DEBUG
debughex((char *)(&totaltime),2);
totaltime=0;
debug("\r");
#endif
}
// Energy saving mode
void power_down(){
stopADC();
power_all_disable();
}
// Wait until radio tx done & poweroff
void wait_for_radio(){
wdt_enable(WDTO_120MS);
wdt_flag=false;
pcint_flag = false;
cli();
// Sleep until radio ready or wdt 60ms
while (bit_is_set(PINA,PA7) || (!wdt_flag) ){
WDTCSR |= _BV(WDIE);
sleep();
cli(); // disable interrupts before testing wdt_flag
}
// disable radio -> low power until next tx
rf24_powerDown();
if(!wdt_flag) // radio ok... wait until 60ms
{
WDTCSR |= _BV(WDIE); // reenable wdt interrupt
sleep();
}
return;
}
// Load nRF lib setup in Ram
void setupRadio(){
rf24_CONFIG = 0;
rf24_RF_CH = 90;
rf24_RF_SETUP = 0x26;
rf24_FEATURE = 0;//_BV(EN_DPL)|_BV(EN_ACK_PAY)|_BV(EN_DYN_ACK);
rf24_DYNPD = 0x00;
rf24_RX_PW[0]=PKTLEN;
rf24_RX_PW[1]=PKTLEN;
rf24_SETUP_RETR = 0x00;
rf24_EN_AA = 0x00;
}
// Restart USI & Reinit nRF24
void initRadio(){
power_usi_enable();
rf24_init();
rf24_writeRegister(RX_ADDR_P0,(uint8_t*)ADDR,5);
rf24_writeRegister(TX_ADDR,(uint8_t*)ADDR,5);
}
// ****
// Transmit data buffer
void txData(){
uint8_t crc,cpt,a,b,len;
uint8_t *in, *out;
// Pkt ID
buffer[1] = id;
buffer[2] = pid++;
len = buffer[0] & 0x0F;
#ifdef DEBUG
debughex(buffer,len);
debug("\r");
#endif
// CRC Calc
buffer[3] = 0; // CRC =0 in crc calc;
crc=0; cpt= len; in=(uint8_t*)buffer;
while(cpt--) crc = _crc8_ccitt_update(crc,*(in++));
buffer[3] = crc;
// Hamming compute
cpt= len ;
if(cpt & 1) buffer[cpt++]=0; // odd number => add one 0
cpt/=2; in=(uint8_t*)buffer; out = sendbuffer;
while(cpt--){
a = *(out++)= *(in++);
b = *(out++)= *(in++);
*(out++) = HammingCalculateParity2416(a,b);
}
cpt=4;
while (cpt--){
rf24_send(sendbuffer,PKTLEN);
wait_for_radio();
}
}
int main(void)
{
#ifdef DEBUG
DDRB |= _BV(PB0);
debug("Sonde Start \r");
#endif
uint8_t rvcc=0,rtx=0,delay=6;
uint16_t t_i, lt_i=100;
int vcc;
// Setup
power_down();
setupRadio();
id = eeprom_read_byte((const uint8_t*)EE_Num);
// random seed
initADC();
srand((int)readVcc() * id );
DDRB |= _BV(PB1) ;
PORTB &= ~_BV(PB1);
while(1){
// each 10 runs => read VCC
if(!(rvcc--)){
initADC();
vcc = readVcc();
stopADC();
rvcc=9;
}
// PowerUp DS18B20
w1_start();
// Wait 15ms (for DS18B20 to start)
wdt_enable(WDTO_15MS);
WDTCSR |= _BV(WDIE);
sleep();
// Start DS18B20 Temp conversion
start_meas();
// Wait for 1s
wdt_enable(WDTO_1S);
WDTCSR |= _BV(WDIE);
sleep();
// Read temp & stop DS18B20
t_i = read_meas();//=temp*100;
w1_stop();
// If temp change more than 1 since last tx
if(t_i > lt_i+1 || t_i < lt_i -1){
// Force Tx
rtx=0;
} else {
delay=6;
}
// If temp change more than 2 => reduced delay
if(t_i > lt_i+2 || t_i < lt_i -2){
// Force Tx
delay=2;
}
if(!(rtx--)){
// Send data
initRadio();
buffer[0] = 0x0A | CMD_BIN; // 10 octets :
*(uint16_t*)(buffer+4) = 0x0002; // BIN v2 = vcc+tempDS
*(uint16_t*)(buffer+6) = vcc; // 2 o
*(uint16_t*)(buffer+8) = t_i; // 2 o
txData(buffer);
// keep tx temp
lt_i = t_i;
rtx=5;
//radio off
rf24_powerDown();
}
power_down();
wait_for_next(delay);
}
}