Library for interfacing to Sparkfun Weather Meters.
Dependents: WeatherStation Deneme testgeneral ... more
Revision 0:457832d52954, committed 2012-02-25
- Comitter:
- AdamGreen
- Date:
- Sat Feb 25 03:23:51 2012 +0000
- Commit message:
Changed in this revision
diff -r 000000000000 -r 457832d52954 Anemometer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Anemometer.cpp Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,60 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Implementation of class to interface for anemometer sensor with Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#include <mbed.h> +#include "Anemometer.h" + + +#define REV_PER_SECOND_TO_KMPH 2.4f + + +CAnemometer::CAnemometer(PinName AnemometerPin, unsigned int IgnoreTimeForDebounceInMicroSeconds) + : CDebouncedFallingEdgeCounter(AnemometerPin, IgnoreTimeForDebounceInMicroSeconds) +{ + m_CurrentWindSpeed = 0.0f; + ResetMaximumWindSpeed(); + m_OneSecondTicker.attach_us<CAnemometer>(this, &CAnemometer::OneSecondTickerISR, 1000000); +} + + +void CAnemometer::ResetMaximumWindSpeed() +{ + m_MaximumWindSpeed = m_CurrentWindSpeed; +} + + +void CAnemometer::OneSecondTickerISR() +{ + unsigned int GetCurrentCount = GetCountAndZero(); + + m_CurrentWindSpeed = (float)GetCurrentCount * REV_PER_SECOND_TO_KMPH; + if (m_CurrentWindSpeed > m_MaximumWindSpeed) + { + m_MaximumWindSpeed = m_CurrentWindSpeed; + } +} + +float CAnemometer::GetCurrentWindSpeed() +{ + return m_CurrentWindSpeed; +} + + +float CAnemometer::GetMaximumWindSpeed() +{ + return m_MaximumWindSpeed; +}
diff -r 000000000000 -r 457832d52954 Anemometer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Anemometer.h Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,48 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Header file for class to interface with anemometer sensor of Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#ifndef _ANEMOMETER_H_ +#define _ANEMOMETER_H_ + +#include "DebouncedFallingEdgeCounter.h" + + +namespace AFP +{ + +class CAnemometer : protected CDebouncedFallingEdgeCounter +{ +protected: + Ticker m_OneSecondTicker; + float m_CurrentWindSpeed; + float m_MaximumWindSpeed; + +public: + CAnemometer(PinName AnemometerPin, unsigned int IgnoreTimeForDebounceInMicroSeconds = 1000); + + float GetCurrentWindSpeed(); + float GetMaximumWindSpeed(); + void ResetMaximumWindSpeed(); + +protected: + void OneSecondTickerISR(); +}; + +} // namespace AFP +using namespace AFP; + +#endif // _ANEMOMETER_H_
diff -r 000000000000 -r 457832d52954 DebouncedFallingEdgeCounter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DebouncedFallingEdgeCounter.cpp Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,100 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Implementation for wrapper class of InterruptIn used for counting falling edge + events with specified hold off time for the purpose of debouncing. +*/ +#include <mbed.h> +#include "DebouncedFallingEdgeCounter.h" + + +CDebouncedFallingEdgeCounter::CDebouncedFallingEdgeCounter(PinName InterruptInPin, unsigned int IgnoreTimeForDebounceInMicroSeconds) + : m_FallingEdgeInterruptIn(InterruptInPin) +{ + m_Timer.start(); + m_IgnoreTimeForDebounce = IgnoreTimeForDebounceInMicroSeconds; + InitLastFallingEdgeTime(); + + ZeroCount(); + + m_FallingEdgeInterruptIn.mode(PullUp); + m_FallingEdgeInterruptIn.fall<CDebouncedFallingEdgeCounter>(this, &CDebouncedFallingEdgeCounter::FallingEdgeISR); +} + + +void CDebouncedFallingEdgeCounter::InitLastFallingEdgeTime() +{ + InitLastFallingEdgeTime((unsigned int)m_Timer.read_us()); +} + + +void CDebouncedFallingEdgeCounter::InitLastFallingEdgeTime(unsigned int CurrentTime) +{ + m_LastFallingEdgeTime = CurrentTime - m_IgnoreTimeForDebounce; +} + + +void CDebouncedFallingEdgeCounter::FallingEdgeISR() +{ + // UNDONE: Can I just use whatever timer the m_Timer uses under the covers? + unsigned int CurrentTime = (unsigned int)m_Timer.read_us(); + + if (TimeSinceLastFallingEdge(CurrentTime) >= m_IgnoreTimeForDebounce) + { + m_FallingEdgeCount++; + m_LastFallingEdgeTime = CurrentTime; + } +} + + +unsigned int CDebouncedFallingEdgeCounter::TimeSinceLastFallingEdge(unsigned int CurrentTime) +{ + return CurrentTime - m_LastFallingEdgeTime; +} + + +unsigned int CDebouncedFallingEdgeCounter::GetCountAndZero() +{ + unsigned int CurrentCount; + + CurrentCount = GetCount(); + ZeroCount(); + return CurrentCount; +} + + +unsigned int CDebouncedFallingEdgeCounter::GetCount() +{ + RefreshTimers(); + + return m_FallingEdgeCount; +} + + +void CDebouncedFallingEdgeCounter::ZeroCount() +{ + m_FallingEdgeCount = 0; +} + + +void CDebouncedFallingEdgeCounter::RefreshTimers() +{ + unsigned int CurrentTime = (unsigned int)m_Timer.read_us(); + + if (TimeSinceLastFallingEdge(CurrentTime) > m_IgnoreTimeForDebounce) + { + // Protect from timer overflow. + InitLastFallingEdgeTime(CurrentTime); + } +}
diff -r 000000000000 -r 457832d52954 DebouncedFallingEdgeCounter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DebouncedFallingEdgeCounter.h Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,52 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Header file for wrapper class of InterruptIn used for counting falling edge + events with specified hold off time for the purpose of debouncing. +*/ +#ifndef _DEBOUNCED_FALLING_EDGE_COUNT_H_ +#define _DEBOUNCED_FALLING_EDGE_COUNT_H_ + +namespace AFP +{ + +class CDebouncedFallingEdgeCounter +{ +protected: + InterruptIn m_FallingEdgeInterruptIn; + // UNDONE: Run for over 30 minutes and make sure that this rolls over as expected. + Timer m_Timer; + unsigned int m_IgnoreTimeForDebounce; + unsigned int m_LastFallingEdgeTime; + unsigned int m_FallingEdgeCount; + +public: + CDebouncedFallingEdgeCounter(PinName InterruptInPin, unsigned int IgnoreTimeForDebounceInMicroSeconds); + + unsigned int GetCountAndZero(); + void ZeroCount(); + unsigned int GetCount(); + +protected: + void InitLastFallingEdgeTime(); + void InitLastFallingEdgeTime(unsigned int CurrentTime); + void FallingEdgeISR(); + void RefreshTimers(); + unsigned int TimeSinceLastFallingEdge(unsigned int CurrentTime); +}; + +} // namespace AFP +using namespace AFP; + +#endif // _DEBOUNCED_FALLING_EDGE_COUNT_H_
diff -r 000000000000 -r 457832d52954 RainGauge.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RainGauge.h Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,52 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Header file for class to interface with the rain gauge sensor of the Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#ifndef _RAIN_GAUGE_H_ +#define _RAIN_GAUGE_H_ + +#include "DebouncedFallingEdgeCounter.h" + + +#define MILLIMETERS_OF_RAIN_PER_COUNT 0.2794f + + +namespace AFP +{ + +class CRainGauge : protected CDebouncedFallingEdgeCounter +{ +public: + CRainGauge(PinName RainGaugePin, unsigned int IgnoreTimeForDebounceInMicroSeconds = 1000) + : CDebouncedFallingEdgeCounter(RainGaugePin, IgnoreTimeForDebounceInMicroSeconds) + { + } + + void Reset() + { + ZeroCount(); + } + + float GetRainfall() + { + return (float)GetCount() * MILLIMETERS_OF_RAIN_PER_COUNT; + } +}; + +} // namespace AFP +using namespace AFP; + +#endif // _RAIN_GAUGE_H_
diff -r 000000000000 -r 457832d52954 WeatherMeters.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WeatherMeters.cpp Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,59 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Implementation of class to interface with Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#include <mbed.h> +#include "WeatherMeters.h" + + +CWeatherMeters::CWeatherMeters(PinName AnemometerPin, + PinName RainGaugePin, + PinName WindVanePin, + float WindVaneSeriesResistance) : m_Anemometer(AnemometerPin), + m_RainGauge(RainGaugePin), + m_WindVane(WindVanePin, WindVaneSeriesResistance) +{ +} + + +void CWeatherMeters::GetMeasurements(SMeasurements* pMeasurements) +{ + pMeasurements->WindDirectionString = m_WindVane.GetWindDirectionAsString(); + pMeasurements->WindDirectionAngle = m_WindVane.GetWindDirectionAsAngle(); + pMeasurements->WindSpeed = m_Anemometer.GetCurrentWindSpeed(); + pMeasurements->MaximumWindSpeed = m_Anemometer.GetMaximumWindSpeed(); + pMeasurements->Rainfall = m_RainGauge.GetRainfall(); +} + + +void CWeatherMeters::Reset() +{ + ResetRainfall(); + ResetMaximumWindSpeed(); +} + + +void CWeatherMeters::ResetRainfall() +{ + m_RainGauge.Reset(); +} + + +void CWeatherMeters::ResetMaximumWindSpeed() +{ + m_Anemometer.ResetMaximumWindSpeed(); +} +
diff -r 000000000000 -r 457832d52954 WeatherMeters.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WeatherMeters.h Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,130 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Header file for class to interface with Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#ifndef _WEATHER_METERS_H_ +#define _WEATHER_METERS_H_ + +#include "WindVane.h" +#include "RainGauge.h" +#include "Anemometer.h" + + +namespace AFP +{ + +/** A class to interface with the Sparkfun Weather Meters. + http://www.sparkfun.com/products/8942 + + This set of weather meters from Sparkfun includes anemometer (wind speed), + wind vane, and rain gauge. All of the sensors use reed switches so that + the electronics can detect motion/location in the sensor hardware via + magnets placed in the sensors without actually exposing the electonic + switches themselves to the elements. A reed switch closes as the + anemometer spins and the rain gauge empties. The wind vane includes + 8 reed switches, each with a different valued resistor attached so that + the voltage will vary depending on where the magnet in the vane is + located. + * Example: + * @code +#include <mbed.h> +#include "WeatherMeters.h" + +int main() +{ + CWeatherMeters WeatherMeters(p9, p10, p15); + for (;;) + { + CWeatherMeters::SMeasurements Measurements; + + WeatherMeters.GetMeasurements(&Measurements); + + printf("Direction: %s\n", Measurements.WindDirectionString); + printf("Depth: %f\n",Measurements.Rainfall); + printf("Current speed: %f\n", Measurements.WindSpeed); + printf("Maximum speed: %f\n", Measurements.MaximumWindSpeed); + + wait(1.0f); + } +} + * @endcode + */ +class CWeatherMeters +{ +protected: + CAnemometer m_Anemometer; + CRainGauge m_RainGauge; + CWindVane m_WindVane; + +public: + /** A structure in which the current measurements registered by the weather + meters are returned from the GetMeasurements() method. + */ + struct SMeasurements + { + const char* WindDirectionString; /**< String representing current wind direction. Example: "North" */ + float WindDirectionAngle; /**< Wind direction in degrees from north. */ + float WindSpeed; /**< Current wind speed in km/hour. */ + float MaximumWindSpeed; /**< Maximum wind speed measured since last reset. Measured in km/hour. */ + float Rainfall; /**< Amount of rainfall since last reset. Measured in mm. */ + }; + + /** Create a CWeatherMeters object, binds it to the specified input pins, + and initializes the required interrupt handlers. + + @param AnemometerPin The mbed pin which is connected to the anemometer + sensor. Must be a pin on which the mbed supports InterruptIn. + @param RainGauagePin The mbed pin which is connected to the rain gauge + sensor. Must be a pin on which the mbed supports InterruptIn. + @param WindVanePin The mbed pin which is connected to the wind vane + sensor. Must be a pin on which the mbed supports AnalogIn. + @param WindVaneSeriesResistance The value of the resistance which is + in series with the wind vane sensor and along with the + varying resistance of the wind vane sensor itself, acts as a + voltage divider. + */ + CWeatherMeters(PinName AnemometerPin, + PinName RainGaugePin, + PinName WindVanePin, + float WindVaneSeriesResistance = 10000.0f); + + /** Gets current weather meter measurements. + + NOTE: Should call this method on a regular basis (every 15 minutes or + less) to keep internal timers from overflowing. + + @param pMeasurements points to the measurement structure to be filled in + with the current measurement from the sensors. The historical + values in this structure such as rainfall and maximum wind + speed can be reset by calls to ResetRainfall(), + ResetMaximumWindSpeed(), and Reset(). + */ + void GetMeasurements(SMeasurements* pMeasurements); + + /** Resets all historical measurements: rainfall and maximum wind speed. */ + void Reset(); + + /** Resets the cumulative rainfall measurement. */ + void ResetRainfall(); + + /** Resets the maximum wind speed measurement. */ + void ResetMaximumWindSpeed(); +}; + +} // namespace AFP +using namespace AFP; + +#endif // _WEATHER_METERS_H_
diff -r 000000000000 -r 457832d52954 WindVane.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WindVane.cpp Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,96 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Declaration of class to interface with wind vane sensor Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#include <mbed.h> +#include "WindVane.h" + + +#define REV_PER_SECOND_TO_KMPH 2.4f +#define PARALLEL_R(R1, R2) (((R1) * (R2)) / ((R1) + (R2))) +#define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0])) + +struct SDescription +{ + const char* DirectionString; + float DirectionAngle; + float SensorResistance; +}; + + +static SDescription g_WindVaneDescriptionTable[16] = { + { "North", 0.0f, 33.0f * 1000.0f }, + { "North North East", 22.5f, PARALLEL_R(33.0f * 1000.0f, 8.2f * 1000.0f) }, + { "North East", 45.0f, 8.2f * 1000.0f }, + { "East North East", 67.5f, PARALLEL_R(8.2f * 1000.0f, 1000.0f) }, + { "East", 90.0f, 1000.0f }, + { "East South East", 112.5f, PARALLEL_R(1000.0f, 2.2f * 1000.0f) }, + { "South East", 135.0f, 2.2f * 1000.0f }, + { "South South East", 157.5f, PARALLEL_R(2.2f * 1000.0f, 3.9f * 1000.0f) }, + { "South", 180.0f, 3.9f * 1000.0f }, + { "South South West", 202.5f, PARALLEL_R(3.9f * 1000.0f, 16.0f * 1000.0f) }, + { "South West", 225.0f, 16.0f * 1000.0f }, + { "West South West", 247.5f, PARALLEL_R(16.0f * 1000.0f, 120.0f * 1000.0f) }, + { "West", 270.0f, 120.0f * 1000.0f }, + { "West North West", 292.5f, PARALLEL_R(120.0f * 1000.0f, 64.9f * 1000.0f) }, + { "North West", 315.0f, 64.9f * 1000.0f }, + { "North North West", 337.5f, PARALLEL_R(64.9f * 1000.0f, 33.0f * 1000.0f) } +}; + + +CWindVane::CWindVane(PinName WindVanePin, float WindVaneSeriesResistance) + : m_WindVaneAnalogIn(WindVanePin) +{ + for (size_t i = 0 ; i < ARRAY_SIZE(g_WindVaneDescriptionTable) ; i++) + { + SDescription* pDescription = &g_WindVaneDescriptionTable[i]; + + m_WindVaneVoltageTable[i] = pDescription->SensorResistance / + (pDescription->SensorResistance + WindVaneSeriesResistance); + } +} + +const char* CWindVane::GetWindDirectionAsString() +{ + return g_WindVaneDescriptionTable[DetermineWindDirectionIndex()].DirectionString; +} + +float CWindVane::GetWindDirectionAsAngle() +{ + return g_WindVaneDescriptionTable[DetermineWindDirectionIndex()].DirectionAngle; +} + +size_t CWindVane::DetermineWindDirectionIndex() +{ + float WindVaneSensorVoltage = m_WindVaneAnalogIn.read(); + + // Default to the first entry being closest. + size_t ClosestIndex = 0; + float ClosestDelta = fabs(m_WindVaneVoltageTable[0] - WindVaneSensorVoltage); + + // Walk the rest of the entries to see if there is another which is closer. + for (size_t i = 1 ; i < ARRAY_SIZE(m_WindVaneVoltageTable) ; i++) + { + float Delta = fabs(m_WindVaneVoltageTable[i] - WindVaneSensorVoltage); + if (Delta < ClosestDelta) + { + ClosestDelta = Delta; + ClosestIndex = i; + } + } + + return ClosestIndex; +}
diff -r 000000000000 -r 457832d52954 WindVane.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WindVane.h Sat Feb 25 03:23:51 2012 +0000 @@ -0,0 +1,43 @@ +/* Copyright 2012 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Implementation of class to interface with wind vane sensor Sparkfun Weather Meters: + http://www.sparkfun.com/products/8942 +*/ +#ifndef _WIND_VANE_H_ +#define _WIND_VANE_H_ + +namespace AFP +{ + +class CWindVane +{ +protected: + AnalogIn m_WindVaneAnalogIn; + float m_WindVaneVoltageTable[16]; + +public: + CWindVane(PinName WindVanePin, float WindVaneSeriesResistance = 10000.0f); + + const char* GetWindDirectionAsString(); + float GetWindDirectionAsAngle(); + +protected: + size_t DetermineWindDirectionIndex(); +}; + +} // namespace AFP +using namespace AFP; + +#endif // _WIND_VANE_H_