ecco il succo del mio cerebro, non è definitivo, non ci ho tolto i bacherozzi, ma cominciamo con questo
Satelliti, tutti uguali, cambia solo la loro #define
#include <SoftwareSerial.h>
#define RX 1 // *** D1, Pin 6
#define TX 2 // *** D2, Pin 7
#define LED 4 // *** D4, Pin 3
#define AT 0 // *** D0, pin 4
SoftwareSerial Radio(RX, TX);
unsigned long int tempo;
int temp; // temperatura in centesimi di grado
int oldt; // vecchia 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
#define INDIRIZZO 'A'
#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(4, OUTPUT);
pinMode(AT, OUTPUT);
digitalWrite(4, 0);
digitalWrite(AT, 1);
}
void loop(void)
{
digitalWrite(4, 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;
}
digitalWrite(4, 0);
// spengo il termometro
// ora, solo se la temperatura è cambiata
if (abs(temp - oldt) > 50)
{
// solo se è cambiata piu' di mezzo grado
oldt = temp;
trasmetti();
}
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(void)
{
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);
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
// 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
// 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, sarà 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);
// 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)
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
// salvo il caso di 2 trasmissione quasi contemporanee al millisecondo
// se un'altro satellite sta scrivendo, gli lascio il tempo di finire
}
// 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
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;
}
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 instead of 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;
}