├── LICENSE.md
├── README.md
├── credits.md
├── daliCommands.h
├── daliMaster.cpp
├── daliMaster.h
└── examples
├── pulse
├── README.md
└── pulse.ino
├── serialControl
├── README.md
└── serialControl.ino
├── setAddress
├── README.md
└── setAddress.ino
└── simple
├── README.md
└── simple.ino
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Dave Loba
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # daliMaster
2 |
3 | This is an Arduino™ library to control your DALI lamps with the brand new [daliMaster](https://www.ebay.it/itm/254211672779) shield, with built-in DALI bus power supply system. B:boom::boom:m!
Do you want to use this board with your Raspberry Pi also? Take a look [here](https://www.ebay.it/itm/254473848167)..double B:boom::boom:m!
4 |
5 | ## Description
6 |
7 | ### What is DALI?
8 |
9 | DALI (Digital Addressable Lighting Interface) is a powerful protocol to control lighting. Through DALI you can dimmer your led lamps, ask them status, recall a predefined scenario and so on. If you want more information about DALI you can find many useful links to the bottom of this page.
10 |
11 | ### Can I use DALI with my Arduino™?
12 |
13 | Well, the answer is YES.
14 |
15 | ### How?
16 |
17 | With [daliMaster](https://www.ebay.it/itm/254211672779) shield! As the name suggests, that shield transforms your Arduino™ in a DALI master, acting as a bridge between I2C interface and DALI bus. Let's make an example to explain how it works.
18 |
19 | ## Getting Started
20 |
21 | * Fit [daliMaster](https://www.ebay.it/itm/254211672779) shield on your Arduino™
22 |
23 | * Make connections (you can find an example [here](https://www.ebay.it/itm/254211672779))
24 | * Connect your lamps to their ballasts
25 | * Connect your ballast to mains..be careful!
26 | * Connect your ballasts and [daliMaster](https://www.ebay.it/itm/254211672779) shield to DALI bus
27 | * Connect your 24V DC power supply to mains and to [daliMaster](https://www.ebay.it/itm/254211672779)..again, be careful!
28 |
29 | * If I'm right, now you should have all of lamps on. Let's turn them off.
30 |
31 | * Connect Arduino™ to your computer.
32 |
33 | * Download this library and load **daliMaster/examples/serialControl.ino**
34 |
35 | * Now open serial monitor, select 115000 as baudrate and you should see:
36 | ```
37 | daliMaster start..
38 | i2c master begin..
39 | device(0x23) is ready!
40 | ```
41 | * Well, write and send this command:
42 | ```
43 | -d -b 0
44 | ```
45 | * If everything went well your lamps now are off. But we don't like darkness, so let's switch them on to the minimum:
46 | ```
47 | -d -b 1
48 | ```
49 | * Cool! Let's push them to maximum:
50 | ```
51 | -d -b 254
52 | ```
53 | Easy, isn't it? Now you can modulate all lamps from 0 up to 254 with those simple commands. :thumbsup:
54 |
55 | ## Next
56 |
57 | See more informations about serial commands [here](/examples/serialControl/README.MD). See other examples to play with your lamps (I suggest to try [Pulse.ino](/examples/pulse)). See also the following links to know more about DALI and LW14, the chip from which the [daliMaster](https://www.ebay.it/itm/254211672779) is powered by.
58 |
59 | ## Useful links
60 |
61 | ### LW14
62 | * [LW14 datasheet](https://www.codemercs.com/downloads/ledwarrior/LW14_Datasheet.pdf)
63 |
64 | ### DALI
65 | * [main commands](https://www.acmesystems.it/www_raspberry/openhab_dali/dali_commands.pdf)
66 | * DALI international standard (English/French) [60929 © IEC:2006](http://jnhb.fszjzx.com/upload/biaozhun/pdf/IEC60929Y2006.PDF)
67 |
68 | ## Built With
69 |
70 | * [Eclipse IDE for C/C++ Developers](https://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/lunar)
71 | * [Arduino IDE](https://www.arduino.cc/en/main/software)
72 |
73 | ## Versioning
74 |
75 | * v.1 First release 21/01/2018
76 |
77 | ## Credits
78 |
79 | * **Code Mercenaries** - *Original Raspberry Pi library for LW14 Modules* - [LED-Warrior14](https://www.codemercs.com/en/software)
80 |
81 | see [credits.md](credits.md) file for details.
82 |
83 | ## License
84 |
85 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
86 |
--------------------------------------------------------------------------------
/credits.md:
--------------------------------------------------------------------------------
1 | CREDITS
2 |
3 | daliMaster library for Arduino™ daliMaster shield by [Loba](mailto:davide.loba@gmail.com)
4 |
5 | Sep 2017
6 |
7 | _____________________________________________________________________
8 |
9 | Original Rasberry Pi library by Code Mercenaries
10 | https://www.codemercs.com/en/33-led-warrior/270-led-warrior14-2
11 |
12 | Code Mercenaries Hard- und Software GmbH
13 | Karl-Marx-Strasse 147A
14 | 12529 Schönefeld
15 | Deutschland
16 |
17 | Dec 2016
18 |
--------------------------------------------------------------------------------
/daliCommands.h:
--------------------------------------------------------------------------------
1 | #ifndef __DALI_COMMANDS__
2 | #define __DALI_COMMANDS__
3 |
4 | /*
5 | *
6 | * DALI
7 | *
8 | * 1 start bit
9 | * 8 address bits: 1 individual or group address bit (Y) , 6 address bits, 1 select bit (S)
10 | * 8 data bits
11 | * 2 stop bits
12 | *
13 | * ADDRESS BYTE:
14 | * Short or group address YAAAAAAS
15 | * Short addresses (from 0 to 63) 0AAAAAAS
16 | * Group addresses (from 0 to 15) 100AAAAS
17 | * Broadcast 1111111S
18 |
19 | * Special command 101CCCC1
20 | * Special command 110CCCC1
21 | *
22 | *
23 | * S: selector bit:
24 | * S = ‘0’ direct arc power level following
25 | * S = ‘1’ command following (indirect)
26 | * Y = ‘0’ short address
27 | * Y = ‘1’ group address or broadcast
28 | *
29 | * A: significant address bit
30 | * C: significant command bit
31 | *
32 | * examples:
33 | *
34 | * Direct arc power control command
35 | * YAAA AAA0 XXXX XXXX
36 | *
37 | * indirect arc power control commands
38 | * YAAA AAA1 XXXX XXXX (16-31)
39 | *
40 | * configuration commands
41 | * YAAA AAA1 XXXX XXXX (32-128)
42 | *
43 | * query commands
44 | * YAAA AAA1 XXXX XXXX (144-196)
45 | *
46 | * special commands
47 | * 101CCCC1 XXXX XXXX or
48 | * 110CCCC1 XXXX XXXX
49 | *
50 | *
51 | */
52 |
53 | /*
54 | * DALI indect commands (0 ... 31)
55 | * (IEC-60929, E.4.3.3.1.2)
56 | *
57 | */
58 | #define DALI_CMD_OFF 0x00
59 | #define DALI_CMD_UP 0x01
60 | #define DALI_CMD_DOWN 0x02
61 | #define DALI_CMD_STEP_UP 0x03
62 | #define DALI_CMD_STEP_DOWN 0x04
63 | #define DALI_CMD_MAX_LEVEL 0x05
64 | #define DALI_CMD_MIN_LEVEL 0x06
65 | #define DALI_CMD_STEP_DOWN_AND_OFF 0x07
66 | #define DALI_CMD_ON_AND_STEP_UP 0x08
67 | #define DALI_CMD_ENABLE_DAPC_SEQUENCE 0x09
68 | #define DALI_CMD_GO_TO_SCENE 0x10 //possible values from 0x10 to 0x1F
69 |
70 | /*
71 | * ->DALI configuration commands (32 ... 128)
72 | * (IEC-60929, E.4.3.3.2)
73 | */
74 | #define DALI_CMD_RESET 32
75 | #define DALI_CMD_STORE_LEVEL 33
76 | #define DALI_CMD_STORE_DTR_SA 128
77 |
78 | /*
79 | * ->DALI query commands (144 ... 255)
80 | * (IEC-60929, E.4.3.3.3)
81 | */
82 | #define DALI_CMD_QUERY_STATUS 144
83 | #define DALI_CMD_QUERY_BALLAST 145
84 | #define DALI_CMD_QUERY_FAIL 146
85 | #define DALI_CMD_QUERY_MISS_SA 150
86 | #define DALI_CMD_QUERY_DTR 152
87 | #define DALI_CMD_QUERY_PHY_MIN 154
88 | #define DALI_CMD_QUERY_LEVEL 160
89 | #define DALI_CMD_QUERY_MAX 161
90 | #define DALI_CMD_QUERY_MIN 162
91 |
92 | /*
93 | * ->DALI special commands (144 ... 255)
94 | * (IEC-60929, E.4.3.3.4)
95 | * note that the following codes
96 | * does not match with the commands
97 | * numbers in the paragraph E.4.3.3.4.
98 | * These code are the real command
99 | * representation from binary code.
100 | * e.g.:
101 | * Command 261: 1010 1001 0000 0000 "COMPARE"
102 | * 1010 1011 = 169
103 | */
104 | #define DALI_CMD_TERMINATE 161
105 | #define DALI_CMD_STORE_DTR 163
106 | #define DALI_CMD_INITIALISE 165
107 | #define DALI_CMD_RANDOMISE 167
108 | #define DALI_CMD_COMPARE 169
109 | #define DALI_CMD_WITHDRAW 171
110 |
111 | #define DALI_CMD_SEARCHADDRH 177
112 | #define DALI_CMD_SEARCHADDRM 179
113 | #define DALI_CMD_SEARCHADDRL 181
114 |
115 | #define DALI_CMD_PROG_SA 183
116 | #define DALI_CMD_VERIFY_SA 185
117 | #define DALI_CMD_QUERY_SA 187
118 |
119 |
120 | #endif
121 |
--------------------------------------------------------------------------------
/daliMaster.cpp:
--------------------------------------------------------------------------------
1 | #include "daliMaster.h"
2 |
3 | //______________________________public_________________________
4 |
5 | bool DALIMASTER::begin(const int16_t &myDevice){
6 |
7 |
8 | Serial.println(F("i2c master begin.."));
9 |
10 | if(myDevice < 1 || myDevice > 127){
11 | Serial.println(F("wrong device address!"));
12 | return false;
13 | }
14 |
15 | Wire.beginTransmission(myDevice);
16 | int res = Wire.endTransmission();
17 |
18 | if(!res == 0){
19 | Serial.println(F("no answer from device!"));
20 | return false;
21 | }
22 |
23 | setDevice(myDevice);
24 | return true;
25 | }
26 |
27 |
28 | uint8_t DALIMASTER::scanI2cBus(uint8_t & numDev){
29 |
30 | numDev = 0;
31 | uint8_t i, res = 0;
32 |
33 | for(i = 1; i < 127; i++){
34 |
35 | Wire.beginTransmission(i);
36 | res = Wire.endTransmission();
37 |
38 | if(res == 0){
39 |
40 | Serial.print(F("i2c device found at: 0x"));
41 | if(i < 16)
42 | Serial.print(F("0"));
43 | Serial.print(i, HEX);
44 | Serial.print(F(" ("));
45 | Serial.print(i);
46 | Serial.print(F(")"));
47 | Serial.println();
48 | numDev++;
49 | }
50 | }
51 |
52 | return true;
53 | }
54 |
55 |
56 | bool DALIMASTER::setNewAddr(uint8_t addr){
57 |
58 | if(addr < 1 || addr > 127){
59 | Serial.println(F("wrong address, not set"));
60 | return false;
61 | }
62 |
63 | uint8_t data[] = {addr, (uint8_t)~addr}; //negated addr value to check by the chip
64 | return i2cWrite(this->device, LW14_REG_ADDR, LW14_REG_ADDR_LENGTH, data);
65 | }
66 |
67 |
68 | bool DALIMASTER::regRead(uint8_t addr, uint8_t *data){
69 |
70 | uint8_t length = 0;
71 |
72 | switch(addr){
73 | case LW14_REG_STATUS:
74 | length = LW14_REG_STATUS_LENGTH;
75 | break;
76 | case LW14_REG_CMD:
77 | length = LW14_REG_CMD_LENGTH;
78 | break;
79 | case LW14_REG_SIGNATURE:
80 | length = LW14_REG_SIGNATURE_LENGTH;
81 | break;
82 | default:
83 | Serial.println(F("wrong register address"));
84 | return false;
85 | }
86 |
87 | memset(data,0,length);
88 |
89 | return lw14Read(addr, length, data);
90 | }
91 |
92 |
93 | bool DALIMASTER::regClean(){
94 |
95 | uint8_t dummy[LW14_REG_CMD_LENGTH];
96 | memset(dummy,0,LW14_REG_CMD_LENGTH);
97 | return lw14Read(LW14_REG_CMD, LW14_REG_CMD_LENGTH, dummy);
98 | }
99 |
100 |
101 | bool DALIMASTER::waitForBus(uint16_t timeout){
102 |
103 | uint8_t status[LW14_REG_STATUS_LENGTH];
104 | memset(status,0,LW14_REG_STATUS_LENGTH);
105 | uint32_t previous = millis();
106 |
107 | while(millis() - previous < timeout){ //wait until bus is free
108 |
109 | if(this->regRead(LW14_REG_STATUS,status)
110 | & bitRead(status[0], LW14_STATUS_BUS_BUSY) == 0
111 | & bitRead(status[0], LW14_STATUS_BUS_ERROR) == 0)
112 | return true;
113 |
114 | //this->printReg(LW14_REG_STATUS, status); //DEBUG
115 | }
116 |
117 | return false;
118 | }
119 |
120 | bool DALIMASTER::waitForTel1(uint16_t timeout){
121 |
122 | uint8_t status[LW14_REG_STATUS_LENGTH];
123 | memset(status,0,LW14_REG_STATUS_LENGTH);
124 | uint32_t previous = millis();
125 |
126 | while(millis() - previous < timeout){ //wait until all bits of status reg == 0
127 |
128 | if(this->regRead(LW14_REG_STATUS,status)
129 | & bitRead(status[0], LW14_STATUS_VALID_REPLY)
130 | & bitRead(status[0], LW14_STATUS_1_BYTE_TELEGRAM))
131 | return true;
132 |
133 | //this->printReg(LW14_REG_STATUS, status); //DEBUG
134 | }
135 |
136 | return false;
137 | }
138 |
139 | bool DALIMASTER::waitForTel2(uint16_t timeout){
140 |
141 | uint8_t status[LW14_REG_STATUS_LENGTH];
142 | memset(status,0,LW14_REG_STATUS_LENGTH);
143 | uint32_t previous = millis();
144 |
145 | while(millis() - previous < timeout){ //wait until all bits of status reg == 0
146 |
147 | if(this->regRead(LW14_REG_STATUS,status)
148 | & bitRead(status[0], LW14_STATUS_VALID_REPLY)
149 | & bitRead(status[0], LW14_STATUS_2_BYTE_TELEGRAM))
150 | return true;
151 |
152 | //this->printReg(LW14_REG_STATUS, status); //DEBUG
153 | }
154 |
155 | return false;
156 | }
157 |
158 |
159 | bool DALIMASTER::waitForIdle(uint16_t timeout){
160 |
161 | uint8_t status[LW14_REG_STATUS_LENGTH];
162 | memset(status,0,LW14_REG_STATUS_LENGTH);
163 | uint32_t previous = millis();
164 |
165 | while(millis() - previous < timeout){ //wait until all bits of status reg == 0
166 | if(this->regRead(LW14_REG_STATUS,status)
167 | & status[0] == 0)
168 | return true;
169 |
170 | //this->printReg(LW14_REG_STATUS, status); //DEBUG
171 | }
172 |
173 | return false;
174 | }
175 |
176 | bool DALIMASTER::directCmd(uint8_t addr, uint8_t arc){
177 | //direct arc power control command (E.4.3.3.1.1)
178 | switch(arc){
179 |
180 | case 0 ... 254:{
181 | return cmdSend(addr, arc);
182 | }break;
183 |
184 | default:
185 | Serial.println(F("wrong arc level"));
186 | }
187 |
188 | return false;
189 | }
190 |
191 | bool DALIMASTER::indirectCmd(uint8_t addr, uint8_t arc){
192 | //indirect arc power control commands (E.4.3.3.1.2)
193 |
194 | switch(arc){
195 |
196 | case 0 ... 31:{
197 | return cmdSend(addr, arc);
198 | } break;
199 |
200 | default:
201 | Serial.println(F("wrong indirect command"));
202 | }
203 |
204 | return false;
205 | }
206 |
207 |
208 | bool DALIMASTER::configCmd(uint8_t addr, uint8_t cmd){
209 | //configuration commands (E.4.3.3.2)
210 |
211 | switch(cmd){
212 |
213 | case 32 ... 128:{
214 | return cmdSendTwice(addr, cmd);
215 | } break;
216 |
217 | default:
218 | Serial.println(F("wrong configuration command"));
219 | }
220 |
221 | return false;
222 | }
223 |
224 | bool DALIMASTER::queryCmd(uint8_t addr, uint8_t cmd){
225 | //query commands (E.4.3.3.3)
226 | switch(cmd){
227 |
228 | case 144 ... 255:{ //query commands
229 | return cmdSend(addr, cmd);
230 | } break;
231 |
232 | default:
233 | Serial.println(F("wrong query command"));
234 | }
235 |
236 | return false;
237 | }
238 |
239 |
240 | bool DALIMASTER::specialCmd(uint8_t cmd1, uint8_t cmd2){
241 | //special commands (E.4.3.3.4)
242 |
243 | /*
244 | * TODO
245 | *
246 | * Switch case to grab if we need to doubled command
247 | *
248 | *
249 | */
250 | return cmdSend(cmd1, cmd2);
251 | //or return cmdSendTwice(cmd_1, cmd_2);
252 | }
253 |
254 | void DALIMASTER::printReg(uint8_t addr, uint8_t *data){
255 |
256 | switch(addr){
257 | case LW14_REG_STATUS:
258 | case LW14_REG_CMD:
259 | case LW14_REG_SIGNATURE:
260 | break;
261 | default:
262 | Serial.println(F("wrong register address"));
263 | return;
264 | }
265 |
266 | Serial.print(F("(0x"));
267 | if(addr < 16) Serial.print(F("0"));
268 | Serial.print(addr, HEX);
269 | Serial.print(F(")"));
270 |
271 | switch(addr){
272 |
273 | case LW14_REG_STATUS:
274 |
275 | Serial.print(F(" Status reg"));
276 | Serial.print(F(": "));
277 | Serial.print(data[0]);
278 | Serial.println(F(" ->bits"));
279 | this->printStatusBits(data[0]);
280 |
281 | break;
282 |
283 | case LW14_REG_CMD:
284 |
285 | Serial.print(F(" Command reg: "));
286 | for(int i = 0; i < LW14_REG_CMD_LENGTH; i++){
287 | Serial.print(data[i]);
288 | Serial.print("..");
289 | }
290 |
291 | break;
292 |
293 | case LW14_REG_SIGNATURE:
294 |
295 | Serial.print(F(" Signature reg: "));
296 | for(int i = 0; i < LW14_REG_SIGNATURE_LENGTH; i++){
297 | Serial.print(data[i]);
298 | Serial.print(F(".."));
299 | }
300 | Serial.println();
301 |
302 | break;
303 | }
304 | }
305 |
306 | uint8_t DALIMASTER::setBroadcastAddress(unsigned char mode){
307 | return (0xFE | mode);
308 | }
309 |
310 |
311 | uint8_t DALIMASTER::setGroupAddress(uint8_t group, uint8_t mode){
312 | return (0x80 | ((group & 16) << 1) | mode);
313 | }
314 |
315 |
316 | uint8_t DALIMASTER::setShortAddress(uint8_t device, uint8_t mode){
317 | return (((device & 63) << 1) | mode);
318 | }
319 |
320 |
321 | //______________________________private______________________________________
322 |
323 | void DALIMASTER::setDevice(uint8_t setMe){
324 |
325 | this->device = setMe;
326 | Serial.print(F("device(0x"));
327 | if(this->device < 16)
328 | Serial.print(F("0"));
329 | Serial.print(this->device, HEX);
330 | Serial.println(F(") is ready!"));
331 |
332 | }
333 |
334 |
335 | bool DALIMASTER::cmdSendTwice(uint8_t addr, uint8_t command){
336 |
337 | if(!cmdSend(addr, command))
338 | return false;
339 |
340 | if(!this->waitForBus(100)) //100ms should be the max interval between
341 | return false;
342 |
343 | if(!cmdSend(addr, command))
344 | return false;
345 |
346 | return true;
347 | }
348 |
349 |
350 | bool DALIMASTER::cmdSend(uint8_t addr, uint8_t command){
351 | return lw14Write(addr, command);
352 | }
353 |
354 |
355 | bool DALIMASTER::lw14Write(uint8_t data1, uint8_t data2){
356 |
357 | uint8_t telegram[] = { data1, data2 }; //2 byte commands
358 |
359 | Serial.print(F("dali telegram --> byte 1: "));
360 | Serial.print(telegram[0]);
361 | Serial.print(F("("));
362 | this->printBits(telegram[0]);
363 | Serial.print(F("), byte 2: "));
364 | Serial.print(telegram[1]);
365 | Serial.print(F("("));
366 | this->printBits(telegram[1]);
367 | Serial.print(F(")"));
368 | Serial.println();
369 |
370 | return i2cWrite(this->device, LW14_REG_CMD, LW14_REG_CMD_LENGTH, telegram) ;
371 | }
372 |
373 |
374 | bool DALIMASTER::lw14Read(uint8_t addr, uint8_t length, uint8_t *data){
375 |
376 | if(length > 6 || length < 1){
377 | Serial.println(F("wrong or not handled register length!"));
378 | return false;
379 | }
380 |
381 | return i2cRead(this->device, addr, length, data);
382 | }
383 |
384 |
385 | bool DALIMASTER::i2cWrite(uint8_t device, uint8_t addr, uint8_t length, uint8_t *data){
386 |
387 | Wire.beginTransmission(device); //select slave
388 | Wire.write(addr);//move to this register
389 |
390 | for(int i = 0; i < length; i++){
391 | Wire.write(data[i]); //write 1 byte each time
392 | /*
393 | Serial.print(data[i]);
394 | Serial.print("->\t");
395 | this->printBits(data[i]);
396 | Serial.println();
397 | */
398 | }
399 |
400 | switch(Wire.endTransmission()){
401 | case 0:
402 | Serial.println(F("success"));
403 | return true;
404 | break;
405 | case 1:
406 | Serial.println(F("data too long to fit in transmit buffer"));
407 | break;
408 | case 2:
409 | Serial.println(F("received NACK on transmit of address"));
410 | break;
411 | case 3:
412 | Serial.println(F("received NACK on transmit of data"));
413 | break;
414 | case 4:
415 | Serial.println(F("other error"));
416 | break;
417 | default:
418 | Serial.println(F("error not handled"));
419 | }
420 |
421 | return false;
422 | }
423 |
424 |
425 | bool DALIMASTER::i2cRead(uint8_t device, uint8_t addr, uint8_t length, uint8_t *data){
426 |
427 | Wire.beginTransmission(device);
428 | Wire.write(addr); //move to this register
429 | Wire.endTransmission();
430 |
431 | Wire.requestFrom(device, length);
432 |
433 | if(Wire.available()){
434 | for(int i = 0; i < length; i++){
435 | data[i] = Wire.read();
436 | }
437 | }else{
438 | Wire.endTransmission();
439 | return false;
440 | }
441 |
442 | Wire.endTransmission();
443 | return true;
444 | }
445 |
446 |
447 | void DALIMASTER::printStatusBits(uint8_t myByte){
448 |
449 | //Serial.println(F("\tno.\t7\t6\t5\t4\t3\t2\t1\t0"));
450 | Serial.println(F("\tcode.\tBUS\tBUSY\tOVER\tERR\tREPLY\tTIME\t2TEL\t1TEL"));
451 |
452 | Serial.print(F("\tvalue\t"));
453 | for(int i = 7; i >= 0; i--){
454 | Serial.print(bitRead(myByte,i));
455 | Serial.print(F("\t"));
456 | }
457 |
458 | Serial.println();
459 | }
460 |
461 | void DALIMASTER::printBits(uint8_t myByte){
462 | for(int i = 7; i >= 0; i--){
463 | Serial.print(bitRead(myByte,i));
464 | }
465 | }
466 |
--------------------------------------------------------------------------------
/daliMaster.h:
--------------------------------------------------------------------------------
1 | #ifndef __DALI_MASTER__
2 | #define __DALI_MASTER__
3 |
4 | #include "Arduino.h"
5 | #include "daliCommands.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | //default I2C address
12 | #define BAUDRATE 115200
13 | #define MAX_CHARS 10U
14 |
15 | //default I2C address
16 | #define LW14_DEF_ADDR 0x23U
17 |
18 | #define LW14_I2C_DELAY 2000 //us
19 |
20 | //mode
21 | #define LW14_MODE_DACP 0x00 //direct arc power control
22 | #define LW14_MODE_CMD 0x01
23 |
24 | //register addresses
25 | #define LW14_REG_STATUS 0x00
26 | #define LW14_REG_CMD 0x01
27 | #define LW14_REG_CONFIG 0x02
28 | #define LW14_REG_SIGNATURE 0xF0
29 | #define LW14_REG_ADDR 0xFE
30 |
31 | //register length
32 | #define LW14_REG_STATUS_LENGTH 1
33 | #define LW14_REG_CMD_LENGTH 2
34 | #define LW14_REG_CONFIG_LENGTH 1
35 | #define LW14_REG_SIGNATURE_LENGTH 6
36 | #define LW14_REG_ADDR_LENGTH 2
37 |
38 | //status register bitset
39 | #define LW14_STATUS_1_BYTE_TELEGRAM 0
40 | #define LW14_STATUS_2_BYTE_TELEGRAM 1
41 | #define LW14_STATUS_REPLY_TIMEFRAME 2
42 | #define LW14_STATUS_VALID_REPLY 3
43 | #define LW14_STATUS_FRAME_ERROR 4
44 | #define LW14_STATUS_OVERRUN 5
45 | #define LW14_STATUS_BUS_BUSY 6
46 | #define LW14_STATUS_BUS_ERROR 7
47 |
48 | //DALI stuff
49 | #define DALI_BUS_TIMEOUT 2000
50 | #define MAX_LAMPS_NUM 64
51 | #define DELETE_SA 255U
52 | #define DALI_YES 255U
53 | #define DALI_BROADCAST 255U
54 | #define RESET_DELAY 500000
55 | #define ERR_CODE -1
56 |
57 | /*
58 | 0x00 STATUS REGISTER bits:
59 | 7 - Bus Error Status, 0 = OK, 1 = Bus fault
60 | 6 - Busy, 0 = ready, 1 = Busy
61 | 5 - Overrun
62 | 4 - Frame Error
63 | 3 - Valid REPLY (reset by reading 0x01)
64 | 2 - Reply Timeframe, <22 Te since last command
65 | 1 - 2 Bytes telegram received (reset by reading 0x01)
66 | 0 - 1 Byte telegram received (reset by reading 0x01)
67 | */
68 |
69 | class DALIMASTER{
70 |
71 | private:
72 |
73 | /*
74 | *
75 | * set dali master device number
76 | *
77 | */
78 | void setDevice(uint8_t);
79 |
80 | /*
81 | *
82 | * send cmd
83 | * doubled if needed by dali specification
84 | * @addr
85 | * @command
86 | *
87 | */
88 | bool cmdSend(uint8_t, uint8_t);
89 | bool cmdSendTwice(uint8_t, uint8_t);
90 |
91 |
92 | /*
93 | *
94 | * write command to lw14
95 | * return true if everything is ok
96 | *
97 | */
98 | bool lw14Write(uint8_t, uint8_t);
99 |
100 | /*
101 | *
102 | * read register from lw14
103 | * fill array
104 | * return false if something goes wrong
105 | *
106 | *@address
107 | *@length
108 | *@*data[]
109 | *
110 | */
111 | bool lw14Read(uint8_t, uint8_t, uint8_t *);
112 |
113 |
114 | /*
115 | *
116 | * i2c read and write functions
117 | * device, address, length, buffer arrat
118 | *
119 | */
120 |
121 | bool i2cRead(uint8_t, uint8_t, uint8_t, uint8_t *);
122 | bool i2cWrite(uint8_t, uint8_t, uint8_t, uint8_t *);
123 |
124 | /*
125 | *
126 | * print every single bit
127 | * of one byte num
128 | * useful to print lw14 status register
129 | *
130 | */
131 |
132 | void printStatusBits(uint8_t);
133 | void printBits(uint8_t);
134 |
135 |
136 | /*_____________________________public____________________________*/
137 |
138 | public:
139 |
140 | uint8_t device;
141 |
142 | bool begin(const int16_t &);
143 |
144 | /*
145 | *
146 | * scan i2c bus
147 | * print device found
148 | *
149 | * update reference with their number
150 | * return true
151 | *
152 | */
153 | uint8_t scanI2cBus(uint8_t &);
154 |
155 |
156 | /*
157 | *
158 | * set a new i2C address to led warrior module 14
159 | * and return true if everything is ok
160 | *
161 | */
162 | bool setNewAddr(uint8_t);
163 |
164 | /*
165 | *
166 | * read lw14 register
167 | * and fill array with results
168 | *
169 | * @register address
170 | * @data[]
171 | *
172 | */
173 | bool regRead(uint8_t, uint8_t *);
174 | bool regClean();
175 |
176 | /*
177 | * Wait for a free bus
178 | * Wait for status regs of 0
179 | * or wait for an incoming 1 byte telegram
180 | * or wait for an incoming 2 byte telegram
181 | */
182 | bool waitForBus(uint16_t);
183 | bool waitForIdle(uint16_t);
184 | bool waitForTel1(uint16_t);
185 | bool waitForTel2(uint16_t);
186 |
187 |
188 | /*
189 | *
190 | * Dali commands
191 | * see dali specification for details
192 | *
193 | */
194 |
195 | bool directCmd(uint8_t, uint8_t);
196 |
197 | bool indirectCmd(uint8_t, uint8_t);
198 |
199 | bool configCmd(uint8_t, uint8_t);
200 |
201 | bool queryCmd(uint8_t, uint8_t);
202 |
203 | bool specialCmd(uint8_t, uint8_t);
204 |
205 | /*
206 | *
207 | * print LW14 registers
208 | *
209 | */
210 | void printReg(uint8_t, uint8_t *);
211 |
212 | /*
213 | *
214 | * set the correct Dali address
215 | * the first one is address ???
216 | * the second one is mode (direct or command) ???
217 | * and return it back
218 | *
219 | */
220 |
221 | uint8_t setBroadcastAddress(uint8_t);
222 | uint8_t setGroupAddress(uint8_t, uint8_t);
223 | uint8_t setShortAddress(uint8_t, uint8_t);
224 |
225 | };
226 |
227 | #endif
228 |
--------------------------------------------------------------------------------
/examples/pulse/README.md:
--------------------------------------------------------------------------------
1 | # pulse.ino
2 |
3 | Be careful! This example is cool but puts the voltage regulator of your [daliMaster](https://www.ebay.it/itm/254211672779) under stress (in fact this code is used for the stress tests of the board). Consider adding a heatsink on LM317.
4 |
5 | But now..**let's try it!**
6 |
--------------------------------------------------------------------------------
/examples/pulse/pulse.ino:
--------------------------------------------------------------------------------
1 | #include
2 | DALIMASTER master;
3 |
4 | uint8_t daliAddr = 0;
5 |
6 | void setup() {
7 |
8 | Wire.begin();
9 | Serial.begin(BAUDRATE);
10 | Serial.setTimeout(1); //useful
11 | delay(1000);
12 | Serial.println("Start..");
13 |
14 | master.begin(LW14_DEF_ADDR);
15 | daliAddr = master.setBroadcastAddress(LW14_MODE_DACP);
16 | }
17 |
18 | void loop() {
19 |
20 | for(int i = 254; i > 150; i--){
21 |
22 | if(!master.waitForBus(DALI_BUS_TIMEOUT) | !master.directCmd(daliAddr, i))
23 | Serial.println(F("error."));
24 | }
25 |
26 | for(int i = 150; i < 255; i++){
27 |
28 | if(!master.waitForBus(DALI_BUS_TIMEOUT) | !master.directCmd(daliAddr, i))
29 | Serial.println(F("error."));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/serialControl/README.md:
--------------------------------------------------------------------------------
1 | # serialControl.ino
2 |
3 | Here there is a list of commands that you can send to your Arduino™ through serial port to control daliMaster shield.
4 |
5 | ## Getting started
6 |
7 | Load the program *serialControl.ino* under *examples* folder, open serial monitor and set baudrate to 115000. Write your command in the upper form and press return to send it. Remember that you can send up to 4 arguments at a time. The program will echo the received command and if it is correct it will be execute.
8 | ### Hello world
9 | ```
10 | daliMaster start..
11 | i2c master begin..
12 | device(0x23) is ready!
13 | ```
14 | ### I2C bus scan
15 |
16 | **-s**
17 | Scan I2C bus and report if any I2C devices has been found with their address. Default daliMaster address is 35 (0x23).
18 | ```
19 | -s
20 | received cmd-> -s,,,,
21 | scanning i2c bus..
22 | i2c device found at: 0x23 (35)
23 | i2c devices found: 1
24 | done.
25 | ```
26 | ### Set new I2C address
27 | **-a [new address]**
28 | Set another I2C address to the daliMaster LW14 chip. Values of 128 and more are not accepted.
29 | ```
30 | -a 24
31 | received cmd-> -a,24,,,
32 | setting 24 as new i2c address to lw14..
33 | success
34 | done.
35 | ```
36 | ### Read LW14 register
37 | **-r [register address]**
38 |
39 | Read LW14 register and echo result. See [LW14 datasheet](http://shop.codemercs.com/media/files_public/okutobbwyxn/LW14_Datasheet.pdf) for more details.
40 | * (0x00) STATUS REGISTER
41 | The status register is one byte that contains the bus status and command status flags:
42 | 7 - Bus Error Status *(0 = Bus OK, 1 = Bus fault)*
43 | 6 - Busy *(0 = ready, 1 = busy)*
44 | 5 - Overrun
45 | 4 - Frame Error
46 | 3 - Valid Reply
47 | 2 - Reply Timeframe (*< 22 Te since last command 1 or 2 Byte telegram received*)
48 | 1 - Two byte telegram received
49 | 0 - One byte telegram received
50 | * (0x01) COMMAND REGISTER
51 | The command register has two bytes which directly represent the DALI command. Please refer to the DALI specification for details on the commands.
52 | * (0xFE) SIGNATURE REGISTER
53 | The signature register can be used to identify LW14 and get the revision information for the chips firmware.
54 |
55 |
56 | #### Register reading example
57 | In this example we will ask ballast its phisicaly minimun level and read the response.
58 | First do a dummy reading to free previous messagges on 0x01 LW14 register. Do not mind output.
59 | ```
60 | -r 1
61 | ```
62 | Query lamp with short address 8 with DALI_CMD_QUERY_PHY_MIN code (154).
63 | ```
64 | -q -s 8 154
65 | received cmd-> -q,-s,8,154,
66 | query command
67 | dali telegram --> byte 1: 17(00010001), byte 2: 154(10011010)
68 | success
69 | (now you should read Command reg(0x01) to see the response)
70 | done.
71 | ```
72 | Now if we read the (0x00) STATUS REGISTER we will find that a reply is available.
73 | ```
74 | -r 0
75 | received cmd-> -r,0,,,
76 | reading lw14 register..
77 | (0x00) Status reg: 41 ->bits
78 | code BUS BUSY OVER ERR REPLY TIME 2TEL 1TEL
79 | value 0 0 0 0 1 0 0 1
80 | done.
81 | ```
82 | This register will change quickly after the query in this way.
83 | ```
84 | code BUS BUSY OVER ERR REPLY TIME 2TEL 1TEL
85 | value 0 1 0 0 0 0 0 0
86 | ```
87 | Busy = '1' indicates that the last command has not yet been transmitted. Any new command sent to register 1 will be ignored until the last command has been transmitted and the busy bit is cleared.
88 | ```
89 | code BUS BUSY OVER ERR REPLY TIME 2TEL 1TEL
90 | value 0 0 0 0 0 1 0 0
91 | ```
92 | Time = 1 indicates that the time frame for a reply from the last addressed device has not yet timed out and is reset to zero after 22 Te (see DALI specification) or on bus activity.
93 | ```
94 | code BUS BUSY OVER ERR REPLY TIME 2TEL 1TEL
95 | value 0 0 0 0 1 0 0 1
96 | ```
97 | Valid Reply = 1 if a telegram has been received within 22 Te (see DALI specification) of sending a command. 1Tel = 1 means that 1 byte telegram has been received. The bit is reset on reading register 0x01.
98 |
99 |
100 | So we have a Valid reply and it is a one byte telegram. So read the (0x01) COMMAND REGISTER to get this telegram.
101 | ```
102 | -r 1
103 | received cmd-> -r,1,,,
104 | reading lw14 register..
105 | (0x01) Command reg: 170..0..done.
106 | ```
107 | So, ballast physical minimum is 170. Notice that even if DALI permits 254 levels, ballast cannot dim light under this value.
108 |
109 | ### Address
110 | There are 3 types of addresses:
111 | * **-s [NUM]** short addresses: as DALI specification, each ballast can be reached with a single address from 0 up to 63. When this short address is not already set, ballast reacts only to broadcast commands. To assign this address see the example.
112 | * **-g [NUM]** group addresses: from 0 up to 15. *Please refer to the DALI specification for details on the commands*
113 | * **-b** broadcast: commands sent with a broadcast address will reach every ballast.
114 |
115 | ### DALI forward telegram
116 | #### direct ARC command
117 | **-d [ADDRESS] [LEVEL]**
118 | ```
119 | -d -s 8 200
120 | ```
121 | Command ballast with address 8 to 200 arc power level.
122 | ```
123 | -d -b 0
124 | ```
125 | Command all ballast to switch to 0 (off).
126 | #### indirect command
127 | **-i [ADDRESS] [COMMAND]**
128 | ```
129 | -i -b 5
130 | ```
131 | Set all ballast arc power levels to the "MAX LEVEL" without fading.
132 | #### configuration command
133 | **-c [ADDRESS] [COMMAND]**
134 | ```
135 | -c -s 8 128
136 | ```
137 | Tell ballast 8 to store DTR as its short address.
138 | #### query command
139 | **-q [ADDRESS] [COMMAND]**
140 | ```
141 | -q -s 8 160
142 | ```
143 | Ballast will response with actual arc power level. To read the response, see register reading specifications.
144 | #### special command
145 | **-x [COMMAND] [COMMAND]** *Please refer to the DALI specification for details on the commands*
146 |
--------------------------------------------------------------------------------
/examples/serialControl/serialControl.ino:
--------------------------------------------------------------------------------
1 | #define MAX_CMD 4
2 |
3 | #include
4 | DALIMASTER master;
5 |
6 | void flush();
7 | void setup();
8 |
9 | void loop() {
10 |
11 | if(Serial.available() > 0){
12 |
13 | delay(100); //wait a moment to fill buffer
14 |
15 | String cmd[MAX_CMD];
16 | for(int i = 0; i < MAX_CMD; i++){
17 | String buf = Serial.readStringUntil(' '); //space char
18 | buf = buf.substring(0,buf.indexOf('\r'));
19 | buf = buf.substring(0,buf.indexOf('\n'));
20 | cmd[i]= buf;
21 | }
22 |
23 | Serial.print(F("received cmd-> "));
24 | for(int i = 0; i < MAX_CMD; i++){
25 | Serial.print(cmd[i]);
26 | Serial.print(",");
27 | }
28 | Serial.println();
29 |
30 | bool res = false;
31 |
32 | if(cmd[0].equals("-s")){ //scan i2c bus
33 |
34 | Serial.println(F("scanning i2c bus.."));
35 |
36 | uint8_t devices = 0;
37 | res = master.scanI2cBus(devices);
38 | Serial.print(F("i2c devices found: "));
39 | Serial.println(devices);
40 |
41 | }else if(cmd[0].equals("-a")){ //-a [new i2c address] set new address to lw14
42 |
43 | Serial.print(F("setting "));
44 | Serial.print(cmd[1]);
45 | Serial.println(F(" as new i2c address to lw14.."));
46 | res = master.setNewAddr(cmd[1].toInt());
47 |
48 | }else if(cmd[0].equals("-r")){ //-r [reg address] read lw14 register
49 |
50 | Serial.println(F("reading lw14 register.."));
51 |
52 | uint8_t data[LW14_REG_SIGNATURE_LENGTH]; //max reg length
53 | res = master.regRead(cmd[1].toInt(), data);
54 | master.printReg(cmd[1].toInt(), data);
55 |
56 | }else{ //define and send DALI forward telegram
57 |
58 | uint8_t daliMode, daliAddr, daliCmd = 0;
59 | daliMode = cmd[0].equals("-d")? LW14_MODE_DACP : LW14_MODE_CMD;
60 |
61 | if(!cmd[0].equals("-x")){ //do this just for non-special(x) cmd
62 |
63 | if(cmd[1].equals("-s")){
64 |
65 | if(cmd[2].toInt() < 0 || cmd[2].toInt() > 63){
66 | Serial.println(F("wrong short address"));
67 | return;
68 | }
69 |
70 | daliAddr = master.setShortAddress(cmd[2].toInt(),daliMode);
71 | daliCmd = cmd[3].toInt();
72 |
73 | }else if(cmd[1].equals("-b")){
74 |
75 | daliAddr = master.setBroadcastAddress(daliMode);
76 | daliCmd = cmd[2].toInt();
77 |
78 | }else if(cmd[1].equals("-g")){
79 |
80 | if(cmd[2].toInt() < 0 || cmd[2].toInt() > 15){
81 | Serial.println(F("wrong group address"));
82 | return;
83 | }
84 |
85 | daliAddr = master.setGroupAddress(cmd[2].toInt(),daliMode);
86 | daliCmd = cmd[3].toInt();
87 |
88 | }else{
89 | Serial.println(F("wrong recipient type"));
90 | return;
91 | }
92 | }
93 |
94 | if(cmd[0].equals("-d")){ //direct arc power command
95 |
96 | Serial.println(F("direct arc power command"));
97 | res = master.directCmd(daliAddr, daliCmd);
98 |
99 | }else if(cmd[0].equals("-i")){ //indirect arc power command
100 |
101 | Serial.println(F("indirect arc power command"));
102 | res = master.indirectCmd(daliAddr, daliCmd);
103 |
104 | }else if(cmd[0].equals("-c")){ //configuration command
105 |
106 | Serial.println(F("configuration command"));
107 | res = master.configCmd(daliAddr, daliCmd);
108 |
109 | }else if(cmd[0].equals("-q")){ //query command
110 |
111 | Serial.println(F("query command"));
112 | res = master.queryCmd(daliAddr, daliCmd);
113 | if(res)
114 | Serial.println(F("(now you should read Command reg(0x01) to see the response)"));
115 |
116 | }else if(cmd[0].equals("-x")){ //special command
117 |
118 | Serial.println(F("special command"));
119 | res = master.specialCmd(cmd[1].toInt(), cmd[2].toInt()); //use original cmd
120 |
121 | }else{
122 |
123 | Serial.println(F("wrong command"));
124 | return;
125 |
126 | }
127 | }
128 |
129 |
130 | if(res){
131 | Serial.println(F("done."));
132 | }else{
133 | Serial.println(F("error."));
134 | }
135 |
136 | }
137 |
138 |
139 | } //end of loop
140 |
141 | //---functions
142 |
143 | void flush(){
144 | while(Serial.available()>0) Serial.read();
145 | }
146 |
147 |
148 | void setup() {
149 |
150 | Wire.begin();
151 | Serial.begin(BAUDRATE);
152 | Serial.setTimeout(1); //useful
153 | delay(1000);
154 | Serial.println(F("start.."));
155 |
156 | if(!master.begin(LW14_DEF_ADDR))
157 | exit(1);
158 | }
159 |
--------------------------------------------------------------------------------
/examples/setAddress/README.md:
--------------------------------------------------------------------------------
1 | # setAddress.ino
2 |
3 | Open the Serial monitor set baudrate to 115000 and follow the instruction to set custom DALI address.
4 |
--------------------------------------------------------------------------------
/examples/setAddress/setAddress.ino:
--------------------------------------------------------------------------------
1 | #include
2 | DALIMASTER master;
3 |
4 | uint8_t myData[LW14_REG_CMD_LENGTH];
5 | uint32_t previous = 0;
6 |
7 | void flush();
8 | void setup();
9 |
10 | void loop() {
11 |
12 | if(Serial.available() > 0){
13 |
14 | delay(100); //wait a moment to fill buffer
15 |
16 | String buf = Serial.readStringUntil('\n');
17 | flush(); //needed
18 |
19 | uint16_t daliSa = buf.toInt();
20 | bool res = false;
21 |
22 | switch (daliSa) {
23 |
24 | case 0 ... 63:{
25 |
26 | Serial.print(F("This command will assign \'"));
27 | Serial.print(daliSa);
28 | Serial.println(F("\' as new address with a broadcasted command."));
29 | Serial.println(F("Be sure that just one ballast will receive it. Continue? (digit \"Y\" for YES)"));
30 |
31 | while(true){ //wait for Y
32 |
33 | if(Serial.available() > 0){
34 |
35 | delay(100); //wait a moment to fill buffer
36 |
37 | String buf = Serial.readStringUntil('\n');
38 |
39 | if(buf.indexOf('Y') != -1 | buf.indexOf('y') != -1){
40 |
41 | /*
42 | 60929 © IEC:2006
43 | Only one ballast connected separately to the control unit for a simplified addressing method:
44 | Send first the new short address (0AAA AAA1) by command 257 "DATA TRANSFER REGISTER (DTR)",
45 | verify the content of the DTR and send command 128 "STORE DTR AS SHORT ADDRESS" two times.
46 | */
47 |
48 | uint8_t dtr = master.setShortAddress(daliSa, LW14_MODE_CMD); //DTR structure 0AAA AAA1
49 | uint8_t broadcastAddr = master.setBroadcastAddress(LW14_MODE_CMD);
50 |
51 | Serial.println(F("\r\n---> Store new address into DTR <---")); //DEBUG
52 |
53 | if(!master.regClean() | !master.specialCmd(DALI_CMD_STORE_DTR, dtr)){
54 | Serial.println(F("unable to set DTR!"));
55 | break;
56 | }
57 |
58 | if(!master.waitForIdle(DALI_BUS_TIMEOUT)){
59 | Serial.println(F("idle timeout!")); //DEBUG
60 | break;
61 | }
62 |
63 | Serial.println(F("\r\n---> Read DTR back and check it again.. <---")); //DEBUG
64 |
65 | if(!master.regClean() | !master.queryCmd(broadcastAddr, DALI_CMD_QUERY_DTR)){
66 | Serial.println(F("unable to read DTR back!"));
67 | break;
68 | }
69 |
70 | if(!master.waitForTel1(DALI_BUS_TIMEOUT)){
71 | Serial.println(F("telegram timeout!")); //DEBUG
72 | break;
73 | }
74 |
75 | if(!master.regRead(LW14_REG_CMD, myData) | myData[0] != dtr){
76 | Serial.println(F("DTR does not match!")); //DEBUG
77 | break;
78 | }
79 |
80 | Serial.println(F("\r\n--> DTR match! Now save as new address <--")); //DEBUG
81 |
82 | if(!master.configCmd(broadcastAddr, DALI_CMD_STORE_DTR_SA))
83 | break;
84 |
85 | if(!master.waitForIdle(DALI_BUS_TIMEOUT)){
86 | Serial.println(F("idle timeout!")); //DEBUG
87 | break;
88 | }
89 |
90 | Serial.println(F("\r\n--> Ask if there is a ballast with the given address that is able to communicate <--")); //DEBUG
91 |
92 | if(!master.regClean() | !master.queryCmd(master.setShortAddress(daliSa, LW14_MODE_CMD), DALI_CMD_QUERY_BALLAST))
93 | break;
94 |
95 | if(!master.waitForTel1(DALI_BUS_TIMEOUT)){
96 | Serial.println(F("telegram timeout!")); //DEBUG
97 | break;
98 | }
99 |
100 | if(!master.regRead(LW14_REG_CMD, myData) | myData[0] != DALI_YES)
101 | break;
102 |
103 | Serial.println(F("\r\n--> Well, now make it flash! <--")); //DEBUG
104 |
105 | master.indirectCmd(master.setShortAddress(daliSa, LW14_MODE_CMD), DALI_CMD_OFF);
106 | master.waitForBus(DALI_BUS_TIMEOUT);
107 | delay(200);
108 | master.indirectCmd(master.setShortAddress(daliSa, LW14_MODE_CMD), DALI_CMD_MAX_LEVEL);
109 | res = true;
110 |
111 | // break; //exit while(true);
112 |
113 | }
114 |
115 | /*else{
116 | break;
117 | }*/
118 |
119 | break;
120 |
121 | } //end of if Serial is available
122 | } //end of while(true)
123 |
124 | } break;
125 |
126 | default:
127 |
128 | Serial.println(F("wrong DALI short address. "));
129 |
130 | } //end of switch
131 |
132 | if(res){
133 | Serial.println(F("\r\n--> New address assigned and verified. Done. <--"));
134 | Serial.println();
135 | }else{
136 | Serial.println(F("\r\n--> Error. <--"));
137 | Serial.println();
138 | }
139 |
140 | Serial.println(F("Digit address to set (0-63) to repeate the procedure."));
141 | flush();
142 | }
143 |
144 |
145 | } //end of loop
146 |
147 | //---functions
148 |
149 | void flush(){
150 | while(Serial.available()>0) Serial.read();
151 | }
152 |
153 |
154 | void setup() {
155 |
156 | Wire.begin();
157 | Serial.begin(BAUDRATE);
158 | Serial.setTimeout(1); //useful
159 | delay(1000);
160 | Serial.println("Start..");
161 |
162 | if(!master.begin(LW14_DEF_ADDR))
163 | exit(1);
164 |
165 | Serial.println("Digit address to set (0-63):");
166 | }
167 |
--------------------------------------------------------------------------------
/examples/simple/README.md:
--------------------------------------------------------------------------------
1 | # simple.ino
2 |
3 | Simple program that set one lamp with a direct arc command and query its actual level to confirm the right receiving of the message. Open the Serial monitor, set baudrate to 115000 and see the output. Remember to change *DALISA* and *LEVEL* definitions according with your setup.
4 |
5 | Note the use of those methods:
6 |
7 | * **DALIMASTER::regClean()**
8 |
9 |
10 | Read 0x01 LW14 command register just to reset LW14 status register bits of incoming messages.
11 | * **DALIMASTER::waitForBus(TIMEOUT)**
12 |
13 |
14 | Wait for bit *LW14_STATUS_BUS_BUSY* and bit *LW14_STATUS_BUS_ERROR* of *0x00 LW14 STATUS REGISTER* to be '0'.
15 | * **DALIMASTER::waitForTel1(TIMEOUT)**
16 |
17 |
18 | Wait for bit *LW14_STATUS_VALID_REPLY* and bit *LW14_STATUS_1_BYTE_TELEGRAM* of *0x01 LW14 COMMAND REGISTER* to be '1'. After that, a new message is available into 0x01 LW14 command register.
19 |
--------------------------------------------------------------------------------
/examples/simple/simple.ino:
--------------------------------------------------------------------------------
1 | #define DALISA 8
2 | #define LEVEL 205
3 |
4 | #include
5 |
6 | DALIMASTER master;
7 |
8 | void setup() {
9 |
10 | Wire.begin();
11 | Serial.begin(BAUDRATE);
12 | Serial.setTimeout(1); //useful
13 | delay(1000);
14 | Serial.println("Start..");
15 |
16 | if(!master.begin(LW14_DEF_ADDR))
17 | errorHandler(1);
18 |
19 | Serial.print(F("Set lamp "));
20 | Serial.print(DALISA);
21 | Serial.print(F(" to "));
22 | Serial.print(LEVEL);
23 | Serial.println();
24 |
25 | uint8_t daliAddr = 0;
26 | daliAddr = master.setShortAddress(DALISA, LW14_MODE_DACP);
27 |
28 | if(!master.waitForBus(DALI_BUS_TIMEOUT) | !master.directCmd(daliAddr, LEVEL))
29 | errorHandler(2);
30 |
31 | Serial.print(F("Now ask lamp level"));
32 | Serial.println();
33 |
34 | daliAddr = master.setShortAddress(DALISA, LW14_MODE_CMD);
35 |
36 | if(!master.regClean())
37 | errorHandler(4);
38 |
39 | if(!master.waitForBus(DALI_BUS_TIMEOUT) | !master.queryCmd(daliAddr, DALI_CMD_QUERY_LEVEL))
40 | errorHandler(5);
41 |
42 | uint8_t myData[2];
43 |
44 | if(!master.waitForTel1(DALI_BUS_TIMEOUT) | !master.regRead(LW14_REG_CMD, myData))
45 | errorHandler(6);
46 |
47 | Serial.print(F("Actual lamp level is "));
48 | Serial.print(myData[0]);
49 | Serial.println(F(". End."));
50 |
51 | }
52 |
53 | void loop(){
54 | //do nothing
55 | }
56 |
57 | void errorHandler(uint8_t code){
58 | Serial.println(F("error "));
59 | Serial.println(code);
60 | Serial.println(F("end."));
61 | exit(1);
62 | }
63 |
64 |
--------------------------------------------------------------------------------