Вот мой вариант
//--- One-wire //
#include <OneWire.h>
#define ONE_WIRE_BUS 7
#define DS_Power 8
#define DS_Gnd 6
OneWire oneWire(ONE_WIRE_BUS);
#include <DallasTemperature.h>
DallasTemperature sensors(&oneWire); //DS18B20
#define LED 5
int tests=0;
#define chclient 1 // номер клиента 1...
#define timeoutper 400 // таймаут запросов от сервера.
#define timesend 300 // интервал отправки данных,для обычных датчиков можно установить время выше.
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
unsigned long time1=0;
unsigned long time2=0;
#include <avr/sleep.h>
#include <avr/wdt.h>
#define CNT 30 // количество циклов по 8 секунд между "посылками" (30 = 4 минуты между посылками)
int count; //переменная для счётчика циклов
volatile boolean wdt_tripped=1;
boolean mode = 1; //0 - нормальный режим (редко отправляем данные и не моргаем), 1 - тестовый режим (данные отправляем раз в 8 секунд и моргаем светодиодом)
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
//
// 0 -прием , 1 -передача
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL,0xF0F0F0F0D2LL};
//
// структура принятых данных.МЕНЯТЬ НЕЛЬЗЯ
typedef struct{
byte identifier;
byte val1;
byte val2;
byte val3;
byte val4;
}
nf0;
nf0 servernf;
// структура отправляемых данных.Изменяемые данные.Размер структуры должен быть не больше 32 байт !
typedef struct{
byte identifier;// номер передатчика.МЕНЯТЬ НЕЛЬЗЯ
int temperature_Sensor;// передаём температуру.
int Analog;
unsigned int Error_Message; // счетчик ошибок
unsigned long count;// счетчик передач для контроля качества канала
}
nf1;
nf1 clientnf;
/* ************************************** */
void setup()
{
Serial.begin(9600);
pinMode(DS_Power, OUTPUT);
pinMode(DS_Gnd, OUTPUT);
digitalWrite(DS_Power, HIGH);
digitalWrite(DS_Gnd, LOW);
radio.begin();
delay(2);
// выбор скорости
// radio.setDataRate(RF24_250KBPS);
radio.setDataRate(RF24_1MBPS);
// radio.setDataRate(RF24_2MBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setChannel(100); //тут установка канала
radio.setCRCLength(RF24_CRC_16);
radio.setAutoAck(false); // выключить аппаратное потверждение
radio.setRetries(15,15);
radio.openReadingPipe(1,pipes[0]); // Открываем канал приема
radio.openWritingPipe(pipes[1]); // Открываем канал передачи
clientnf.identifier = chclient;
sensors.begin();
wdt_disable();
wdt_reset();
wdt_enable(WDTO_8S); //пробуждение каждые 8 сек
count = 0;
// светик
pinMode(LED, OUTPUT);
}
byte errorstate;
void loop()
{
wdt_interrupt_mode();
if (wdt_tripped)
{
count++;
wdt_tripped = 0;
// отправим данные, если уже "пора"
if (count == ((mode==1) ? (count) : (CNT)))
{
// зажжем светодиод
if (mode == 1)
{
digitalWrite(LED, HIGH);
}
radio.powerUp(); //подаём питание на NRF24
delay(20);
// тут будут опросы сенсоров
sensors.requestTemperatures(); // опрос датчика температуры улица
clientnf.temperature_Sensor = sensors.getTempCByIndex(0)*10; // опрос датчика температуры улица
//Serial.println(sensors.getTempCByIndex(0));
clientnf.Analog=readVcc();
//**************************************************************/
if (clientnf.count <= 2147483646)
{
clientnf.count++; // счетчик передач для контроля качества канала
}
else
{
clientnf.count = 0;
}
radio.stopListening();
bool ok = radio.write( &clientnf, sizeof(clientnf) );
radio.startListening();
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > timeoutper )
{
timeout = true;
}
if ( timeout )
{
// счетчик ошибок
clientnf.Error_Message++;
errorstate++; // счетчик ошибок для повтора
}
else
{
radio.read( &servernf, sizeof(servernf) );
errorstate=0;
}
if (errorstate>=50)
{
errorstate=0; // не более 3 попыток для повтора
}
count = 0;
// погасим светодиод
if (mode == 1)
{
digitalWrite(LED, LOW);
}
}
}
if(mode == 1 && tests<10)
{
tests++;
}
else
{
mode = 0;
}
radio.powerDown(); // отключаем питание RF24
delay(20);
system_sleep(); //МК засыпает
} // конец loop
long readVcc()
{
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(75); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
// result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
// result = 1074150L / result; // Calculate Vcc (in mV); 1125300 = 1.05*1023*1000
result = 1094610L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 //Подбирал сам по тестеру
return result; // Vcc in millivolts
}
void system_sleep()
{
delay(2); // Wait for serial traffic
_SFR_BYTE(ADCSRA) &= ~_BV(ADEN); // Switch ADC off
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode(); // System sleeps here
sleep_disable();
_SFR_BYTE(ADCSRA) |= _BV(ADEN); // Switch ADC on
}
void wdt_interrupt_mode() {
wdt_reset();
WDTCSR |= _BV(WDIE); // Restore WDT interrupt mode
}
ISR(WDT_vect) {
wdt_tripped=1; // set global volatile variable
}
Режим сна взял
здесь, там же есть и измерение питания, но я нарыл в другом месте, возможны отличия. Код для nRF хаба TACL. Ну и в железе. Светодиод переместил на D5 для экономии, используется только при отладке. Светодиод питания и стаб убрал.