-
Notifications
You must be signed in to change notification settings - Fork 0
/
light-sensor.ino
209 lines (166 loc) · 4.46 KB
/
light-sensor.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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <Wire.h>
#include <BH1750.h>
#include <MKRWAN.h>
#include <ArduinoJson.h>
#include "arduino_secrets.h"
BH1750 lightMeter;
int ledPin = 0;
LoRaModem modem;
String appEui = "XXXXXXXXXXXXXX"; // your ttn app eui
String appKey = "XXXXXXXXXXXXXXXXXXXXXXXXX"; // your ttn app key
float brightness;
int brightness_perc;
int power;
bool is_man_on = false;
bool is_man_off = false;
void setup(){
setup_lora();
setup_light_sensor();
}
void loop() {
loop_light_sensor();
loop_lora();
delay(60000); // send brightness once a minute
}
/**
* Initialises the light sensor
* LED out pin supports PWM to modify brightness
*/
void setup_light_sensor() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
// Initialise the I2C bus
Wire.begin();
lightMeter.begin();
}
/**
* Initialises connection to TTN
* Adapted from:
* https://docs.arduino.cc/tutorials/mkr-wan-1310/mkr-wan-library-examples
*/
void setup_lora() {
Serial.begin(115200);
while (!Serial);
// change this to your regional band (eg. US915, AS923, ...)
if (!modem.begin(EU868)) {
Serial.println("Failed to start module");
while (1) {}
};
Serial.print("Your module version is: ");
Serial.println(modem.version());
Serial.print("Your device EUI is: ");
Serial.println(modem.deviceEUI());
int connected = modem.joinOTAA(appEui, appKey);
if (!connected) {
Serial.println("Something went wrong; are you indoor? Move near a window and retry");
while (1) {}
}
// Set poll interval to 60 secs.
modem.minPollInterval(60);
}
/**
* Measures the light level
* Adapted from:
* https://github.com/claws/BH1750
*/
void loop_light_sensor() {
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
// Typical Sunrise/Sunset reading is 400 lux
// Therefore any brighter than this leads to streetlight being switched off
// Otherwise inverse scale the brightness between 0 - 255 (8-bit PWM)
if (is_man_on) {
brightness = 255;
}
else if (is_man_off) {
brightness = 0;
}
else if (lux < 400) {
brightness = (lux / 1.57) - 255;
brightness = abs(brightness);
} else {
brightness = 0;
}
// store percentage level of brightness
brightness_perc = int((brightness / 255) * 100);
// Calculating power consumption with a PWM signal is:
// Power Consumption = Duty Cycle * Load Power
// Duty Cycle == Brightness Percentage in this case
// Load Power == Operating voltage * Operating current - in this case 2.3V and 20mA
float load_power = 2.3 * 0.02;
float duty_cycle = brightness_perc * 0.01;
float p = duty_cycle * load_power;
p = p * 1000;
power = round(p);
Serial.print("Brightness(%): ");
Serial.println(brightness_perc);
Serial.print("Power(mW): ");
Serial.println(power);
analogWrite(ledPin, brightness);
}
/**
* Communicates brightness and power to application server using LoRa
* Strictly uplink messaging (messages aren't received from TTN)
* Adapted from:
* https://docs.arduino.cc/tutorials/mkr-wan-1310/mkr-wan-library-examples
*/
void loop_lora() {
StaticJsonDocument<200> stats;
stats["brightness"] = brightness_perc;
stats["power"] = power;
// Serialize the JSON object to a byte array
String jsonString;
serializeJson(stats, jsonString);
Serial.print("Sending: " + jsonString + " - ");
int err;
modem.beginPacket();
modem.print(jsonString);
err = modem.endPacket(true);
if (err > 0) {
Serial.println("Message sent correctly!");
} else {
Serial.println("Error sending message");
}
// wait for downlink message...
delay(1000);
if (!modem.available()) {
Serial.println("No downlink message received at this time.");
return;
}
char rcv[64];
int i = 0;
while (modem.available()) {
rcv[i++] = (char)modem.read();
}
// check the 3 digit status code
String code_string;
char code[4];
for (int j = 0; j < 3; j++) {
code[j] = rcv[j];
}
code[3] = '\0'; // null terminator
code_string = String(code);
Serial.print("Received: ");
Serial.print(code_string);
Serial.println();
if (code_string == "100") {
Serial.println("Manual ON mode set...");
is_man_on = true;
is_man_off = false;
return;
}
if (code_string == "101") {
Serial.println("Manual OFF mode set...");
is_man_on = false;
is_man_off = true;
return;
}
if (code_string == "999") {
Serial.println("Reverted to STANDARD mode...");
is_man_on = false;
is_man_off = false;
return;
}
}