e questo è dopo la prima passata col Neocid, spero che di bacherozzi non ce ne siano più
// Non e' piu' stagione di riscaldamento,
// di Nelson StandardOil e il suo collega anonimo
#define INDIRIZZO 'A'
// define spostata qui per trovarla facilmente al cambio di satellite
#include <SoftwareSerial.h>
#define RX 1 // *** D1, Pin 6
#define TX 2 // *** D2, Pin 7
#define TER 4 // *** D4, Pin 3
#define AT 0 // *** D0, pin 4
SoftwareSerial Radio(RX, TX);
int temp; // temperatura in centesimi di grado
int oldt; // temperatura precedente, per trasmettere solo se cambia
#define SOGLIA 50 // valore di soglia per la trasmissione nuova temperatura
// Librerie termometro
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3 // *** D3, Pin 2
// Su il protocollo onewire
OneWire oneWire(ONE_WIRE_BUS);
// dichiariamo un termometro sul bus unewire
DallasTemperature sensors(&oneWire);
#define TEMPOSTABILE 20000
// 20 secondi per stabilizzare il termometro...........
// per la comunicazione
#define START '#'
char messaggio[] = "#A0123x"; // inizializzare stringa di trasmissione
#define TIMEOUT 1000 // timeout per ricevere ack;
#define TENTATIVI 3 // numero di ritentativi di trasmissione
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
EMPTY_INTERRUPT(WDT_vect)
void setup(void)
{
pinMode(TER, OUTPUT);
pinMode(AT, OUTPUT);
digitalWrite(TER, 0);
digitalWrite(AT, 1);
}
void loop(void)
{
digitalWrite(TER, 1); // energia al termometro
delay(TEMPOSTABILE);// per dare il tempo di stabilizzarsi
sensors.begin();
// leggo
sensors.requestTemperatures(); // Send the command to get temperatures
temp = sensors.getTempCByIndex(0) * 100;
if (temp < 0)
{
temp = 0;
}
if (temp > 9000)
{
temp = 9000;
}
// spengo il termometro
digitalWrite(TER, 0);
// ora, solo se la temperatura è cambiata oltre SOGLIA
if (abs(temp - oldt) > SOGLIA)
{
oldt = temp;
trasmetti(temp);
}
Sleep_now(1, 7); //quanti cicli di sleep, divisore
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
}
void trasmetti(int temp)
{
//variabile locale stesso nome di variabile globale, per non alterare la globale
messaggio[0] = START;
messaggio[1] = INDIRIZZO;
messaggio[5] = temp % 10 + '0';
temp = temp / 10;
messaggio[4] = temp % 10 + '0';
temp = temp / 10;
messaggio[3] = temp % 10 + '0';
temp = temp / 10;
messaggio[2] = temp % 10 + '0';
messaggio[6] = '\0';
messaggio[6] = checkchar(messaggio);
messaggio[7] = '\0';
// accendo la radio
digitalWrite(AT, 0); // abbasso set
delay(80); //tempo di reazione
digitalWrite(AT, 1); // alzo set, radio accesa
delay(200); // tempo di reazione, adesso è ON
Radio.begin(9600);// sembra sia meglio tenere le velocità casomai un poco piu' basse
delay(100); // forse non serve questo delay
for (byte i = 0; i < TENTATIVI; i++)
{
// esegue una serie di tentativi di trasmissione
// esce se riceve esito OK
if (txconfermata(messaggio)) // esegue una trasmissione confermata del messaggio
{
break;
}
// se confermata esce dal ciclo subito
// se invece sono arrivato fin qui...
// male, trasmissione non confermata
// per evitare il pericolo di collisione:
// aspetto un tempo proporzionale al mio indirizzo
// un minimo per garantire la fine della trasmissione attuale
delay(100);// che speriamo bastino
// adesso quello che prima stava trasmettendo è fermo, spero
// la parte proporzionale
delay((INDIRIZZO + 1 - 'A') * 10); // 10 millisecondi per A, 20 per B e così via
}
// se sono arrivato qui delle due l'una: una trasmissione confermata
// oppure tanti tentativi ciccati, comunque torno a dormire: si vede che la centrale è spenta
delay(80);
// spengo la radio
digitalWrite(AT, 0); // abbasso set
delay(80); //tempo di reazione, adesso siamo in AT mode
Radio.print("AT+SLEEP");
delay(80); // anche questo delay forse non serve
// via set
digitalWrite(AT, 1);
// adesso la radio è spenta
}
bool txconfermata(char messaggio[])
{
// esegue una trasmissione confermata del messaggio
// restituisce true se ha ricevuto ack
// svuoto il buffer di seriale (che dovrebbe essere già vuoto, ma...)
delay(2); // se ci fosse una trasmissione in corso, questo ritardo mi da il tempo di intercettarla
while (Radio.available())
{
Radio.read();
delay(1);
// siccome la velocità di svuotamento è circa uguale a quella di trasmissione
// se un'altro satellite sta scrivendo, gli lascio il tempo di finire
// salvo il caso di 2 trasmissioni quasi contemporanee al millisecondo
}
// trasmetto il messaggio
Radio.print(messaggio);
// adesso aspetto un timeout
// e leggo il buffer di seriale
byte stato = 0; // per la macchina a stati che riconosce ack
unsigned long int tempo = millis(); // per il timeout
delay(10); // tempo per la centrale di elaborare il messaggio e ritrasmettere, ottenuto per tentativi
char messaggiocorretto [] = {START, INDIRIZZO, 'O', 'K'};
while (millis() - tempo < TIMEOUT)
{
if (Radio.available())
{
char cx = Radio.read();
if (cx == messaggiocorretto [stato])
{
stato++;
}
else
{
return 0;
}
if (stato == 4)
{
return 1;
// dovrebbe essere 1
}
}
}
return 0; // giusta regola qui ci dovremmo arrivare solo in caso si timeout
}
void Config_wdt(byte timeout)
{
cli();
wdt_reset(); // reset watchdog timer
MCUSR &= ~(1 << WDRF); // clear reset flag
WDTCR = (1 << WDE) | (1 << WDCE); // enable watchdog
WDTCR = (1 << WDIE) | timeout; // watchdog interrupt al posto di reset
//+reset, timeout can be 15,30,60,120,250,500ms or 1,2,4,8s
sei();
}
void Sleep_now(byte i, byte timeout)
{
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
Config_wdt(timeout);
for (byte y = i; y > 0; --y)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set type of sleepmode
power_all_disable(); // disable unneeded loads
wdt_reset(); // timer should start at zero
sleep_enable(); // approach sleep mode
sleep_mode(); // enter sleep mode (confirm)
sleep_disable(); // entrance point when woken up
power_all_enable(); // re-enable the loads
}
}
char checkchar(char messaggio[])
{
// restituisce il carattere di controllo per il messaggio in ingresso
// una cosa semplice, non troppo elaborata
byte appoggio = 0;
byte index = 0;
while (messaggio[index])
{
appoggio = ((appoggio >> 1) | (appoggio << 7)) ^ messaggio[index++];
}
return (char)(appoggio % 93) + 33;
}