Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Enclosures / 3D Printing
  3. MySensors weather station

MySensors weather station

Scheduled Pinned Locked Moved Enclosures / 3D Printing
138 Posts 16 Posters 58.6k Views 15 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • gohanG Offline
    gohanG Offline
    gohan
    Mod
    wrote on last edited by
    #98

    Doesn't it have a library?

    dbemowskD 1 Reply Last reply
    0
    • gohanG gohan

      Doesn't it have a library?

      dbemowskD Offline
      dbemowskD Offline
      dbemowsk
      wrote on last edited by
      #99

      @gohan It does, but it is an untested library. This is the test code that I ran using that library:

      #include "AS5047.h"
      #include <SPI.h>
      #include <EEPROM.h>
      
      #define SWITCH_PIN 7 //The north calibration switch
      
      AS5047 myAS5047(5); // SS pin
       
      int address = 0;      //EEPROM address counter
      int north_offset = 0;
      long value;
      int dir;
      bool button;
      
      void setup()
      {
        SPI.begin;
        Serial.begin(9600);
      
        pinMode(SWITCH_PIN, INPUT_PULLUP);
      
        north_offset = EEPROM.read(address);
      }
      
      void loop()
      {
        value=(360*myAS5047.sensor_read())/16383;
        dir = ((value - north_offset) < 0) ? 360 - abs(value - north_offset) : value - north_offset;
        
        Serial.print("measured direction: ");
        Serial.println(dir);
        Serial.print("north_offset: ");
        Serial.println(north_offset);
      
        button = digitalRead(SWITCH_PIN);
        north_offset = EEPROM.read(address);
        if (!button && north_offset != value) {
          EEPROM.write(address, value);
          north_offset = value;
          Serial.println("Button pressed");
        }
        
        delay(1000);
      }
      

      This test worked fine, now I am trying to merge this with my weather station sketch. I am not very familiar with working with SPI. In the setup() method, they call SPI.begin(). I am just trying to figure out what I need to do for merging the code.

      Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
      Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

      1 Reply Last reply
      0
      • dbemowskD Offline
        dbemowskD Offline
        dbemowsk
        wrote on last edited by
        #100

        Should all of the SPI stuff be included in the library?

        Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
        Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

        1 Reply Last reply
        0
        • dbemowskD Offline
          dbemowskD Offline
          dbemowsk
          wrote on last edited by
          #101

          So now I have the direction sensor on the SPI bus with the CS pin connected to D5 on my easy newbie board. If I run my sample program for the direction sensor to test it on the bus with the nRF24 radio, I get readings and it seems to work fine. The problem is, if I run my modified rain sensor sketch seen below, I cannot get the radio to work.

          /*
           Arduino Tipping Bucket Rain Gauge
          
           April 26, 2015
          
           Version 2.0
          
           Arduino Tipping Bucket Rain Gauge
          
           Utilizing a tipping bucket sensor, your Vera home automation controller and the MySensors.org
           gateway you can measure and sense local rain.  This sketch will create two devices on your
           Vera controller.  One will display your total precipitation for the last 5 days.  The other, 
           a sensor that changes state if there is recent rain (up to last 120 hours)  above a threshold.  
           Both these settings are user definable.
          
           There is a build overview video here: https://youtu.be/1eMfKQaLROo
          
           This sketch features the following:
          
           * Allows you to set the rain threshold in mm
           * Allows you to determine the tripped indicator window up to 120 hours.
           * Displays the last 5 days of rain in Variable1 through Variable5
             of the Rain Sensor device
           * Configuration changes to Sensor device updated every hour
           * Should run on any Arduino
           * Will retain Tripped/Not Tripped status and data in a power interruption, saving small amount
             of data to EEPROM (Circular Buffer to maximize life of EEPROM)
           * LED status indicator
           * Optional Temp/Humidity (DHT-22 or DHT-11) and Light LUX (BH1750) sensors. To use, uncomment
             #define DHT_ON  and/or #define LUX_ON
           * Optionally send total accumulation of each day's rainfall or send only individual days rainfall totals.
             Uncomment #define USE_DAILY to display individual daily rainfall.  If it is commented out it will display
             a cumulative total rainfall (day4 = day1+day2+day3+day4 etc)
          
           by @BulldogLowell and @PeteWill for free public use
          
           */
          
          #define MY_DEBUG // Enable MySensors debug prints to serial monitor
          
          // Enable and select radio type attached
          #define MY_RADIO_NRF24
          //#define MY_RADIO_RFM69
          
          //#define MY_NODE_ID 7 //uncomment this line to assign a static ID
          
          #include <SPI.h>
          #include <math.h>
          #include <TimeLib.h>
          #include "AS5047.h"
          #include <MySensors.h>
          
          #define SKETCH_NAME "Weather Station"
          #define SKETCH_VERSION "2.0"
          
          #define DWELL_TIME 40  // this allows for radio to come back to power after a transmission, ideally 0 
          
          //#define DEBUG_ON  // Rain gauge specific debug messages. 
          #define DHT_ON // uncomment out this line to enable DHT sensor
          //#define LUX_ON // uncomment out this line to enable BH1750 sensor
          //#define USE_DAILY // Uncomment to display individual daily rainfall totals in the variables sent to your controller. If it's commented it will add each day to the next for a cumulative total.
          
          #define NORTH_SWITCH_PIN 7 //The north calibration switch
          #define AS5047_CHIP_SELECT_PIN 5 //The north calibration switch
          
          #define TIP_SENSOR_PIN 2 //The tipping bucket rain sensor
          #define CALIBRATE_FACTOR 60 // amount of rain per rain bucket tip e.g. 5 is .05mm
          #define DHT_LUX_DELAY 300000  //Delay in milliseconds that the DHT and LUX sensors will wait before sending data
          #define WIND_DIR_DELAY 300000  //Delay in milliseconds that the DHT and LUX sensors will wait before sending data
          
          #define CHILD_ID_RAIN_LOG 3  // Keeps track of accumulated rainfall
          #define CHILD_ID_TRIPPED_INDICATOR 4  // Indicates Tripped when rain detected
          #define CHILD_ID_WIND 5  // Indicates Tripped when rain detected
          
          #define EEPROM_NORTH_OFFSET_LOCATION 0  // location of the EEPROM circular buffer
          #define EEPROM_BUFFER_LOCATION 1  // location of the EEPROM circular buffer
          #define E_BUFFER_LENGTH 240
          #define RAIN_BUCKET_SIZE 120
          
          #ifdef  DEBUG_ON
            #define DEBUG_PRINT(x)   Serial.print(x)
            #define DEBUG_PRINTLN(x) Serial.println(x)
            #define SERIAL_START(x)  Serial.begin(x)
            #else
            #define DEBUG_PRINT(x)
            #define DEBUG_PRINTLN(x)
            #define SERIAL_START(x)
          #endif
          //
          MyMessage msgRainRate(CHILD_ID_RAIN_LOG, V_RAINRATE);
          MyMessage msgRain(CHILD_ID_RAIN_LOG, V_RAIN);
          //
          MyMessage msgRainVAR1(CHILD_ID_RAIN_LOG, V_VAR1);
          MyMessage msgRainVAR2(CHILD_ID_RAIN_LOG, V_VAR2);
          MyMessage msgRainVAR3(CHILD_ID_RAIN_LOG, V_VAR3);
          MyMessage msgRainVAR4(CHILD_ID_RAIN_LOG, V_VAR4);
          MyMessage msgRainVAR5(CHILD_ID_RAIN_LOG, V_VAR5);
          //
          MyMessage msgTripped(CHILD_ID_TRIPPED_INDICATOR, V_TRIPPED);
          MyMessage msgTrippedVar1(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
          MyMessage msgTrippedVar2(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
          
          MyMessage msgWindSpeed(CHILD_ID_WIND, V_WIND);
          MyMessage msgWindGust(CHILD_ID_WIND, V_GUST);
          MyMessage msgWindDirection(CHILD_ID_WIND, V_DIRECTION);
          //
          #ifdef DHT_ON
            #include <DHT.h>
            #define CHILD_ID_HUM 0
            #define CHILD_ID_TEMP 1
            #define HUMIDITY_SENSOR_DIGITAL_PIN 3
            DHT dht;
            float lastTemp;
            float lastHum;
            bool metric = false;
            MyMessage msgHum(CHILD_ID_HUM, V_HUM);
            MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
          #endif
          //
          #ifdef LUX_ON
            //BH1750 is connected to SCL (analog input A5) and SDA (analog input A4)
            #include <BH1750.h>
            #include <Wire.h>
            #define CHILD_ID_LIGHT 2
            BH1750 lightSensor;
            MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
            unsigned int lastlux;
            uint8_t heartbeat = 10; //Used to send the light lux to gateway as soon as the device is restarted and after the DHT_LUX_DELAY has happened 10 times
          #endif
          
          AS5047 myAS5047(5); //AS5047_CHIP_SELECT_PIN); //Wind direction magnetic position sensor
          uint8_t north_offset;
          bool button;
          int wind_direction;
          int last_direction;
          
          unsigned long sensorPreviousMillis;
          unsigned long windDirPreviousMillis;
          int eepromIndex;
          int tipSensorPin = 3; // Pin the tipping bucket is connected to. Must be interrupt capable pin
          int ledPin = 5; // Pin the LED is connected to.  PWM capable pin required
          #ifdef DEBUG_ON
          unsigned long dataMillis;
          unsigned long serialInterval = 600000UL;
          #endif
          const unsigned long oneHour = 3600000UL;
          unsigned long lastTipTime;
          unsigned long lastRainTime; //Used for rainRate calculation
          unsigned int rainBucket [RAIN_BUCKET_SIZE] ; /* 24 hours x 5 Days = 120 hours */
          unsigned int rainRate = 0;
          uint8_t rainWindow = 72;         //default rain window in hours.  Will be overwritten with msgTrippedVar1.
          volatile int wasTippedBuffer = 0;
          int rainSensorThreshold = 50; //default rain sensor sensitivity in hundredths.  Will be overwritten with msgTrippedVar2.
          uint8_t state = 0;
          uint8_t oldState = 2; //Setting the default to something other than 1 or 0
          unsigned int lastRainRate = 0;
          int lastMeasure = 0;
          bool gotTime = false;
          uint8_t lastHour;
          uint8_t currentHour;
          //
          void presentation()  {
            // Register all sensors to gw (they will be created as child devices)
            sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
            wait(DWELL_TIME);
            present(CHILD_ID_RAIN_LOG, S_RAIN);
            wait(DWELL_TIME);
            present(CHILD_ID_TRIPPED_INDICATOR, S_MOTION);
            wait(DWELL_TIME);
          
            present(CHILD_ID_WIND, S_WIND);
            wait(DWELL_TIME);
          
          #ifdef DHT_ON
            present(CHILD_ID_HUM, S_HUM);
            wait(DWELL_TIME);
            present(CHILD_ID_TEMP, S_TEMP);
            wait(DWELL_TIME);
          #endif
          
          
          #ifdef LUX_ON
            present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
          #endif
          
            DEBUG_PRINTLN(F("Sensor Presentation Complete"));
          }
          
          void setup()
          {
            #ifndef MY_DEBUG
            SERIAL_START(115200);  //Start serial if MySensors debugging isn't enabled
            #endif
            //
            pinMode(NORTH_SWITCH_PIN, INPUT_PULLUP);
            
            // Set up the IO
            pinMode(TIP_SENSOR_PIN, INPUT_PULLUP);
            attachInterrupt (digitalPinToInterrupt(TIP_SENSOR_PIN), sensorTipped, FALLING);  // depending on location of the hall effect sensor may need CHANGE
            pinMode(ledPin, OUTPUT);
            digitalWrite(ledPin, HIGH);
            //
            //Sync time with the server
            //
            unsigned long functionTimeout = millis();
            while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL)
            {
              requestTime();
              DEBUG_PRINTLN(F("Getting Time"));
              wait(1000); // call once per second
              DEBUG_PRINTLN(F("."));
            }
            currentHour = hour();
            lastHour = hour();
            //
            //retrieve from EEPROM stored values on a power cycle.
            //
            
            //Get the north offset direction
            north_offset = loadState(EEPROM_NORTH_OFFSET_LOCATION)*2;
            
            bool isDataOnEeprom = false;
            for (int i = 0; i < E_BUFFER_LENGTH; i++)
            {
              uint8_t locator = loadState(EEPROM_BUFFER_LOCATION + i);
              if (locator == 0xFE)  // found the EEPROM circular buffer index
              {
                eepromIndex = EEPROM_BUFFER_LOCATION + i;
                DEBUG_PRINT(F("EEPROM Index "));
                DEBUG_PRINTLN(eepromIndex);
                //Now that we have the buffer index let's populate the rainBucket[] with data from eeprom
                loadRainArray(eepromIndex);
                isDataOnEeprom = true;
                break;
              }
            }
            //
            if (!isDataOnEeprom) // Added for the first time it is run on a new Arduino
            {
              DEBUG_PRINTLN(F("I didn't find valid EEPROM Index, so I'm writing one to location 0"));
              eepromIndex = EEPROM_BUFFER_LOCATION;
              saveState(eepromIndex, 0xFE);
              saveState(eepromIndex + 1, 0xFE);
              //then I will clear out any bad data
              for (int i = 2; i <= E_BUFFER_LENGTH; i++)
              {
                saveState(i, 0x00);
              }
            }
            #ifdef DEBUG_ON
            dataMillis = millis();
            #endif
            lastTipTime = millis(); 
            //
            request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
            wait(DWELL_TIME);
            request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
            wait(DWELL_TIME);
            //
          #ifdef DHT_ON
            dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
            metric = getConfig().isMetric;
            //metric = false;
            wait(DWELL_TIME);
          #endif
            //
          #ifdef LUX_ON
            lightSensor.begin();
          #endif
            //
            transmitRainData(); //Setup complete send any data loaded from eeprom to gateway
          }
          
          void loop()
          {
            if (state)
            {
              prettyFade();  // breathe if tripped
            }
            else
            {
              slowFlash();   // blink if not tripped
            }
          #ifdef DEBUG_ON  // Serial Debug Block
            if ( (millis() - dataMillis) >= serialInterval)
            {
              for (int i = 24; i <= 120; i = i + 24)
              {
                updateSerialData(i);
              }
              dataMillis = millis();
            }
          #endif
          
            //NORTH_SWITCH_PIN
            button = digitalRead(NORTH_SWITCH_PIN);
            if (!button) {
              setNorthOffset();
            } 
            
            //
            // let's constantly check to see if the rain in the past rainWindow hours is greater than rainSensorThreshold
            //
            int measure = 0; // Check to see if we need to show sensor tripped in this block
            for (int i = 0; i < rainWindow; i++)
            {
              measure += rainBucket [i];
              if (measure != lastMeasure)
              {
                //      DEBUG_PRINT(F("measure value (total rainBucket within rainWindow): "));
                //      DEBUG_PRINTLN(measure);
                lastMeasure = measure;
              }
            }
            //
            state = (measure >= (rainSensorThreshold * 100));
            if (state != oldState)
            {
              send(msgTripped.set(state));
              wait(DWELL_TIME);
              DEBUG_PRINT(F("New Sensor State... Sensor: "));
              DEBUG_PRINTLN(state ? "Tripped" : "Not Tripped");
              oldState = state;
            }
            //WIND_DIR_DELAY
            if (millis() - windDirPreviousMillis > WIND_DIR_DELAY)
            {
              wind_direction = getWindDirection();
              if (wind_direction != last_direction)
              {
                send(msgWindDirection.set(wind_direction));
              }
              last_direction = wind_direction;
              windDirPreviousMillis = millis();
            }
            //
            unsigned long tipDelay = millis() - lastRainTime;
            if (wasTippedBuffer) // if was tipped, then update the 24hour total and transmit to Vera
            {
              DEBUG_PRINTLN(F("Sensor Tipped"));
              DEBUG_PRINT(F("rainBucket [0] value: "));
              DEBUG_PRINTLN(rainBucket [0]);
              send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); //Calculate the total rain for the day
              wait(DWELL_TIME);
              wasTippedBuffer--;
              rainRate = ((oneHour) / tipDelay);
              if (rainRate != lastRainRate)
              {
                send(msgRainRate.set(rainRate, 1));
                wait(DWELL_TIME);
                DEBUG_PRINT(F("RainRate= "));
                DEBUG_PRINTLN(rainRate);
                lastRainRate = rainRate;
              }
              lastRainTime = lastTipTime;
            }
            //
            currentHour = hour();
            if (currentHour != lastHour)
            {
              DEBUG_PRINTLN(F("One hour elapsed."));
              send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); // send today's rainfall
              wait(DWELL_TIME);
              saveState(eepromIndex, highByte(rainBucket[0]));
              saveState(eepromIndex + 1, lowByte(rainBucket[0]));
              DEBUG_PRINT(F("Saving rainBucket[0] to eeprom. rainBucket[0] = "));
              DEBUG_PRINTLN(rainBucket[0]);
              for (int i = RAIN_BUCKET_SIZE - 1; i >= 0; i--)//cascade an hour of values back into the array
              {
                rainBucket [i + 1] = rainBucket [i];
              }
              request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
              wait(DWELL_TIME);
              request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
              wait(DWELL_TIME);
              rainBucket[0] = 0;
              eepromIndex = eepromIndex + 2;
              if (eepromIndex > EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH)
              {
                eepromIndex = EEPROM_BUFFER_LOCATION;
              }
              DEBUG_PRINT(F("Writing to EEPROM.  Index: "));
              DEBUG_PRINTLN(eepromIndex);
              saveState(eepromIndex, 0xFE);
              saveState(eepromIndex + 1, 0xFE);
              requestTime(); // sync the time every hour
              wait(DWELL_TIME);
              transmitRainData();
              rainRate = 0;
              send(msgRainRate.set(rainRate, 1));
              wait(DWELL_TIME);
              DEBUG_PRINTLN(F("Sending rainRate is 0 to controller"));
              lastHour = hour();
            }
            if (millis() - sensorPreviousMillis > DHT_LUX_DELAY)
            {
              #ifdef DHT_ON  //DHT Code
                doDHT();
              #endif
              #ifdef LUX_ON
                doLUX();
              #endif
              sensorPreviousMillis = millis();
            }
          }
          
          int getWindDirection() 
          {
            north_offset = loadState(EEPROM_NORTH_OFFSET_LOCATION);
            
            int value = readDir();
            int dir = ((value - north_offset) < 0) ? 360 - abs(value - north_offset) : value - north_offset;
              DEBUG_PRINT("Wind direction: ");
              DEBUG_PRINTLN(dir);
            return dir;
          }
          
          //
          void setNorthOffset() 
          {
            int value = readDir();
            if (north_offset != value)
            {
              saveState(EEPROM_NORTH_OFFSET_LOCATION, value/2);
              north_offset = value;
              DEBUG_PRINT("North offset set to: ");
              DEBUG_PRINTLN(value/2);
            }
          }
          int readDir() 
          {
            int value = (359*myAS5047.sensor_read())/16383;
            return value;
          }
          //
          #ifdef DHT_ON
          void doDHT(void)
          {
            float temperature = dht.getTemperature();
              if (isnan(temperature)) 
              {
                DEBUG_PRINTLN(F("Failed reading temperature from DHT"));
              } else if (temperature != lastTemp) 
              {
                lastTemp = temperature;
                if (!metric) 
                {
                  temperature = dht.toFahrenheit(temperature);
                }
                send(msgTemp.set(temperature, 1));
                wait(DWELL_TIME);
                DEBUG_PRINT(F("Temperature is: "));
                DEBUG_PRINTLN(temperature);
              }
              float humidity = dht.getHumidity();;
              if (isnan(humidity)) 
              {
                DEBUG_PRINTLN(F("Failed reading humidity from DHT"));
              } else if (humidity != lastHum) 
              {
                lastHum = humidity;
                send(msgHum.set(humidity, 1));
                wait(DWELL_TIME);
                DEBUG_PRINT(F("Humidity is: "));
                DEBUG_PRINTLN(humidity);
              }
          }
          #endif
          //
          #ifdef LUX_ON
          void doLUX(void)
          {
            unsigned int lux = lightSensor.readLightLevel();// Get Lux value
            DEBUG_PRINT(F("Current LUX Level: "));
            DEBUG_PRINTLN(lux);
            heartbeat++;
            if (lux != lastlux || heartbeat > 10) 
            {
              send(msg.set(lux));
              lastlux = lux;
            }
            if (heartbeat > 10) 
            {
              heartbeat = 0;
            }
          }
          #endif
          //
          void sensorTipped()
          {
            unsigned long thisTipTime = millis();
            if (thisTipTime - lastTipTime > 100UL)
            {
              rainBucket[0] += CALIBRATE_FACTOR; // adds CALIBRATE_FACTOR hundredths of unit each tip
              wasTippedBuffer++;
            }
            lastTipTime = thisTipTime;
          }
          //
          int rainTotal(int hours)
          {
            int total = 0;
            for ( int i = 0; i <= hours; i++)
            {
              total += rainBucket [i];
            }
            return total;
          }
          
          #ifdef DEBUG_ON
          void updateSerialData(int x)
          {
            DEBUG_PRINT(F("Rain last "));
            DEBUG_PRINT(x);
            DEBUG_PRINTLN(F(" hours: "));
            float tipCount = 0;
            for (int i = 0; i < x; i++)
            {
              tipCount = tipCount + rainBucket [i];
            }
            tipCount = tipCount / 100;
            DEBUG_PRINTLN(tipCount);
          }
          #endif
          
          void loadRainArray(int eValue) // retrieve stored rain array from EEPROM on powerup
          {
            for (int i = 1; i < RAIN_BUCKET_SIZE; i++)
            {
              eValue = eValue - 2;
              if (eValue < EEPROM_BUFFER_LOCATION)
              {
                eValue = EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH;
              }
              DEBUG_PRINT(F("EEPROM location: "));
              DEBUG_PRINTLN(eValue);
              uint8_t rainValueHigh = loadState(eValue);
              uint8_t rainValueLow = loadState(eValue + 1);
              unsigned int rainValue = rainValueHigh << 8;
              rainValue |= rainValueLow;
              rainBucket[i] = rainValue;
              //
              DEBUG_PRINT(F("rainBucket[ value: "));
              DEBUG_PRINT(i);
              DEBUG_PRINT(F("] value: "));
              DEBUG_PRINTLN(rainBucket[i]);
            }
          }
          
          void transmitRainData(void)
          {
            DEBUG_PRINT(F("In transmitRainData. currentHour = "));
            DEBUG_PRINTLN(currentHour);
            int rainUpdateTotal = 0;
            for (int i = currentHour; i >= 0; i--)
            {
              rainUpdateTotal += rainBucket[i];
              DEBUG_PRINT(F("Adding rainBucket["));
              DEBUG_PRINT(i);
              DEBUG_PRINTLN(F("] to rainUpdateTotal."));
            }
            DEBUG_PRINT(F("TX Day 1: rainUpdateTotal = "));
            DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
            send(msgRainVAR1.set((float)rainUpdateTotal / 100.0, 1)); //Send current day rain totals (resets at midnight)
            wait(DWELL_TIME);
          #ifdef USE_DAILY
            rainUpdateTotal = 0;
          #endif
            for (int i = currentHour + 24; i > currentHour; i--)
            {
              rainUpdateTotal += rainBucket[i];
              DEBUG_PRINT(F("Adding rainBucket["));
              DEBUG_PRINT(i);
              DEBUG_PRINTLN(F("] to rainUpdateTotal."));
            }
            DEBUG_PRINT(F("TX Day 2: rainUpdateTotal = "));
            DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
            send(msgRainVAR2.set((float)rainUpdateTotal / 100.0, 1));
            wait(DWELL_TIME);
          #ifdef USE_DAILY
            rainUpdateTotal = 0;
          #endif
            for (int i = currentHour + 48; i > currentHour + 24; i--)
            {
              rainUpdateTotal += rainBucket[i];
              DEBUG_PRINT(F("Adding rainBucket["));
              DEBUG_PRINT(i);
              DEBUG_PRINTLN(F("] to rainUpdateTotal."));
            }
            DEBUG_PRINT(F("TX Day 3: rainUpdateTotal = "));
            DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
            send(msgRainVAR3.set((float)rainUpdateTotal / 100.0, 1));
            wait(DWELL_TIME);
          #ifdef USE_DAILY
            rainUpdateTotal = 0;
          #endif
            for (int i = currentHour + 72; i > currentHour + 48; i--)
            {
              rainUpdateTotal += rainBucket[i];
              DEBUG_PRINT(F("Adding rainBucket["));
              DEBUG_PRINT(i);
              DEBUG_PRINTLN(F("] to rainUpdateTotal."));
            }
            DEBUG_PRINT(F("TX Day 4: rainUpdateTotal = "));
            DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
            send(msgRainVAR4.set((float)rainUpdateTotal / 100.0, 1));
            wait(DWELL_TIME);
          #ifdef USE_DAILY
            rainUpdateTotal = 0;
          #endif
            for (int i = currentHour + 96; i > currentHour + 72; i--)
            {
              rainUpdateTotal += rainBucket[i];
              DEBUG_PRINT(F("Adding rainBucket["));
              DEBUG_PRINT(i);
              DEBUG_PRINTLN(F("] to rainUpdateTotal."));
            }
            DEBUG_PRINT(F("TX Day 5: rainUpdateTotal = "));
            DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
            send(msgRainVAR5.set((float)rainUpdateTotal / 100.0, 1));
            wait(DWELL_TIME);
          }
          
          void receive(const MyMessage &message)
          {
            if (message.sensor == CHILD_ID_RAIN_LOG)
            {
              // nothing to do here
            }
            else if (message.sensor == CHILD_ID_TRIPPED_INDICATOR)
            {
              if (message.type == V_VAR1)
              {
                rainWindow = atoi(message.data);
                if (rainWindow > 120)
                {
                  rainWindow = 120;
                }
                else if (rainWindow < 1)
                {
                  rainWindow = 1;
                }
                if (rainWindow != atoi(message.data))   // if I changed the value back inside the boundries, push that number back to Vera
                {
                  send(msgTrippedVar1.set(rainWindow));
                }
              }
              else if (message.type == V_VAR2)
              {
                rainSensorThreshold = atoi(message.data);
                if (rainSensorThreshold > 10000)
                {
                  rainSensorThreshold = 10000;
                }
                else if (rainSensorThreshold < 1)
                {
                  rainSensorThreshold = 1;
                }
                if (rainSensorThreshold != atoi(message.data))  // if I changed the value back inside the boundries, push that number back to Vera
                {
                  send(msgTrippedVar2.set(rainSensorThreshold));
                }
              }
            }
          }
          
          void prettyFade(void)
          {
            float val = (exp(sin(millis() / 2000.0 * PI)) - 0.36787944) * 108.0;
            analogWrite(ledPin, val);
          }
          
          void slowFlash(void)
          {
            static bool ledState = true;
            static unsigned long pulseStart = millis();
            if (millis() - pulseStart < 100UL)
            {
              digitalWrite(ledPin, !ledState);
              pulseStart = millis();
            }
          }
          
          void receiveTime(unsigned long newTime)
          {
            DEBUG_PRINTLN(F("Time received..."));
            setTime(newTime);
            char theTime[6];
            sprintf(theTime, "%d:%2d", hour(), minute());
            DEBUG_PRINTLN(theTime);
          }
          

          These are the errors that I get when I try to run the code:

          Starting sensor (RNNNA-, 2.0.0)
          TSM:INIT
          !TSM:RADIO:FAIL
          !TSM:FAILURE
          TSM:PDT
          

          If I disconnect the direction sensor and start it, the radio works fine. The odd thing is that when I run the test code for the direction sensor with the radio connected to the bus, that works fine.

          Any ideas?

          Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
          Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

          Nca78N 1 Reply Last reply
          0
          • dbemowskD dbemowsk

            So now I have the direction sensor on the SPI bus with the CS pin connected to D5 on my easy newbie board. If I run my sample program for the direction sensor to test it on the bus with the nRF24 radio, I get readings and it seems to work fine. The problem is, if I run my modified rain sensor sketch seen below, I cannot get the radio to work.

            /*
             Arduino Tipping Bucket Rain Gauge
            
             April 26, 2015
            
             Version 2.0
            
             Arduino Tipping Bucket Rain Gauge
            
             Utilizing a tipping bucket sensor, your Vera home automation controller and the MySensors.org
             gateway you can measure and sense local rain.  This sketch will create two devices on your
             Vera controller.  One will display your total precipitation for the last 5 days.  The other, 
             a sensor that changes state if there is recent rain (up to last 120 hours)  above a threshold.  
             Both these settings are user definable.
            
             There is a build overview video here: https://youtu.be/1eMfKQaLROo
            
             This sketch features the following:
            
             * Allows you to set the rain threshold in mm
             * Allows you to determine the tripped indicator window up to 120 hours.
             * Displays the last 5 days of rain in Variable1 through Variable5
               of the Rain Sensor device
             * Configuration changes to Sensor device updated every hour
             * Should run on any Arduino
             * Will retain Tripped/Not Tripped status and data in a power interruption, saving small amount
               of data to EEPROM (Circular Buffer to maximize life of EEPROM)
             * LED status indicator
             * Optional Temp/Humidity (DHT-22 or DHT-11) and Light LUX (BH1750) sensors. To use, uncomment
               #define DHT_ON  and/or #define LUX_ON
             * Optionally send total accumulation of each day's rainfall or send only individual days rainfall totals.
               Uncomment #define USE_DAILY to display individual daily rainfall.  If it is commented out it will display
               a cumulative total rainfall (day4 = day1+day2+day3+day4 etc)
            
             by @BulldogLowell and @PeteWill for free public use
            
             */
            
            #define MY_DEBUG // Enable MySensors debug prints to serial monitor
            
            // Enable and select radio type attached
            #define MY_RADIO_NRF24
            //#define MY_RADIO_RFM69
            
            //#define MY_NODE_ID 7 //uncomment this line to assign a static ID
            
            #include <SPI.h>
            #include <math.h>
            #include <TimeLib.h>
            #include "AS5047.h"
            #include <MySensors.h>
            
            #define SKETCH_NAME "Weather Station"
            #define SKETCH_VERSION "2.0"
            
            #define DWELL_TIME 40  // this allows for radio to come back to power after a transmission, ideally 0 
            
            //#define DEBUG_ON  // Rain gauge specific debug messages. 
            #define DHT_ON // uncomment out this line to enable DHT sensor
            //#define LUX_ON // uncomment out this line to enable BH1750 sensor
            //#define USE_DAILY // Uncomment to display individual daily rainfall totals in the variables sent to your controller. If it's commented it will add each day to the next for a cumulative total.
            
            #define NORTH_SWITCH_PIN 7 //The north calibration switch
            #define AS5047_CHIP_SELECT_PIN 5 //The north calibration switch
            
            #define TIP_SENSOR_PIN 2 //The tipping bucket rain sensor
            #define CALIBRATE_FACTOR 60 // amount of rain per rain bucket tip e.g. 5 is .05mm
            #define DHT_LUX_DELAY 300000  //Delay in milliseconds that the DHT and LUX sensors will wait before sending data
            #define WIND_DIR_DELAY 300000  //Delay in milliseconds that the DHT and LUX sensors will wait before sending data
            
            #define CHILD_ID_RAIN_LOG 3  // Keeps track of accumulated rainfall
            #define CHILD_ID_TRIPPED_INDICATOR 4  // Indicates Tripped when rain detected
            #define CHILD_ID_WIND 5  // Indicates Tripped when rain detected
            
            #define EEPROM_NORTH_OFFSET_LOCATION 0  // location of the EEPROM circular buffer
            #define EEPROM_BUFFER_LOCATION 1  // location of the EEPROM circular buffer
            #define E_BUFFER_LENGTH 240
            #define RAIN_BUCKET_SIZE 120
            
            #ifdef  DEBUG_ON
              #define DEBUG_PRINT(x)   Serial.print(x)
              #define DEBUG_PRINTLN(x) Serial.println(x)
              #define SERIAL_START(x)  Serial.begin(x)
              #else
              #define DEBUG_PRINT(x)
              #define DEBUG_PRINTLN(x)
              #define SERIAL_START(x)
            #endif
            //
            MyMessage msgRainRate(CHILD_ID_RAIN_LOG, V_RAINRATE);
            MyMessage msgRain(CHILD_ID_RAIN_LOG, V_RAIN);
            //
            MyMessage msgRainVAR1(CHILD_ID_RAIN_LOG, V_VAR1);
            MyMessage msgRainVAR2(CHILD_ID_RAIN_LOG, V_VAR2);
            MyMessage msgRainVAR3(CHILD_ID_RAIN_LOG, V_VAR3);
            MyMessage msgRainVAR4(CHILD_ID_RAIN_LOG, V_VAR4);
            MyMessage msgRainVAR5(CHILD_ID_RAIN_LOG, V_VAR5);
            //
            MyMessage msgTripped(CHILD_ID_TRIPPED_INDICATOR, V_TRIPPED);
            MyMessage msgTrippedVar1(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
            MyMessage msgTrippedVar2(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
            
            MyMessage msgWindSpeed(CHILD_ID_WIND, V_WIND);
            MyMessage msgWindGust(CHILD_ID_WIND, V_GUST);
            MyMessage msgWindDirection(CHILD_ID_WIND, V_DIRECTION);
            //
            #ifdef DHT_ON
              #include <DHT.h>
              #define CHILD_ID_HUM 0
              #define CHILD_ID_TEMP 1
              #define HUMIDITY_SENSOR_DIGITAL_PIN 3
              DHT dht;
              float lastTemp;
              float lastHum;
              bool metric = false;
              MyMessage msgHum(CHILD_ID_HUM, V_HUM);
              MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
            #endif
            //
            #ifdef LUX_ON
              //BH1750 is connected to SCL (analog input A5) and SDA (analog input A4)
              #include <BH1750.h>
              #include <Wire.h>
              #define CHILD_ID_LIGHT 2
              BH1750 lightSensor;
              MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
              unsigned int lastlux;
              uint8_t heartbeat = 10; //Used to send the light lux to gateway as soon as the device is restarted and after the DHT_LUX_DELAY has happened 10 times
            #endif
            
            AS5047 myAS5047(5); //AS5047_CHIP_SELECT_PIN); //Wind direction magnetic position sensor
            uint8_t north_offset;
            bool button;
            int wind_direction;
            int last_direction;
            
            unsigned long sensorPreviousMillis;
            unsigned long windDirPreviousMillis;
            int eepromIndex;
            int tipSensorPin = 3; // Pin the tipping bucket is connected to. Must be interrupt capable pin
            int ledPin = 5; // Pin the LED is connected to.  PWM capable pin required
            #ifdef DEBUG_ON
            unsigned long dataMillis;
            unsigned long serialInterval = 600000UL;
            #endif
            const unsigned long oneHour = 3600000UL;
            unsigned long lastTipTime;
            unsigned long lastRainTime; //Used for rainRate calculation
            unsigned int rainBucket [RAIN_BUCKET_SIZE] ; /* 24 hours x 5 Days = 120 hours */
            unsigned int rainRate = 0;
            uint8_t rainWindow = 72;         //default rain window in hours.  Will be overwritten with msgTrippedVar1.
            volatile int wasTippedBuffer = 0;
            int rainSensorThreshold = 50; //default rain sensor sensitivity in hundredths.  Will be overwritten with msgTrippedVar2.
            uint8_t state = 0;
            uint8_t oldState = 2; //Setting the default to something other than 1 or 0
            unsigned int lastRainRate = 0;
            int lastMeasure = 0;
            bool gotTime = false;
            uint8_t lastHour;
            uint8_t currentHour;
            //
            void presentation()  {
              // Register all sensors to gw (they will be created as child devices)
              sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
              wait(DWELL_TIME);
              present(CHILD_ID_RAIN_LOG, S_RAIN);
              wait(DWELL_TIME);
              present(CHILD_ID_TRIPPED_INDICATOR, S_MOTION);
              wait(DWELL_TIME);
            
              present(CHILD_ID_WIND, S_WIND);
              wait(DWELL_TIME);
            
            #ifdef DHT_ON
              present(CHILD_ID_HUM, S_HUM);
              wait(DWELL_TIME);
              present(CHILD_ID_TEMP, S_TEMP);
              wait(DWELL_TIME);
            #endif
            
            
            #ifdef LUX_ON
              present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
            #endif
            
              DEBUG_PRINTLN(F("Sensor Presentation Complete"));
            }
            
            void setup()
            {
              #ifndef MY_DEBUG
              SERIAL_START(115200);  //Start serial if MySensors debugging isn't enabled
              #endif
              //
              pinMode(NORTH_SWITCH_PIN, INPUT_PULLUP);
              
              // Set up the IO
              pinMode(TIP_SENSOR_PIN, INPUT_PULLUP);
              attachInterrupt (digitalPinToInterrupt(TIP_SENSOR_PIN), sensorTipped, FALLING);  // depending on location of the hall effect sensor may need CHANGE
              pinMode(ledPin, OUTPUT);
              digitalWrite(ledPin, HIGH);
              //
              //Sync time with the server
              //
              unsigned long functionTimeout = millis();
              while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL)
              {
                requestTime();
                DEBUG_PRINTLN(F("Getting Time"));
                wait(1000); // call once per second
                DEBUG_PRINTLN(F("."));
              }
              currentHour = hour();
              lastHour = hour();
              //
              //retrieve from EEPROM stored values on a power cycle.
              //
              
              //Get the north offset direction
              north_offset = loadState(EEPROM_NORTH_OFFSET_LOCATION)*2;
              
              bool isDataOnEeprom = false;
              for (int i = 0; i < E_BUFFER_LENGTH; i++)
              {
                uint8_t locator = loadState(EEPROM_BUFFER_LOCATION + i);
                if (locator == 0xFE)  // found the EEPROM circular buffer index
                {
                  eepromIndex = EEPROM_BUFFER_LOCATION + i;
                  DEBUG_PRINT(F("EEPROM Index "));
                  DEBUG_PRINTLN(eepromIndex);
                  //Now that we have the buffer index let's populate the rainBucket[] with data from eeprom
                  loadRainArray(eepromIndex);
                  isDataOnEeprom = true;
                  break;
                }
              }
              //
              if (!isDataOnEeprom) // Added for the first time it is run on a new Arduino
              {
                DEBUG_PRINTLN(F("I didn't find valid EEPROM Index, so I'm writing one to location 0"));
                eepromIndex = EEPROM_BUFFER_LOCATION;
                saveState(eepromIndex, 0xFE);
                saveState(eepromIndex + 1, 0xFE);
                //then I will clear out any bad data
                for (int i = 2; i <= E_BUFFER_LENGTH; i++)
                {
                  saveState(i, 0x00);
                }
              }
              #ifdef DEBUG_ON
              dataMillis = millis();
              #endif
              lastTipTime = millis(); 
              //
              request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
              wait(DWELL_TIME);
              request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
              wait(DWELL_TIME);
              //
            #ifdef DHT_ON
              dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
              metric = getConfig().isMetric;
              //metric = false;
              wait(DWELL_TIME);
            #endif
              //
            #ifdef LUX_ON
              lightSensor.begin();
            #endif
              //
              transmitRainData(); //Setup complete send any data loaded from eeprom to gateway
            }
            
            void loop()
            {
              if (state)
              {
                prettyFade();  // breathe if tripped
              }
              else
              {
                slowFlash();   // blink if not tripped
              }
            #ifdef DEBUG_ON  // Serial Debug Block
              if ( (millis() - dataMillis) >= serialInterval)
              {
                for (int i = 24; i <= 120; i = i + 24)
                {
                  updateSerialData(i);
                }
                dataMillis = millis();
              }
            #endif
            
              //NORTH_SWITCH_PIN
              button = digitalRead(NORTH_SWITCH_PIN);
              if (!button) {
                setNorthOffset();
              } 
              
              //
              // let's constantly check to see if the rain in the past rainWindow hours is greater than rainSensorThreshold
              //
              int measure = 0; // Check to see if we need to show sensor tripped in this block
              for (int i = 0; i < rainWindow; i++)
              {
                measure += rainBucket [i];
                if (measure != lastMeasure)
                {
                  //      DEBUG_PRINT(F("measure value (total rainBucket within rainWindow): "));
                  //      DEBUG_PRINTLN(measure);
                  lastMeasure = measure;
                }
              }
              //
              state = (measure >= (rainSensorThreshold * 100));
              if (state != oldState)
              {
                send(msgTripped.set(state));
                wait(DWELL_TIME);
                DEBUG_PRINT(F("New Sensor State... Sensor: "));
                DEBUG_PRINTLN(state ? "Tripped" : "Not Tripped");
                oldState = state;
              }
              //WIND_DIR_DELAY
              if (millis() - windDirPreviousMillis > WIND_DIR_DELAY)
              {
                wind_direction = getWindDirection();
                if (wind_direction != last_direction)
                {
                  send(msgWindDirection.set(wind_direction));
                }
                last_direction = wind_direction;
                windDirPreviousMillis = millis();
              }
              //
              unsigned long tipDelay = millis() - lastRainTime;
              if (wasTippedBuffer) // if was tipped, then update the 24hour total and transmit to Vera
              {
                DEBUG_PRINTLN(F("Sensor Tipped"));
                DEBUG_PRINT(F("rainBucket [0] value: "));
                DEBUG_PRINTLN(rainBucket [0]);
                send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); //Calculate the total rain for the day
                wait(DWELL_TIME);
                wasTippedBuffer--;
                rainRate = ((oneHour) / tipDelay);
                if (rainRate != lastRainRate)
                {
                  send(msgRainRate.set(rainRate, 1));
                  wait(DWELL_TIME);
                  DEBUG_PRINT(F("RainRate= "));
                  DEBUG_PRINTLN(rainRate);
                  lastRainRate = rainRate;
                }
                lastRainTime = lastTipTime;
              }
              //
              currentHour = hour();
              if (currentHour != lastHour)
              {
                DEBUG_PRINTLN(F("One hour elapsed."));
                send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); // send today's rainfall
                wait(DWELL_TIME);
                saveState(eepromIndex, highByte(rainBucket[0]));
                saveState(eepromIndex + 1, lowByte(rainBucket[0]));
                DEBUG_PRINT(F("Saving rainBucket[0] to eeprom. rainBucket[0] = "));
                DEBUG_PRINTLN(rainBucket[0]);
                for (int i = RAIN_BUCKET_SIZE - 1; i >= 0; i--)//cascade an hour of values back into the array
                {
                  rainBucket [i + 1] = rainBucket [i];
                }
                request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
                wait(DWELL_TIME);
                request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
                wait(DWELL_TIME);
                rainBucket[0] = 0;
                eepromIndex = eepromIndex + 2;
                if (eepromIndex > EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH)
                {
                  eepromIndex = EEPROM_BUFFER_LOCATION;
                }
                DEBUG_PRINT(F("Writing to EEPROM.  Index: "));
                DEBUG_PRINTLN(eepromIndex);
                saveState(eepromIndex, 0xFE);
                saveState(eepromIndex + 1, 0xFE);
                requestTime(); // sync the time every hour
                wait(DWELL_TIME);
                transmitRainData();
                rainRate = 0;
                send(msgRainRate.set(rainRate, 1));
                wait(DWELL_TIME);
                DEBUG_PRINTLN(F("Sending rainRate is 0 to controller"));
                lastHour = hour();
              }
              if (millis() - sensorPreviousMillis > DHT_LUX_DELAY)
              {
                #ifdef DHT_ON  //DHT Code
                  doDHT();
                #endif
                #ifdef LUX_ON
                  doLUX();
                #endif
                sensorPreviousMillis = millis();
              }
            }
            
            int getWindDirection() 
            {
              north_offset = loadState(EEPROM_NORTH_OFFSET_LOCATION);
              
              int value = readDir();
              int dir = ((value - north_offset) < 0) ? 360 - abs(value - north_offset) : value - north_offset;
                DEBUG_PRINT("Wind direction: ");
                DEBUG_PRINTLN(dir);
              return dir;
            }
            
            //
            void setNorthOffset() 
            {
              int value = readDir();
              if (north_offset != value)
              {
                saveState(EEPROM_NORTH_OFFSET_LOCATION, value/2);
                north_offset = value;
                DEBUG_PRINT("North offset set to: ");
                DEBUG_PRINTLN(value/2);
              }
            }
            int readDir() 
            {
              int value = (359*myAS5047.sensor_read())/16383;
              return value;
            }
            //
            #ifdef DHT_ON
            void doDHT(void)
            {
              float temperature = dht.getTemperature();
                if (isnan(temperature)) 
                {
                  DEBUG_PRINTLN(F("Failed reading temperature from DHT"));
                } else if (temperature != lastTemp) 
                {
                  lastTemp = temperature;
                  if (!metric) 
                  {
                    temperature = dht.toFahrenheit(temperature);
                  }
                  send(msgTemp.set(temperature, 1));
                  wait(DWELL_TIME);
                  DEBUG_PRINT(F("Temperature is: "));
                  DEBUG_PRINTLN(temperature);
                }
                float humidity = dht.getHumidity();;
                if (isnan(humidity)) 
                {
                  DEBUG_PRINTLN(F("Failed reading humidity from DHT"));
                } else if (humidity != lastHum) 
                {
                  lastHum = humidity;
                  send(msgHum.set(humidity, 1));
                  wait(DWELL_TIME);
                  DEBUG_PRINT(F("Humidity is: "));
                  DEBUG_PRINTLN(humidity);
                }
            }
            #endif
            //
            #ifdef LUX_ON
            void doLUX(void)
            {
              unsigned int lux = lightSensor.readLightLevel();// Get Lux value
              DEBUG_PRINT(F("Current LUX Level: "));
              DEBUG_PRINTLN(lux);
              heartbeat++;
              if (lux != lastlux || heartbeat > 10) 
              {
                send(msg.set(lux));
                lastlux = lux;
              }
              if (heartbeat > 10) 
              {
                heartbeat = 0;
              }
            }
            #endif
            //
            void sensorTipped()
            {
              unsigned long thisTipTime = millis();
              if (thisTipTime - lastTipTime > 100UL)
              {
                rainBucket[0] += CALIBRATE_FACTOR; // adds CALIBRATE_FACTOR hundredths of unit each tip
                wasTippedBuffer++;
              }
              lastTipTime = thisTipTime;
            }
            //
            int rainTotal(int hours)
            {
              int total = 0;
              for ( int i = 0; i <= hours; i++)
              {
                total += rainBucket [i];
              }
              return total;
            }
            
            #ifdef DEBUG_ON
            void updateSerialData(int x)
            {
              DEBUG_PRINT(F("Rain last "));
              DEBUG_PRINT(x);
              DEBUG_PRINTLN(F(" hours: "));
              float tipCount = 0;
              for (int i = 0; i < x; i++)
              {
                tipCount = tipCount + rainBucket [i];
              }
              tipCount = tipCount / 100;
              DEBUG_PRINTLN(tipCount);
            }
            #endif
            
            void loadRainArray(int eValue) // retrieve stored rain array from EEPROM on powerup
            {
              for (int i = 1; i < RAIN_BUCKET_SIZE; i++)
              {
                eValue = eValue - 2;
                if (eValue < EEPROM_BUFFER_LOCATION)
                {
                  eValue = EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH;
                }
                DEBUG_PRINT(F("EEPROM location: "));
                DEBUG_PRINTLN(eValue);
                uint8_t rainValueHigh = loadState(eValue);
                uint8_t rainValueLow = loadState(eValue + 1);
                unsigned int rainValue = rainValueHigh << 8;
                rainValue |= rainValueLow;
                rainBucket[i] = rainValue;
                //
                DEBUG_PRINT(F("rainBucket[ value: "));
                DEBUG_PRINT(i);
                DEBUG_PRINT(F("] value: "));
                DEBUG_PRINTLN(rainBucket[i]);
              }
            }
            
            void transmitRainData(void)
            {
              DEBUG_PRINT(F("In transmitRainData. currentHour = "));
              DEBUG_PRINTLN(currentHour);
              int rainUpdateTotal = 0;
              for (int i = currentHour; i >= 0; i--)
              {
                rainUpdateTotal += rainBucket[i];
                DEBUG_PRINT(F("Adding rainBucket["));
                DEBUG_PRINT(i);
                DEBUG_PRINTLN(F("] to rainUpdateTotal."));
              }
              DEBUG_PRINT(F("TX Day 1: rainUpdateTotal = "));
              DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
              send(msgRainVAR1.set((float)rainUpdateTotal / 100.0, 1)); //Send current day rain totals (resets at midnight)
              wait(DWELL_TIME);
            #ifdef USE_DAILY
              rainUpdateTotal = 0;
            #endif
              for (int i = currentHour + 24; i > currentHour; i--)
              {
                rainUpdateTotal += rainBucket[i];
                DEBUG_PRINT(F("Adding rainBucket["));
                DEBUG_PRINT(i);
                DEBUG_PRINTLN(F("] to rainUpdateTotal."));
              }
              DEBUG_PRINT(F("TX Day 2: rainUpdateTotal = "));
              DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
              send(msgRainVAR2.set((float)rainUpdateTotal / 100.0, 1));
              wait(DWELL_TIME);
            #ifdef USE_DAILY
              rainUpdateTotal = 0;
            #endif
              for (int i = currentHour + 48; i > currentHour + 24; i--)
              {
                rainUpdateTotal += rainBucket[i];
                DEBUG_PRINT(F("Adding rainBucket["));
                DEBUG_PRINT(i);
                DEBUG_PRINTLN(F("] to rainUpdateTotal."));
              }
              DEBUG_PRINT(F("TX Day 3: rainUpdateTotal = "));
              DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
              send(msgRainVAR3.set((float)rainUpdateTotal / 100.0, 1));
              wait(DWELL_TIME);
            #ifdef USE_DAILY
              rainUpdateTotal = 0;
            #endif
              for (int i = currentHour + 72; i > currentHour + 48; i--)
              {
                rainUpdateTotal += rainBucket[i];
                DEBUG_PRINT(F("Adding rainBucket["));
                DEBUG_PRINT(i);
                DEBUG_PRINTLN(F("] to rainUpdateTotal."));
              }
              DEBUG_PRINT(F("TX Day 4: rainUpdateTotal = "));
              DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
              send(msgRainVAR4.set((float)rainUpdateTotal / 100.0, 1));
              wait(DWELL_TIME);
            #ifdef USE_DAILY
              rainUpdateTotal = 0;
            #endif
              for (int i = currentHour + 96; i > currentHour + 72; i--)
              {
                rainUpdateTotal += rainBucket[i];
                DEBUG_PRINT(F("Adding rainBucket["));
                DEBUG_PRINT(i);
                DEBUG_PRINTLN(F("] to rainUpdateTotal."));
              }
              DEBUG_PRINT(F("TX Day 5: rainUpdateTotal = "));
              DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
              send(msgRainVAR5.set((float)rainUpdateTotal / 100.0, 1));
              wait(DWELL_TIME);
            }
            
            void receive(const MyMessage &message)
            {
              if (message.sensor == CHILD_ID_RAIN_LOG)
              {
                // nothing to do here
              }
              else if (message.sensor == CHILD_ID_TRIPPED_INDICATOR)
              {
                if (message.type == V_VAR1)
                {
                  rainWindow = atoi(message.data);
                  if (rainWindow > 120)
                  {
                    rainWindow = 120;
                  }
                  else if (rainWindow < 1)
                  {
                    rainWindow = 1;
                  }
                  if (rainWindow != atoi(message.data))   // if I changed the value back inside the boundries, push that number back to Vera
                  {
                    send(msgTrippedVar1.set(rainWindow));
                  }
                }
                else if (message.type == V_VAR2)
                {
                  rainSensorThreshold = atoi(message.data);
                  if (rainSensorThreshold > 10000)
                  {
                    rainSensorThreshold = 10000;
                  }
                  else if (rainSensorThreshold < 1)
                  {
                    rainSensorThreshold = 1;
                  }
                  if (rainSensorThreshold != atoi(message.data))  // if I changed the value back inside the boundries, push that number back to Vera
                  {
                    send(msgTrippedVar2.set(rainSensorThreshold));
                  }
                }
              }
            }
            
            void prettyFade(void)
            {
              float val = (exp(sin(millis() / 2000.0 * PI)) - 0.36787944) * 108.0;
              analogWrite(ledPin, val);
            }
            
            void slowFlash(void)
            {
              static bool ledState = true;
              static unsigned long pulseStart = millis();
              if (millis() - pulseStart < 100UL)
              {
                digitalWrite(ledPin, !ledState);
                pulseStart = millis();
              }
            }
            
            void receiveTime(unsigned long newTime)
            {
              DEBUG_PRINTLN(F("Time received..."));
              setTime(newTime);
              char theTime[6];
              sprintf(theTime, "%d:%2d", hour(), minute());
              DEBUG_PRINTLN(theTime);
            }
            

            These are the errors that I get when I try to run the code:

            Starting sensor (RNNNA-, 2.0.0)
            TSM:INIT
            !TSM:RADIO:FAIL
            !TSM:FAILURE
            TSM:PDT
            

            If I disconnect the direction sensor and start it, the radio works fine. The odd thing is that when I run the test code for the direction sensor with the radio connected to the bus, that works fine.

            Any ideas?

            Nca78N Offline
            Nca78N Offline
            Nca78
            Hardware Contributor
            wrote on last edited by
            #102

            @dbemowsk my guess is your sensor tries to communicate on the SPI bus and prevents communication with NRF24.
            I don't know what is in you AS5047 files so I'm not sure but I suppose it's taking over the SPI bus at creation, you should try to force the CSN pin used for the as5047 to HIGH in before() method to disable it before MySensors library starts using the radio.

            dbemowskD 1 Reply Last reply
            0
            • Nca78N Nca78

              @dbemowsk my guess is your sensor tries to communicate on the SPI bus and prevents communication with NRF24.
              I don't know what is in you AS5047 files so I'm not sure but I suppose it's taking over the SPI bus at creation, you should try to force the CSN pin used for the as5047 to HIGH in before() method to disable it before MySensors library starts using the radio.

              dbemowskD Offline
              dbemowskD Offline
              dbemowsk
              wrote on last edited by dbemowsk
              #103

              @Nca78 ok, so I tried adding this:

              void before()
              {
                digitalWrite(AS5047_CHIP_SELECT_PIN, HIGH);
              }
              

              This seems to now allow the radio to connect, but I am still having some trouble. I then tried removing setting the CSN pin high in the before(), and adding it to the constructor of the library class here:

              AS5047::AS5047(uint16_t SelectPin)
                       : _ss(SelectPin)
              {
                       pinMode(_ss, OUTPUT);
                       SPCR = (1<<SPE) | (1<<MSTR) | (1<<CPHA) | (1<<SPR1) | (1<<SPR0); // slow down clock speed, set up spi
                       digitalWrite(_ss, HIGH); //<<-------------
                       SPI.begin();
              }
              

              This seemed to do the same as putting it in the begin() method, but still having some trouble. I am going to see if I can work through the problems on my own, but I may post if I have questions. Let me know if you see problems with what I did to the class.

              Thanks.

              Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
              Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

              YveauxY 1 Reply Last reply
              0
              • dbemowskD dbemowsk

                @Nca78 ok, so I tried adding this:

                void before()
                {
                  digitalWrite(AS5047_CHIP_SELECT_PIN, HIGH);
                }
                

                This seems to now allow the radio to connect, but I am still having some trouble. I then tried removing setting the CSN pin high in the before(), and adding it to the constructor of the library class here:

                AS5047::AS5047(uint16_t SelectPin)
                         : _ss(SelectPin)
                {
                         pinMode(_ss, OUTPUT);
                         SPCR = (1<<SPE) | (1<<MSTR) | (1<<CPHA) | (1<<SPR1) | (1<<SPR0); // slow down clock speed, set up spi
                         digitalWrite(_ss, HIGH); //<<-------------
                         SPI.begin();
                }
                

                This seemed to do the same as putting it in the begin() method, but still having some trouble. I am going to see if I can work through the problems on my own, but I may post if I have questions. Let me know if you see problems with what I did to the class.

                Thanks.

                YveauxY Offline
                YveauxY Offline
                Yveaux
                Mod
                wrote on last edited by Yveaux
                #104

                @dbemowsk it's good practice to have a pull up resistor on each SPI CS line (approx. 10k).
                It can save you a lot of hassle when multiple devices share the same SPI bus.

                http://yveaux.blogspot.nl

                dbemowskD 1 Reply Last reply
                1
                • YveauxY Yveaux

                  @dbemowsk it's good practice to have a pull up resistor on each SPI CS line (approx. 10k).
                  It can save you a lot of hassle when multiple devices share the same SPI bus.

                  dbemowskD Offline
                  dbemowskD Offline
                  dbemowsk
                  wrote on last edited by
                  #105

                  @Yveaux Thanks, this is easy enough. I have some small 1/8w 10k resistors with a small bit of room in the proto area of the easy newbie board yet, I will add one in.

                  Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                  Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                  YveauxY 1 Reply Last reply
                  0
                  • dbemowskD dbemowsk

                    @Yveaux Thanks, this is easy enough. I have some small 1/8w 10k resistors with a small bit of room in the proto area of the easy newbie board yet, I will add one in.

                    YveauxY Offline
                    YveauxY Offline
                    Yveaux
                    Mod
                    wrote on last edited by
                    #106

                    @dbemowsk said in MySensors weather station:

                    I will add one in.

                    Two, one for each SPI device ;-)

                    http://yveaux.blogspot.nl

                    dbemowskD 1 Reply Last reply
                    0
                    • YveauxY Yveaux

                      @dbemowsk said in MySensors weather station:

                      I will add one in.

                      Two, one for each SPI device ;-)

                      dbemowskD Offline
                      dbemowskD Offline
                      dbemowsk
                      wrote on last edited by
                      #107

                      @Yveaux I thought the nRF24 radios would have had it built in to the module, but I never checked. It is just that and the magnetic direction sensor on the SPI bus. After thinking about it too, I may just add the resistor on to the small board I have inside the wind speed and direction sensor case that the wire harness connects to, or do you think it would be better if it was closer to the arduino? If that is the case, then I would stick with my original plan to put it in the little bit of leftover space in the proto area of the easy newbie board. Jumper wires are getting a bit cramped in that space though, so if I can avoid it I will.

                      Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                      Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                      YveauxY 1 Reply Last reply
                      0
                      • dbemowskD dbemowsk

                        @Yveaux I thought the nRF24 radios would have had it built in to the module, but I never checked. It is just that and the magnetic direction sensor on the SPI bus. After thinking about it too, I may just add the resistor on to the small board I have inside the wind speed and direction sensor case that the wire harness connects to, or do you think it would be better if it was closer to the arduino? If that is the case, then I would stick with my original plan to put it in the little bit of leftover space in the proto area of the easy newbie board. Jumper wires are getting a bit cramped in that space though, so if I can avoid it I will.

                        YveauxY Offline
                        YveauxY Offline
                        Yveaux
                        Mod
                        wrote on last edited by Yveaux
                        #108

                        @dbemowsk the nrf module doesn't have a pullup on CS.
                        Where you put them doesn't really matter. It's just to have a defined, unselected state when the lines are not actively driven by the microcontroller.
                        If it is too much trouble in your current hardware, then skip the pull-ups and save them for your next piece of hardware. The same can be achieved in software, but you just must make sure all CS lines are made inactive (high) before doing anything with the SPI bus. Before() is a good place to achieve this, but bad designed drivers that use eg the constructor to do spi initialization could still beat you to it...
                        Therefore pull-ups are preferred.

                        http://yveaux.blogspot.nl

                        dbemowskD 2 Replies Last reply
                        0
                        • YveauxY Yveaux

                          @dbemowsk the nrf module doesn't have a pullup on CS.
                          Where you put them doesn't really matter. It's just to have a defined, unselected state when the lines are not actively driven by the microcontroller.
                          If it is too much trouble in your current hardware, then skip the pull-ups and save them for your next piece of hardware. The same can be achieved in software, but you just must make sure all CS lines are made inactive (high) before doing anything with the SPI bus. Before() is a good place to achieve this, but bad designed drivers that use eg the constructor to do spi initialization could still beat you to it...
                          Therefore pull-ups are preferred.

                          dbemowskD Offline
                          dbemowskD Offline
                          dbemowsk
                          wrote on last edited by
                          #109

                          @Yveaux If I am going to do one for the radio too, I can put one in the case of the wind sensor and one in the proto area for the radio. I think I'll be alright. It will eliminate confusion on the programming end.

                          Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                          Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                          1 Reply Last reply
                          0
                          • YveauxY Yveaux

                            @dbemowsk the nrf module doesn't have a pullup on CS.
                            Where you put them doesn't really matter. It's just to have a defined, unselected state when the lines are not actively driven by the microcontroller.
                            If it is too much trouble in your current hardware, then skip the pull-ups and save them for your next piece of hardware. The same can be achieved in software, but you just must make sure all CS lines are made inactive (high) before doing anything with the SPI bus. Before() is a good place to achieve this, but bad designed drivers that use eg the constructor to do spi initialization could still beat you to it...
                            Therefore pull-ups are preferred.

                            dbemowskD Offline
                            dbemowskD Offline
                            dbemowsk
                            wrote on last edited by
                            #110

                            @Yveaux So if this is done in software, is it better to be done in the before() method rather than the constructor of the library class? If the nRF24 radios do not have a built in pull up on the CS line, does the MySensors library somehow take care of this in one of it's class files? I haven't seen a push to have designers of MySensors hardware include pull-ups on the nRF24's CS line...

                            Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                            Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                            YveauxY 1 Reply Last reply
                            0
                            • dbemowskD dbemowsk

                              @Yveaux So if this is done in software, is it better to be done in the before() method rather than the constructor of the library class? If the nRF24 radios do not have a built in pull up on the CS line, does the MySensors library somehow take care of this in one of it's class files? I haven't seen a push to have designers of MySensors hardware include pull-ups on the nRF24's CS line...

                              YveauxY Offline
                              YveauxY Offline
                              Yveaux
                              Mod
                              wrote on last edited by Yveaux
                              #111

                              @dbemowsk said in MySensors weather station:

                              @Yveaux So if this is done in software, is it better to be done in the before() method rather than the constructor of the library class?

                              It all depends on initialization order of the classes, which isn't trivial. For global static instances (declared outside a function like loop()) the constructor will be called before the before() call, but if one places an instance inside a function or dynamically creates it things will be different. So, when designing a library you simply can't be sure when your constructie is called...

                              I'm not sure right now if the drivers actively pull the CS line high at startup, but IMHO they should.
                              The fact that some mySensors hardware designs lack pull-ups on CS is probably because the SPI bus isn't shared in many cases, and maybe because people aren't aware.
                              This would be a good item to add to a design checklist, if only we had one :-)

                              http://yveaux.blogspot.nl

                              dbemowskD 1 Reply Last reply
                              1
                              • YveauxY Yveaux

                                @dbemowsk said in MySensors weather station:

                                @Yveaux So if this is done in software, is it better to be done in the before() method rather than the constructor of the library class?

                                It all depends on initialization order of the classes, which isn't trivial. For global static instances (declared outside a function like loop()) the constructor will be called before the before() call, but if one places an instance inside a function or dynamically creates it things will be different. So, when designing a library you simply can't be sure when your constructie is called...

                                I'm not sure right now if the drivers actively pull the CS line high at startup, but IMHO they should.
                                The fact that some mySensors hardware designs lack pull-ups on CS is probably because the SPI bus isn't shared in many cases, and maybe because people aren't aware.
                                This would be a good item to add to a design checklist, if only we had one :-)

                                dbemowskD Offline
                                dbemowskD Offline
                                dbemowsk
                                wrote on last edited by
                                #112

                                @Yveaux Great explanation, thanks.

                                I am close to having things all working. I will post more as I progress.

                                Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                                Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                                1 Reply Last reply
                                0
                                • dbemowskD Offline
                                  dbemowskD Offline
                                  dbemowsk
                                  wrote on last edited by
                                  #113

                                  OK, so here is my easy newbie board layout showing pin connections and header plug identifications. I am still working on the code a bit. I still need to work in the wind speed and wind gust code and figure out the calculations for that. I am nearing the point of full sensor testing. I will then need to figure out my power situation.
                                  0_1500169191817_upload-6df2b074-decd-4232-958c-973fb97d1173

                                  Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                                  Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                                  1 Reply Last reply
                                  1
                                  • dbemowskD Offline
                                    dbemowskD Offline
                                    dbemowsk
                                    wrote on last edited by
                                    #114

                                    Here are some of the final pics of the wind sensor assembly. The first one shows the circuit board mounting assembly. I have a small channel on the top and bottom sides of the mounting plate to hold rubber O-ring seals to keep water out. The seals can be seen to the left of the image.
                                    0_1500170436823_upload-15dd3888-b1c6-4e4b-8b03-32a0533eec63

                                    Next is just a wide angle shot of all the parts. The connector for the anemometer reed switch feeds through the hole next to the wire harness board and plugs into a header on that board.
                                    0_1500170696031_upload-bca62065-4537-4f33-a19e-cb472587f0ef

                                    The last pic is the fully assembled unit with the wire harness attached. I added a shot of the O-rings sandwiched between the layers to keep water out.
                                    0_1500171521761_upload-fd7d3c7c-9ac7-4a13-8a91-d6423d083117

                                    Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                                    Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                                    mfalkviddM 1 Reply Last reply
                                    2
                                    • dbemowskD dbemowsk

                                      Here are some of the final pics of the wind sensor assembly. The first one shows the circuit board mounting assembly. I have a small channel on the top and bottom sides of the mounting plate to hold rubber O-ring seals to keep water out. The seals can be seen to the left of the image.
                                      0_1500170436823_upload-15dd3888-b1c6-4e4b-8b03-32a0533eec63

                                      Next is just a wide angle shot of all the parts. The connector for the anemometer reed switch feeds through the hole next to the wire harness board and plugs into a header on that board.
                                      0_1500170696031_upload-bca62065-4537-4f33-a19e-cb472587f0ef

                                      The last pic is the fully assembled unit with the wire harness attached. I added a shot of the O-rings sandwiched between the layers to keep water out.
                                      0_1500171521761_upload-fd7d3c7c-9ac7-4a13-8a91-d6423d083117

                                      mfalkviddM Online
                                      mfalkviddM Online
                                      mfalkvidd
                                      Mod
                                      wrote on last edited by
                                      #115

                                      @dbemowsk great work, thanks for sharing!

                                      My 3D printer does not create watertight prints. Water seems to be able to slowly pass through the walls. Hopefully your printer is better, but it might be something to look out for.

                                      dbemowskD 1 Reply Last reply
                                      0
                                      • mfalkviddM mfalkvidd

                                        @dbemowsk great work, thanks for sharing!

                                        My 3D printer does not create watertight prints. Water seems to be able to slowly pass through the walls. Hopefully your printer is better, but it might be something to look out for.

                                        dbemowskD Offline
                                        dbemowskD Offline
                                        dbemowsk
                                        wrote on last edited by
                                        #116

                                        @mfalkvidd The walls of the upper and lower case are pretty thick. I used 100% infill which was probably a bit overboard, but I didn't want any water in it. That is why I also put the rubber O-rings in the middle. With the sides compressing that rubber it gives it a pretty good seal. I was originally going to make gaskets. but I found the O-rings to be a better fit.

                                        Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                                        Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                                        1 Reply Last reply
                                        1
                                        • dbemowskD Offline
                                          dbemowskD Offline
                                          dbemowsk
                                          wrote on last edited by
                                          #117

                                          So for those that have wind sensors on your setups, what are you using for your V_GUST value that you send back to the controller?

                                          Vera Plus running UI7 with MySensors, Sonoffs and 1-Wire devices
                                          Visit my website for more Bits, Bytes and Ramblings from me: http://dan.bemowski.info/

                                          YveauxY 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          13

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular