├── 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 | --------------------------------------------------------------------------------