You are on page 1of 5

1.

/*
2. by Gromain59
3. Translated By Mike Deuschle
4. mike.dausch@gmail.com
5.
6. Material part:
7. - Triac driven by a digital output via an optocoupler
8. - AC opto-coupler for detecting the zero crossing of phase
9.
10. Software part:
11. - A hardware interrupt input 2 at the zero crossing of phase
12. - A software interrupt that occurs between 100us and 1400us.
13. => Interrupt interval is variable to obtain a light curve by linear orders, because of
the shape of the sinusoidal signal.
14. we have:
15. 1. Detection of the transition to zero on input 2
16. 2. execution of detection_zero (): processing channel with a setpoint of 0% and 100%
17. 3. deactivating hardware interrupt, enabling the software interrupt on the basis of delay
[0]
18. 4. interrupt after delay [c2] ?s (c2 = 0)
19. 5. execution of controle_canaux ()
20. => Index increment c2
21. and if c2 is greater than 49, then this is the last cycle
22. => Turn OFF of all channels
23. => Activate the hardware interrupt
24. otherwise:
25. => Activation of output channels with 98% to record (either a 469?s delay) or if
26. => Interrupt reconfiguration of time with another delay, delay [c2]
27.
28. To change the setpoint of a channel, you must send via the serial monitor a frame of the
form:
29. " D/0/45/F"
30. => Space
31. => "D" to indicate the start of the frame
32. => "/" As separator
33. => The affected channel (0 to 7 here)
34. => "/" As separator
35. => The desired level (from 0% to 100%)
36. => "/" As separator
37. => "F" to indicate the end of the frame
38.
39. Once the frame received, the function sscanf is responsible for retrieving data.
40. It converts the received record levels (0 to 50 levels)
41.
42. Resources:
43. http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/30 for first test
44. http://www.hoelscher-hi.de/hendrik/english/dimmer.htm for electronics
45. http://www.abcelectronique.com/bigonoff/domocan.php?par=3efd4 for electronics and soft
(PIC)
46. arduino forum
47.
48. */
49.
50. #include <TimerOne.h> // for the interruption time
http://www.arduino.cc/playground/Code/Timer1
51. #include <stdio.h> // for the treatment of the frame containing the change orders
52.
53. // timeout value for the reception of the frame
54. int tps_max_lecture = 200; // reading code, counter max between all the characters of a
code
55. int tps_max_carte = 1000; // max meter between reception of a character
56.
57.
58. long curve[] = {
59. 1469 , // 98 % 1 225,3V retard / zéro = 1469 ms
60. 287 , // 96 % 2 222,7V retard / zéro = 1867 ms
61. 234 , // 94 % 3 220,6V retard / zéro = 2154 ms
62. 201 , // 92 % 4 218,2V retard / zéro = 2388 ms
63. 180 , // 90 % 5 215,4V retard / zéro = 2589 ms
64. 164 , // 88 % 6 213,3V retard / zéro = 2769 ms
65. 152 , // 86 % 7 210,8V retard / zéro = 2933 ms
66. 143 , // 84 % 8 208V retard / zéro = 3085 ms
67. 135 , // 82 % 9 205,7V retard / zéro = 3228 ms
68. 129 , // 80 % 10 202,8V retard / zéro = 3363 ms
69. 124 , // 78 % 11 200,5V retard / zéro = 3492 ms
70. 120 , // 76 % 12 197,6V retard / zéro = 3616 ms
71. 116 , // 74 % 13 195,2V retard / zéro = 3736 ms
72. 112 , // 72 % 14 192,4V retard / zéro = 3852 ms
73. 110 , // 70 % 15 189,6V retard / zéro = 3964 ms
74. 108 , // 68 % 16 186,8V retard / zéro = 4074 ms
75. 106 , // 66 % 17 184V retard / zéro = 4182 ms
76. 105 , // 64 % 18 180,9V retard / zéro = 4288 ms
77. 103 , // 62 % 19 178,1V retard / zéro = 4393 ms
78. 102 , // 60 % 20 175,1V retard / zéro = 4496 ms
79. 101 , // 58 % 21 172,1V retard / zéro = 4598 ms
80. 101 , // 56 % 22 168,9V retard / zéro = 4699 ms
81. 100 , // 54 % 23 166,2V retard / zéro = 4800 ms
82. 100 , // 52 % 24 162,6V retard / zéro = 4900 ms
83. 100 , // 50 % 25 159,3V retard / zéro = 5000 ms
84. 101 , // 48 % 26 155,8V retard / zéro = 5100 ms
85. 100 , // 46 % 27 152,6V retard / zéro = 5201 ms
86. 101 , // 44 % 28 149,1V retard / zéro = 5301 ms
87. 102 , // 42 % 29 145,3V retard / zéro = 5402 ms
88. 103 , // 40 % 30 141,8V retard / zéro = 5504 ms
89. 105 , // 38 % 31 138V retard / zéro = 5607 ms
90. 106 , // 36 % 32 133,8V retard / zéro = 5712 ms
91. 108 , // 34 % 33 130V retard / zéro = 5818 ms
92. 110 , // 32 % 34 126V retard / zéro = 5926 ms
93. 112 , // 30 % 35 121,7V retard / zéro = 6036 ms
94. 116 , // 28 % 36 117,1V retard / zéro = 6148 ms
95. 120 , // 26 % 37 112,6V retard / zéro = 6264 ms
96. 124 , // 24 % 38 107,7V retard / zéro = 6384 ms
97. 129 , // 22 % 39 102,4V retard / zéro = 6508 ms
98. 135 , // 20 % 40 97,2V retard / zéro = 6637 ms
99. 143 , // 18 % 41 92V retard / zéro = 6772 ms
100. 152 , // 16 % 42 85,7V retard / zéro = 6915 ms
101. 164 , // 14 % 43 79,4V retard / zéro = 7067 ms
102. 180 , // 12 % 44 72,8V retard / zéro = 7231 ms
103. 201 , // 10 % 45 64,8V retard / zéro = 7411 ms
104. 234 , // 8 % 46 56,4V retard / zéro = 7612 ms
105. 286 , // 6 % 47 46V retard / zéro = 7846 ms
106. 399 , // 4 % 48 32,4V retard / zéro = 8132 ms
107. 500 , //
108. 1469 // 2 % 49 0V retard / zéro = 8531 ms
109. };
110.
111. int set[] = { // set channel level (0 = 100%, 50 = 0%)
112. 0, // Output 0
113. 0, // output 1
114. 0, // output 2
115. 0, // output 3
116. 0, // output 4
117. 0, // output 5
118. 0, // output 6
119. 0, // output 7
120. };
121.
122. int output [] = { // assign a pin for each channel.
123. 4, // Output 0
124. 3, // output 1
125. 5, // output 2
126. 0, // output 3
127. 0, // output 4
128. 0, // output 5
129. 0, // output 6
130. 0, // output 7
131. };
132.
133. volatile int c1 = 0; // index c1 for reading data from each channel (No pin,
luggage)
134. volatile int c2 = 0; // c2 index number passing through the loop control phase
delay (49 passages)
135.
136. // Definition of macros to drive the output
137. #define lightON(index) (digitalWrite(output[index], HIGH))
138. #define lightOFF(index) (digitalWrite(output[index], LOW))
139.
140.
141. void setup () {// Start of setup
142.
143. // Initialize the serial
144. Serial.begin (9600);
145.
146. // Initialize the channel outputs (triacs)
147. for (c1 = 0; c1 <= 7; c1++) {// we traverse the 8 channels to configure
148. pinMode(output[c1], OUTPUT); // we associate each channel has a
pin, which sets the output digital
149. lightOFF(output[c1]); // and we switch off the output
150. }
151.
152. Serial.println( "Gromain 8-CHANNEL DIMMER v0.2");
153. Serial.println( "FRAME EXPECTED: <space> 'D' / 'Output Port' / 'Value of DIM'
/ 'F'");
154.
155.
156. // Initialize the interruption time Timer1
157. Timer1.initialize(); // Initialize TimerOne library for the freq we need
158.
159.
160. // Attach the interrupt 0 to pin 2 for the detection of zero crossing (Zero Cross
Detection)
161. attachInterrupt(0, detection_zero, FALLING); // Attach an Interrupt to Pin 2
(Interrupt 0) for Zero Cross Detection
162.
163. } // End of setup
164.
165. void detection_zero() {// function associated with the interrupt 0
166.
167. detachInterrupt(0); // disables the interrupt on zero crossing
168.
169. c2 = 0;
170.
171. for (c1 = 0; c1 <= 7; c1++) {// we scan the 8 outputs to check their orders
172. if (set[c1] >= 49 ) {// if set 0%
173. lightOFF(c1); // then we switch off
174. }
175.
176. if (set[c1]<= 0){// if set 100%
177. lightON(c1); // then we light
178. }
179.
180. }
181.
182. Timer1.attachInterrupt(controle_canaux, curve[c2]); // we attach the
interruption time
183.
184. } // End of detection_zero
185.
186. void controle_canaux() {// here we verified whether the triac must be initiated
187.
188. c2=c2++;
189.
190. attachInterrupt(0, detection_zero, FALLING); // we attach an interrupt on pin
2 (interrupt 0)
191. Timer1.detachInterrupt(); // we detach the interruption time
192.
193. if (c2 >= 49) {// If last cycle then (49 for 50hz - 41 for 60Hz)
194.
195. for (c1 = 0; c1 <= 7; c1++) {// we scan the 8 outputs
196. lightOFF(c1); // and we put out the channel for the next cycle
197. }
198.
199.
200. }
201. else { // else
202.
203. Timer1.attachInterrupt(controle_canaux, curve[c2]); // we attach a break time
204.
205. for (c1 = 0; c1 <= 7; c1++) { // we scan the 8 outputs to check their orders
206. if (set[c1] == c2) // if is set equal to the processed (no change in
the loop)
207. {lightON(c1);} // then we light the channel
208. }
209.
210. } // End function controle_canaux
211.
212. }
213. void loop() {// Main Loop
214.
215. int n = 0;
216.
217. if (Serial.available ()> 0) {
218. n = lecture();
219. }
220.
221. }
222.
223. int lecture() {// read a frame type: "D / aaa / bbb / F
224. // Or "D" starting character frame
225. // Or "yyyy" No output which is set to modify
226. // Or "bbbb" new set of output (between 0 and 100%)
227.
228.
229.
230. char buf[15] = " ";
231. int timeout = 0;
232. int i = 0;
233. int n1 = 0;
234. int n2 = 0;
235. char c1, c2;
236.
237. while (Serial.available() > 0) {
238. if(i!=14){
239. buf[i] = Serial.read ();
240. i++;
241. }
242.
243. timeout++;
244.
245. if (timeout>tps_max_lecture)
246. {Serial.println("T1");
247. return -1;
248. }
249. if (timeout> tps_max_lecture)
250. {Serial.println("T2");
251. return -2;
252. }
253. }
254. sscanf(buf, "%c/%d/%d/%c", &c1, &n1, &n2, &c2); // decoding frame
255.
256. if (c1 == 'D' && c2 == 'F') {// Check if the plot starts out by D and ending
in F
257.
258. int nouv_cons = n2; // we store the new value for the work then
259.
260. nouv_cons = constrain(nouv_cons, 0, 100); // on the new terminal value
between 0 and 100%
261. Serial.print("Output ");
262. Serial.print(n1);
263. Serial.print(" , new value of: ");
264. Serial.print(nouv_cons);
265. Serial.print(" % index, delay: ");
266.
267. set[n1] = (50 - (nouv_cons / 2)); // it converts the value 0-100% in no
phase delay
268.
269. Serial.println (set[n1]);
270. }
271. else // if character from the beginning or end of frame not recognized
272. {Serial.println("Code Unknown");}
273.
274. return i;
275.
276. }