summaryrefslogtreecommitdiffstats
path: root/mysensors/testnode
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2023-10-12 22:15:29 +0200
committermanuel <manuel@mausz.at>2023-10-12 22:15:29 +0200
commit68c812fe8c690b8a24637076f83537d6a2e94f32 (patch)
tree071992659d4b4e0329f0969e4af0d0c894f112f6 /mysensors/testnode
parent28a73cb136b18b0407e0e15de4fafa881cc40114 (diff)
downloadarduino-68c812fe8c690b8a24637076f83537d6a2e94f32.tar.gz
arduino-68c812fe8c690b8a24637076f83537d6a2e94f32.tar.bz2
arduino-68c812fe8c690b8a24637076f83537d6a2e94f32.zip
Move mysensors project to subdirectory
Diffstat (limited to 'mysensors/testnode')
-rw-r--r--mysensors/testnode/.gitignore5
-rw-r--r--mysensors/testnode/platformio.ini26
-rw-r--r--mysensors/testnode/src/main.cpp316
3 files changed, 347 insertions, 0 deletions
diff --git a/mysensors/testnode/.gitignore b/mysensors/testnode/.gitignore
new file mode 100644
index 0000000..89cc49c
--- /dev/null
+++ b/mysensors/testnode/.gitignore
@@ -0,0 +1,5 @@
1.pio
2.vscode/.browse.c_cpp.db*
3.vscode/c_cpp_properties.json
4.vscode/launch.json
5.vscode/ipch
diff --git a/mysensors/testnode/platformio.ini b/mysensors/testnode/platformio.ini
new file mode 100644
index 0000000..d4ceb9b
--- /dev/null
+++ b/mysensors/testnode/platformio.ini
@@ -0,0 +1,26 @@
1; PlatformIO Project Configuration File
2;
3; Build options: build flags, source filter, extra scripting
4; Upload options: custom port, speed and extra flags
5; Library options: dependencies, extra library storages
6;
7; Please visit documentation for the other options and examples
8; http://docs.platformio.org/en/stable/projectconf.html
9
10[platformio]
11default_envs = pro8MHzatmega328
12
13[env:miniatmega328]
14platform=atmelavr
15board=miniatmega328
16framework=arduino
17
18[env:pro8MHzatmega328]
19platform=atmelavr
20board=pro8MHzatmega328
21framework=arduino
22; minicore/optirun uses 38400 for 8MHz
23upload_speed=38400
24
25[platformio]
26lib_dir=/home/manuel/coding/Arduino/libraries
diff --git a/mysensors/testnode/src/main.cpp b/mysensors/testnode/src/main.cpp
new file mode 100644
index 0000000..999c32a
--- /dev/null
+++ b/mysensors/testnode/src/main.cpp
@@ -0,0 +1,316 @@
1/**
2 * The MySensors Arduino library handles the wireless radio link and protocol
3 * between your home built sensors/actuators and HA controller of choice.
4 * The sensors forms a self healing radio network with optional repeaters. Each
5 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
6 * network topology allowing messages to be routed to nodes.
7 */
8
9// Enable debug prints to serial monitor
10#define MY_DEBUG
11
12// configure radio
13#define MY_RADIO_RFM69
14
15/** @brief RFM69 frequency to use (RF69_433MHZ for 433MHz, RF69_868MHZ for 868MHz or RF69_915MHZ for 915MHz). */
16#define MY_RFM69_FREQUENCY RF69_868MHZ
17
18/** @brief Enable this if you're running the RFM69HW model. */
19//#define MY_IS_RFM69HW
20
21/** @brief RFM69 Network ID. Use the same for all nodes that will talk to each other. */
22#define MY_RFM69_NETWORKID 1
23
24/** @brief Node id defaults to AUTO (tries to fetch id from controller). */
25#define MY_NODE_ID 4
26
27/** @brief If set, transport traffic is unmonitored and GW connection is optional */
28#define MY_TRANSPORT_DONT_CARE_MODE
29
30/** @brief Node parent defaults to AUTO (tries to find a parent automatically). */
31#define MY_PARENT_NODE_ID 0
32
33/** @brief The user-defined AES key to use for EEPROM personalization */
34#include "aes_key.h"
35
36// Enable repeater functionality for this node
37//#define MY_REPEATER_FEATURE
38
39/** @brief Enables RFM69 automatic transmit power control class. */
40//#define MY_RFM69_ATC
41
42#ifdef MY_AES_KEY
43/** @brief enables RFM69 encryption */
44#define MY_RFM69_ENABLE_ENCRYPTION
45#endif
46
47#include <Arduino.h>
48#include <MySensors.h>
49
50enum sensor_type : uint8_t
51{
52 SENSOR_RELAY = (1u << 0),
53 SENSOR_DIMMER = (1u << 1),
54 SENSOR_BUTTON = (1u << 2),
55 SENSOR_SCENE = (1u << 3),
56};
57
58struct sensor_t
59{
60 uint8_t id;
61 uint8_t type;
62 struct
63 {
64 uint8_t pin; // relay pin
65 } relay;
66 struct
67 {
68 uint8_t pin; // dimmer pin
69 uint16_t level; // current dim level (0 to 100)
70 } dimmer;
71};
72
73struct sensor_t sensors[] = {
74 {
75 .id = 0,
76 .type = SENSOR_RELAY,
77 .relay = { .pin = 3 },
78 },
79 {
80 .id = 1,
81 .type = SENSOR_RELAY | SENSOR_DIMMER,
82 .relay = { .pin = 4 },
83 .dimmer = { .pin = 6, .level = 100 },
84 },
85};
86
87//#define SAVE_RESTORE
88
89#define NUM(a) (sizeof(a) / sizeof(*a))
90
91#define RELAY_ON 1 // GPIO value to write to turn on attached relay
92#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
93
94#define DIMMER_FADE_DELAY 10 // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
95
96#define TEMP_SENSOR_ID 254
97#define TEMP_READ_INTERVAL 1000L // read temp every 1 sec
98#define TEMP_N_READS_MSG 60*60 // force temp message every n reads
99#define TEMP_OFFSET 0
100
101MyMessage msg(0, V_STATUS);
102
103inline void checkTemperature(void);
104bool relayRead(struct sensor_t *sensor);
105void relayWrite(struct sensor_t *sensor, bool state, bool send_update=false);
106void flipRelay(struct sensor_t *sensor, bool send_update=false);
107void fadeDimmer(struct sensor_t *sensor, uint8_t level, bool send_update=false);
108
109void before()
110{
111 // set relay pins to output mode + restore to last known state
112 for (uint8_t i = 0; i < NUM(sensors); i++)
113 {
114 struct sensor_t *sensor = &sensors[i];
115 if (sensor->type & SENSOR_RELAY)
116 {
117 pinMode(sensor->relay.pin, OUTPUT);
118#ifdef SAVE_RESTORE
119 digitalWrite(sensor->relay.pin, loadState(sensor->id) ? RELAY_ON : RELAY_OFF);
120#else
121 digitalWrite(sensor->relay.pin, RELAY_ON);
122#endif
123 }
124
125 if (sensor->type & SENSOR_DIMMER)
126 {
127 pinMode(sensor->dimmer.pin, OUTPUT);
128#ifdef SAVE_RESTORE
129 digitalWrite(sensor->relay.pin, loadState(NUM(sensors) + sensor->id));
130#else
131 analogWrite(sensor->dimmer.pin, map(sensor->dimmer.level, 0, 100, 0, 255));
132#endif
133 }
134 }
135
136#ifdef MY_AES_KEY
137 const uint8_t user_aes_key[16] = { MY_AES_KEY };
138 uint8_t cur_aes_key[16];
139 hwReadConfigBlock((void*)&cur_aes_key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, sizeof(cur_aes_key));
140 if (memcmp(&user_aes_key, &cur_aes_key, 16) != 0)
141 {
142 hwWriteConfigBlock((void*)user_aes_key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, sizeof(user_aes_key));
143 debug(PSTR("AES key written\n"));
144 }
145#endif
146}
147
148void setup()
149{
150#ifdef MY_IS_RFM69HW
151 _radio.setHighPower(true);
152#endif
153#ifdef MY_RFM69_ATC
154 _radio.enableAutoPower(-70);
155 debug(PSTR("ATC enabled\n"));
156#endif
157}
158
159void presentation()
160{
161 sendSketchInfo("TVLight", "1.0");
162
163 // register all sensors to gw (they will be created as child devices)
164 for (uint8_t i = 0; i < NUM(sensors); i++)
165 {
166 struct sensor_t *sensor = &sensors[i];
167 if (sensor->type & SENSOR_DIMMER)
168 present(sensor->id, S_DIMMER);
169 else if (sensor->type & SENSOR_RELAY)
170 present(sensor->id, S_BINARY);
171 }
172
173#if TEMP_SENSOR_ID >= 0
174 present(TEMP_SENSOR_ID, S_TEMP);
175#endif
176}
177
178void loop()
179{
180 //TODO maybe call _radio.rcCalibration() all 1000x changes?
181#if TEMP_SENSOR_ID >= 0
182 checkTemperature();
183#endif
184}
185
186inline void checkTemperature(void)
187{
188 static unsigned long lastTempUpdate = millis();
189 static unsigned int numTempUpdates = 0;
190 static float lastTemp = 0;
191 static MyMessage msgTemp(TEMP_SENSOR_ID, V_TEMP);
192
193 unsigned long now = millis();
194 if (now - lastTempUpdate > TEMP_READ_INTERVAL)
195 {
196 float temp = _radio.readTemperature() + TEMP_OFFSET;
197 lastTempUpdate = now;
198 if (isnan(temp))
199 Serial.println(F("Failed reading temperature"));
200 else if (abs(temp - lastTemp) >= 2 || numTempUpdates == TEMP_N_READS_MSG)
201 {
202 lastTemp = temp;
203 numTempUpdates = 0;
204 send(msgTemp.set(temp, 2));
205#ifdef MY_DEBUG
206 char str_temp[6];
207 dtostrf(temp, 4, 2, str_temp);
208 debug(PSTR("Temperature: %s °C\n"), str_temp);
209#endif
210 }
211 else
212 ++numTempUpdates;
213 }
214}
215
216void receive(const MyMessage &message)
217{
218 if (message.type == V_STATUS || message.type == V_PERCENTAGE)
219 {
220 uint8_t sensor_id = message.sensor;
221 if (sensor_id >= NUM(sensors))
222 {
223 Serial.print(F("Invalid sensor id:"));
224 Serial.println(sensor_id);
225 return;
226 }
227
228 struct sensor_t *sensor = &sensors[sensor_id];
229 if (message.type == V_STATUS && sensor->type & SENSOR_RELAY)
230 {
231 if (mGetCommand(message) == C_REQ)
232 send(msg.setType(V_STATUS).setSensor(sensor->id).set(relayRead(sensor)));
233 else if (mGetCommand(message) == C_SET)
234 relayWrite(sensor, message.getBool());
235 }
236 else if (message.type == V_PERCENTAGE && sensor->type & SENSOR_DIMMER)
237 {
238 if (mGetCommand(message) == C_REQ)
239 send(msg.setType(V_PERCENTAGE).setSensor(sensor->id).set(sensor->dimmer.level));
240 else if (mGetCommand(message) == C_SET)
241 {
242 uint16_t level = message.getUInt();
243 if (level > 255)
244 return;
245 fadeDimmer(sensor, level);
246 }
247 }
248 }
249}
250
251bool relayRead(struct sensor_t *sensor)
252{
253 if (sensor->type & SENSOR_RELAY)
254 return digitalRead(sensor->relay.pin) == RELAY_ON;
255 return false;
256}
257
258void relayWrite(struct sensor_t *sensor, bool state, bool send_update)
259{
260 if (!(sensor->type & SENSOR_RELAY))
261 return;
262
263 Serial.print(F("Incoming change for relay: "));
264 Serial.print(sensor->relay.pin);
265 Serial.print(F(", New state: "));
266 Serial.println(state);
267
268 digitalWrite(sensor->relay.pin, state ? RELAY_ON : RELAY_OFF);
269
270#ifdef SAVE_RESTORE
271 saveState(sensor->id, state ? RELAY_ON : RELAY_OFF);
272#endif
273
274 if (send_update)
275 send(msg.setType(V_STATUS).setSensor(sensor->id).set(state));
276}
277
278void flipRelay(struct sensor_t *sensor, bool send_update)
279{
280 relayWrite(sensor, relayRead(sensor) ? RELAY_OFF : RELAY_ON, send_update);
281}
282
283void fadeDimmer(struct sensor_t *sensor, uint8_t level, bool send_update)
284{
285 if (!(sensor->type & SENSOR_DIMMER))
286 return;
287
288 Serial.print(F("Incoming change for dimmer: "));
289 Serial.print(sensor->dimmer.pin);
290 Serial.print(F(", Old level: "));
291 Serial.print(sensor->dimmer.level);
292 Serial.print(F(", New level: "));
293 Serial.println(level);
294
295 if (level > 0 && sensor->type & SENSOR_RELAY && !relayRead(sensor))
296 relayWrite(sensor, RELAY_ON);
297
298 int delta = ((int8_t)(level - sensor->dimmer.level) < 0) ? -1 : 1;
299 while (sensor->dimmer.level != level)
300 {
301 sensor->dimmer.level += delta;
302 analogWrite(sensor->dimmer.pin, map(sensor->dimmer.level, 0, 100, 0, 255));
303 delay(DIMMER_FADE_DELAY);
304 }
305
306 if (level == 0 && sensor->type & SENSOR_RELAY && relayRead(sensor))
307 relayWrite(sensor, RELAY_OFF);
308
309#ifdef SAVE_RESTORE
310 saveState(NUM(sensors) + sensor->id, level);
311#endif
312
313 if (send_update)
314 send(msg.setType(V_PERCENTAGE).setSensor(sensor->id).set(level));
315}
316