int txPin = 9; // pin connected to RF transmitter int i; // counter to send command pulses int pulse; // count pulse repetitions int incomingByte = 0; // for incoming serial data // hard coded commands (see txButton): 1 - pulse start, 2 - zero, 3 - one, 4 - pause, 5 - low int button1[45]={44, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; int button2[43]={43, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; int button3[41]={40, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 5, 3, 4, 2, 4, 2, 4, 2}; int button4[43]={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2, 4, 2}; int button5[43]={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2}; int button6[43]={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2, 4, 2, 4, 2}; int button7[41]={40, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 5, 3, 4, 2, 4, 2}; int button8[43]={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2}; int button9[43]={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2}; int button10[43]={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 2, 4, 3, 4, 2, 4, 2, 4, 2}; int button11[41]={40, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 5, 2, 4, 3, 4, 2}; void setup () { pinMode(txPin, OUTPUT); Serial.begin(9600); Serial.println("Number = button; a to press 0; b to shut off all"); } void loop(){ if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read(); switch(incomingByte) { case 49: txButton(button1); Serial.println("Switching on 1"); break; case 50: txButton(button2); Serial.println("Switching on 2"); break; case 51: txButton(button3); Serial.println("Switching on 3"); break; case 52: txButton(button4); Serial.println("Switching on 4"); break; case 53: txButton(button5); Serial.println("Switching on 5"); break; case 54: txButton(button6); Serial.println("Switching on 6"); break; case 55: txButton(button7); Serial.println("Switching on 7"); break; case 56: txButton(button8); Serial.println("Switching on 8"); break; case 57: txButton(button9); Serial.println("Switching on 9"); break; case 97: txButton(button10); Serial.println("Switching on 0"); break; case 98: txButton(button11); Serial.println("Switching All off"); break; } } // end if serial available }// end void loop // transmit command. Due to transmitter (or something, I don't know) transmission code should be INVERTED. Ex: one is coded as LOW-delay->HIGH instead of HIGH-delay-LOW void txButton(int cmd[]) { Serial.print("Processing. Array size is "); Serial.println(cmd[0]); digitalWrite(txPin, HIGH); // not sure if its required, just an attempt to start transmission to enable AGC of the receiver delay(1000); for (pulse= 0; pulse <= 100; pulse=pulse+1) { // repeat command 100 times for (i = 1; i < cmd[0]+1; i = i + 1) { // transmit command switch(cmd[i]) { case 1: // start digitalWrite(txPin, HIGH); delayMicroseconds(550); digitalWrite(txPin, LOW); // Serial.print("s"); break; case 2: // "zero", that is short high spike digitalWrite(txPin, LOW); delayMicroseconds(110); digitalWrite(txPin, HIGH); // Serial.print("0"); break; case 3: // "one", that is long high spike digitalWrite(txPin, LOW); delayMicroseconds(303); digitalWrite(txPin, HIGH); // Serial.print("1"); break; case 4: // pause, that is short low spike digitalWrite(txPin, HIGH); delayMicroseconds(110); digitalWrite(txPin, LOW); // Serial.print("p"); break; case 5: // low, that is long low spike digitalWrite(txPin, HIGH); delayMicroseconds(290); digitalWrite(txPin, LOW); // Serial.print("l"); break; } } } }
#include <avr/pgmspace.h> // needed to use PROGMEM #define txPin 8 // pin connected to RF transmitter (pin 8) byte i; // command pulses counter for Livolo (0 - 100) byte pulse; // counter for command repeat // commands stored in PROGMEM arrays (see on PROGMEM use here: http://arduino.cc/forum/index.php?topic=53240.0) // first array element is length of command const prog_uchar button1[45] PROGMEM ={44, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; const prog_uchar button2[43] PROGMEM ={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; const prog_uchar button3[41] PROGMEM ={40, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 5, 3, 4, 2, 4, 2, 4, 2}; const prog_uchar button4[43] PROGMEM ={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2, 4, 2}; const prog_uchar button5[43] PROGMEM ={42, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2}; const prog_uchar button7[41] PROGMEM ={40, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 5, 3, 4, 2, 4, 2}; const prog_uchar button11[41] PROGMEM ={40, 1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 5, 3, 4, 2, 5, 2, 4, 3, 4, 2}; // pointers to command arrays PROGMEM const prog_uchar *buttonPointer[] = {button1, button2, button3, button4, button5, button7, button11}; void setup() { // sipmle example: send button "button2" once. Note that array elements numbered starting from "0" (so button1 is 0, button2 is 1 and so on) txButton(1); } void loop() { } // transmitting part // zeroes and ones here are not actual 0 and 1. I just called these pulses for my own convenience. // also note that I had to invert pulses to get everything working // that said in actual command "start pulse" is long low; "zero" = short high; "one" = long high; "pause" is short low; "low" is long low. void txButton(byte cmd) { prog_uchar *currentPointer = (prog_uchar *)pgm_read_word(&buttonPointer[cmd]); // current pointer to command array passed as txButton(cmd) argument byte cmdCounter = pgm_read_byte(¤tPointer[0]); // read array length for (pulse= 0; pulse <= 180; pulse = pulse+1) { // how many times to transmit a command for (i = 1; i < cmdCounter+1; i = i + 1) { // counter for reading command array byte currentCmd = pgm_read_byte(¤tPointer[i]); // readpulse type from array switch(currentCmd) { // transmit pulse case 1: // start pulse digitalWrite(txPin, HIGH); delayMicroseconds(550); digitalWrite(txPin, LOW); break; case 2: // "zero" digitalWrite(txPin, LOW); delayMicroseconds(110); digitalWrite(txPin, HIGH); break; case 3: // "one" digitalWrite(txPin, LOW); delayMicroseconds(303); digitalWrite(txPin, HIGH); break; case 4: // "pause" digitalWrite(txPin, HIGH); delayMicroseconds(110); digitalWrite(txPin, LOW); break; case 5: // "low" digitalWrite(txPin, HIGH); delayMicroseconds(290); digitalWrite(txPin, LOW); break; } } } digitalWrite(txPin, LOW); }
#include <avr/pgmspace.h> // needed to use PROGMEM #define txPin 8 // pin connected to RF transmitter (pin 8) byte i; // command pulses counter for Livolo (0 - 100) byte pulse; // counter for command repeat // commands stored in PROGMEM arrays (see on PROGMEM use here: http://arduino.cc/forum/index.php?topic=53240.0) // first array element is length of command const prog_uchar start[30] PROGMEM = {1, 2, 4, 2, 4, 2, 4, 3, 5, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; // remote ID - no need to store it with each command const prog_uchar button1[15] PROGMEM ={14, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; // only command bits const prog_uchar button2[13] PROGMEM ={12, 5, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2}; const prog_uchar button3[11] PROGMEM ={10, 5, 3, 5, 3, 4, 2, 4, 2, 4, 2}; const prog_uchar button4[13] PROGMEM ={12, 4, 2, 4, 2, 5, 3, 4, 2, 4, 2, 4, 2}; const prog_uchar button5[13] PROGMEM ={12, 5, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2}; const prog_uchar button7[11] PROGMEM ={10, 5, 3, 4, 2, 5, 3, 4, 2, 4, 2}; const prog_uchar button11[11] PROGMEM ={10, 5, 3, 4, 2, 5, 2, 4, 3, 4, 2}; // pointers to command arrays PROGMEM const prog_uchar *buttonPointer[] = {start, button1, button2, button3, button4, button5, button7, button11}; void setup() { // sipmle example: send button "button2" once. Note that array elements numbered starting from "0" (so button1 is 0, button2 is 1 and so on) // Serial.begin(9600); } void loop() { txButton(3); delay(1000); } // transmitting part // zeroes and ones here are not actual 0 and 1. I just called these pulses for my own convenience. // also note that I had to invert pulses to get everything working // that said in actual command "start pulse" is long low; "zero" = short high; "one" = long high; "pause" is short low; "low" is long low. void txButton(byte cmd) { prog_uchar *currentPointer = (prog_uchar *)pgm_read_word(&buttonPointer[cmd]); // current pointer to command array passed as txButton(cmd) argument byte cmdCounter = pgm_read_byte(¤tPointer[0]); // read array length prog_uchar *currentPointerStart = (prog_uchar *)pgm_read_word(&buttonPointer[0]); // current pointer to start command array for (pulse= 0; pulse <= 180; pulse = pulse+1) { // how many times to transmit a command for (i = 0; i<30; i=i+1) { byte currentCmd = pgm_read_byte(¤tPointerStart[i]); sendPulse(currentCmd); // Serial.print(currentCmd); // Serial.print(", "); } for (i = 1; i < cmdCounter+1; i = i + 1) { // counter for reading command array byte currentCmd = pgm_read_byte(¤tPointer[i]); // readpulse type from array sendPulse(currentCmd); // Serial.print(currentCmd); // Serial.print(", "); } } } void sendPulse(byte txPulse) { switch(txPulse) { // transmit pulse case 1: // start pulse digitalWrite(txPin, HIGH); delayMicroseconds(550); digitalWrite(txPin, LOW); break; case 2: // "zero" digitalWrite(txPin, LOW); delayMicroseconds(110); digitalWrite(txPin, HIGH); break; case 3: // "one" digitalWrite(txPin, LOW); delayMicroseconds(303); digitalWrite(txPin, HIGH); break; case 4: // "pause" digitalWrite(txPin, HIGH); delayMicroseconds(110); digitalWrite(txPin, LOW); break; case 5: // "low" digitalWrite(txPin, HIGH); delayMicroseconds(290); digitalWrite(txPin, LOW); break; } digitalWrite(txPin, LOW); }
#define txPin 8 // pin connected to RF transmitter (pin 8) byte i; // just a counter byte pulse; // counter for command repeat boolean high = true; // pulse "sign" // keycodes #1: 0, #2: 96, #3: 120, #4: 24, #5: 80, #6: 48, #7: 108, #8: 12, #9: 72; #10: 40, #OFF: 106 // real remote IDs: 6400; 19303 // tested "virtual" remote ID: 8500, other IDs could work too, as long as they do not exceed 16 bit // known issue: not all 16 bit remote ID are valid // have not tested other buttons, but as there is dimmer control, some keycodes could be strictly system // use: sendButton(remoteID, keycode); // see void loop for an example of use void setup() { } void loop() { sendButton(6400, 120); // blink button #3 every 3 seconds using remote with remoteID #6400 delay(3000); } void sendButton(unsigned int remoteID, byte keycode) { for (pulse= 0; pulse <= 180; pulse = pulse+1) { // how many times to transmit a command sendPulse(1); // Start high = true; // first pulse is always high for (i = 16; i>0; i--) { // transmit remoteID byte txPulse=bitRead(remoteID, i-1); // read bits from remote ID selectPulse(txPulse); } for (i = 7; i>0; i--) { // transmit keycode byte txPulse=bitRead(keycode, i-1); // read bits from keycode selectPulse(txPulse); } } digitalWrite(txPin, LOW); } // build transmit sequence so that every high pulse is followed by low and vice versa void selectPulse(byte inBit) { switch (inBit) { case 0: for (byte ii=1; ii<3; ii++) { if (high == true) { // if current pulse should be high, send High Zero sendPulse(2); } else { // else send Low Zero sendPulse(4); } high=!high; // invert next pulse } break; case 1: // if current pulse should be high, send High One if (high == true) { sendPulse(3); } else { // else send Low One sendPulse(5); } high=!high; // invert next pulse break; } } // transmit pulses // slightly corrected pulse length, use old (commented out) values if these not working for you void sendPulse(byte txPulse) { switch(txPulse) { // transmit pulse case 1: // Start digitalWrite(txPin, HIGH); delayMicroseconds(500); // 550 digitalWrite(txPin, LOW); break; case 2: // "High Zero" digitalWrite(txPin, LOW); delayMicroseconds(100); // 110 digitalWrite(txPin, HIGH); break; case 3: // "High One" digitalWrite(txPin, LOW); delayMicroseconds(300); // 303 digitalWrite(txPin, HIGH); break; case 4: // "Low Zero" digitalWrite(txPin, HIGH); delayMicroseconds(100); // 110 digitalWrite(txPin, LOW); break; case 5: // "Low One" digitalWrite(txPin, HIGH); delayMicroseconds(300); // 290 digitalWrite(txPin, LOW); break; } }
/* Livolo.h - Library for Livolo wireless switches. Created by Sergey Chernov, October 25, 2013. Released into the public domain. */ #ifndef Livolo_h #define Livolo_h #include "Arduino.h" class Livolo { public: Livolo(byte pin); void sendButton(unsigned int remoteID, byte keycode); private: byte txPin; byte i; // just a counter byte pulse; // counter for command repeat boolean high; // pulse "sign" void selectPulse(byte inBit); void sendPulse(byte txPulse); }; #endif
/* Livolo.cpp - Library for Livolo wireless switches. Created by Sergey Chernov, October 25, 2013. Released into the public domain. 01/12/2013 - code optimization, thanks Maarten! http://forum.arduino.cc/index.php?topic=153525.msg1489857#msg1489857 */ #include "Arduino.h" #include "Livolo.h" Livolo::Livolo(byte pin) { pinMode(pin, OUTPUT); txPin = pin; } // keycodes #1: 0, #2: 96, #3: 120, #4: 24, #5: 80, #6: 48, #7: 108, #8: 12, #9: 72; #10: 40, #OFF: 106 // real remote IDs: 6400; 19303 // tested "virtual" remote IDs: 10550; 8500; 7400 // other IDs could work too, as long as they do not exceed 16 bit // known issue: not all 16 bit remote ID are valid // have not tested other buttons, but as there is dimmer control, some keycodes could be strictly system // use: sendButton(remoteID, keycode), see example blink.ino; void Livolo::sendButton(unsigned int remoteID, byte keycode) { for (pulse= 0; pulse <= 180; pulse = pulse+1) { // how many times to transmit a command sendPulse(1); // Start high = true; // first pulse is always high for (i = 16; i>0; i--) { // transmit remoteID byte txPulse=bitRead(remoteID, i-1); // read bits from remote ID selectPulse(txPulse); } for (i = 7; i>0; i--) { // transmit keycode byte txPulse=bitRead(keycode, i-1); // read bits from keycode selectPulse(txPulse); } } digitalWrite(txPin, LOW); } // build transmit sequence so that every high pulse is followed by low and vice versa void Livolo::selectPulse(byte inBit) { switch (inBit) { case 0: for (byte ii=1; ii<3; ii++) { if (high == true) { // if current pulse should be high, send High Zero sendPulse(2); } else { // else send Low Zero sendPulse(4); } high=!high; // invert next pulse } break; case 1: // if current pulse should be high, send High One if (high == true) { sendPulse(3); } else { // else send Low One sendPulse(5); } high=!high; // invert next pulse break; } } // transmit pulses // slightly corrected pulse length, use old (commented out) values if these not working for you void Livolo::sendPulse(byte txPulse) { switch(txPulse) { // transmit pulse case 1: // Start digitalWrite(txPin, HIGH); delayMicroseconds(500); // 550 // digitalWrite(txPin, LOW); break; case 2: // "High Zero" digitalWrite(txPin, LOW); delayMicroseconds(100); // 110 digitalWrite(txPin, HIGH); break; case 3: // "High One" digitalWrite(txPin, LOW); delayMicroseconds(300); // 303 digitalWrite(txPin, HIGH); break; case 4: // "Low Zero" digitalWrite(txPin, HIGH); delayMicroseconds(100); // 110 digitalWrite(txPin, LOW); break; case 5: // "Low One" digitalWrite(txPin, HIGH); delayMicroseconds(300); // 290 digitalWrite(txPin, LOW); break; } }
This is a library to control Livolo branded wireless switches. Features: - emulates buttons 1 to 0 and ALL OFF of Livolo remote controller Usage: Basically you need two things to get it to work: 1) Create Livolo instance 2) Use sendButton (unsigned int remoteID, byte keycode) function to "push" the buttons sendButton function uses to arguments: remote ID and keycode. Typically, remote IDs are 16 bit unsigned values, but not all of them are valid (maybe there are some IDs reserved only for system use or there is something I don't know). Tested remote IDs: - read from real remote IDs: 6400; 19303 - "virtual" remote IDs: 10550; 8500; 7400 You can try and find new IDs as well: put your switch into learning mode and start sendButton with remote ID you wish to use. If it is a valid ID, switch will accept it. Keycodes read from real remote: #1: 0, #2: 96, #3: 120, #4: 24, #5: 80, #6: 48, #7: 108, #8: 12, #9: 72; #10: 40, #OFF: 106 Keycodes are 7 bit values (actually I use 8 bit values, just skip most significant (leftmost) bit), but other keycodes could be reserved for system use (dimmer, for example). For an example sketch see blink.ino under examples folder.
// Simple blink example of Livolo.h library for Livolo wireless light switches #include <livolo.h> Livolo livolo(8); // transmitter connected to pin #8 void setup() { } void loop() { livolo.sendButton(6400, 120); // blink button #3 every 3 seconds using remote with remoteID #6400 delay(3000); }
Source: https://habr.com/ru/post/211594/
All Articles