#include <SPI.h>
#include "RF24.h"
#include <Wire.h>
#include "HTU21D.h"
#include <avr / sleep.h>
#include <avr / wdt.h>
#define CNT 30 // number of cycles for 8 seconds between the "premises" (30 = 4 minutes between sending)
int count; // Variable for the cycle counter
volatile boolean wdt_tripped = 1;
// Description of the module parameters
500 // #define SID identifier External sensor 1
#define NumSensors 4 // number of sensors (and another mandatory enter values ??- the name of the sensor)
boolean mode = 0; // 0 - normal mode (rarely sends data and does not blink)
// 1 - Test mode (send data every 8 seconds and the LED to blink)
////////////////////////////////////////////////// ///////////////////////////
// Create a structure for transmitting values
typedef struct {
int SensorID; // Handle sensor
int ParamID; // Parameter identifier
float ParamValue; // Value
char Comment [16]; // Comment
}
Message;
#define LED 9
#define BUTTON 4
// Create a structure to describe the parameters
typedef struct {
float Value; // Value
char Note [16]; // Comment
}
Parameter;
int tests = 0;
////////////////////////////////////////////////// ///////////////////////////
Parameter MySensors [NumSensors + 1] = {// description of sensors (primary and initialization)
NumSensors, "SN4 (in & out)", // in the "comment" indicate explanatory information about the sensor and the number of sensors
0, "Temp, C", // temperature with internal sensor
0, "Hum,%", // relative humidity with integrated sensors
0, "BATT, Flag", // the status of the battery is in order (0 - "dead", 1 - "live")
0, "VCC, V", // supply voltage (for internal data MK)
};
Message sensor;
////////////////////////////////////////////////// ///////////////////////////
// RF24 radio (CE, CSN);
RF24 radio (8,7);
// Choose two "pipe" (choose your own)
const uint64_t pipes [2] = {
0xF0F0F0F0A1LL, 0xF0F0F0F0A2LL};
////////////////////////////////////////////////// ///////////////////////////
HTU21D myHumidity;
// Sleep for MK
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
}
void setup ()
{
wdt_disable ();
wdt_reset ();
wdt_enable (WDTO_8S); // Awakening every 8 seconds
count = 0;
// Svetik
pinMode (LED, OUTPUT);
// Inizializatsiya HTU21D
myHumidity.begin ();
radio.begin ();
//radio.setPALevel(RF24_PA_HIGH); // The power level (only works with the version of RF + PA)
radio.setDataRate (RF24_250KBPS); // Transfer Rate
radio.setRetries (15,15);
// Channel number on which work (pick your own)
radio.setChannel (100);
radio.openWritingPipe (pipes [0]);
radio.openReadingPipe (1, pipes [1]);
radio.stopListening (); // Disable the receive mode
// At the start of turn "test" mode - send data frequently and LED to blink
mode = 1;
}
void loop (void)
{
// Here you can increase the time interval between the mandrel data RF24 due to cycle counter
wdt_interrupt_mode ();
if (wdt_tripped) {
count ++;
wdt_tripped = 0;
// Send the data if you are already "it is time"
if (count == ((mode == 1)? (count): (CNT))) {
calculateValue ();
// LED will light
if (mode == 1) {
digitalWrite (LED, HIGH);
}
radio.powerUp (); //; Ideas on food NRF24
delay (20);
for (int i = 1; i <= NumSensors; i ++) {
sendSensorMessage (i);
}
radio.powerDown (); // Disable the power RF24
delay (20);
count = 0;
// Extinguish LED
if (mode == 1) {
digitalWrite (LED, LOW);
}
}
}
if (tests <10) {
mode = 1;
tests ++;
}
else {
mode = 0;
}
// Sleep!
system_sleep (); // MC falls asleep
}
// Function calculation of all sensor values
void calculateValue () {
// Code to retrieve data
// Built-in temperature and humidity sensor (HTU21D)
MySensors [1] .Value = myHumidity.readTemperature ();
MySensors [2] .Value = myHumidity.readHumidity ();
// If the voltage is greater than 2.67V - Battery "alive" (1)
// If less - "die soon" (0)
MySensors [3] .Value = (MySensors [4] .Value> 2.67)? 1: 0;
// Supply voltage
MySensors [4] .Value = ((float) readVcc ()) / 1000.0;
return;
}
// Send the message (parameter identifier)
void sendSensorMessage (int ParamID) {
// Prepare the data for transmission to the structure
sensor.SensorID = SID;
sensor.ParamID = ParamID;
sensor.ParamValue = MySensors [ParamID] .Value;
memcpy (& sensor.Comment, (char *) MySensors [ParamID] .Note, 16);
// Send data RF24
bool ok = radio.write (& sensor, sizeof (sensor));
delay (20);
return;
}
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
return result; // Vcc in millivolts
}