Commit d12c5238758a004eb7be70800dc413291d65a75f

Authored by qqqlab
Committed by GitHub
1 parent 7c023deb

.

Examples/Commissioning/Commissioning.ino 0 → 100644
  1 +/*###########################################################################
  2 +DALI Interface Demo
  3 +
  4 +Commissioning demo - assign short addresses to all LED Drivers on the DALI bus
  5 +
  6 +Works with Arduino ATMEGA328 + Mikroe DALI Click
  7 +
  8 +----------------------------------------------------------------------------
  9 +Changelog:
  10 +2020-11-08 Created & tested on ATMega328 @ 8Mhz
  11 +----------------------------------------------------------------------------
  12 + Commisioning.ino - copyright qqqlab.com / github.com/qqqlab
  13 +
  14 + This program is free software: you can redistribute it and/or modify
  15 + it under the terms of the GNU General Public License as published by
  16 + the Free Software Foundation, either version 3 of the License, or
  17 + (at your option) any later version.
  18 +
  19 + This program is distributed in the hope that it will be useful,
  20 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22 + GNU General Public License for more details.
  23 +
  24 + You should have received a copy of the GNU General Public License
  25 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  26 +###########################################################################*/
  27 +
  28 +#define DALI_OUTPUT_PIN 3
  29 +#define DALI_INPUT_PIN 4
  30 +
  31 +#include "qqqDali.h"
  32 +
  33 +Dali dali;
  34 +
  35 +void setup() {
  36 + Serial.begin(115200);
  37 + Serial.println("DALI Commisioning Demo");
  38 +
  39 + //start the DALI interfaces
  40 + //arguments: tx_pin, rx_pin (negative values disable transmitter / receiver)
  41 + //Note: the receiver pins should be on different PCINT groups, e.g one
  42 + //receiver on pin0-7 (PCINT2) one on pin8-13 (PCINT0) and one on pin14-19 (PCINT1)
  43 + dali.begin(DALI_OUTPUT_PIN, DALI_INPUT_PIN);
  44 +
  45 + menu();
  46 +}
  47 +
  48 +
  49 +void loop() {
  50 + while (Serial.available() > 0) {
  51 + int incomingByte = Serial.read();
  52 + switch(incomingByte) {
  53 + case '1': scan_short_addr(); menu(); break;
  54 + case '2': delete_short_addr(); menu(); break;
  55 + case '3': commission_wo_short(); menu(); break;
  56 + case '4': commission_all(); menu(); break;
  57 + }
  58 + }
  59 +}
  60 +
  61 +void menu() {
  62 + Serial.println("----------------------------");
  63 + Serial.println("1 Scan all short addresses");
  64 + Serial.println("2 Dele1te all short addresses");
  65 + Serial.println("3 Commission w/o short adr");
  66 + Serial.println("4 Commission all short addresses");
  67 + Serial.println("----------------------------");
  68 +}
  69 +
  70 +void delete_short_addr() {
  71 + Serial.println("Running: Delete all short addresses");
  72 + //remove all short addresses
  73 + dali.cmd(DALI_DATA_TRANSFER_REGISTER0,0xFF);
  74 + dali.cmd(DALI_SET_SHORT_ADDRESS, 0xFF);
  75 +}
  76 +
  77 +void scan_short_addr() {
  78 + Serial.println("Running: Scan all short addresses");
  79 + uint8_t sa;
  80 + for(sa = 0; sa<64; sa++) {
  81 + int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa);
  82 + if(rv!=DALI_RESULT_NO_REPLY) {
  83 + Serial.print(sa);
  84 + Serial.print(" status=0x");
  85 + Serial.print(rv,HEX);
  86 + Serial.print(" minLevel=");
  87 + Serial.print(dali.cmd(DALI_QUERY_MIN_LEVEL,sa));
  88 + for(uint8_t i=0;i<5;i++) {
  89 + dali.set_level(254,sa);
  90 + Serial.print(".");
  91 + delay(500);
  92 + dali.set_level(0,sa);
  93 + Serial.print(".");
  94 + delay(500);
  95 + }
  96 + Serial.println();
  97 + }
  98 +// }else{
  99 +// //remove all short addres for this sa
  100 +// dali.cmd(DALI_DATA_TRANSFER_REGISTER0,0xFF);
  101 +// dali.cmd(DALI_SET_SHORT_ADDRESS, sa);
  102 +// }
  103 + }
  104 +}
  105 +
  106 +//might need a couple of calls to find everything...
  107 +void commission_wo_short(){
  108 + Serial.println("Running: Commission w/o short adr");
  109 + dali.commission(0xff); //init_arg=0b11111111 : all without short address
  110 +}
  111 +
  112 +void commission_all(){
  113 + Serial.println("Running: Commission all");
  114 + dali.commission(0x00); //init_arg=0b00000000 : all
  115 +}
... ...
qqqDali.cpp
... ... @@ -394,4 +394,138 @@ uint8_t Dali::set_value(uint16_t setcmd, uint16_t getcmd, uint8_t v, uint8_t adr
394 394 return 0;
395 395 }
396 396  
397   -
  397 +
  398 +//======================================================================
  399 +// Commissioning short addresses
  400 +//======================================================================
  401 +
  402 +//Sets the slave Note 1 to the INITIALISE status for15 minutes.
  403 +//Commands 259 to 270 are enabled only for a slave in this
  404 +//status.
  405 +
  406 +//set search address
  407 +void Dali::set_searchaddr(uint32_t adr) {
  408 + this->cmd(DALI_SEARCHADDRH,adr>>16);
  409 + this->cmd(DALI_SEARCHADDRM,adr>>8);
  410 + this->cmd(DALI_SEARCHADDRL,adr);
  411 +}
  412 +
  413 +//set search address, but set only changed bytes
  414 +void Dali::set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current) {
  415 + if( (uint8_t)(adr_new>>16) != (uint8_t)(adr_current>>16) ) this->cmd(DALI_SEARCHADDRH,adr_new>>16);
  416 + if( (uint8_t)(adr_new>>8) != (uint8_t)(adr_current>>8) ) this->cmd(DALI_SEARCHADDRM,adr_new>>8);
  417 + if( (uint8_t)(adr_new) != (uint8_t)(adr_current) ) this->cmd(DALI_SEARCHADDRL,adr_new);
  418 +}
  419 +
  420 +//Is the random address smaller or equal to the search address?
  421 +uint8_t Dali::compare() {
  422 + return (0xff == this->cmd(DALI_COMPARE,0x00));
  423 +}
  424 +
  425 +
  426 +
  427 +//The slave shall store the received 6-bit address (AAAAAA) as a short address if it is selected.
  428 +void Dali::program_short_address(uint8_t shortadr) {
  429 + this->cmd(DALI_PROGRAM_SHORT_ADDRESS, (shortadr << 1) | 0x01);
  430 +}
  431 +
  432 +//What is the short address of the slave being selected?
  433 +uint8_t Dali::query_short_address() {
  434 + return this->cmd(DALI_QUERY_SHORT_ADDRESS, 0x00) >> 1;
  435 +}
  436 +
  437 +//find addr with binary search
  438 +uint32_t Dali::find_addr() {
  439 + uint32_t adr = 0x800000;
  440 + uint32_t addsub = 0x400000;
  441 + uint32_t adr_last = adr;
  442 + this->set_searchaddr(adr);
  443 +
  444 + while(addsub) {
  445 + this->set_searchaddr_diff(adr,adr_last);
  446 + adr_last = adr;
  447 + uint8_t cmp = this->compare();
  448 + //Serial.print("cmp ");
  449 + //Serial.print(adr,HEX);
  450 + //Serial.print(" = ");
  451 + //Serial.println(cmp);
  452 + if(cmp) adr-=addsub; else adr+=addsub;
  453 + addsub >>= 1;
  454 + }
  455 + this->set_searchaddr_diff(adr,adr_last);
  456 + adr_last = adr;
  457 + if(!this->compare()) {
  458 + adr++;
  459 + this->set_searchaddr_diff(adr,adr_last);
  460 + }
  461 + return adr;
  462 +}
  463 +
  464 +//init_arg=11111111 : all without short address
  465 +//init_arg=00000000 : all
  466 +//init_arg=0AAAAAA1 : only for this shortadr
  467 +uint8_t Dali::commission(uint8_t init_arg) {
  468 + uint8_t cnt = 0;
  469 + uint8_t arr[64];
  470 + uint8_t sa;
  471 + for(sa=0; sa<64; sa++) arr[sa]=0;
  472 +
  473 + //find existing short addresses
  474 +// if(init_arg==0xff) {
  475 + Serial.println("Short adr");
  476 + for(sa = 0; sa<64; sa++) {
  477 + int16_t rv = this->cmd(DALI_QUERY_STATUS,sa);
  478 + if(rv!=DALI_RESULT_NO_REPLY) {
  479 + arr[sa]=1;
  480 + cnt++;
  481 + Serial.print(sa);
  482 + Serial.print(" status=0x");
  483 + Serial.print(rv,HEX);
  484 + Serial.print(" minLevel=");
  485 + Serial.println(this->cmd(DALI_QUERY_MIN_LEVEL,sa));
  486 + }
  487 + }
  488 +// }
  489 +
  490 + this->cmd(DALI_INITIALISE,init_arg);
  491 + this->cmd(DALI_RANDOMISE,0x00);
  492 + delay(100);
  493 +
  494 + while(cnt<64) {
  495 + //Serial.print("addr=");
  496 + //Serial.println(this->get_random_address(0xff),HEX);
  497 +
  498 + uint32_t adr = this->find_addr();
  499 + if(adr>0xffffff) break;
  500 + Serial.print("found adr=");
  501 + Serial.println(adr,HEX);
  502 +
  503 + //Serial.print("short adr=");
  504 + //Serial.println(dali_query_short_address());
  505 +
  506 + //find available address
  507 + for(sa=0; sa<64; sa++) {
  508 + if(arr[sa]==0) break;
  509 + }
  510 + if(sa>=64) break;
  511 + arr[sa] = 1;
  512 + cnt++;
  513 +
  514 + Serial.print("program short adr=");
  515 + Serial.println(sa);
  516 + this->program_short_address(sa);
  517 + //dali_program_short_address(0xff);
  518 +
  519 + Serial.print("read short adr=");
  520 + Serial.println(this->query_short_address());
  521 +
  522 + this->cmd(DALI_WITHDRAW,0x00);
  523 + }
  524 +
  525 + this->cmd(DALI_TERMINATE,0x00);
  526 + return cnt;
  527 +}
  528 +
  529 +
  530 +
  531 +//======================================================================
... ...
qqqDali.h
... ... @@ -23,28 +23,36 @@ Changelog:
23 23  
24 24 class Dali {
25 25 public:
26   - void begin(int8_t tx_pin, int8_t rx_pin);
  26 + void begin(int8_t tx_pin, int8_t rx_pin);
27 27  
28 28 //high level functions
29   - void set_level(uint8_t level, uint8_t adr=0xFF); //set arc level
30   - int16_t cmd(uint16_t cmd, uint8_t arg); //execute DALI command, use a DALI_xxx command define as cmd argument, returns negative DALI_RESULT_xxx or reply byte
31   - uint8_t set_operating_mode(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
32   - uint8_t set_max_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
33   - uint8_t set_min_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
34   - uint8_t set_system_failure_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
35   - uint8_t set_power_on_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
36   -
  29 + void set_level(uint8_t level, uint8_t adr=0xFF); //set arc level
  30 + int16_t cmd(uint16_t cmd, uint8_t arg); //execute DALI command, use a DALI_xxx command define as cmd argument, returns negative DALI_RESULT_xxx or reply byte
  31 + uint8_t set_operating_mode(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  32 + uint8_t set_max_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  33 + uint8_t set_min_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  34 + uint8_t set_system_failure_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  35 + uint8_t set_power_on_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
37 36  
  37 + //commissioning
  38 + uint8_t commission(uint8_t init_arg=0xff);
  39 + void set_searchaddr(uint32_t adr);
  40 + void set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current);
  41 + uint8_t compare();
  42 + void program_short_address(uint8_t shortadr);
  43 + uint8_t query_short_address();
  44 + uint32_t find_addr();
  45 +
38 46  
39 47 //low level functions
40 48 typedef void (*EventHandlerReceivedDataFuncPtr)(Dali *sender, uint8_t *data, uint8_t len);
41 49 EventHandlerReceivedDataFuncPtr EventHandlerReceivedData;
42 50  
43   - uint8_t send(uint8_t* tx_msg, uint8_t tx_len_bytes);
44   - uint8_t sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_ms=500);
45   - int16_t tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_ms=500);
46   - void ISR_timer();
47   - void ISR_pinchange();
  51 + uint8_t send(uint8_t* tx_msg, uint8_t tx_len_bytes);
  52 + uint8_t sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_ms=500);
  53 + int16_t tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_ms=500);
  54 + void ISR_timer();
  55 + void ISR_pinchange();
48 56  
49 57 #define DALI_HOOK_COUNT 3
50 58  
... ... @@ -52,16 +60,16 @@ public:
52 60 private:
53 61 //low level functions
54 62 enum tx_stateEnum { TX_IDLE=0,TX_START,TX_START_X,TX_BIT,TX_BIT_X,TX_STOP1,TX_STOP1_X,TX_STOP2,TX_STOP2_X,TX_STOP3};
55   - uint8_t tx_pin; //transmitter pin
56   - uint8_t tx_msg[3]; //message to transmit
57   - uint8_t tx_len; //number of bits to transmit
  63 + uint8_t tx_pin; //transmitter pin
  64 + uint8_t tx_msg[3]; //message to transmit
  65 + uint8_t tx_len; //number of bits to transmit
58 66 volatile uint8_t tx_pos; //current bit transmit position
59 67 volatile tx_stateEnum tx_state; //current state
60 68 volatile uint8_t tx_collision; //collistion occured
61 69 volatile uint8_t tx_bus_low; //bus is low according to transmitter?
62 70  
63 71 enum rx_stateEnum { RX_IDLE,RX_START,RX_BIT};
64   - uint8_t rx_pin; //receiver pin
  72 + uint8_t rx_pin; //receiver pin
65 73 volatile uint8_t rx_last_bus_low; //receiver as low at last pinchange
66 74 volatile uint32_t rx_last_change_ts; //timestamp last pinchange
67 75 volatile rx_stateEnum rx_state; //current state
... ...