-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathWeatherStationSlave.ino
186 lines (156 loc) · 5.69 KB
/
WeatherStationSlave.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* Weather Station Slave
* PaulRB
* March 2016
* For ATTiny85 @1MHz, BOD disabled
* ATTiny core used: https://github.com/SpenceKonde/ATTinyCore
* Current consumption ~0.5mA
*/
#include <avr/sleep.h>
#define WIND_DIR_SENSOR A3
#define RAIN_SENSOR 4
#define WIND_SPEED_SENSOR 1
#define SENSOR_ENABLE 2
#define SERIAL_OUT 0
#define WIND_GUST_PERIOD 6000UL
#define COMPASS_DIRECTIONS 16
//long windDirTot = 0;
//long windDirCount = 0;
long windDirTot[COMPASS_DIRECTIONS];
unsigned int maxWindGustCount = 0;
unsigned int windSpeedCount = 0;
unsigned int rainCount = 0;
//long windDirPrev = 0;
unsigned int windGustCount = 0;
byte windSpeedEdgeCount = 0;
int prevWindSpeedSensor = LOW;
int prevRainSensor = LOW;
unsigned long lastWindGustTime;
unsigned long lastReportTime;
const int reading[COMPASS_DIRECTIONS] = {147, 172, 208, 281, 368, 437, 531, 624, 710, 780, 817, 870, 909, 938, 970, 1023};
const int compass[COMPASS_DIRECTIONS] = {112, 67, 90, 157, 135, 202, 180, 22, 45, 247, 225, 337, 0, 292, 315, 270};
void setup() {
// Enable various power-savings
bitSet(PRR, PRTIM1); // power-off Timer 1
bitSet(PRR, PRADC); // power-off ADC
bitSet(PRR, PRUSI); // disable USI
bitClear(ADCSRA, ADEN); // Disable ADC
set_sleep_mode(SLEEP_MODE_IDLE);
//pinMode(SERIAL_OUT, INPUT_PULLUP); // not needed, Wemos D3 has built-in pull-up
}
void loop() {
unsigned long timeNow = millis();
// Check for request from master
if (digitalRead(SERIAL_OUT) == LOW) {
// Time the length of the low pulse
unsigned long startTime = millis();
while (digitalRead(SERIAL_OUT) == LOW);
unsigned long endTime = millis();
// Was the low pulse long enough?
if (endTime - startTime >= 8) {
//Check that the line is high & stable
startTime = endTime;
endTime += 10;
while (digitalRead(SERIAL_OUT) == HIGH && endTime >= millis());
// Has line been high & stable ?
if (millis() > endTime) {
// Find most common wind direction over the reporting period
long maxWindDirTot = 0;
byte maxWindDirIndex = 0;
for (byte i = 0; i < COMPASS_DIRECTIONS; i++) {
if (windDirTot[i] > maxWindDirTot) {
maxWindDirTot = windDirTot[i];
maxWindDirIndex = i;
}
//Reset for next reporting period
windDirTot[i] = 0;
}
int windDir = compass[maxWindDirIndex];
// Calculate average wind direction over the reporting period
//int windDir;
//if (windDirCount > 0) windDir = windDirTot / windDirCount; else windDir = 0;
//while (windDir >= 360) windDir -= 360;
//while (windDir < 0) windDir += 360;
// Send all sensor data to master
pinMode(SERIAL_OUT, OUTPUT);
Serial.begin(9600);
Serial.write(highByte(windDir));
Serial.write(lowByte(windDir));
Serial.write(highByte(windSpeedCount));
Serial.write(lowByte(windSpeedCount));
Serial.write(highByte(maxWindGustCount));
Serial.write(lowByte(maxWindGustCount));
Serial.write(highByte(rainCount));
Serial.write(lowByte(rainCount));
Serial.flush();
Serial.end();
pinMode(SERIAL_OUT, INPUT); // INPUT_PULLUP not needed because Wemos D3 has built-in pullup
// Zero counters for next reporting period
//windDirTot = 0;
//windDirCount = 0;
windSpeedCount = 0;
maxWindGustCount = 0;
rainCount = 0;
}
}
}
// Check Wind speed sensor
pinMode(WIND_SPEED_SENSOR, INPUT_PULLUP);
int currWindSpeedSensor = digitalRead(WIND_SPEED_SENSOR);
pinMode(WIND_SPEED_SENSOR, INPUT);
if (currWindSpeedSensor != prevWindSpeedSensor) {
windSpeedEdgeCount++;
if (windSpeedEdgeCount > 1) {
windSpeedEdgeCount = 0;
windSpeedCount++;
}
windGustCount++;
prevWindSpeedSensor = currWindSpeedSensor;
// Now check the wind direction sensor
// Enable sensor only to take reading. Reduces current
bitClear(PRR, PRADC); // power-on ADC
bitSet(ADCSRA, ADEN); // Enable ADC
pinMode(SENSOR_ENABLE, OUTPUT);
digitalWrite(SENSOR_ENABLE, HIGH);
int readingNow = analogRead(WIND_DIR_SENSOR);
pinMode(SENSOR_ENABLE, INPUT);
bitClear(ADCSRA, ADEN); // Disable ADC
bitSet(PRR, PRADC); // power-off ADC
// Translate analog reading into compass direction
// Can be one of 16 values, but there could be some
// analog noise, so the reading[] array contains values
// mid-way between the expected readings.
byte i;
for (i = 0; i < COMPASS_DIRECTIONS && readingNow >= reading[i]; i++);
windDirTot[i]++;
//int windDirNow = compass[i];
// Check if sensor has swept through 0 degrees, moving in either direction
//if (windDirNow - windDirPrev > 180) windDirNow -= 360;
//if (windDirPrev - windDirNow > 180) windDirNow += 360;
// Update total and count of data points for calculating average
//windDirTot += windDirNow;
//windDirCount++;
//windDirPrev = windDirNow;
}
// Check rain sensor
pinMode(RAIN_SENSOR, INPUT_PULLUP);
int currRainSensor = digitalRead(RAIN_SENSOR);
pinMode(RAIN_SENSOR, INPUT);
if (currRainSensor != prevRainSensor) {
if (prevRainSensor == HIGH) rainCount++;
prevRainSensor = currRainSensor;
}
// Time to check for wind gust?
unsigned long windGustPeriod = timeNow - lastWindGustTime;
if (windGustPeriod >= WIND_GUST_PERIOD) {
lastWindGustTime += WIND_GUST_PERIOD;
// New highest wind gust?
if (windGustCount > maxWindGustCount) maxWindGustCount = windGustCount;
// Zero gust count for next period
windGustCount = 0;
}
// Go to sleep until next 1ms timer interrupt
sleep_enable();
sleep_mode();
sleep_disable();
}