Difference between revisions of "DFF4.1"
Konnekting (talk | contribs) |
Konnekting (talk | contribs) (→Help: added details on how to find error with non-switching relais.) |
||
Line 99: | Line 99: | ||
// MCP23017 Output register<->pin map | // MCP23017 Output register<->pin map | ||
− | #define | + | #define GPA0 0 // E 1 |
− | #define | + | #define GPA1 1 // E 0 |
− | #define | + | #define GPA2 2 |
− | #define | + | #define GPA3 3 |
− | #define | + | #define GPA4 4 |
− | #define | + | #define GPA5 5 |
− | #define | + | #define GPA6 6 |
− | #define | + | #define GPA7 7 |
− | #define | + | #define GPB0 8 |
− | #define | + | #define GPB1 9 |
− | #define | + | #define GPB2 10 // B 0 |
− | #define | + | #define GPB3 11 // B 1 |
− | #define | + | #define GPB4 12 // C 0 |
− | #define | + | #define GPB5 13 // C 1 |
− | #define | + | #define GPB6 14 // D 0 |
− | #define | + | #define GPB7 15 // D 1 |
+ | #define A_SET GPB1 | ||
+ | #define A_RESET GPB0 | ||
− | #define | + | #define B_SET GPB3 |
− | #define | + | #define B_RESET GPB2 |
− | #define | + | #define C_SET GPB5 |
− | #define | + | #define C_RESET GPB4 |
− | #define | + | #define D_SET GPB7 |
− | #define | + | #define D_RESET GPB6 |
− | #define | + | #define E_SET GPA0 |
− | #define | + | #define E_RESET GPA1 |
− | #define | + | #define F_SET GPA2 |
− | #define | + | #define F_RESET GPA3 |
− | #define | + | #define G_SET GPA4 |
− | #define | + | #define G_RESET GPA5 |
− | #define | + | #define H_SET GPA6 |
− | #define | + | #define H_RESET GPA7 |
− | + | boolean state[16]; | |
− | |||
void setup() { | void setup() { | ||
+ | |||
SerialUSB.begin(115200); | SerialUSB.begin(115200); | ||
+ | while (!SerialUSB) { | ||
+ | delay(100); | ||
+ | } | ||
SerialUSB.println("SetupMCP Relais Test ..."); | SerialUSB.println("SetupMCP Relais Test ..."); | ||
Line 157: | Line 162: | ||
for (int i = 0; i < 16; i++) { | for (int i = 0; i < 16; i++) { | ||
mcp.pinMode(i, OUTPUT); | mcp.pinMode(i, OUTPUT); | ||
+ | state[i]=false; | ||
+ | setMCP(i, false); | ||
} | } | ||
− | + | //#define D 100 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
SerialUSB.println("... done"); | SerialUSB.println("... done"); | ||
+ | digitalWrite(LED, LOW); | ||
// initial delay | // initial delay | ||
Line 184: | Line 185: | ||
String cmd; | String cmd; | ||
+ | |||
+ | char c[4]; | ||
+ | |||
+ | |||
void loop() { | void loop() { | ||
Line 189: | Line 194: | ||
cmd = SerialUSB.readStringUntil('\n'); | cmd = SerialUSB.readStringUntil('\n'); | ||
− | if (cmd.length() | + | if (cmd.length() == 2) { |
+ | |||
SerialUSB.print("Command: "); | SerialUSB.print("Command: "); | ||
SerialUSB.println(cmd); | SerialUSB.println(cmd); | ||
Line 242: | Line 248: | ||
SerialUSB.println("\n\nWaiting for command...[a-h0-1]"); | SerialUSB.println("\n\nWaiting for command...[a-h0-1]"); | ||
+ | |||
+ | } else if (cmd.length() == 4) { | ||
+ | SerialUSB.print("Command: "); | ||
+ | SerialUSB.println(cmd); | ||
+ | |||
+ | if (cmd == "gpa0") { | ||
+ | state[GPA0] = !state[GPA0]; | ||
+ | setMCP(GPA0, state[GPA0gpb5]); | ||
+ | } else | ||
+ | if (cmd == "gpa1") { | ||
+ | state[GPA1] = !state[GPA1]; | ||
+ | setMCP(GPA1, state[GPA1]); | ||
+ | } else | ||
+ | if (cmd == "gpa2") { | ||
+ | state[GPA2] = !state[GPA2]; | ||
+ | setMCP(GPA2, state[GPA2]); | ||
+ | } else | ||
+ | if (cmd == "gpa3") { | ||
+ | state[GPA3] = !state[GPA3]; | ||
+ | setMCP(GPA3, state[GPA3]); | ||
+ | } else | ||
+ | if (cmd == "gpa4") { | ||
+ | state[GPA4] = !state[GPA4]; | ||
+ | setMCP(GPA4, state[GPA4]); | ||
+ | } else | ||
+ | if (cmd == "gpa5") { | ||
+ | state[GPA5] = !state[GPA5]; | ||
+ | setMCP(GPA5, state[GPA5]); | ||
+ | } else | ||
+ | if (cmd == "gpa6") { | ||
+ | state[GPA6] = !state[GPA6]; | ||
+ | setMCP(GPA6, state[GPA6]); | ||
+ | } else | ||
+ | if (cmd == "gpa7") { | ||
+ | state[GPA7] = !state[GPA7]; | ||
+ | setMCP(GPA7, state[GPA7]); | ||
+ | } else | ||
+ | if (cmd == "gpb0") { | ||
+ | state[GPB0] = !state[GPB0]; | ||
+ | setMCP(GPB0, state[GPB0]); | ||
+ | } else | ||
+ | if (cmd == "gpb1") { | ||
+ | state[GPB1] = !state[GPB1]; | ||
+ | setMCP(GPB1, state[GPB1]); | ||
+ | } else | ||
+ | if (cmd == "gpb2") { | ||
+ | state[GPB2] = !state[GPB2]; | ||
+ | setMCP(GPB2, state[GPB2]); | ||
+ | } else | ||
+ | if (cmd == "gpb3") { | ||
+ | state[GPB3] = !state[GPB3]; | ||
+ | setMCP(GPB3, state[GPB3]); | ||
+ | } else | ||
+ | if (cmd == "gpb4") { | ||
+ | state[GPB4] = !state[GPB4]; | ||
+ | setMCP(GPB4, state[GPB4]); | ||
+ | } else | ||
+ | if (cmd == "gpb5") { | ||
+ | state[GPB5] = !state[GPB5]; | ||
+ | setMCP(GPB5, state[GPB5]); | ||
+ | } else | ||
+ | if (cmd == "gpb6") { | ||
+ | state[GPB6] = !state[GPB6]; | ||
+ | setMCP(GPB6, state[GPB6]); | ||
+ | } else | ||
+ | if (cmd == "gpb7") { | ||
+ | state[GPB7] = !state[GPB7]; | ||
+ | setMCP(GPB7, state[GPB7]); | ||
+ | } | ||
+ | |||
} | } | ||
+ | } | ||
+ | void setMCP(int i, boolean s){ | ||
+ | SerialUSB.print("Set addr #"); | ||
+ | SerialUSB.print(i); | ||
+ | SerialUSB.print(" to "); | ||
+ | SerialUSB.println(s); | ||
+ | mcp.digitalWrite(i, s); | ||
} | } | ||
Line 258: | Line 341: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | If there are relais that do not switch, follow these steps: | ||
+ | |||
+ | # Set MCP IO pin one by one and check if voltage (0V vs. 3.3V) can be measured between MCP IC and ULN2803 IC. | ||
+ | # Measure also the voltage on ULN2803 output pin. | ||
+ | If MCP fires 0V (low), ULN should almost show 5V (typically 4.8V) on output. If MCP fires 3.3V (high) the ULN output voltage will go down to almost 0V (low), but typically 0.7V. If itÄs 0.9V, it will work as well. But if voltage just drops to 1..1.5V, the ULN driver IC is bad and needs to be replaced. Make sure you use a genuine one and not a china-copy. | ||
== Links == | == Links == | ||
[[Category:Device/Kits]] | [[Category:Device/Kits]] |
Latest revision as of 11:55, 20 February 2022
DFF4.1 | |
---|---|
Developer | Alexander Christian |
Status | Version 1.0 finished |
Microcontroller/Board | M0dularisM+ |
KNX connectivity | Siemens BCU, Eugen's µBCU |
Description
The purpose of this actuator is, to control Roto Rototronic skylight with shutters and/or sun blinds. It has 4 "channels". Each channel internally uses two relays: One for the open-action, and one for the close-action.
Of course you can also control your Roto Rototronic skylight with help of a standard switch-actuator. But then you don't have the possibility to "open the window 75%" or "close the shutter 80%". The firmware for DFF4.1 provides all this neat feature that you know from typical shutter/blinds actuators.
Hardware
This actuator consists of the following REG parts:
- M0dularis+
- 8x Button + 8x LED
- 8x Relay Bistable, bus powered (8 relays in total, 2 for each channel = 4 channels).
I2C address on application board:
A0: 1 A1: 0 A2: 0
I2C address on frontend board:
A0: 0 A1: 0 A2: 0
Software
User Documentation
Check here for the DFF4.1 User Manual
Developer Documentation
Firmware sourcecode is on github: https://github.com/KONNEKTING/DFF4.1 Follow this guide for updating the firmare from source-code: KONNEKTING USB Firmware Update
Get a DIY kit
You are interested in this actuator? Great! This device is available as a DIY kit.
The kit includes all required parts with pre-soldered SMD parts and pre-flashed controller board.
You only need:
- soldering iron and solder
- a screw driver
- a sharp knife with a fine tip
- a working KNX installation where you can connect the device to
- ~2-3hrs to build it according to the build instructions linked on this page
- a computer: Windows, Linux or MAC that is able to run KONNEKTING Suite plus a KNX IP Interface or an KNX IP Router.
- for updating the firmware: A Mini USB cable (Not Micro-USB like on your smartphone. Mini USB is a big thicker as Micro USB)
Please write a mail to info@konnekting.de and refer to this page.
Build It
This actuator uses three PCBs, a bunch of SMD components as well as a lot of mechanical parts. As most users are not able to solder SMD, the PCBs are pre-soldered with all SMD components. Due to the big amount of parts, this actuator comes as a DIY kit: You have to solder non-SMD parts yourself and build up the device and finally flash the firmware with help of a USB connection.
Check here for the DFF4.1 Building Instructions
Help
If relays do not work as expected, you can run this test-sketch to be able to switch relais by serial console. Commands follow this syntax (\n = LF/LineFeed/NewLine):
[a-h0-1]\n
f.i. "a0" disables relay A, "f1" enables relay F On startup all relays are disabled. It is recommended to use this test without attached window/shutter, but with am multimeter/continuity-tester to be able to test relay by relay.
1#include <Wire.h>
2#include <Adafruit_MCP23017.h>
3
4Adafruit_MCP23017 mcp;
5#define LED A5
6#define EN A0
7
8// MCP23017 Output register<->pin map
9#define GPA0 0 // E 1
10#define GPA1 1 // E 0
11#define GPA2 2
12#define GPA3 3
13#define GPA4 4
14#define GPA5 5
15#define GPA6 6
16#define GPA7 7
17#define GPB0 8
18#define GPB1 9
19#define GPB2 10 // B 0
20#define GPB3 11 // B 1
21#define GPB4 12 // C 0
22#define GPB5 13 // C 1
23#define GPB6 14 // D 0
24#define GPB7 15 // D 1
25
26#define A_SET GPB1
27#define A_RESET GPB0
28
29#define B_SET GPB3
30#define B_RESET GPB2
31
32#define C_SET GPB5
33#define C_RESET GPB4
34
35#define D_SET GPB7
36#define D_RESET GPB6
37
38#define E_SET GPA0
39#define E_RESET GPA1
40
41#define F_SET GPA2
42#define F_RESET GPA3
43
44#define G_SET GPA4
45#define G_RESET GPA5
46
47#define H_SET GPA6
48#define H_RESET GPA7
49
50boolean state[16];
51
52void setup() {
53
54
55 SerialUSB.begin(115200);
56 while (!SerialUSB) {
57 delay(100);
58 }
59
60 SerialUSB.println("SetupMCP Relais Test ...");
61
62 pinMode(LED, OUTPUT);
63 pinMode(EN, OUTPUT);
64 digitalWrite(LED, HIGH);
65 digitalWrite(EN, HIGH);
66
67
68 mcp.begin(1);
69
70 for (int i = 0; i < 16; i++) {
71 mcp.pinMode(i, OUTPUT);
72 state[i]=false;
73 setMCP(i, false);
74 }
75
76//#define D 100
77
78
79 SerialUSB.println("... done");
80 digitalWrite(LED, LOW);
81
82 // initial delay
83 delay(1000);
84 SerialUSB.println("Initial delay done.");
85 SerialUSB.println("Waiting for command...[a-h0-1]");
86}
87
88//84
89#define WAIT_TIME 84
90
91//16
92#define SET_TIME 16
93
94String cmd;
95
96char c[4];
97
98
99
100void loop() {
101
102 cmd = SerialUSB.readStringUntil('\n');
103
104 if (cmd.length() == 2) {
105
106 SerialUSB.print("Command: ");
107 SerialUSB.println(cmd);
108
109 if (cmd == "a1") {
110 pulseMCP(A_SET);
111 } else if (cmd == "a0") {
112 pulseMCP(A_RESET);
113 }
114
115 else if (cmd == "b1") {
116 pulseMCP(B_SET);
117 } else if (cmd == "b0") {
118 pulseMCP(B_RESET);
119 }
120
121 else if (cmd == "c1") {
122 pulseMCP(C_SET);
123 } else if (cmd == "c0") {
124 pulseMCP(C_RESET);
125 }
126
127 else if (cmd == "d1") {
128 pulseMCP(D_SET);
129 } else if (cmd == "d0") {
130 pulseMCP(D_RESET);
131 }
132
133 else if (cmd == "e1") {
134 pulseMCP(E_SET);
135 } else if (cmd == "e0") {
136 pulseMCP(E_RESET);
137 }
138
139 else if (cmd == "f1") {
140 pulseMCP(F_SET);
141 } else if (cmd == "f0") {
142 pulseMCP(F_RESET);
143 }
144
145 else if (cmd == "g1") {
146 pulseMCP(G_SET);
147 } else if (cmd == "g0") {
148 pulseMCP(G_RESET);
149 }
150
151 else if (cmd == "h1") {
152 pulseMCP(H_SET);
153 } else if (cmd == "h0") {
154 pulseMCP(H_RESET);
155 }
156
157 SerialUSB.println("\n\nWaiting for command...[a-h0-1]");
158
159 } else if (cmd.length() == 4) {
160 SerialUSB.print("Command: ");
161 SerialUSB.println(cmd);
162
163 if (cmd == "gpa0") {
164 state[GPA0] = !state[GPA0];
165 setMCP(GPA0, state[GPA0gpb5]);
166 } else
167 if (cmd == "gpa1") {
168 state[GPA1] = !state[GPA1];
169 setMCP(GPA1, state[GPA1]);
170 } else
171 if (cmd == "gpa2") {
172 state[GPA2] = !state[GPA2];
173 setMCP(GPA2, state[GPA2]);
174 } else
175 if (cmd == "gpa3") {
176 state[GPA3] = !state[GPA3];
177 setMCP(GPA3, state[GPA3]);
178 } else
179 if (cmd == "gpa4") {
180 state[GPA4] = !state[GPA4];
181 setMCP(GPA4, state[GPA4]);
182 } else
183 if (cmd == "gpa5") {
184 state[GPA5] = !state[GPA5];
185 setMCP(GPA5, state[GPA5]);
186 } else
187 if (cmd == "gpa6") {
188 state[GPA6] = !state[GPA6];
189 setMCP(GPA6, state[GPA6]);
190 } else
191 if (cmd == "gpa7") {
192 state[GPA7] = !state[GPA7];
193 setMCP(GPA7, state[GPA7]);
194 } else
195 if (cmd == "gpb0") {
196 state[GPB0] = !state[GPB0];
197 setMCP(GPB0, state[GPB0]);
198 } else
199 if (cmd == "gpb1") {
200 state[GPB1] = !state[GPB1];
201 setMCP(GPB1, state[GPB1]);
202 } else
203 if (cmd == "gpb2") {
204 state[GPB2] = !state[GPB2];
205 setMCP(GPB2, state[GPB2]);
206 } else
207 if (cmd == "gpb3") {
208 state[GPB3] = !state[GPB3];
209 setMCP(GPB3, state[GPB3]);
210 } else
211 if (cmd == "gpb4") {
212 state[GPB4] = !state[GPB4];
213 setMCP(GPB4, state[GPB4]);
214 } else
215 if (cmd == "gpb5") {
216 state[GPB5] = !state[GPB5];
217 setMCP(GPB5, state[GPB5]);
218 } else
219 if (cmd == "gpb6") {
220 state[GPB6] = !state[GPB6];
221 setMCP(GPB6, state[GPB6]);
222 } else
223 if (cmd == "gpb7") {
224 state[GPB7] = !state[GPB7];
225 setMCP(GPB7, state[GPB7]);
226 }
227
228 }
229}
230
231void setMCP(int i, boolean s){
232 SerialUSB.print("Set addr #");
233 SerialUSB.print(i);
234 SerialUSB.print(" to ");
235 SerialUSB.println(s);
236 mcp.digitalWrite(i, s);
237}
238
239void pulseMCP(int i) {
240 SerialUSB.print("Pulse at addr #");
241 SerialUSB.print(i);
242
243 mcp.digitalWrite(i, HIGH);
244 delay(SET_TIME);
245 mcp.digitalWrite(i, LOW);
246 delay(WAIT_TIME);
247 SerialUSB.println(" *DONE*");
248}
If there are relais that do not switch, follow these steps:
- Set MCP IO pin one by one and check if voltage (0V vs. 3.3V) can be measured between MCP IC and ULN2803 IC.
- Measure also the voltage on ULN2803 output pin.
If MCP fires 0V (low), ULN should almost show 5V (typically 4.8V) on output. If MCP fires 3.3V (high) the ULN output voltage will go down to almost 0V (low), but typically 0.7V. If itÄs 0.9V, it will work as well. But if voltage just drops to 1..1.5V, the ULN driver IC is bad and needs to be replaced. Make sure you use a genuine one and not a china-copy.