summaryrefslogtreecommitdiffstats
path: root/oliver/lr_stripes/src
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-02-05 13:01:01 +0100
committermanuel <manuel@mausz.at>2020-02-05 13:01:01 +0100
commite60bc43eb30ab72ec9fdfae581058bf8acfd8586 (patch)
treecbfd8665cfab33e4e4298d3418b62b9542641771 /oliver/lr_stripes/src
parent95e5f22a558beeaac8895400e406837656a057e0 (diff)
downloadarduino-e60bc43eb30ab72ec9fdfae581058bf8acfd8586.tar.gz
arduino-e60bc43eb30ab72ec9fdfae581058bf8acfd8586.tar.bz2
arduino-e60bc43eb30ab72ec9fdfae581058bf8acfd8586.zip
update to platform IO
Diffstat (limited to 'oliver/lr_stripes/src')
-rw-r--r--oliver/lr_stripes/src/lr_stripes.cpp369
l---------oliver/lr_stripes/src/lr_stripes.ino1
2 files changed, 369 insertions, 1 deletions
diff --git a/oliver/lr_stripes/src/lr_stripes.cpp b/oliver/lr_stripes/src/lr_stripes.cpp
new file mode 100644
index 0000000..7059f8b
--- /dev/null
+++ b/oliver/lr_stripes/src/lr_stripes.cpp
@@ -0,0 +1,369 @@
1#include <Arduino.h>
2#include <ESP8266mDNS.h>
3#include <ArduinoOTA.h>
4#include <PubSubClient.h>
5#include <WiFiManager.h>
6#include <Bounce2.h>
7#include "secrets.h"
8
9const char* autoconf_ssid = AUTOCONF_SSID; //AP name for WiFi setup AP which your ESP will open when not able to connect to other WiFi
10const char* autoconf_pwd = AUTOCONF_PASSWORD; // AP password so noone else can connect to the ESP in case your router fails
11const char* mqtt_server = "192.168.1.2"; //MQTT Server IP, your home MQTT server eg Mosquitto on RPi, or some public MQTT
12const int mqtt_port = 1883; //MQTT Server PORT, default is 1883 but can be anything.
13
14const char* mqtt_pingall_sub = "home/pingall";
15const char* mqtt_pingall_pub = "home/pingall/response";
16
17#define MQTT_BASE "home/livingroom/ledstripe"
18const char* mqtt_device_boot = MQTT_BASE "/device";
19
20enum sensor_type : uint8_t
21{
22 SENSOR_RELAY = (1u << 0),
23 SENSOR_DIMMER = (1u << 1),
24 SENSOR_BUTTON = (1u << 2),
25};
26
27struct sensor_t
28{
29 uint8_t type;
30 struct
31 {
32 uint8_t pin; // relay pin
33 const char *mqtt_sub;
34 const char *mqtt_pub;
35 } relay;
36 struct
37 {
38 uint8_t pin; // push button pin
39 Bounce bounce;
40 } button;
41 struct
42 {
43 uint8_t pin; // dimmer pin
44 uint8_t level; // current dim level (0 to 100)
45 const char *mqtt_sub;
46 const char *mqtt_pub;
47 } dimmer;
48};
49
50struct sensor_t sensors[] = {
51 {
52 .type = SENSOR_RELAY | SENSOR_BUTTON | SENSOR_DIMMER,
53 .relay = {
54 .pin = D5,
55 .mqtt_sub = MQTT_BASE,
56 .mqtt_pub = MQTT_BASE "/status"
57 },
58 .button = {
59 .pin = D0,
60 .bounce = Bounce(),
61 },
62 .dimmer = {
63 .pin = D8,
64 .level = 100,
65 .mqtt_sub = MQTT_BASE "/brightness",
66 .mqtt_pub = MQTT_BASE "/brightness/status"
67 },
68 }
69};
70
71//#define SAVE_RESTORE
72
73#define NUM(a) (sizeof(a) / sizeof(*a))
74
75#define RELAY_ON 1 // GPIO value to write to turn on attached relay
76#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
77
78#define DIMMER_FADE_DELAY 40 // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
79
80WiFiClient espClient;
81PubSubClient client(espClient);
82char convBuffer[10];
83
84bool relayRead(struct sensor_t *sensor);
85void relayWrite(struct sensor_t *sensor, bool state, bool send_update=false);
86void flipRelay(struct sensor_t *sensor, bool send_update=false);
87void checkButtons(void);
88inline uint8_t pwmValue(uint8_t level);
89void fadeDimmer(struct sensor_t *sensor, uint8_t level, bool send_update=false);
90
91void setup()
92{
93 Serial.begin(115200);
94 pinMode(BUILTIN_LED, OUTPUT);
95 analogWriteRange(100);
96
97 // set relay pins to output mode + restore to last known state
98 for (uint8_t i = 0; i < NUM(sensors); i++)
99 {
100 struct sensor_t *sensor = &sensors[i];
101 if (sensor->type & SENSOR_RELAY)
102 {
103 pinMode(sensor->relay.pin, OUTPUT);
104#ifdef SAVE_RESTORE
105#error "not implemented"
106#else
107 digitalWrite(sensor->relay.pin, RELAY_OFF);
108#endif
109 }
110
111 if (sensor->type & SENSOR_DIMMER)
112 {
113 pinMode(sensor->dimmer.pin, OUTPUT);
114#ifdef SAVE_RESTORE
115#error "not implemented"
116#else
117 uint8_t level = sensor->dimmer.level;
118#endif
119 if ((sensor->type & SENSOR_RELAY) && !relayRead(sensor))
120 level = 0;
121 analogWrite(sensor->dimmer.pin, pwmValue(level));
122 }
123
124 if (sensor->type & SENSOR_BUTTON)
125 {
126 pinMode(sensor->button.pin, INPUT);
127 sensor->button.bounce.attach(sensor->button.pin);
128 }
129 }
130
131 WiFiManager wifiManager;
132 wifiManager.autoConnect(autoconf_ssid, autoconf_pwd);
133
134 setup_ota();
135
136 client.setServer(mqtt_server, mqtt_port);
137 client.setCallback(callback);
138
139 digitalWrite(BUILTIN_LED, HIGH); //Turn off led as default
140}
141
142void setup_ota()
143{
144 // Set OTA Password, and change it in platformio.ini
145 ArduinoOTA.setPassword(OTA_PASSWORD);
146 ArduinoOTA.onStart([]() {});
147 ArduinoOTA.onEnd([]() {});
148 ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {});
149 ArduinoOTA.onError([](ota_error_t error)
150 {
151 if (error == OTA_AUTH_ERROR); // Auth failed
152 else if (error == OTA_BEGIN_ERROR); // Begin failed
153 else if (error == OTA_CONNECT_ERROR); // Connect failed
154 else if (error == OTA_RECEIVE_ERROR); // Receive failed
155 else if (error == OTA_END_ERROR); // End failed
156 });
157 ArduinoOTA.begin();
158}
159
160void reconnect()
161{
162 // Loop until we're reconnected
163 while (!client.connected())
164 {
165 // Create a random client ID
166 String clientId = "ESP8266Client-";
167 clientId += String(random(0xffff), HEX);
168
169 // Attempt to connect
170 if (client.connect(clientId.c_str()))
171 {
172 // Once connected, publish an announcement...
173 client.publish(mqtt_device_boot, "connected");
174 // ... and resubscribe
175 client.subscribe(mqtt_pingall_sub);
176
177 // publish states
178 for (uint8_t i = 0; i < NUM(sensors); i++)
179 {
180 struct sensor_t *sensor = &sensors[i];
181 if (sensor->type & SENSOR_RELAY)
182 {
183 Serial.println(sensor->relay.mqtt_sub);
184 client.subscribe(sensor->relay.mqtt_sub);
185 client.publish(sensor->relay.mqtt_pub, relayRead(sensor) ? "1" : "0",
186 true);
187 }
188
189 if (sensor->type & SENSOR_DIMMER)
190 {
191 Serial.println(sensor->dimmer.mqtt_sub);
192 client.subscribe(sensor->dimmer.mqtt_sub);
193 itoa(sensor->dimmer.level, convBuffer, 10);
194 client.publish(sensor->dimmer.mqtt_pub, convBuffer, true);
195 }
196 }
197 }
198 else
199 {
200 // Wait 5 seconds before retrying
201 delay(5000);
202 }
203 }
204}
205
206void callback(char* topic, byte* payload, unsigned int length)
207{
208 char c_payload[length];
209 memcpy(c_payload, payload, length);
210 c_payload[length] = '\0';
211
212 if (strcmp(topic, mqtt_pingall_sub) == 0)
213 {
214 blink();
215 client.publish(mqtt_pingall_pub,
216 "{\"livingroom_ledstrip\":\"connected\"}");
217 return;
218 }
219
220 for (uint8_t i = 0; i < NUM(sensors); i++)
221 {
222 struct sensor_t *sensor = &sensors[i];
223 if (sensor->type & SENSOR_RELAY
224 && length > 0
225 && strcmp(topic, sensor->relay.mqtt_sub) == 0)
226 {
227 blink();
228 relayWrite(sensor, payload[0] == '1', true);
229 return;
230 }
231
232 if (sensor->type & SENSOR_DIMMER
233 && length > 0
234 && strcmp(topic, sensor->dimmer.mqtt_sub) == 0)
235 {
236 blink();
237 uint8_t level = atoi((char *)payload);
238 fadeDimmer(sensor, (level > 100) ? 100 : level, true);
239 return;
240 }
241 }
242}
243
244void blink()
245{
246 //Blink on received MQTT message
247 digitalWrite(BUILTIN_LED, LOW);
248 delay(25);
249 digitalWrite(BUILTIN_LED, HIGH);
250}
251
252void loop()
253{
254 if (!client.connected())
255 reconnect();
256 client.loop();
257 ArduinoOTA.handle();
258 checkButtons();
259}
260
261bool relayRead(struct sensor_t *sensor)
262{
263 if (sensor->type & SENSOR_RELAY)
264 return digitalRead(sensor->relay.pin) == RELAY_ON;
265 return false;
266}
267
268void relayWrite(struct sensor_t *sensor, bool state, bool send_update)
269{
270 if (!(sensor->type & SENSOR_RELAY))
271 return;
272
273 Serial.print(F("Incoming change for relay: "));
274 Serial.print(sensor->relay.pin);
275 Serial.print(F(", New state: "));
276 Serial.println(state);
277
278 digitalWrite(sensor->relay.pin, state ? RELAY_ON : RELAY_OFF);
279
280 if (sensor->type & SENSOR_DIMMER)
281 analogWrite(sensor->dimmer.pin, state ? pwmValue(sensor->dimmer.level) : 0);
282
283#ifdef SAVE_RESTORE
284#error "not implemented"
285#endif
286
287 if (send_update)
288 client.publish(sensor->relay.mqtt_pub, state ? "1" : "0", true);
289}
290
291void flipRelay(struct sensor_t *sensor, bool send_update)
292{
293 relayWrite(sensor, relayRead(sensor) ? RELAY_OFF : RELAY_ON, send_update);
294}
295
296inline void checkButtons(void)
297{
298 for (uint8_t i = 0; i < NUM(sensors); i++)
299 {
300 struct sensor_t *sensor = &sensors[i];
301 if (sensor->type & SENSOR_BUTTON)
302 {
303 sensor->button.bounce.update();
304 if (sensor->button.bounce.fell())
305 flipRelay(sensor, true);
306 }
307 }
308}
309
310const uint8_t pwmtable[101] PROGMEM = {
311 // value below 0 turns of the power supply
312 0, 10, 10, 11, 11, 11, 11, 12, 12, 12,
313 13, 13, 13, 13, 14, 14, 14, 15, 15, 15,
314 16, 16, 17, 17, 17, 18, 18, 19, 19, 19,
315 20, 20, 21, 21, 22, 22, 23, 23, 24, 25,
316 25, 26, 26, 27, 28, 28, 29, 30, 30, 31,
317 32, 32, 33, 34, 35, 35, 36, 37, 38, 39,
318 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
319 50, 51, 52, 54, 55, 56, 58, 59, 60, 62,
320 63, 65, 66, 68, 69, 71, 72, 74, 76, 78,
321 79, 81, 83, 85, 87, 89, 91, 93, 95, 98,
322 100
323};
324
325inline uint8_t pwmValue(uint8_t level)
326{
327 //uint8_t lvl = 100 - (uint8_t)pgm_read_byte(&pwmtable[level]);
328 //return (lvl < 10) 10 : lvl;
329 //level = (level > 0 && level < 10) ? 10 : level;
330 //return 100 - level;
331 return 100 - (uint8_t)pgm_read_byte(&pwmtable[level]);
332}
333
334void fadeDimmer(struct sensor_t *sensor, uint8_t level, bool send_update)
335{
336 if (!(sensor->type & SENSOR_DIMMER))
337 return;
338 if (level > 100)
339 level = 100;
340
341 Serial.print(F("Incoming change for dimmer: "));
342 Serial.print(sensor->dimmer.pin);
343 Serial.print(F(", New level: "));
344 Serial.println(level);
345
346 if (level > 0 && sensor->type & SENSOR_RELAY && !relayRead(sensor))
347 relayWrite(sensor, RELAY_ON, send_update);
348
349 int delta = ((int8_t)(level - sensor->dimmer.level) < 0) ? -1 : 1;
350 while (sensor->dimmer.level != level)
351 {
352 sensor->dimmer.level += delta;
353 analogWrite(sensor->dimmer.pin, pwmValue(sensor->dimmer.level));
354 delay(DIMMER_FADE_DELAY);
355 }
356
357 if (level == 0 && sensor->type & SENSOR_RELAY && relayRead(sensor))
358 relayWrite(sensor, RELAY_OFF, send_update);
359
360#ifdef SAVE_RESTORE
361#error "not implemented"
362#endif
363
364 if (send_update)
365 {
366 itoa(level, convBuffer, 10);
367 client.publish(sensor->dimmer.mqtt_pub, convBuffer, true);
368 }
369}
diff --git a/oliver/lr_stripes/src/lr_stripes.ino b/oliver/lr_stripes/src/lr_stripes.ino
deleted file mode 120000
index a8026eb..0000000
--- a/oliver/lr_stripes/src/lr_stripes.ino
+++ /dev/null
@@ -1 +0,0 @@
1../lr_stripes.ino \ No newline at end of file