IoT hub nRF24 receiver with a temperature sensor master
authorPat Thoyts <patthoyts@users.sourceforge.net>
Wed, 21 Oct 2015 14:32:39 +0000 (15:32 +0100)
committerPat Thoyts <patthoyts@users.sourceforge.net>
Wed, 21 Oct 2015 14:32:39 +0000 (15:32 +0100)
Radio_Clock_Receiver.ino [new file with mode: 0644]

diff --git a/Radio_Clock_Receiver.ino b/Radio_Clock_Receiver.ino
new file mode 100644 (file)
index 0000000..47356e4
--- /dev/null
@@ -0,0 +1,372 @@
+// Radio Transmitting Clock
+//
+// Circuit consists of an Arduino Nano with a DS13xx, NRF24L01+ board
+// and I2C for connecting the LED display device.
+// We have the I2C interface connected to a pair of mosfets to
+// brodge to 3V3 signalling and a 78L33 device is putting 3V3 on the breadboard
+// main power bus. The NRF24 board is 3V3 only.
+// Added an LED with 330R to pin 6 for heartbeat.
+#define F_CPU 20000000UL
+#include <Arduino.h>
+#include <Wire.h>
+#include <MilliTimer.h>
+#include <SPI.h>
+#include <RHDatagram.h>
+#include <RH_NRF24.h>
+#include <LEDPulse.h>
+#include <RTClib.h>
+#include <OneWire.h>
+#include <DallasTemperature.h>
+#include <DisplayI2C.h>
+#include <LiquidCrystal_I2C.h>
+
+static void I2C_Init();
+static void LCD_Init();
+static void RTC_Init();
+static void Radio_Init();
+static void DS18B20_Init();
+static void LedDisplay_Init();
+static void printAddress(DeviceAddress address);
+
+#define RADIO_CE_PIN 8
+#define RADIO_CHANNEL 85
+const uint8_t SENSOR_HUB_ADDRESS = 1;
+
+#define LCD_ADDR 0x20
+#define LCD_EN_BIT 4
+#define LCD_RW_BIT 5
+#define LCD_RS_BIT 6
+#define LCD_D4_BIT 0
+#define LCD_BL_BIT 7
+LiquidCrystal_I2C LCD(LCD_ADDR, LCD_EN_BIT, LCD_RW_BIT, LCD_RS_BIT,
+                      LCD_D4_BIT, LCD_D4_BIT+1, LCD_D4_BIT+2, LCD_D4_BIT+3);
+
+OneWire W1Bus(4); // OneWire bus connected to pin 4.
+DallasTemperature w1sensors(&W1Bus);
+DeviceAddress w1address;
+RH_NRF24 nrf24;
+RHDatagram Radio(nrf24, SENSOR_HUB_ADDRESS);
+DisplayI2C LedDisplay(0x22, 1);
+RTC_DS1307 RTC;
+MilliTimer HeartbeatTimer, DS18B20Timer, OutputTimer, TimingTimer;
+LEDPulse Heartbeat(6);
+DateTime CurrentTime;
+float CurrentTemperature = 0.0f;
+float SlaveTemperature = 0.0f;
+uint8_t SlaveAddress = 0;
+bool UseRadio = false;
+bool UseDS18B20 = false;
+bool UseRTC = false;
+bool UseLCDDisplay = false;
+bool UseLedDisplay = false;
+bool LedDisplayUpdate = false;
+
+enum OutputState_t {Output_None, Output_A, Output_B, Output_C,
+                    Output_D, Output_E, Output_F, Output_G,
+                    Output_H, Output_I, Output_Temperature,
+                    Output_RequestNext, Output_LCD};
+OutputState_t OutputState = Output_None;
+
+void setup()
+{
+    Wire.begin();
+    Serial.begin(57600);
+    delay(400);
+    Serial.println(F("# NRF24 Clock Receiver"));
+    I2C_Init();
+    LCD_Init();
+    RTC_Init();
+    Radio_Init();
+    DS18B20_Init();
+    LedDisplay_Init();
+    pinMode(7, OUTPUT); digitalWrite(7, LOW);
+}
+
+void loop()
+{
+    bool new_date = false;
+    if (LedDisplayUpdate)
+    {
+        LedDisplay.Update();
+        LedDisplayUpdate = false;
+    }
+    if (HeartbeatTimer.poll(10))
+    {
+        Heartbeat.Next();
+    }
+    if (TimingTimer.poll(10))
+    {
+        PORTD ^= _BV(7);
+    }
+    if (OutputState != Output_None)
+    {
+        Output();
+    }
+    if (UseDS18B20 && DS18B20Timer.poll(1500))
+    {
+        // read the temperature result from our chosen sensor.
+        CurrentTemperature = w1sensors.getTempC(w1address);
+        // trigger another conversion.
+        //w1sensors.requestTemperatures();
+    }
+    if (UseRadio && Radio.available())
+    {
+        uint8_t buffer[RH_NRF24_MAX_MESSAGE_LEN];
+        uint8_t len = sizeof(buffer), client_addr, target_addr, id = 0, flags = 0;
+        if (Radio.recvfrom(buffer, &len, &client_addr, &target_addr, &id, &flags))
+        {
+            SlaveAddress = client_addr;
+            SlaveTemperature = *(float *)buffer;
+        }
+    }
+    if (OutputTimer.poll(1000))
+    {
+        OutputState = Output_A;
+    }
+}
+
+static void Output()
+{
+    switch (OutputState)
+    {
+        case Output_A:
+        {
+            if (UseLedDisplay)
+            {
+                if (UseDS18B20)
+                {
+                    LedDisplay.SetValue(CurrentTemperature * 100);
+                }
+            }
+            OutputState = Output_B;
+            break;
+        }
+        case Output_B:
+        {
+            if (CurrentTime.unixtime() == 0)
+            {
+                Serial.print(millis()/1000, DEC);
+                OutputState = Output_Temperature;
+            }
+            else
+                OutputState = Output_C;
+            break;
+        }
+        case Output_C:
+        {
+            Serial.print(CurrentTime.unixtime(), DEC);
+            Serial.print(' ');
+            OutputState = Output_D;
+            break;
+        }
+        case Output_D:
+        {
+            Serial.print(CurrentTime.day(), DEC);
+            Serial.print('/');
+            OutputState = Output_E;
+            break;
+        }
+        case Output_E:
+        {
+            Serial.print(CurrentTime.month(), DEC);
+            Serial.print('/');
+            OutputState = Output_F;
+            break;
+        }
+        case Output_F:
+        {
+            Serial.print(CurrentTime.year(), DEC);
+            Serial.print(' ');
+            OutputState = Output_G;
+            break;
+        }
+        case Output_G:
+        {
+            if (CurrentTime.hour() < 10) Serial.print('0');
+            Serial.print(CurrentTime.hour(), DEC);
+            Serial.print(':');
+            OutputState = Output_H;
+            break;
+        }
+        case Output_H:
+        {
+            if (CurrentTime.minute() < 10) Serial.print('0');
+            Serial.print(CurrentTime.minute(), DEC);
+            Serial.print(':');
+            OutputState = Output_I;
+            break;
+        }
+        case Output_I:
+        {
+            if (CurrentTime.second() < 10) Serial.print('0');
+            Serial.print(CurrentTime.second(), DEC);
+            OutputState = Output_Temperature;
+            break;
+        }
+        case Output_Temperature:
+        {
+            Serial.print(' ');
+            Serial.print(CurrentTemperature);
+            if (SlaveTemperature != 0.0f)
+            {
+                Serial.print(F(" ["));
+                Serial.print(SlaveAddress, HEX);
+                Serial.print(' ');
+                Serial.print(SlaveTemperature);
+                Serial.print(']');
+            }
+            Serial.println();
+            OutputState = Output_RequestNext;
+            break;
+        }
+        case Output_RequestNext:
+        {
+            // trigger another conversion.
+            w1sensors.requestTemperatures();
+            OutputState = Output_LCD;
+            break;
+        }
+        case Output_LCD:
+        {
+            if (UseLCDDisplay)
+            {
+                LCD.clear();
+                LCD.print(CurrentTemperature);
+                if (UseRTC)
+                {
+                    LCD.setCursor(0, 1);
+                    DateTime now = RTC.now();
+                    PrintTimeOnStream(&LCD, now);
+                }
+            }
+            OutputState = Output_None;
+            break;
+        }
+    }
+}
+
+static void Radio_Init()
+{
+    // defaults to channel 2, 2Mbps and 0dBm
+    if (Radio.init())
+    {
+        nrf24.setChannel(RADIO_CHANNEL);
+        Radio.setThisAddress(SENSOR_HUB_ADDRESS);
+        UseRadio = true;
+        Serial.println(F("Radio initialized"));
+    }
+    else
+    {
+        Serial.println(F("Radio initialization failed"));
+    }
+}
+
+static void DS18B20_Init()
+{
+    Serial.println(F("Initializing OneWire bus..."));
+    w1sensors.begin();
+    w1sensors.setResolution(12);
+    w1sensors.setWaitForConversion(false);
+    int count = w1sensors.getDeviceCount();
+    for (int n = 0; n < count; ++n)
+    {
+        if (w1sensors.getAddress(w1address, n))
+        {
+            Serial.print(n);
+            Serial.print(F(": "));
+            printAddress(&Serial, w1address);
+            Serial.println();
+            UseDS18B20 = true;
+            w1sensors.requestTemperatures();
+        }
+    }
+}
+
+static void printAddress(Print *stream, DeviceAddress address)
+{
+    for (int n = 0; n < 8; ++n)
+    {
+        if (address[n] < 16)
+            stream->print('0');
+        stream->print(address[n], HEX);
+    }
+}
+
+// print the time (HH:MM:SS) on a stream.
+static void PrintTimeOnStream(Print *stream, DateTime now)
+{
+    if(now.hour() < 10) stream->print('0');
+    stream->print(now.hour());
+    stream->print(':');
+    if(now.minute() < 10) stream->print('0');
+    stream->print(now.minute());
+    stream->print(':');
+    if(now.second() < 10) stream->print('0');
+    stream->print(now.second());
+}
+
+static void I2C_Init()
+{
+    for (uint8_t addr = 0; addr < 127; ++addr)
+    {
+        Wire.beginTransmission(addr);
+        uint8_t err = Wire.endTransmission();
+        if (err == 0)
+        {
+            Serial.print(F("# Found I2C device at 0x"));
+            if (addr < 16) Serial.print('0');
+            Serial.print(addr, HEX);
+            if (addr == 0x20) { Serial.print(F(" (LCD)")); UseLCDDisplay = true; }
+            if (addr == 0x22) { Serial.print(F(" (LED)")); UseLedDisplay = true; }
+            if (addr == 0x57) { Serial.print(F(" (EEPROM)")); }
+            if (addr == 0x68) { Serial.print(F(" (RTC)")); UseRTC = true;}
+            Serial.println();
+        }
+        else if (err == 4)
+        {
+            Serial.print(F("# Unknown error at address 0x"));
+            if (addr < 16) Serial.print('0');
+            Serial.print(addr, HEX);
+        }
+    }
+}
+
+static void LCD_Init()
+{
+    if (UseLCDDisplay)
+    {
+        LCD.begin(16, 2);
+        LCD.clear();
+        LCD.print(F("Radio Clock Recvr"));
+        LCD.setCursor(0,1);
+        LCD.print(F("v1.0"));
+    }
+}
+
+static void RTC_Init()
+{
+    if (UseRTC)
+    {
+        RTC.begin();
+        //RTC.adjust(DateTime(__DATE__, __TIME__));
+        if (!RTC.isrunning())
+        {
+            Serial.println(F("WARNING: RTC uninitialized"));
+        }
+    }
+}
+
+static void LedDisplay_Init()
+{
+    if (UseLedDisplay)
+    {
+        DisplayI2C::SetupTimer2();
+        LedDisplay.Setup();
+    }
+}
+
+ISR(TIMER2_OVF_vect)
+{
+    TCNT2 = DisplayI2C::TimerInterval; // reset the timer
+    LedDisplayUpdate = true;           // set flag for loop function
+}