From 690b54b9dee0ad0883123a8e9126a40aa01d8b39 Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Thu, 7 Jan 2021 01:10:42 +0000 Subject: [PATCH] Start moving to new hardware --- .../{Weather.ino => SparkFun/SparkFun.ino} | 0 Weather/Arduino/SparkFun/makefile | 11 + Weather/Arduino/{ => SparkFun}/publish.bat | 0 .../Arduino/SwitchDoc/Adafruit_ADS1015.cpp | 372 ++++++++++++++++ Weather/Arduino/SwitchDoc/Adafruit_ADS1015.h | 157 +++++++ .../Arduino/SwitchDoc/SDL_Weather_80422.cpp | 398 ++++++++++++++++++ Weather/Arduino/SwitchDoc/SDL_Weather_80422.h | 84 ++++ Weather/Arduino/SwitchDoc/SwitchDoc.ino | 146 +++++++ Weather/Arduino/SwitchDoc/elapsedMillis.h | 82 ++++ Weather/Arduino/SwitchDoc/makefile | 14 + Weather/Arduino/makefile | 11 - 11 files changed, 1264 insertions(+), 11 deletions(-) rename Weather/Arduino/{Weather.ino => SparkFun/SparkFun.ino} (100%) create mode 100644 Weather/Arduino/SparkFun/makefile rename Weather/Arduino/{ => SparkFun}/publish.bat (100%) create mode 100644 Weather/Arduino/SwitchDoc/Adafruit_ADS1015.cpp create mode 100644 Weather/Arduino/SwitchDoc/Adafruit_ADS1015.h create mode 100644 Weather/Arduino/SwitchDoc/SDL_Weather_80422.cpp create mode 100644 Weather/Arduino/SwitchDoc/SDL_Weather_80422.h create mode 100644 Weather/Arduino/SwitchDoc/SwitchDoc.ino create mode 100644 Weather/Arduino/SwitchDoc/elapsedMillis.h create mode 100644 Weather/Arduino/SwitchDoc/makefile delete mode 100644 Weather/Arduino/makefile diff --git a/Weather/Arduino/Weather.ino b/Weather/Arduino/SparkFun/SparkFun.ino similarity index 100% rename from Weather/Arduino/Weather.ino rename to Weather/Arduino/SparkFun/SparkFun.ino diff --git a/Weather/Arduino/SparkFun/makefile b/Weather/Arduino/SparkFun/makefile new file mode 100644 index 0000000..b589fb8 --- /dev/null +++ b/Weather/Arduino/SparkFun/makefile @@ -0,0 +1,11 @@ +weather: + mkdir -p bin/ + arduino-cli compile --fqbn arduino:avr:uno Weather.ino --output-dir bin + +install: +# kubectl scale --replicas=0 --namespace=home-monitor deployment/weather-serial-reader + arduino-cli upload -b arduino:avr:uno -p /dev/ttyACM0 --input-dir bin +# kubectl scale --replicas=1 --namespace=home-monitor deployment/weather-serial-reader + +clean: + rm -rf bin/ diff --git a/Weather/Arduino/publish.bat b/Weather/Arduino/SparkFun/publish.bat similarity index 100% rename from Weather/Arduino/publish.bat rename to Weather/Arduino/SparkFun/publish.bat diff --git a/Weather/Arduino/SwitchDoc/Adafruit_ADS1015.cpp b/Weather/Arduino/SwitchDoc/Adafruit_ADS1015.cpp new file mode 100644 index 0000000..5ccb141 --- /dev/null +++ b/Weather/Arduino/SwitchDoc/Adafruit_ADS1015.cpp @@ -0,0 +1,372 @@ +/**************************************************************************/ +/*! + @file Adafruit_ADS1015.cpp + @author K.Townsend (Adafruit Industries) + @license BSD (see license.txt) + + Driver for the ADS1015/ADS1115 ADC + + This is a library for the Adafruit MPL115A2 breakout + ----> https://www.adafruit.com/products/??? + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + @section HISTORY + + v1.0 - First release +*/ +/**************************************************************************/ +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +#include "Adafruit_ADS1015.h" + +/**************************************************************************/ +/*! + @brief Abstract away platform differences in Arduino wire library +*/ +/**************************************************************************/ +static uint8_t i2cread(void) { + #if ARDUINO >= 100 + return Wire.read(); + #else + return Wire.receive(); + #endif +} + +/**************************************************************************/ +/*! + @brief Abstract away platform differences in Arduino wire library +*/ +/**************************************************************************/ +static void i2cwrite(uint8_t x) { + #if ARDUINO >= 100 + Wire.write((uint8_t)x); + #else + Wire.send(x); + #endif +} + +/**************************************************************************/ +/*! + @brief Writes 16-bits to the specified destination register +*/ +/**************************************************************************/ +static void writeRegister(uint8_t i2cAddress, uint8_t reg, uint16_t value) { + Wire.beginTransmission(i2cAddress); + i2cwrite((uint8_t)reg); + i2cwrite((uint8_t)(value>>8)); + i2cwrite((uint8_t)(value & 0xFF)); + Wire.endTransmission(); +} + +/**************************************************************************/ +/*! + @brief Writes 16-bits to the specified destination register +*/ +/**************************************************************************/ +static uint16_t readRegister(uint8_t i2cAddress, uint8_t reg) { + Wire.beginTransmission(i2cAddress); + i2cwrite(ADS1015_REG_POINTER_CONVERT); + Wire.endTransmission(); + Wire.requestFrom(i2cAddress, (uint8_t)2); + return ((i2cread() << 8) | i2cread()); +} + +/**************************************************************************/ +/*! + @brief Instantiates a new ADS1015 class w/appropriate properties +*/ +/**************************************************************************/ +Adafruit_ADS1015::Adafruit_ADS1015(uint8_t i2cAddress) +{ + m_i2cAddress = i2cAddress; + m_conversionDelay = ADS1015_CONVERSIONDELAY+10; + m_bitShift = 4; + m_gain = GAIN_TWOTHIRDS; /* +/- 6.144V range (limited to VDD +0.3V max!) */ +} + +/**************************************************************************/ +/*! + @brief Instantiates a new ADS1115 class w/appropriate properties +*/ +/**************************************************************************/ +Adafruit_ADS1115::Adafruit_ADS1115(uint8_t i2cAddress) +{ + m_i2cAddress = i2cAddress; + m_conversionDelay = ADS1115_CONVERSIONDELAY; + m_bitShift = 0; + m_gain = GAIN_TWOTHIRDS; /* +/- 6.144V range (limited to VDD +0.3V max!) */ +} + +/**************************************************************************/ +/*! + @brief Sets up the HW (reads coefficients values, etc.) +*/ +/**************************************************************************/ +void Adafruit_ADS1015::begin() { + Wire.begin(); +} + +/**************************************************************************/ +/*! + @brief Sets the gain and input voltage range +*/ +/**************************************************************************/ +void Adafruit_ADS1015::setGain(adsGain_t gain) +{ + m_gain = gain; +} + +/**************************************************************************/ +/*! + @brief Gets a gain and input voltage range +*/ +/**************************************************************************/ +adsGain_t Adafruit_ADS1015::getGain() +{ + return m_gain; +} + +/**************************************************************************/ +/*! + @brief Gets a single-ended ADC reading from the specified channel +*/ +/**************************************************************************/ +uint16_t Adafruit_ADS1015::readADC_SingleEnded(uint8_t channel) { + if (channel > 3) + { + return 0; + } + + // Start with default values + uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val) + ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val) + ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) + ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) + ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default) + ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default) + + // Set PGA/voltage range + config |= m_gain; + + // Set single-ended input channel + switch (channel) + { + case (0): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_0; + break; + case (1): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_1; + break; + case (2): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_2; + break; + case (3): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_3; + break; + } + + // Set 'start single-conversion' bit + config |= ADS1015_REG_CONFIG_OS_SINGLE; + + // Write config register to the ADC + writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config); + // Serial.print("Config");Serial.println(config, HEX); + // Wait for the conversion to complete + delay(m_conversionDelay); + + // Read the conversion results + // Shift 12-bit results right 4 bits for the ADS1015 + return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift; +} + +/**************************************************************************/ +/*! + @brief Reads the conversion results, measuring the voltage + difference between the P (AIN0) and N (AIN1) input. Generates + a signed value since the difference can be either + positive or negative. +*/ +/**************************************************************************/ +int16_t Adafruit_ADS1015::readADC_Differential_0_1() { + // Start with default values + uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val) + ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val) + ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) + ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) + ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default) + ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default) + + // Set PGA/voltage range + config |= m_gain; + + // Set channels + config |= ADS1015_REG_CONFIG_MUX_DIFF_0_1; // AIN0 = P, AIN1 = N + + // Set 'start single-conversion' bit + config |= ADS1015_REG_CONFIG_OS_SINGLE; + + // Write config register to the ADC + writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config); + + // Wait for the conversion to complete + delay(m_conversionDelay); + + // Read the conversion results + uint16_t res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift; + if (m_bitShift == 0) + { + return (int16_t)res; + } + else + { + // Shift 12-bit results right 4 bits for the ADS1015, + // making sure we keep the sign bit intact + if (res > 0x07FF) + { + // negative number - extend the sign to 16th bit + res |= 0xF000; + } + return (int16_t)res; + } +} + +/**************************************************************************/ +/*! + @brief Reads the conversion results, measuring the voltage + difference between the P (AIN2) and N (AIN3) input. Generates + a signed value since the difference can be either + positive or negative. +*/ +/**************************************************************************/ +int16_t Adafruit_ADS1015::readADC_Differential_2_3() { + // Start with default values + uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val) + ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val) + ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) + ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) + ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default) + ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default) + + // Set PGA/voltage range + config |= m_gain; + + // Set channels + config |= ADS1015_REG_CONFIG_MUX_DIFF_2_3; // AIN2 = P, AIN3 = N + + // Set 'start single-conversion' bit + config |= ADS1015_REG_CONFIG_OS_SINGLE; + + // Write config register to the ADC + writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config); + + // Wait for the conversion to complete + delay(m_conversionDelay); + + // Read the conversion results + uint16_t res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift; + if (m_bitShift == 0) + { + return (int16_t)res; + } + else + { + // Shift 12-bit results right 4 bits for the ADS1015, + // making sure we keep the sign bit intact + if (res > 0x07FF) + { + // negative number - extend the sign to 16th bit + res |= 0xF000; + } + return (int16_t)res; + } +} + +/**************************************************************************/ +/*! + @brief Sets up the comparator to operate in basic mode, causing the + ALERT/RDY pin to assert (go from high to low) when the ADC + value exceeds the specified threshold. + + This will also set the ADC in continuous conversion mode. +*/ +/**************************************************************************/ +void Adafruit_ADS1015::startComparator_SingleEnded(uint8_t channel, int16_t threshold) +{ + // Start with default values + uint16_t config = ADS1015_REG_CONFIG_CQUE_1CONV | // Comparator enabled and asserts on 1 match + ADS1015_REG_CONFIG_CLAT_LATCH | // Latching mode + ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) + ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) + ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default) + ADS1015_REG_CONFIG_MODE_CONTIN | // Continuous conversion mode + ADS1015_REG_CONFIG_MODE_CONTIN; // Continuous conversion mode + + // Set PGA/voltage range + config |= m_gain; + + // Set single-ended input channel + switch (channel) + { + case (0): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_0; + break; + case (1): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_1; + break; + case (2): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_2; + break; + case (3): + config |= ADS1015_REG_CONFIG_MUX_SINGLE_3; + break; + } + + // Set the high threshold register + // Shift 12-bit results left 4 bits for the ADS1015 + writeRegister(m_i2cAddress, ADS1015_REG_POINTER_HITHRESH, threshold << m_bitShift); + + // Write config register to the ADC + writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config); +} + +/**************************************************************************/ +/*! + @brief In order to clear the comparator, we need to read the + conversion results. This function reads the last conversion + results without changing the config value. +*/ +/**************************************************************************/ +int16_t Adafruit_ADS1015::getLastConversionResults() +{ + // Wait for the conversion to complete + delay(m_conversionDelay); + + // Read the conversion results + uint16_t res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift; + if (m_bitShift == 0) + { + return (int16_t)res; + } + else + { + // Shift 12-bit results right 4 bits for the ADS1015, + // making sure we keep the sign bit intact + if (res > 0x07FF) + { + // negative number - extend the sign to 16th bit + res |= 0xF000; + } + return (int16_t)res; + } +} + + diff --git a/Weather/Arduino/SwitchDoc/Adafruit_ADS1015.h b/Weather/Arduino/SwitchDoc/Adafruit_ADS1015.h new file mode 100644 index 0000000..7b3b554 --- /dev/null +++ b/Weather/Arduino/SwitchDoc/Adafruit_ADS1015.h @@ -0,0 +1,157 @@ +/**************************************************************************/ +/*! + @file Adafruit_ADS1015.h + @author K. Townsend (Adafruit Industries) + @license BSD (see license.txt) + + This is a library for the Adafruit ADS1015 breakout board + ----> https://www.adafruit.com/products/??? + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + @section HISTORY + + v1.0 - First release + v1.1 - Added ADS1115 support - W. Earl +*/ +/**************************************************************************/ +#ifndef Adafruit_ADS1015_h +#define Adafruit_ADS1015_h + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + + + +/*========================================================================= + I2C ADDRESS/BITS + -----------------------------------------------------------------------*/ + #define ADS1015_ADDRESS (0x48) // 1001 000 (ADDR = GND) +/*=========================================================================*/ + +/*========================================================================= + CONVERSION DELAY (in mS) + -----------------------------------------------------------------------*/ + #define ADS1015_CONVERSIONDELAY (1) + #define ADS1115_CONVERSIONDELAY (8) +/*=========================================================================*/ + +/*========================================================================= + POINTER REGISTER + -----------------------------------------------------------------------*/ + #define ADS1015_REG_POINTER_MASK (0x03) + #define ADS1015_REG_POINTER_CONVERT (0x00) + #define ADS1015_REG_POINTER_CONFIG (0x01) + #define ADS1015_REG_POINTER_LOWTHRESH (0x02) + #define ADS1015_REG_POINTER_HITHRESH (0x03) +/*=========================================================================*/ + +/*========================================================================= + CONFIG REGISTER + -----------------------------------------------------------------------*/ + #define ADS1015_REG_CONFIG_OS_MASK (0x8000) + #define ADS1015_REG_CONFIG_OS_SINGLE (0x8000) // Write: Set to start a single-conversion + #define ADS1015_REG_CONFIG_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress + #define ADS1015_REG_CONFIG_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion + + #define ADS1015_REG_CONFIG_MUX_MASK (0x7000) + #define ADS1015_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default) + #define ADS1015_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3 + #define ADS1015_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3 + #define ADS1015_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3 + #define ADS1015_REG_CONFIG_MUX_SINGLE_0 (0x4000) // Single-ended AIN0 + #define ADS1015_REG_CONFIG_MUX_SINGLE_1 (0x5000) // Single-ended AIN1 + #define ADS1015_REG_CONFIG_MUX_SINGLE_2 (0x6000) // Single-ended AIN2 + #define ADS1015_REG_CONFIG_MUX_SINGLE_3 (0x7000) // Single-ended AIN3 + + #define ADS1015_REG_CONFIG_PGA_MASK (0x0E00) + #define ADS1015_REG_CONFIG_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3 + #define ADS1015_REG_CONFIG_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1 + #define ADS1015_REG_CONFIG_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2 (default) + #define ADS1015_REG_CONFIG_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4 + #define ADS1015_REG_CONFIG_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8 + #define ADS1015_REG_CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16 + + #define ADS1015_REG_CONFIG_MODE_MASK (0x0100) + #define ADS1015_REG_CONFIG_MODE_CONTIN (0x0000) // Continuous conversion mode + #define ADS1015_REG_CONFIG_MODE_SINGLE (0x0100) // Power-down single-shot mode (default) + + #define ADS1015_REG_CONFIG_DR_MASK (0x00E0) + #define ADS1015_REG_CONFIG_DR_128SPS (0x0000) // 128 samples per second + #define ADS1015_REG_CONFIG_DR_250SPS (0x0020) // 250 samples per second + #define ADS1015_REG_CONFIG_DR_490SPS (0x0040) // 490 samples per second + #define ADS1015_REG_CONFIG_DR_920SPS (0x0060) // 920 samples per second + #define ADS1015_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default) + #define ADS1015_REG_CONFIG_DR_2400SPS (0x00A0) // 2400 samples per second + #define ADS1015_REG_CONFIG_DR_3300SPS (0x00C0) // 3300 samples per second + + #define ADS1015_REG_CONFIG_CMODE_MASK (0x0010) + #define ADS1015_REG_CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default) + #define ADS1015_REG_CONFIG_CMODE_WINDOW (0x0010) // Window comparator + + #define ADS1015_REG_CONFIG_CPOL_MASK (0x0008) + #define ADS1015_REG_CONFIG_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default) + #define ADS1015_REG_CONFIG_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active + + #define ADS1015_REG_CONFIG_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted + #define ADS1015_REG_CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default) + #define ADS1015_REG_CONFIG_CLAT_LATCH (0x0004) // Latching comparator + + #define ADS1015_REG_CONFIG_CQUE_MASK (0x0003) + #define ADS1015_REG_CONFIG_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions + #define ADS1015_REG_CONFIG_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions + #define ADS1015_REG_CONFIG_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions + #define ADS1015_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default) +/*=========================================================================*/ + +typedef enum +{ + GAIN_TWOTHIRDS = ADS1015_REG_CONFIG_PGA_6_144V, + GAIN_ONE = ADS1015_REG_CONFIG_PGA_4_096V, + GAIN_TWO = ADS1015_REG_CONFIG_PGA_2_048V, + GAIN_FOUR = ADS1015_REG_CONFIG_PGA_1_024V, + GAIN_EIGHT = ADS1015_REG_CONFIG_PGA_0_512V, + GAIN_SIXTEEN = ADS1015_REG_CONFIG_PGA_0_256V +} adsGain_t; + +class Adafruit_ADS1015 +{ +protected: + // Instance-specific properties + uint8_t m_i2cAddress; + uint8_t m_conversionDelay; + uint8_t m_bitShift; + adsGain_t m_gain; + + public: + Adafruit_ADS1015(uint8_t i2cAddress = ADS1015_ADDRESS); + void begin(void); + uint16_t readADC_SingleEnded(uint8_t channel); + int16_t readADC_Differential_0_1(void); + int16_t readADC_Differential_2_3(void); + void startComparator_SingleEnded(uint8_t channel, int16_t threshold); + int16_t getLastConversionResults(); + void setGain(adsGain_t gain); + adsGain_t getGain(void); + + private: +}; + +// Derive from ADS1105 & override construction to set properties +class Adafruit_ADS1115 : public Adafruit_ADS1015 +{ + public: + Adafruit_ADS1115(uint8_t i2cAddress = ADS1015_ADDRESS); + + private: +}; + + +#endif diff --git a/Weather/Arduino/SwitchDoc/SDL_Weather_80422.cpp b/Weather/Arduino/SwitchDoc/SDL_Weather_80422.cpp new file mode 100644 index 0000000..f53dd44 --- /dev/null +++ b/Weather/Arduino/SwitchDoc/SDL_Weather_80422.cpp @@ -0,0 +1,398 @@ +/* + SDL_Weather_80422.cpp - Library for SwitchDoc Labs WeatherRack. + SparkFun Weather Station Meters + Argent Data Systems + Created by SwitchDoc Labs July 27, 2014. + Released into the public domain. + Version 1.1 - updated constants to suppport 3.3V + Version 1.6 - Support for ADS1015 in WeatherPiArduino Board February 7, 2015 +*/ + +#include "Arduino.h" + +#include +#include "SDL_Weather_80422.h" + + +#include "Adafruit_ADS1015.h" + + +Adafruit_ADS1015 ads1015; + + + +//#define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts +//#define NO_PORTD_PINCHANGES // to indicate that port d will not be used for pin change interrupts +// +//#include "PinChangeInt.h" + +// private functions + + +boolean fuzzyCompare(float compareValue, float value) +{ + #define VARYVALUE 0.05 + + /*Serial.print("compareValue="); + Serial.print(compareValue); + Serial.print("value="); + Serial.print(value); + Serial.print(" ");*/ + + if ( (value > (compareValue * (1.0-VARYVALUE))) && (value < (compareValue *(1.0+VARYVALUE))) ) + { + //Serial.println("true"); + return true; + + } + //Serial.println("false"); + return false; + + + +} + +float voltageToDegrees(float value, float defaultWindDirection) +{ + + // Note: The original documentation for the wind vane says 16 positions. Typically only recieve 8 positions. And 315 degrees was wrong. + + // For 5V , use 1.0. For 3.3V (or for ADS1015 or ADS1116) use 0.66, For Grove Base Shield at 3.3V (required for WeatherPiArdunino but not Weather Board) use 0.462 +#define ADJUST3OR5 0.66 +#define PowerVoltage 5.0 + + + if (fuzzyCompare(3.84 * ADJUST3OR5 , value)) + return 0.0; + + if (fuzzyCompare(1.98 * ADJUST3OR5, value)) + return 22.5; + + if (fuzzyCompare(2.25 * ADJUST3OR5, value)) + return 45; + + if (fuzzyCompare(0.41 * ADJUST3OR5, value)) + return 67.5; + + if (fuzzyCompare(0.45 * ADJUST3OR5, value)) + return 90.0; + + if (fuzzyCompare(0.32 * ADJUST3OR5, value)) + return 112.5; + + if (fuzzyCompare(0.90 * ADJUST3OR5, value)) + return 135.0; + + if (fuzzyCompare(0.62 * ADJUST3OR5, value)) + return 157.5; + + if (fuzzyCompare(1.40 * ADJUST3OR5, value)) + return 180; + + if (fuzzyCompare(1.19 * ADJUST3OR5, value)) + return 202.5; + + if (fuzzyCompare(3.08 * ADJUST3OR5, value)) + return 225; + + if (fuzzyCompare(2.93 * ADJUST3OR5, value)) + return 247.5; + + if (fuzzyCompare(4.62 * ADJUST3OR5, value)) + return 270.0; + + if (fuzzyCompare(4.04 * ADJUST3OR5, value)) + return 292.5; + + if (fuzzyCompare(4.34 * ADJUST3OR5, value)) // chart in documentation wrong + return 315.0; + + if (fuzzyCompare(3.43 * ADJUST3OR5, value)) + return 337.5; + + //Serial.print(" FAIL WIND DIRECTION"); + return defaultWindDirection; // return previous value if not found + + +} + + + +// Interrupt routines +// for mega, have to use Port B - only Port B works. +/* +Interrupt 4 - Pin 19 +Interrupt 5 - Pin 18 + +*/ + + + + +unsigned long lastWindTime; + + +void serviceInterruptAnem() +{ + unsigned long currentTime= (unsigned long)(micros()-lastWindTime); + + lastWindTime=micros(); + if(currentTime>1000) // debounce + { + SDL_Weather_80422::_currentWindCount++; + if(currentTime500) // debounce + { + SDL_Weather_80422::_currentRainCount++; +// interrupt_count[19]++; + if(currentTime= compareValue) + { + // sample time exceeded, calculate currentWindSpeed + float _timeSpan; + // _timeSpan = (unsigned long)(micros() - _startSampleTime); + _timeSpan = (micros() - _startSampleTime); + + _currentWindSpeed = ((float)_currentWindCount/(_timeSpan)) * WIND_FACTOR*1000000; + + _currentWindCount = 0; + + _startSampleTime = micros(); + + + } + else + { + //Serial.println("NOT Triggered"); + //Serial.print("time = "); + //Serial.println(micros() - _startSampleTime); + // if not, then return last wind speed + + } + + + + return _currentWindSpeed; +} + +void SDL_Weather_80422::setWindMode(int selectedMode, float sampleTime) // time in seconds +{ + + _sampleTime = sampleTime; + _selectedMode = selectedMode; + + if (_selectedMode == SDL_MODE_SAMPLE) + { + startWindSample(_sampleTime); + } + + + +} diff --git a/Weather/Arduino/SwitchDoc/SDL_Weather_80422.h b/Weather/Arduino/SwitchDoc/SDL_Weather_80422.h new file mode 100644 index 0000000..acad80d --- /dev/null +++ b/Weather/Arduino/SwitchDoc/SDL_Weather_80422.h @@ -0,0 +1,84 @@ +/* + SDL_Weather_80422.h - Library for Weather Sensor + Designed for: SwitchDoc Labs WeatherRack www.switchdoc.com + Argent Data Systems + SparkFun Weather Station Meters + Created by SwitchDoc Labs July 27, 2014. + Released into the public domain. + Version 1.1 - updated constants to suppport 3.3V + Version 1.6 - Support for ADS1015 in WeatherPiArduino Board February 7, 2015 +*/ +#ifndef SDL_Weather_80422_h +#define SDL_Weather_80422_h + +#define SDL_MODE_INTERNAL_AD 0 +#define SDL_MODE_I2C_ADS1015 1 + +// sample mode means return immediately. THe wind speed is averaged at sampleTime or when you ask, whichever is longer +#define SDL_MODE_SAMPLE 0 +// Delay mode means to wait for sampleTime and the average after that time. +#define SDL_MODE_DELAY 1 + +// Note: If you are using the SDL_MODE_I2C_ADS105, then A0 port is not used. Hardwired to ADC-1 on ADS1015 + + +#include "Arduino.h" + + +extern "C" void serviceInterruptAnem(void) __attribute__ ((signal)); +extern "C" void serviceInterruptRain(void) __attribute__ ((signal)); +class SDL_Weather_80422 +{ + public: + SDL_Weather_80422(int pinAnem, int pinRain, int intAnem, int intRain, int ADChannel, int ADMode); + + float get_current_rain_total(); + float current_wind_speed(); + float current_wind_direction(); + float current_wind_direction_voltage(); + float get_wind_gust(); + void reset_rain_total(); + void reset_wind_gust(); + + void setWindMode(int selectedMode, float sampleTime); // time in seconds + + + static unsigned long _shortestWindTime; + static long _currentRainCount; + static long _currentWindCount; + + + + float accessInternalCurrentWindDirection(); + + friend void serviceInterruptAnem(); + friend void serviceInterruptRain(); + + private: + + + int _pinAnem; + int _pinRain; + int _intAnem; + int _intRain; + int _ADChannel; + int _ADMode; + float _sampleTime; + int _selectedMode; + + + + + unsigned long _startSampleTime; + + + float _currentWindSpeed; + + float _currentWindDirection; + + void startWindSample(float sampleTime); + float get_current_wind_speed_when_sampling(); +}; + +#endif + diff --git a/Weather/Arduino/SwitchDoc/SwitchDoc.ino b/Weather/Arduino/SwitchDoc/SwitchDoc.ino new file mode 100644 index 0000000..ffc5503 --- /dev/null +++ b/Weather/Arduino/SwitchDoc/SwitchDoc.ino @@ -0,0 +1,146 @@ +#include "elapsedMillis.h" + +#define ReadInterval 1000 + +// Weather +#define WpinAnem 3 +#define WpinRain 2 + +#define WintAnem 1 +#define WintRain 0 + +#include "SDL_Weather_80422.h" +SDL_Weather_80422 weatherStation(WpinAnem, WpinRain, WintAnem, WintRain, A0, SDL_MODE_INTERNAL_AD); + +// BMP280 Pressure sensor +#include +Adafruit_BMP280 bmp280; + +// TSL2591 Light sensor +#include "Adafruit_TSL2591.h" +Adafruit_TSL2591 tsl2591 = Adafruit_TSL2591(); + +elapsedMillis timeElapsed; + +bool bmp280_Found; +bool tsl2591_Found; + +void setup() +{ + Serial.begin(115200); + + Serial.println("Board starting"); + + bmp280_Found = false; + tsl2591_Found = false; + + randomSeed(analogRead(0)); + + weatherStation.setWindMode(SDL_MODE_SAMPLE, 5.0); + + timeElapsed = ReadInterval; + + char buffer[50]; + + bmp280_Found = bmp280.begin(); + + sprintf(buffer, "BMP280 present: %s", bmp280_Found ? "true" : "false"); + Serial.println(buffer); + + tsl2591_Found = tsl2591.begin(); + + sprintf(buffer, "TSL2591 present: %s", tsl2591_Found ? "true" : "false"); + Serial.println(buffer); +} + +void loop() +{ + if (timeElapsed > ReadInterval) + { + timeElapsed = 0; + + float currentWindSpeed = weatherStation.current_wind_speed() / 1.6; + float currentWindGust = weatherStation.get_wind_gust() / 1.6; + float currentRain = weatherStation.get_current_rain_total() * 0.03937; + + float bmp280_Temperature = 0.0; + float bmp280_Pressure = 0.0; + + if (bmp280_Found) + { + bmp280_Pressure = bmp280.readPressure(); + bmp280_Temperature = bmp280.readTemperature(); + } + + uint32_t tsl2591_Luminosity = 0; + uint16_t tsl2591_IR = 0; + uint16_t tsl2591_Full = 0; + + if (tsl2591_Found) + { + tsl2591_Luminosity = tsl2591.getFullLuminosity(); + tsl2591_IR = tsl2591_Luminosity >> 16; + tsl2591_Full = tsl2591_Luminosity & 0xFFFF; + } + + char returnString[200]; + returnString[0] = '\0'; + + char tempString[15]; + + tempString[0] = '\0'; + strcat(returnString, "wind_speed="); + dtostrf(currentWindSpeed, 0, 2, tempString); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "wind_gust="); + dtostrf(currentWindGust, 0, 2, tempString); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "wind_dir="); + dtostrf(weatherStation.current_wind_direction(), 0, 2, tempString); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "rain="); + dtostrf(currentRain, 0, 2, tempString); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "internal_temp="); + dtostrf(bmp280_Temperature, 0, 2, tempString); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "pressure="); + dtostrf(bmp280_Pressure / 100, 0, 2, tempString); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "ir="); + itoa(tsl2591_IR, tempString, 10); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "visible="); + itoa(tsl2591_Full - tsl2591_IR, tempString, 10); + strcat(returnString, tempString); + strcat(returnString, ","); + + tempString[0] = '\0'; + strcat(returnString, "lux="); + dtostrf(tsl2591.calculateLux(tsl2591_Full, tsl2591_IR), 0, 2, tempString); + strcat(returnString, tempString); + + Serial.println(returnString); + } +} diff --git a/Weather/Arduino/SwitchDoc/elapsedMillis.h b/Weather/Arduino/SwitchDoc/elapsedMillis.h new file mode 100644 index 0000000..7033d5d --- /dev/null +++ b/Weather/Arduino/SwitchDoc/elapsedMillis.h @@ -0,0 +1,82 @@ +/* Elapsed time types - for easy-to-use measurements of elapsed time + * http://www.pjrc.com/teensy/ + * Copyright (c) 2011 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef elapsedMillis_h +#define elapsedMillis_h +#ifdef __cplusplus + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +class elapsedMillis +{ +private: + unsigned long ms; +public: + elapsedMillis(void) { ms = millis(); } + elapsedMillis(unsigned long val) { ms = millis() - val; } + elapsedMillis(const elapsedMillis &orig) { ms = orig.ms; } + operator unsigned long () const { return millis() - ms; } + elapsedMillis & operator = (const elapsedMillis &rhs) { ms = rhs.ms; return *this; } + elapsedMillis & operator = (unsigned long val) { ms = millis() - val; return *this; } + elapsedMillis & operator -= (unsigned long val) { ms += val ; return *this; } + elapsedMillis & operator += (unsigned long val) { ms -= val ; return *this; } + elapsedMillis operator - (int val) const { elapsedMillis r(*this); r.ms += val; return r; } + elapsedMillis operator - (unsigned int val) const { elapsedMillis r(*this); r.ms += val; return r; } + elapsedMillis operator - (long val) const { elapsedMillis r(*this); r.ms += val; return r; } + elapsedMillis operator - (unsigned long val) const { elapsedMillis r(*this); r.ms += val; return r; } + elapsedMillis operator + (int val) const { elapsedMillis r(*this); r.ms -= val; return r; } + elapsedMillis operator + (unsigned int val) const { elapsedMillis r(*this); r.ms -= val; return r; } + elapsedMillis operator + (long val) const { elapsedMillis r(*this); r.ms -= val; return r; } + elapsedMillis operator + (unsigned long val) const { elapsedMillis r(*this); r.ms -= val; return r; } +}; + +class elapsedMicros +{ +private: + unsigned long us; +public: + elapsedMicros(void) { us = micros(); } + elapsedMicros(unsigned long val) { us = micros() - val; } + elapsedMicros(const elapsedMicros &orig) { us = orig.us; } + operator unsigned long () const { return micros() - us; } + elapsedMicros & operator = (const elapsedMicros &rhs) { us = rhs.us; return *this; } + elapsedMicros & operator = (unsigned long val) { us = micros() - val; return *this; } + elapsedMicros & operator -= (unsigned long val) { us += val ; return *this; } + elapsedMicros & operator += (unsigned long val) { us -= val ; return *this; } + elapsedMicros operator - (int val) const { elapsedMicros r(*this); r.us += val; return r; } + elapsedMicros operator - (unsigned int val) const { elapsedMicros r(*this); r.us += val; return r; } + elapsedMicros operator - (long val) const { elapsedMicros r(*this); r.us += val; return r; } + elapsedMicros operator - (unsigned long val) const { elapsedMicros r(*this); r.us += val; return r; } + elapsedMicros operator + (int val) const { elapsedMicros r(*this); r.us -= val; return r; } + elapsedMicros operator + (unsigned int val) const { elapsedMicros r(*this); r.us -= val; return r; } + elapsedMicros operator + (long val) const { elapsedMicros r(*this); r.us -= val; return r; } + elapsedMicros operator + (unsigned long val) const { elapsedMicros r(*this); r.us -= val; return r; } +}; + +#endif // __cplusplus +#endif // elapsedMillis_h + diff --git a/Weather/Arduino/SwitchDoc/makefile b/Weather/Arduino/SwitchDoc/makefile new file mode 100644 index 0000000..1ae88dc --- /dev/null +++ b/Weather/Arduino/SwitchDoc/makefile @@ -0,0 +1,14 @@ +weather: + mkdir -p bin/ + arduino-cli compile --fqbn arduino:avr:uno --output-dir bin + +install: +# kubectl scale --replicas=0 --namespace=home-monitor deployment/weather-serial-reader + arduino-cli upload --fqbn arduino:avr:uno -p /dev/ttyACM0 --input-dir bin +# kubectl scale --replicas=1 --namespace=home-monitor deployment/weather-serial-reader + +debug: + minicom -b 115200 -D /dev/ttyACM0 + +clean: + rm -rf bin/ diff --git a/Weather/Arduino/makefile b/Weather/Arduino/makefile deleted file mode 100644 index 2c19aec..0000000 --- a/Weather/Arduino/makefile +++ /dev/null @@ -1,11 +0,0 @@ -weather: - mkdir -p bin/ - arduino-cli compile -b arduino:avr:uno Weather.ino -o bin/Weather - -install: - kubectl scale --replicas=0 --namespace=home-monitor deployment/weather-serial-reader - arduino-cli upload -b arduino:avr:uno -p /dev/ttyACM0 -i bin/Weather - kubectl scale --replicas=1 --namespace=home-monitor deployment/weather-serial-reader - -clean: - rm -rf bin/ \ No newline at end of file