├── HB-UNI-SenAct-4-4-RC └── HB-UNI-SenAct-4-4-RC.ino ├── HB-UNI-SenAct-4-4-SC └── HB-UNI-SenAct-4-4-SC.ino ├── Images ├── HB-UNI-SenAct-4-4-RC.png ├── HB-UNI-SenAct-4-4-SC.png ├── cc1101.png ├── ccu_addon.png ├── ccu_geraete.png ├── wiring.fzz └── wiring.png └── README.md /HB-UNI-SenAct-4-4-RC/HB-UNI-SenAct-4-4-RC.ino: -------------------------------------------------------------------------------- 1 | //- ----------------------------------------------------------------------------------------------------------------------- 2 | // AskSin++ 3 | // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ 4 | // 2018-08-13 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ 5 | // special thanks to "klassisch" from homematic-forum.de 6 | //- ----------------------------------------------------------------------------------------------------------------------- 7 | // ci-test=yes board=328p aes=no 8 | 9 | // define this to read the device id, serial and device type from bootloader section 10 | // #define USE_OTA_BOOTLOADER 11 | #define USE_WOR 12 | 13 | #define EI_NOTEXTERNAL 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | //#define USE_BATTERY_MODE // bei Batteriebetrieb 21 | #define LOWBAT_VOLTAGE 22 // Batterie-Leermeldung bei Unterschreiten der Spannung von U * 10 22 | 23 | #define RELAY_PIN_1 14 24 | #define RELAY_PIN_2 15 25 | #define RELAY_PIN_3 16 26 | #define RELAY_PIN_4 17 27 | 28 | #define REMOTE_PIN_1 5 29 | #define REMOTE_PIN_2 6 30 | #define REMOTE_PIN_3 7 31 | #define REMOTE_PIN_4 9 32 | 33 | #define LED_PIN 4 34 | #define CONFIG_BUTTON_PIN 8 35 | 36 | // number of available peers per channel 37 | #define PEERS_PER_SwitchChannel 4 38 | #define PEERS_PER_RemoteChannel 4 39 | 40 | #ifdef USE_BATTERY_MODE 41 | #define battOp_ARGUMENT BatterySensor 42 | #define DEV_MODEL 0x34 43 | #define CYCLETIME seconds2ticks(60UL * 60 * 12 * 0.88) // 60 seconds * 60 (= minutes) * 12 (=hours) * corrective factor 44 | #else 45 | #define battOp_ARGUMENT NoBattery 46 | #define DEV_MODEL 0x32 47 | #define CYCLETIME seconds2ticks(60UL * 3 * 0.88) // every 3 minutes 48 | #endif 49 | 50 | #define remISR(device,chan,pin) class device##chan##ISRHandler { \ 51 | public: \ 52 | static void isr () { device.remoteChannel(chan).irq(); } \ 53 | }; \ 54 | device.remoteChannel(chan).button().init(pin); \ 55 | if( digitalPinToInterrupt(pin) == NOT_AN_INTERRUPT ) \ 56 | enableInterrupt(pin,device##chan##ISRHandler::isr,CHANGE); \ 57 | else \ 58 | attachInterrupt(digitalPinToInterrupt(pin),device##chan##ISRHandler::isr,CHANGE); 59 | 60 | // all library classes are placed in the namespace 'as' 61 | using namespace as; 62 | 63 | // define all device properties 64 | const struct DeviceInfo PROGMEM devinfo = { 65 | {0xf3, DEV_MODEL, 0x01},// Device ID 66 | "JPSENACT01", // Device Serial 67 | {0xf3, DEV_MODEL}, // Device Model 68 | 0x10, // Firmware Version 69 | as::DeviceType::Switch, // Device Type 70 | {0x01, 0x00} // Info Bytes 71 | }; 72 | /** 73 | Configure the used hardware 74 | */ 75 | typedef AvrSPI<10, 11, 12, 13> RadioSPI; 76 | typedef AskSin, battOp_ARGUMENT, Radio > Hal; 77 | Hal hal; 78 | 79 | DEFREGISTER(Reg0, MASTERID_REGS, DREG_INTKEY, DREG_CYCLICINFOMSG) 80 | class SwList0 : public RegList0 { 81 | public: 82 | SwList0(uint16_t addr) : RegList0(addr) {} 83 | void defaults() { 84 | clear(); 85 | intKeyVisible(true); 86 | cycleInfoMsg(true); 87 | } 88 | }; 89 | 90 | DEFREGISTER(RemoteReg1, CREG_LONGPRESSTIME, CREG_AES_ACTIVE, CREG_DOUBLEPRESSTIME) 91 | class RemoteList1 : public RegList1 { 92 | public: 93 | RemoteList1 (uint16_t addr) : RegList1(addr) {} 94 | void defaults () { 95 | clear(); 96 | longPressTime(1); 97 | // aesActive(false); 98 | // doublePressTime(0); 99 | } 100 | }; 101 | class RemoteChannel : public Channel, public Button { 102 | private: 103 | uint8_t repeatcnt; 104 | 105 | public: 106 | typedef Channel BaseChannel; 107 | 108 | RemoteChannel () : BaseChannel() {} 109 | virtual ~RemoteChannel () {} 110 | 111 | Button& button () { 112 | return *(Button*)this; 113 | } 114 | 115 | uint8_t status () const { 116 | return 0; 117 | } 118 | 119 | uint8_t flags () const { 120 | return 0; 121 | } 122 | 123 | virtual void state(uint8_t s) { 124 | DHEX(BaseChannel::number()); 125 | Button::state(s); 126 | RemoteEventMsg& msg = (RemoteEventMsg&)this->device().message(); 127 | DPRINT("BATTERY IS LOW? "); DDECLN(this->device().battery().low()); 128 | msg.init(this->device().nextcount(), this->number(), repeatcnt, (s == longreleased || s == longpressed), this->device().battery().low()); 129 | if ( s == released || s == longreleased) { 130 | this->device().sendPeerEvent(msg, *this); 131 | repeatcnt++; 132 | } 133 | else if (s == longpressed) { 134 | this->device().broadcastPeerEvent(msg, *this); 135 | } 136 | } 137 | 138 | uint8_t state() const { 139 | return Button::state(); 140 | } 141 | 142 | bool pressed () const { 143 | uint8_t s = state(); 144 | return s == Button::pressed || s == Button::debounce || s == Button::longpressed; 145 | } 146 | }; 147 | 148 | typedef SwitchChannel SwChannel; 149 | 150 | class MixDevice : public ChannelDevice, 8, SwList0> { 151 | class CycleInfoAlarm : public Alarm { 152 | MixDevice& dev; 153 | public: 154 | CycleInfoAlarm (MixDevice& d) : Alarm (CYCLETIME), dev(d) {} 155 | virtual ~CycleInfoAlarm () {} 156 | 157 | void trigger (AlarmClock& clock) { 158 | set(CYCLETIME); 159 | clock.add(*this); 160 | dev.switchChannel(1).changed(true); 161 | } 162 | } cycle; 163 | 164 | public: 165 | VirtChannel swChannel1, swChannel2, swChannel3, swChannel4; 166 | VirtChannel remChannel5, remChannel6, remChannel7, remChannel8; 167 | public: 168 | typedef ChannelDevice, 8, SwList0> DeviceType; 169 | MixDevice (const DeviceInfo& info, uint16_t addr) : DeviceType(info, addr), cycle(*this) { 170 | DeviceType::registerChannel(swChannel1, 1); 171 | DeviceType::registerChannel(swChannel2, 2); 172 | DeviceType::registerChannel(swChannel3, 3); 173 | DeviceType::registerChannel(swChannel4, 4); 174 | 175 | DeviceType::registerChannel(remChannel5, 5); 176 | DeviceType::registerChannel(remChannel6, 6); 177 | DeviceType::registerChannel(remChannel7, 7); 178 | DeviceType::registerChannel(remChannel8, 8); 179 | } 180 | virtual ~MixDevice () {} 181 | 182 | SwChannel& switchChannel (uint8_t num) { 183 | switch (num) { 184 | case 1: 185 | return swChannel1; 186 | break; 187 | case 2: 188 | return swChannel2; 189 | break; 190 | case 3: 191 | return swChannel3; 192 | break; 193 | case 4: 194 | return swChannel4; 195 | break; 196 | } 197 | } 198 | 199 | RemoteChannel& remoteChannel (uint8_t num) { 200 | switch (num) { 201 | case 5: 202 | return remChannel5; 203 | break; 204 | case 6: 205 | return remChannel6; 206 | break; 207 | case 7: 208 | return remChannel7; 209 | break; 210 | case 8: 211 | return remChannel8; 212 | break; 213 | } 214 | } 215 | 216 | virtual void configChanged () { 217 | if ( /*this->getSwList0().cycleInfoMsg() ==*/ true ) { 218 | DPRINTLN("Activate Cycle Msg"); 219 | sysclock.cancel(cycle); 220 | cycle.set(CYCLETIME); 221 | sysclock.add(cycle); 222 | } 223 | else { 224 | DPRINTLN("Deactivate Cycle Msg"); 225 | sysclock.cancel(cycle); 226 | } 227 | } 228 | }; 229 | MixDevice sdev(devinfo, 0x20); 230 | ConfigButton cfgBtn(sdev); 231 | 232 | void initPeerings (bool first) { 233 | // create internal peerings - CCU2 needs this 234 | if ( first == true ) { 235 | HMID devid; 236 | sdev.getDeviceID(devid); 237 | for ( uint8_t i = 1; i <= 4; ++i ) { 238 | Peer ipeer(devid, i); 239 | sdev.channel(i).peer(ipeer); 240 | } 241 | } 242 | } 243 | 244 | void setup () { 245 | DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER); 246 | bool first = sdev.init(hal); 247 | sdev.switchChannel(1).init(RELAY_PIN_1, false); 248 | sdev.switchChannel(2).init(RELAY_PIN_2, false); 249 | sdev.switchChannel(3).init(RELAY_PIN_3, false); 250 | sdev.switchChannel(4).init(RELAY_PIN_4, false); 251 | 252 | remISR(sdev, 5, REMOTE_PIN_1); 253 | remISR(sdev, 6, REMOTE_PIN_2); 254 | remISR(sdev, 7, REMOTE_PIN_3); 255 | remISR(sdev, 8, REMOTE_PIN_4); 256 | 257 | buttonISR(cfgBtn, CONFIG_BUTTON_PIN); 258 | 259 | initPeerings(first); 260 | #ifdef USE_BATTERY_MODE 261 | hal.activity.stayAwake(seconds2ticks(15)); 262 | hal.battery.low(LOWBAT_VOLTAGE); 263 | // measure battery every 12 hours 264 | hal.battery.init(seconds2ticks(60UL * 60 * 12 * 0.88), sysclock); 265 | #endif 266 | sdev.initDone(); 267 | } 268 | 269 | void loop() { 270 | bool worked = hal.runready(); 271 | bool poll = sdev.pollRadio(); 272 | if ( worked == false && poll == false ) { 273 | #ifdef USE_BATTERY_MODE 274 | hal.activity.savePower >(hal); 275 | #else 276 | hal.activity.savePower >(hal); 277 | #endif 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /HB-UNI-SenAct-4-4-SC/HB-UNI-SenAct-4-4-SC.ino: -------------------------------------------------------------------------------- 1 | //- ----------------------------------------------------------------------------------------------------------------------- 2 | // AskSin++ 3 | // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ 4 | // 2018-08-13 jp112sdl Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ 5 | // special thanks to "klassisch" from homematic-forum.de 6 | //- ----------------------------------------------------------------------------------------------------------------------- 7 | // ci-test=yes board=328p aes=no 8 | 9 | // define this to read the device id, serial and device type from bootloader section 10 | // #define USE_OTA_BOOTLOADER 11 | #define USE_WOR 12 | 13 | #define EI_NOTEXTERNAL 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | //#define USE_BATTERY_MODE // bei Batteriebetrieb 21 | #define LOWBAT_VOLTAGE 22 // Batterie-Leermeldung bei Unterschreiten der Spannung von U * 10 22 | 23 | #define RELAY_PIN_1 A0 24 | #define RELAY_PIN_2 A1 25 | #define RELAY_PIN_3 A2 26 | #define RELAY_PIN_4 A3 27 | 28 | #define SENS_PIN_1 5 29 | #define SENS_PIN_2 6 30 | #define SENS_PIN_3 7 31 | #define SENS_PIN_4 9 32 | 33 | #define SABOTAGE_PIN_1 3 34 | 35 | #define LED_PIN 4 36 | #define CONFIG_BUTTON_PIN 8 37 | 38 | // number of available peers per channel 39 | //#define CREATE_INTERNAL_PEERINGS 40 | #define PEERS_PER_SwitchChannel 6 41 | #define PEERS_PER_SENSCHANNEL 6 42 | 43 | #ifdef USE_BATTERY_MODE 44 | #define battOp_ARGUMENT BatterySensor 45 | #define DEV_MODEL 0x33 46 | #define CYCLETIME seconds2ticks(60UL * 60 * 12 * 0.88) // 60 seconds * 60 (= minutes) * 12 (=hours) * corrective factor 47 | #else 48 | #define battOp_ARGUMENT NoBattery 49 | #define DEV_MODEL 0x31 50 | #define CYCLETIME seconds2ticks(60UL * 3 * 0.88) // every 3 minutes 51 | #endif 52 | 53 | // all library classes are placed in the namespace 'as' 54 | using namespace as; 55 | 56 | // define all device properties 57 | const struct DeviceInfo PROGMEM devinfo = { 58 | {0xf3, DEV_MODEL, 0x01},// Device ID 59 | "JPSENACT01", // Device Serial 60 | {0xf3, DEV_MODEL}, // Device Model 61 | 0x10, // Firmware Version 62 | as::DeviceType::Switch, // Device Type 63 | {0x01, 0x00} // Info Bytes 64 | }; 65 | 66 | /** 67 | Configure the used hardware 68 | */ 69 | typedef AvrSPI<10, 11, 12, 13> RadioSPI; 70 | typedef AskSin, battOp_ARGUMENT, Radio > Hal; 71 | Hal hal; 72 | 73 | DEFREGISTER(Reg0, MASTERID_REGS, DREG_INTKEY, DREG_CYCLICINFOMSG, DREG_SABOTAGEMSG) 74 | class SwList0 : public RegList0 { 75 | public: 76 | SwList0(uint16_t addr) : RegList0(addr) {} 77 | void defaults() { 78 | clear(); 79 | intKeyVisible(true); 80 | sabotageMsg(true); 81 | cycleInfoMsg(true); 82 | } 83 | }; 84 | 85 | 86 | DEFREGISTER(Reg1, CREG_AES_ACTIVE, CREG_MSGFORPOS, CREG_EVENTDELAYTIME, CREG_LEDONTIME, CREG_TRANSMITTRYMAX) 87 | class SensList1 : public RegList1 { 88 | public: 89 | SensList1 (uint16_t addr) : RegList1(addr) {} 90 | void defaults () { 91 | clear(); 92 | msgForPosA(1); 93 | msgForPosB(2); 94 | aesActive(false); 95 | eventDelaytime(0); 96 | ledOntime(100); 97 | transmitTryMax(6); 98 | } 99 | }; 100 | 101 | typedef SwitchChannel SwChannel; 102 | typedef TwoStateChannel SensChannel; 103 | 104 | class MixDevice : public ChannelDevice, 8, SwList0> { 105 | class CycleInfoAlarm : public Alarm { 106 | MixDevice& dev; 107 | public: 108 | CycleInfoAlarm (MixDevice& d) : Alarm (CYCLETIME), dev(d) {} 109 | virtual ~CycleInfoAlarm () {} 110 | 111 | void trigger (AlarmClock& clock) { 112 | set(CYCLETIME); 113 | clock.add(*this); 114 | dev.switchChannel(1).changed(true); 115 | } 116 | } cycle; 117 | 118 | public: 119 | VirtChannel swChannel1, swChannel2, swChannel3, swChannel4; 120 | VirtChannel sensChannel5, sensChannel6, sensChannel7, sensChannel8; 121 | public: 122 | typedef ChannelDevice, 8, SwList0> DeviceType; 123 | MixDevice (const DeviceInfo& info, uint16_t addr) : DeviceType(info, addr), cycle(*this) { 124 | DeviceType::registerChannel(swChannel1, 1); 125 | DeviceType::registerChannel(swChannel2, 2); 126 | DeviceType::registerChannel(swChannel3, 3); 127 | DeviceType::registerChannel(swChannel4, 4); 128 | 129 | DeviceType::registerChannel(sensChannel5, 5); 130 | DeviceType::registerChannel(sensChannel6, 6); 131 | DeviceType::registerChannel(sensChannel7, 7); 132 | DeviceType::registerChannel(sensChannel8, 8); 133 | } 134 | virtual ~MixDevice () {} 135 | 136 | 137 | SwChannel& switchChannel (uint8_t num) { 138 | switch (num) { 139 | case 1: 140 | return swChannel1; 141 | break; 142 | case 2: 143 | return swChannel2; 144 | break; 145 | case 3: 146 | return swChannel3; 147 | break; 148 | case 4: 149 | return swChannel4; 150 | break; 151 | } 152 | } 153 | 154 | SensChannel& sensorChannel (uint8_t num) { 155 | switch (num) { 156 | case 5: 157 | return sensChannel5; 158 | break; 159 | case 6: 160 | return sensChannel6; 161 | break; 162 | case 7: 163 | return sensChannel7; 164 | break; 165 | case 8: 166 | return sensChannel8; 167 | break; 168 | } 169 | } 170 | 171 | virtual void configChanged () { 172 | if ( this->getList0().cycleInfoMsg() == true ) { 173 | DPRINTLN("Activate Cycle Msg"); 174 | sysclock.cancel(cycle); 175 | cycle.set(CYCLETIME); 176 | sysclock.add(cycle); 177 | } 178 | else { 179 | DPRINTLN("Deactivate Cycle Msg"); 180 | sysclock.cancel(cycle); 181 | } 182 | } 183 | }; 184 | MixDevice sdev(devinfo, 0x20); 185 | ConfigButton cfgBtn(sdev); 186 | 187 | void initPeerings (bool first) { 188 | // create internal peerings - CCU2 needs this 189 | if ( first == true ) { 190 | #ifdef CREATE_INTERNAL_PEERINGS 191 | HMID devid; 192 | sdev.getDeviceID(devid); 193 | for ( uint8_t i = 1; i <= 4; ++i ) { 194 | Peer ipeer(devid, i + 4); 195 | sdev.switchChannel(i).peer(ipeer); 196 | } 197 | for ( uint8_t i = 1; i <= 4; ++i ) { 198 | Peer ipeer(devid, i); 199 | sdev.sensorChannel(i + 4).peer(ipeer); 200 | } 201 | #endif 202 | } 203 | } 204 | 205 | void setup () { 206 | DINIT(57600, ASKSIN_PLUS_PLUS_IDENTIFIER); 207 | bool first = sdev.init(hal); 208 | sdev.switchChannel(1).init(RELAY_PIN_1, false); 209 | sdev.switchChannel(2).init(RELAY_PIN_2, false); 210 | sdev.switchChannel(3).init(RELAY_PIN_3, false); 211 | sdev.switchChannel(4).init(RELAY_PIN_4, false); 212 | 213 | sdev.sensorChannel(5).init(SENS_PIN_1, SABOTAGE_PIN_1); 214 | sdev.sensorChannel(6).init(SENS_PIN_2, SABOTAGE_PIN_1); 215 | sdev.sensorChannel(7).init(SENS_PIN_3, SABOTAGE_PIN_1); 216 | sdev.sensorChannel(8).init(SENS_PIN_4, SABOTAGE_PIN_1); 217 | 218 | buttonISR(cfgBtn, CONFIG_BUTTON_PIN); 219 | 220 | initPeerings(first); 221 | 222 | #ifdef USE_BATTERY_MODE 223 | hal.activity.stayAwake(seconds2ticks(15)); 224 | hal.battery.low(LOWBAT_VOLTAGE); 225 | // measure battery every 12 hours 226 | hal.battery.init(seconds2ticks(60UL * 60 * 12 * 0.88), sysclock); 227 | #endif 228 | 229 | sdev.initDone(); 230 | } 231 | 232 | void loop() { 233 | bool worked = hal.runready(); 234 | bool poll = sdev.pollRadio(); 235 | if ( worked == false && poll == false ) { 236 | #ifdef USE_BATTERY_MODE 237 | hal.activity.savePower >(hal); 238 | #else 239 | hal.activity.savePower >(hal); 240 | #endif 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /Images/HB-UNI-SenAct-4-4-RC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/HB-UNI-SenAct-4-4-RC.png -------------------------------------------------------------------------------- /Images/HB-UNI-SenAct-4-4-SC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/HB-UNI-SenAct-4-4-SC.png -------------------------------------------------------------------------------- /Images/cc1101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/cc1101.png -------------------------------------------------------------------------------- /Images/ccu_addon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/ccu_addon.png -------------------------------------------------------------------------------- /Images/ccu_geraete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/ccu_geraete.png -------------------------------------------------------------------------------- /Images/wiring.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/wiring.fzz -------------------------------------------------------------------------------- /Images/wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/32cad2a838cc454bfeb649727319b629f0e575fe/Images/wiring.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HB-UNI-SenAct-4-4 2 | ## Universal 4fach-Aktor und 4fach-Sender (Taster/Schließer) für HomeMatic 3 | 4 | ![RC](Images/HB-UNI-SenAct-4-4-RC.png) 5 | ![SC](Images/HB-UNI-SenAct-4-4-SC.png) 6 | 7 | ## benötigte Hardware 8 | * 1x Arduino Pro Mini **ATmega328P (3.3V / 8MHz)** 9 | * 1x CC1101 Funkmodul **(868 MHz)** 10 | * 1x FTDI Adapter (wird nur zum Flashen benötigt) 11 | * 1x Taster (beliebig... irgendwas, das beim Draufdrücken schließt :smiley:) 12 | * 1x LED 13 | * 1x Widerstand 330 Ohm (R1) 14 | * Draht, um die Komponenten zu verbinden 15 | 16 | ## Verdrahtung 17 | 18 | ![wiring](Images/wiring.png) 19 | 20 | 21 | ## Code flashen 22 | - [AskSinPP Library](https://github.com/pa-pa/AskSinPP) in der Arduino IDE installieren 23 | - Achtung: Die Lib benötigt selbst auch noch weitere Bibliotheken, siehe [README](https://github.com/pa-pa/AskSinPP#required-additional-arduino-libraries). 24 | - je nach Anwendung 25 | - Projekt-Datei [HB-UNI-SenAct-4-4-RC](https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/master/HB-UNI-SenAct-4-4-RC/HB-UNI-SenAct-4-4-RC.ino) herunterladen. 26 | - Projekt-Datei [HB-UNI-SenAct-4-4-SC](https://raw.githubusercontent.com/jp112sdl/HB-UNI-SenAct-4-4/master/HB-UNI-SenAct-4-4-SC/HB-UNI-SenAct-4-4-SC.ino) herunterladen. 27 | - Arduino IDE öffnen 28 | - Heruntergeladene Projekt-Datei öffnen 29 | - Werkzeuge 30 | - Board: Arduino Pro or Pro Mini 31 | - Prozessor: ATmega328P (3.3V 8MHz) 32 | - Port: entsprechend FTDI Adapter 33 | einstellen 34 | - bei Batteriebetrieb: Kommentarzeichen bei `//#define USE_BATTERY_MODE` entfernen 35 | - Achtung: Jeder Schaltbefehl benötigt ein BURST-Telegramm -> DutyCycle! 36 | - Menü "Sketch" -> "Hochladen" auswählen. 37 | 38 | ## Addon installieren 39 | Um die Geräteunterstützung zu aktivieren, wird die aktuellste Version des [JP-HB-Devices Addon](https://github.com/jp112sdl/JP-HB-Devices-addon/releases/latest) benötigt! 40 | 41 | ## Gerät anlernen 42 | Wenn alles korrekt verkabelt und das Addons installiert ist, kann das Gerät angelernt werden.
43 | Über den Button "Gerät anlernen" in der WebUI öffnet sich der Anlerndialog.
44 | Button "HM Gerät anlernen" startet den Anlernmodus.
45 | Nun ist der Taster (an Pin D8) kurz zu drücken.
46 | Die LED (an Pin D4) leuchtet/blinkt für einen Moment.
47 | Anschließend ist das Gerät im Posteingang zu finden.
48 | Dort auf "Fertig" geklickt, wird es nun (jeweils eines der beiden, je nach Projektdatei) in der Geräteübersicht aufgeführt.
49 | ![addon](Images/ccu_geraete.png) 50 |

51 | --------------------------------------------------------------------------------