294 lines
5 KiB
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);
|
|
}
|
|
}
|
|
|