├── README.md ├── master └── master.ino └── sensor ├── sensor.fzz ├── sensor.ino └── sensor.png /README.md: -------------------------------------------------------------------------------- 1 | ## The plan 2 | 3 | Create a cheap and low-power Arduino sensor device (currently for measuring the temperature but could be easily adapted to other Arduino sensors) using an NRF24L01+ 2.4Ghz transceiver to send temperature measurements every X minutes. 4 | 5 | The idea is to have reliable RF communications, using small packet sizes, low transmission rates, whilst maximising communication range and battery life, by using the Arduino's and the transceiver's "Power-Down" modes. 6 | 7 | ## Requirements 8 | * Two Arduino Nanos 9 | * Two NRF24L01+ transceivers 10 | * A DS18B20 One-Wire digital thermometer 11 | * A 4.7KΩ resistor 12 | * Jumper cables 13 | * USB cables 14 | * The Arduino IDE 15 | * Maniacbug's [RF24 Library](https://github.com/maniacbug/RF24) 16 | * Paul Stoffregen's [One-Wire library](http://www.pjrc.com/teensy/arduino_libraries/OneWire.zip) 17 | * Miles Burton's [DallasTemperature library](https://github.com/milesburton/Arduino-Temperature-Control-Library) 18 | * Basic C knowledge 19 | 20 | ## Sensor wiring 21 | 22 | #### Layout 23 | ![](http://i.imgur.com/KO40IwZ.png) 24 | 25 | #### NRF24L01+ Module 26 | 27 | ![](http://g02.a.alicdn.com/kf/UT8_ZyHXolbXXagOFbXp/120207292/UT8_ZyHXolbXXagOFbXp.jpg) 28 | 29 | * VCC -> 3v3 30 | * GND -> GND 31 | * CSN -> D10 32 | * CE -> D9 33 | * MOSI -> D11 34 | * SCK -> D13 35 | * IRQ is not required for our use case, it's an interrupt pin that goes LOW whenever a packet arrives, a packet is sent or the maximum retry count for sending a packet is reached. You can find out more about that [here](https://www.insidegadgets.com/2012/08/22/using-the-nrf24l01-wireless-module/) 36 | * MISO -> D12 37 | 38 | #### DS18B20 Thermometer 39 | 40 | ![](http://37.59.100.119/wp-content/uploads/DS18B20-pinout.jpg) 41 | 42 | * GND -> GND 43 | * D -> D2 44 | * VDD -> 3v3 45 | 46 | Place a 4.7KΩ resistor between D and VCC. 47 | 48 | ## Master node wiring 49 | 50 | #### Layout 51 | 52 | ![](http://i.imgur.com/vb4ZlIy.png) 53 | 54 | #### NRF24L01+ Module 55 | 56 | * VCC -> 3v3 57 | * GND -> GND 58 | * CSN -> D10 59 | * CE -> D9 60 | * MOSI -> D11 61 | * SCK -> D13 62 | * IRQ is not used 63 | * MISO -> D12 64 | 65 | ## Getting it to work 66 | 67 | With the Arduino IDE compile and upload `sensor.ino` to the sensor node, and `master.ino` to the master node. Leave the master node connected to the computer via USB, and open up the the Arduino IDE Serial console (CTRL+SHIFT+M). 68 | 69 | Power up the sensor node a few meters away for testing purposes via USB power or with a direct 5V input on the 5V pin. 70 | 71 | Every 8 seconds you should see the temperature (in °C) displayed on the serial monitor of the master node. 72 | 73 | ## Todo 74 | 75 | * Reduce power usage 76 | * Add GPRS module to the Master node to post temperature to a data logging API 77 | * Test out other sensors (PIR Sensor, humidity, air pressure, smoke detector...) 78 | * Add more sensors all communicating with a single master node which bundles up the data and posts it to the API 79 | * Test battery life using 2 AA batteries and a 5V Step-up module 80 | * Test maximum range in open area, within a building... 81 | 82 | ## Contributing 83 | 84 | Any contribution is welcome, whether it's new ways to keep power usage to a minimum, how to send radio packets in a more reliable manner, how to communicate at an even lower bitrate, how to increase the RF range... Feel free to open up an issue if you have a problem, question, bug or idea. 85 | -------------------------------------------------------------------------------- /master/master.ino: -------------------------------------------------------------------------------- 1 | // -- Includes -- 2 | 3 | // Radio 4 | #include 5 | #include "nRF24L01.h" 6 | #include "RF24.h" 7 | 8 | // -- Global variables -- 9 | 10 | RF24 radio(9,10); 11 | int packetCounter = 0; 12 | 13 | // -- Functions -- 14 | 15 | void setupRadio() 16 | { 17 | // Initiate the radio 18 | radio.begin(); 19 | 20 | // Define the number of retries sending a packet 21 | radio.setRetries(15,15); 22 | 23 | // Define the radio's broadcast channel (0 - 127) 24 | // Must be the same on the sensor and the master node 25 | radio.setChannel(30); 26 | 27 | // Define the radio's bitrate (using cards lowest bitrate) 28 | radio.setDataRate(RF24_250KBPS); 29 | 30 | // Define the radio's power amplifier level (RF24_PA_MIN for debugging, RF24_PA_HIGH for longest range) 31 | radio.setPALevel(RF24_PA_MIN); 32 | 33 | // Enable dynamic payloads for packets 34 | radio.enableDynamicPayloads(); 35 | 36 | // Open reading pipe 37 | radio.openReadingPipe(1, 0xE8E8F0F0E1LL); 38 | 39 | // Start listening for packets 40 | radio.startListening(); 41 | } 42 | 43 | void setup() 44 | { 45 | // Initiate serial connection 46 | Serial.begin(57600); 47 | 48 | // RF Radio setup 49 | setupRadio(); 50 | } 51 | 52 | void loop() 53 | { 54 | // Check if the radio has received any data 55 | if(radio.available()) { 56 | float temperature = 0; 57 | 58 | // Read the packet received into the temperature variable 59 | radio.read(&temperature, sizeof(float)); 60 | 61 | // Print the temperature 62 | Serial.println(temperature); 63 | 64 | // Wait for serial print to complete 65 | delay(100); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sensor/sensor.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liamjack/Arduino-NRF24L01-Thermometer/b3dcde33d6e6510fc98dfdaa7f1342a99d9acdad/sensor/sensor.fzz -------------------------------------------------------------------------------- /sensor/sensor.ino: -------------------------------------------------------------------------------- 1 | // -- Includes -- 2 | 3 | // Sleep 4 | #include 5 | #include 6 | 7 | // Watchdog timer 8 | #include 9 | 10 | // Radio 11 | #include 12 | #include "nRF24L01.h" 13 | #include "RF24.h" 14 | 15 | // Thermometer 16 | #include 17 | #include 18 | 19 | // -- Structures -- 20 | 21 | typedef struct { 22 | uint32_t sensorId; 23 | float temperature; 24 | } dataPacket; 25 | 26 | // -- Constants -- 27 | 28 | const uint32_t sensorId = 1; 29 | 30 | const rf24_datarate_e radioDataRate = RF24_250KBPS; 31 | const rf24_crclength_e radioCRCLength = RF24_CRC_8; 32 | const uint8_t radioPALevel = RF24_PA_MAX; 33 | const uint8_t radioChannel = 50; 34 | 35 | const uint8_t nodeAddress[4] = "n01"; 36 | 37 | const int thermometerResolution = 10; 38 | 39 | // -- Global variables -- 40 | 41 | volatile int f_wdt = 1; 42 | int counter = 0; 43 | int packetCounter = 0; 44 | 45 | RF24 radio(9, 10); 46 | OneWire oneWire(2); 47 | DallasTemperature sensors(&oneWire); 48 | 49 | // -- Functions -- 50 | 51 | void counterHandler() 52 | { 53 | // Increment the sleep counter 54 | counter++; 55 | 56 | // Should be 75 for 10 minutes (75 * 8 = 600 seconds = 10 minutes) 57 | // Use 1 for debugging purposes 58 | 59 | if(counter == 75) { 60 | // Reset the counter to 0 61 | counter = 0; 62 | 63 | // Power up components 64 | power_all_enable(); 65 | 66 | // Power up the radio 67 | radio.powerUp(); 68 | 69 | // Wait for radio to power up 70 | delay(2); 71 | } else { 72 | // Sleep time isn't over yet, sleep some more 73 | enterSleep(); 74 | } 75 | } 76 | 77 | void enterSleep() 78 | { 79 | // Start the watchdog timer 80 | f_wdt = 0; 81 | 82 | // Power down the radio 83 | radio.powerDown(); 84 | 85 | // Enter sleep 86 | sleep_enable(); 87 | sleep_mode(); 88 | 89 | // Wake from sleep 90 | sleep_disable(); 91 | 92 | // Increment the interrupt counter 93 | counterHandler(); 94 | } 95 | 96 | ISR(WDT_vect) 97 | { 98 | // Stop the watchdog timer 99 | f_wdt = 1; 100 | } 101 | 102 | void setupWDT() 103 | { 104 | // Setup the Watchdog timer for an interruption every 8 seconds 105 | 106 | MCUSR &= ~(1<