From d12c5238758a004eb7be70800dc413291d65a75f Mon Sep 17 00:00:00 2001 From: qqqlab <46283638+qqqlab@users.noreply.github.com> Date: Mon, 9 Nov 2020 01:22:18 +0100 Subject: [PATCH] . --- Examples/Commissioning/Commissioning.ino | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ qqqDali.cpp | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- qqqDali.h | 44 ++++++++++++++++++++++++++------------------ 3 files changed, 276 insertions(+), 19 deletions(-) create mode 100644 Examples/Commissioning/Commissioning.ino diff --git a/Examples/Commissioning/Commissioning.ino b/Examples/Commissioning/Commissioning.ino new file mode 100644 index 0000000..72ea451 --- /dev/null +++ b/Examples/Commissioning/Commissioning.ino @@ -0,0 +1,115 @@ +/*########################################################################### +DALI Interface Demo + +Commissioning demo - assign short addresses to all LED Drivers on the DALI bus + +Works with Arduino ATMEGA328 + Mikroe DALI Click + +---------------------------------------------------------------------------- +Changelog: +2020-11-08 Created & tested on ATMega328 @ 8Mhz +---------------------------------------------------------------------------- + Commisioning.ino - copyright qqqlab.com / github.com/qqqlab + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +###########################################################################*/ + +#define DALI_OUTPUT_PIN 3 +#define DALI_INPUT_PIN 4 + +#include "qqqDali.h" + +Dali dali; + +void setup() { + Serial.begin(115200); + Serial.println("DALI Commisioning Demo"); + + //start the DALI interfaces + //arguments: tx_pin, rx_pin (negative values disable transmitter / receiver) + //Note: the receiver pins should be on different PCINT groups, e.g one + //receiver on pin0-7 (PCINT2) one on pin8-13 (PCINT0) and one on pin14-19 (PCINT1) + dali.begin(DALI_OUTPUT_PIN, DALI_INPUT_PIN); + + menu(); +} + + +void loop() { + while (Serial.available() > 0) { + int incomingByte = Serial.read(); + switch(incomingByte) { + case '1': scan_short_addr(); menu(); break; + case '2': delete_short_addr(); menu(); break; + case '3': commission_wo_short(); menu(); break; + case '4': commission_all(); menu(); break; + } + } +} + +void menu() { + Serial.println("----------------------------"); + Serial.println("1 Scan all short addresses"); + Serial.println("2 Dele1te all short addresses"); + Serial.println("3 Commission w/o short adr"); + Serial.println("4 Commission all short addresses"); + Serial.println("----------------------------"); +} + +void delete_short_addr() { + Serial.println("Running: Delete all short addresses"); + //remove all short addresses + dali.cmd(DALI_DATA_TRANSFER_REGISTER0,0xFF); + dali.cmd(DALI_SET_SHORT_ADDRESS, 0xFF); +} + +void scan_short_addr() { + Serial.println("Running: Scan all short addresses"); + uint8_t sa; + for(sa = 0; sa<64; sa++) { + int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa); + if(rv!=DALI_RESULT_NO_REPLY) { + Serial.print(sa); + Serial.print(" status=0x"); + Serial.print(rv,HEX); + Serial.print(" minLevel="); + Serial.print(dali.cmd(DALI_QUERY_MIN_LEVEL,sa)); + for(uint8_t i=0;i<5;i++) { + dali.set_level(254,sa); + Serial.print("."); + delay(500); + dali.set_level(0,sa); + Serial.print("."); + delay(500); + } + Serial.println(); + } +// }else{ +// //remove all short addres for this sa +// dali.cmd(DALI_DATA_TRANSFER_REGISTER0,0xFF); +// dali.cmd(DALI_SET_SHORT_ADDRESS, sa); +// } + } +} + +//might need a couple of calls to find everything... +void commission_wo_short(){ + Serial.println("Running: Commission w/o short adr"); + dali.commission(0xff); //init_arg=0b11111111 : all without short address +} + +void commission_all(){ + Serial.println("Running: Commission all"); + dali.commission(0x00); //init_arg=0b00000000 : all +} diff --git a/qqqDali.cpp b/qqqDali.cpp index 2eb2aef..97d4b4f 100644 --- a/qqqDali.cpp +++ b/qqqDali.cpp @@ -394,4 +394,138 @@ uint8_t Dali::set_value(uint16_t setcmd, uint16_t getcmd, uint8_t v, uint8_t adr return 0; } - + +//====================================================================== +// Commissioning short addresses +//====================================================================== + +//Sets the slave Note 1 to the INITIALISE status for15 minutes. +//Commands 259 to 270 are enabled only for a slave in this +//status. + +//set search address +void Dali::set_searchaddr(uint32_t adr) { + this->cmd(DALI_SEARCHADDRH,adr>>16); + this->cmd(DALI_SEARCHADDRM,adr>>8); + this->cmd(DALI_SEARCHADDRL,adr); +} + +//set search address, but set only changed bytes +void Dali::set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current) { + if( (uint8_t)(adr_new>>16) != (uint8_t)(adr_current>>16) ) this->cmd(DALI_SEARCHADDRH,adr_new>>16); + if( (uint8_t)(adr_new>>8) != (uint8_t)(adr_current>>8) ) this->cmd(DALI_SEARCHADDRM,adr_new>>8); + if( (uint8_t)(adr_new) != (uint8_t)(adr_current) ) this->cmd(DALI_SEARCHADDRL,adr_new); +} + +//Is the random address smaller or equal to the search address? +uint8_t Dali::compare() { + return (0xff == this->cmd(DALI_COMPARE,0x00)); +} + + + +//The slave shall store the received 6-bit address (AAAAAA) as a short address if it is selected. +void Dali::program_short_address(uint8_t shortadr) { + this->cmd(DALI_PROGRAM_SHORT_ADDRESS, (shortadr << 1) | 0x01); +} + +//What is the short address of the slave being selected? +uint8_t Dali::query_short_address() { + return this->cmd(DALI_QUERY_SHORT_ADDRESS, 0x00) >> 1; +} + +//find addr with binary search +uint32_t Dali::find_addr() { + uint32_t adr = 0x800000; + uint32_t addsub = 0x400000; + uint32_t adr_last = adr; + this->set_searchaddr(adr); + + while(addsub) { + this->set_searchaddr_diff(adr,adr_last); + adr_last = adr; + uint8_t cmp = this->compare(); + //Serial.print("cmp "); + //Serial.print(adr,HEX); + //Serial.print(" = "); + //Serial.println(cmp); + if(cmp) adr-=addsub; else adr+=addsub; + addsub >>= 1; + } + this->set_searchaddr_diff(adr,adr_last); + adr_last = adr; + if(!this->compare()) { + adr++; + this->set_searchaddr_diff(adr,adr_last); + } + return adr; +} + +//init_arg=11111111 : all without short address +//init_arg=00000000 : all +//init_arg=0AAAAAA1 : only for this shortadr +uint8_t Dali::commission(uint8_t init_arg) { + uint8_t cnt = 0; + uint8_t arr[64]; + uint8_t sa; + for(sa=0; sa<64; sa++) arr[sa]=0; + + //find existing short addresses +// if(init_arg==0xff) { + Serial.println("Short adr"); + for(sa = 0; sa<64; sa++) { + int16_t rv = this->cmd(DALI_QUERY_STATUS,sa); + if(rv!=DALI_RESULT_NO_REPLY) { + arr[sa]=1; + cnt++; + Serial.print(sa); + Serial.print(" status=0x"); + Serial.print(rv,HEX); + Serial.print(" minLevel="); + Serial.println(this->cmd(DALI_QUERY_MIN_LEVEL,sa)); + } + } +// } + + this->cmd(DALI_INITIALISE,init_arg); + this->cmd(DALI_RANDOMISE,0x00); + delay(100); + + while(cnt<64) { + //Serial.print("addr="); + //Serial.println(this->get_random_address(0xff),HEX); + + uint32_t adr = this->find_addr(); + if(adr>0xffffff) break; + Serial.print("found adr="); + Serial.println(adr,HEX); + + //Serial.print("short adr="); + //Serial.println(dali_query_short_address()); + + //find available address + for(sa=0; sa<64; sa++) { + if(arr[sa]==0) break; + } + if(sa>=64) break; + arr[sa] = 1; + cnt++; + + Serial.print("program short adr="); + Serial.println(sa); + this->program_short_address(sa); + //dali_program_short_address(0xff); + + Serial.print("read short adr="); + Serial.println(this->query_short_address()); + + this->cmd(DALI_WITHDRAW,0x00); + } + + this->cmd(DALI_TERMINATE,0x00); + return cnt; +} + + + +//====================================================================== diff --git a/qqqDali.h b/qqqDali.h index e975882..253032e 100644 --- a/qqqDali.h +++ b/qqqDali.h @@ -23,28 +23,36 @@ Changelog: class Dali { public: - void begin(int8_t tx_pin, int8_t rx_pin); + void begin(int8_t tx_pin, int8_t rx_pin); //high level functions - void set_level(uint8_t level, uint8_t adr=0xFF); //set arc level - 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 - uint8_t set_operating_mode(uint8_t v, uint8_t adr=0xFF); //returns 0 on success - uint8_t set_max_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success - uint8_t set_min_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success - uint8_t set_system_failure_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success - uint8_t set_power_on_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success - + void set_level(uint8_t level, uint8_t adr=0xFF); //set arc level + 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 + uint8_t set_operating_mode(uint8_t v, uint8_t adr=0xFF); //returns 0 on success + uint8_t set_max_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success + uint8_t set_min_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success + uint8_t set_system_failure_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success + uint8_t set_power_on_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success + //commissioning + uint8_t commission(uint8_t init_arg=0xff); + void set_searchaddr(uint32_t adr); + void set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current); + uint8_t compare(); + void program_short_address(uint8_t shortadr); + uint8_t query_short_address(); + uint32_t find_addr(); + //low level functions typedef void (*EventHandlerReceivedDataFuncPtr)(Dali *sender, uint8_t *data, uint8_t len); EventHandlerReceivedDataFuncPtr EventHandlerReceivedData; - uint8_t send(uint8_t* tx_msg, uint8_t tx_len_bytes); - uint8_t sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_ms=500); - int16_t tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_ms=500); - void ISR_timer(); - void ISR_pinchange(); + uint8_t send(uint8_t* tx_msg, uint8_t tx_len_bytes); + uint8_t sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_ms=500); + int16_t tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_ms=500); + void ISR_timer(); + void ISR_pinchange(); #define DALI_HOOK_COUNT 3 @@ -52,16 +60,16 @@ public: private: //low level functions 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}; - uint8_t tx_pin; //transmitter pin - uint8_t tx_msg[3]; //message to transmit - uint8_t tx_len; //number of bits to transmit + uint8_t tx_pin; //transmitter pin + uint8_t tx_msg[3]; //message to transmit + uint8_t tx_len; //number of bits to transmit volatile uint8_t tx_pos; //current bit transmit position volatile tx_stateEnum tx_state; //current state volatile uint8_t tx_collision; //collistion occured volatile uint8_t tx_bus_low; //bus is low according to transmitter? enum rx_stateEnum { RX_IDLE,RX_START,RX_BIT}; - uint8_t rx_pin; //receiver pin + uint8_t rx_pin; //receiver pin volatile uint8_t rx_last_bus_low; //receiver as low at last pinchange volatile uint32_t rx_last_change_ts; //timestamp last pinchange volatile rx_stateEnum rx_state; //current state -- libgit2 0.21.4