Raspberry pi & Raspberry Pico 433MHZ: transmit, receive, relay
This commit is contained in:
parent
d3f887d658
commit
295f4e8a66
22
433/433Utils/.gitignore
vendored
Normal file
22
433/433Utils/.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Mac stuff
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
|
||||||
|
# Compiled executables
|
||||||
|
RPi_utils/RFSniffer
|
||||||
|
RPi_utils/codesend
|
||||||
|
RPi_utils/send
|
||||||
|
|
3
433/433Utils/.gitmodules
vendored
Normal file
3
433/433Utils/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "rc-switch"]
|
||||||
|
path = rc-switch
|
||||||
|
url = https://github.com/sui77/rc-switch.git
|
21
433/433Utils/LICENSE
Normal file
21
433/433Utils/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014-2016 Ninja Blocks Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
67
433/433Utils/README.md
Normal file
67
433/433Utils/README.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# About 433Utils
|
||||||
|
|
||||||
|
433Utils is a collection of code and documentation designed to assist you in the connection and usage of RF 433MHz transmit and receive modules to/with your Arduino and Rapberry Pi.
|
||||||
|
|
||||||
|
It consists of two main sections- Arduino sketches and Raspberry Pi command line utilities. You'll find those in appropriately named folders.
|
||||||
|
|
||||||
|
Despite the name, 433Utils also works with 315MHz transmit and receive modules (tested).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
1. An Arduino (two is ideal)
|
||||||
|
2. A Raspberry Pi
|
||||||
|
3. The git commandline tool, on both your Arduino IDE machine and your RPi
|
||||||
|
4. RF 433MHz modules; a transmitter and receiver
|
||||||
|
5. A Ninja Block and account
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Arduino\_Sketches
|
||||||
|
|
||||||
|
Place the Sketches in your normal Arduino Sketches location. Install any required libraries:
|
||||||
|
|
||||||
|
1. Servo motor library (Should be included in the Arduino IDE)
|
||||||
|
2. _Arduino_ [rc_switch](http://code.google.com/p/rc-switch/) library
|
||||||
|
|
||||||
|
### RPi\_utils
|
||||||
|
|
||||||
|
From your RPi, clone this archive:
|
||||||
|
|
||||||
|
1. ```git clone --recursive git://github.com/ninjablocks/433Utils.git``` (recursive ensure that the rc-switch submodule gets populated which is needed by RPi\_utils)
|
||||||
|
|
||||||
|
2. ```cd 433Utils/RPi_utils```
|
||||||
|
|
||||||
|
3. (As per the original rc_switch distribution) Follow the instructions to install the [wiringpi](https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/) library.
|
||||||
|
After that you can compile the example programs by executing *make*.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### send
|
||||||
|
```sudo ./send systemCode unitCode command```
|
||||||
|
|
||||||
|
This command is unaltered from the original rc\_switch distribution.
|
||||||
|
|
||||||
|
|
||||||
|
### codesend
|
||||||
|
```sudo ./codesend decimalcode```
|
||||||
|
|
||||||
|
This command uses a single Ninja Blocks compatible decimal code. Sniff out codes using the RF\_Sniffer.ino Arduino sketch, included in this distribution.
|
||||||
|
|
||||||
|
You can use codesend to control the wireless servo on your Arduino.
|
||||||
|
(The sketch is Servo\_Receive\_Demo.ino)
|
||||||
|
|
||||||
|
I've implemented the most bare-bones of controls here. Try:
|
||||||
|
|
||||||
|
```sudo ./codesend 500000 # to move the servo up```
|
||||||
|
|
||||||
|
```sudo ./codesend 500001 # to move the servo down```
|
||||||
|
|
||||||
|
```sudo ./codesend 500002 # to move the servo left```
|
||||||
|
|
||||||
|
```sudo ./codesend 500003 # to move the servo right```
|
||||||
|
|
||||||
|
```sudo ./codesend 500004 # to move the servo home```
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
|
||||||
|
Due to limitiations in the implementation of interrupt-driven routines in the underlying RCSwitch library, it is currently not possible to use both the send and receive functionality within the one program.
|
20
433/433Utils/RPi_utils/Makefile
Normal file
20
433/433Utils/RPi_utils/Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
# Defines the RPI variable which is needed by rc-switch/RCSwitch.h
|
||||||
|
CXXFLAGS=-DRPI
|
||||||
|
CFLAGS += -Wall -Os -g
|
||||||
|
|
||||||
|
all: send codesend RFSniffer
|
||||||
|
|
||||||
|
send: ../rc-switch/RCSwitch.o send.o
|
||||||
|
$(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt
|
||||||
|
|
||||||
|
codesend: ../rc-switch/RCSwitch.o codesend.o
|
||||||
|
$(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt
|
||||||
|
|
||||||
|
RFSniffer: ../rc-switch/RCSwitch.o RFSniffer.o
|
||||||
|
$(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) ../rc-switch/*.o *.o send codesend servo RFSniffer
|
||||||
|
|
17
433/433Utils/RPi_utils/README.md
Normal file
17
433/433Utils/RPi_utils/README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# About
|
||||||
|
|
||||||
|
rcswitch-pi is for controlling rc remote controlled power sockets
|
||||||
|
with the raspberry pi. Kudos to the projects [rc-switch](http://code.google.com/p/rc-switch)
|
||||||
|
and [wiringpi](https://projects.drogon.net/raspberry-pi/wiringpi).
|
||||||
|
I just adapted the rc-switch code to use the wiringpi library instead of
|
||||||
|
the library provided by the arduino.
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
First you have to install the [wiringpi](https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/) library.
|
||||||
|
After that you can compile the example program *send* by executing *make*.
|
||||||
|
It uses wiringPi pin no 2 by default. You may want to change the used GPIO pin before compilation of the codesend.cpp source file. (Good Resource for Pin Details https://pinout.xyz/pinout/wiringpi)
|
||||||
|
|
||||||
|
## Note
|
||||||
|
The 'RF\_Sniffer' code is as yet untested. It _should_ work, but it is still being tested thoroughly. It's provided to allow you to start playing with it now.
|
102
433/433Utils/RPi_utils/RFSniffer.cpp
Normal file
102
433/433Utils/RPi_utils/RFSniffer.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
RFSniffer
|
||||||
|
|
||||||
|
Usage: ./RFSniffer [<pulseLength>]
|
||||||
|
[] = optional
|
||||||
|
|
||||||
|
Hacked from http://code.google.com/p/rc-switch/
|
||||||
|
by @justy to provide a handy RF code sniffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../rc-switch/RCSwitch.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
RCSwitch mySwitch;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void light()
|
||||||
|
{
|
||||||
|
digitalWrite(25, LOW);
|
||||||
|
usleep(200000);
|
||||||
|
digitalWrite(25, HIGH);
|
||||||
|
|
||||||
|
//printf("%d\n", digitalRead(25));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
// This pin is not the first pin on the RPi GPIO header!
|
||||||
|
// Consult https://projects.drogon.net/raspberry-pi/wiringpi/pins/
|
||||||
|
// for more information.
|
||||||
|
int PIN = 7;
|
||||||
|
|
||||||
|
if(wiringPiSetup() == -1) {
|
||||||
|
printf("wiringPiSetup failed, exiting...");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pulseLength = 0;
|
||||||
|
if (argv[1] != NULL) pulseLength = atoi(argv[1]);
|
||||||
|
|
||||||
|
mySwitch = RCSwitch();
|
||||||
|
if (pulseLength != 0) mySwitch.setPulseLength(pulseLength);
|
||||||
|
mySwitch.enableReceive(PIN); // Receiver on interrupt 0 => that is pin #2
|
||||||
|
|
||||||
|
pinMode(25, OUTPUT);
|
||||||
|
|
||||||
|
|
||||||
|
#define LIVE 1
|
||||||
|
|
||||||
|
static int i=0;
|
||||||
|
unsigned long value = 0;
|
||||||
|
static int values[LIVE] = {0};
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
while(1) {
|
||||||
|
if (mySwitch.available()) {
|
||||||
|
value = mySwitch.getReceivedValue();
|
||||||
|
values[i] = value;
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
printf("Unknown encoding\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
light();
|
||||||
|
printf("i=%d, Received %lu\n", i, values[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
mySwitch.resetAvailable();
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
if (values[1] == values[0]+1)
|
||||||
|
printf("有我的按钮发来数据\n");
|
||||||
|
}
|
||||||
|
if (i != 1) {
|
||||||
|
if (values[0] == values[1]+1)
|
||||||
|
printf("有我的按钮发来数据\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (i==LIVE) {
|
||||||
|
i=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i=i+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
67
433/433Utils/RPi_utils/codesend.cpp
Normal file
67
433/433Utils/RPi_utils/codesend.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Usage: ./codesend decimalcode [protocol] [pulselength]
|
||||||
|
decimalcode - As decoded by RFSniffer
|
||||||
|
protocol - According to rc-switch definitions
|
||||||
|
pulselength - pulselength in microseconds
|
||||||
|
|
||||||
|
'codesend' hacked from 'send' by @justy
|
||||||
|
|
||||||
|
- The provided rc_switch 'send' command uses the form systemCode, unitCode, command
|
||||||
|
which is not suitable for our purposes. Instead, we call
|
||||||
|
send(code, length); // where length is always 24 and code is simply the code
|
||||||
|
we find using the RF_sniffer.ino Arduino sketch.
|
||||||
|
|
||||||
|
(Use RF_Sniffer.ino to check that RF signals are being produced by the RPi's transmitter
|
||||||
|
or your remote control)
|
||||||
|
*/
|
||||||
|
#include "../rc-switch/RCSwitch.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
// This pin is not the first pin on the RPi GPIO header!
|
||||||
|
// Consult https://projects.drogon.net/raspberry-pi/wiringpi/pins/
|
||||||
|
// for more information.
|
||||||
|
int PIN = 7;
|
||||||
|
|
||||||
|
// Parse the first parameter to this command as an integer
|
||||||
|
int protocol = 0; // A value of 0 will use rc-switch's default value
|
||||||
|
int pulseLength = 0;
|
||||||
|
int bitLength = 24;
|
||||||
|
|
||||||
|
// If no command line argument is given, print the help text
|
||||||
|
if (argc == 1) {
|
||||||
|
printf("Usage: %s decimalcode [protocol] [pulselength] [bitlength]\n", argv[0]);
|
||||||
|
printf("decimalcode\t- As decoded by RFSniffer\n");
|
||||||
|
printf("protocol\t- According to rc-switch definitions\n");
|
||||||
|
printf("pulselength\t- pulselength in microseconds\n");
|
||||||
|
printf("bitlength\t- bit length\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Change protocol and pulse length accroding to parameters
|
||||||
|
char *eptr;
|
||||||
|
unsigned long code = strtoul(argv[1], &eptr, 10);
|
||||||
|
if (argc >= 3)
|
||||||
|
protocol = atoi(argv[2]);
|
||||||
|
if (argc >= 4)
|
||||||
|
pulseLength = atoi(argv[3]);
|
||||||
|
if (argc >= 5)
|
||||||
|
bitLength = atoi(argv[4]);
|
||||||
|
|
||||||
|
if (wiringPiSetup() == -1)
|
||||||
|
return 1;
|
||||||
|
printf("sending code[%lu]\n", code);
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
if (protocol != 0)
|
||||||
|
mySwitch.setProtocol(protocol);
|
||||||
|
if (pulseLength != 0)
|
||||||
|
mySwitch.setPulseLength(pulseLength);
|
||||||
|
mySwitch.enableTransmit(PIN);
|
||||||
|
|
||||||
|
mySwitch.send(code, bitLength);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
62
433/433Utils/RPi_utils/send.cpp
Normal file
62
433/433Utils/RPi_utils/send.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
Usage: ./send <systemCode> <unitCode> <command>
|
||||||
|
Command is 0 for OFF and 1 for ON
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../rc-switch/RCSwitch.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
output PIN is hardcoded for testing purposes
|
||||||
|
see https://projects.drogon.net/raspberry-pi/wiringpi/pins/
|
||||||
|
for pin mapping of the raspberry pi GPIO connector
|
||||||
|
*/
|
||||||
|
int PIN = 7;
|
||||||
|
const char *code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||||
|
|
||||||
|
if (argc < 4) {
|
||||||
|
printf("Sending 433 MHz remote plug control codes, hardcoded on wiringpi pin %d.\n", PIN);
|
||||||
|
printf("Usage: %s <systemCode> <unitCode> <command> [pulseLength]\n", argv[0]);
|
||||||
|
printf("systemCode - First five settings of Type A 10 pole DIP switch, e.g. 11111\n");
|
||||||
|
printf("unitCode - Switch number [1 .. 5] or [10000 .. 00001]\n");
|
||||||
|
printf("command - 0 for OFF and 1 for ON\n");
|
||||||
|
printf("pulseLength - optional pulse length\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *systemCode = argv[1];
|
||||||
|
const char *unitCode;
|
||||||
|
if (strlen(argv[2]) == 5) {
|
||||||
|
unitCode = argv[2];
|
||||||
|
} else if (atoi(argv[2]) > 0 and atoi(argv[2]) < 6) {
|
||||||
|
unitCode = code[atoi(argv[2])];
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int command = atoi(argv[3]);
|
||||||
|
|
||||||
|
if (wiringPiSetup() == -1)
|
||||||
|
return 1;
|
||||||
|
printf("sending systemCode[%s] unitCode[%s] command[%i]\n", systemCode, unitCode, command);
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
if (argv[4] != NULL)
|
||||||
|
mySwitch.setPulseLength(atoi(argv[4]));
|
||||||
|
mySwitch.enableTransmit(PIN);
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case 1:
|
||||||
|
mySwitch.switchOn(systemCode, unitCode);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
mySwitch.switchOff(systemCode, unitCode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("command[%i] is unsupported\n", command);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
17
433/433Utils/rc-switch/.gitignore
vendored
Normal file
17
433/433Utils/rc-switch/.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Mac stuff
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
|
70
433/433Utils/rc-switch/.travis.yml
Normal file
70
433/433Utils/rc-switch/.travis.yml
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
language: c
|
||||||
|
python:
|
||||||
|
- "2.7"
|
||||||
|
|
||||||
|
# Cache PlatformIO packages using Travis CI container-based infrastructure
|
||||||
|
cache:
|
||||||
|
pip: true
|
||||||
|
directories:
|
||||||
|
- "~/.platformio"
|
||||||
|
|
||||||
|
env:
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/Webserver
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/Webserver.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Simple
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Simple.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/TypeC_Intertechno
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeC_Intertechno.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/TypeD_REV
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeD_REV.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches_Lightweight
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches_Lightweight.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/TypeB_WithRotaryOrSlidingSwitches
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeB_WithRotaryOrSlidingSwitches.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/SendDemo
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/SendDemo.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||||
|
- >
|
||||||
|
PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Advanced
|
||||||
|
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Advanced.ino
|
||||||
|
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
# Arduino IDE
|
||||||
|
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
|
||||||
|
- sleep 3
|
||||||
|
- export DISPLAY=:1.0
|
||||||
|
- wget http://downloads.arduino.cc/arduino-1.8.10-linux64.tar.xz
|
||||||
|
- tar xf arduino-1.8.10-linux64.tar.xz
|
||||||
|
- sudo mv arduino-1.8.10 /usr/local/share/arduino
|
||||||
|
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Arduino IDE
|
||||||
|
- ln -s $PWD /usr/local/share/arduino/libraries/rc-switch
|
||||||
|
# PlatformIO
|
||||||
|
# - pip install -U platformio
|
||||||
|
# - platformio update
|
||||||
|
|
||||||
|
script:
|
||||||
|
# Arduino IDE
|
||||||
|
- arduino --verify --board arduino:avr:uno ${ARDUINOIDE_CI_SRC}
|
||||||
|
# PlatformIO
|
||||||
|
# - platformio run --lib="." ${BOARDS}
|
744
433/433Utils/rc-switch/RCSwitch.cpp
Normal file
744
433/433Utils/rc-switch/RCSwitch.cpp
Normal file
@ -0,0 +1,744 @@
|
|||||||
|
/*
|
||||||
|
RCSwitch - Arduino libary for remote control outlet switches
|
||||||
|
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
- Andre Koehler / info(at)tomate-online(dot)de
|
||||||
|
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||||
|
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||||
|
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||||
|
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Andreas Steinel / A.<lastname>(at)gmail(dot)com
|
||||||
|
- Max Horn / max(at)quendi(dot)de
|
||||||
|
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Johann Richard / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo
|
||||||
|
- Matias Cuenca-Acuna
|
||||||
|
|
||||||
|
Project home: https://github.com/sui77/rc-switch/
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RCSwitch.h"
|
||||||
|
|
||||||
|
#ifdef RaspberryPi
|
||||||
|
// PROGMEM and _P functions are for AVR based microprocessors,
|
||||||
|
// so we must normalize these for the ARM processor:
|
||||||
|
#define PROGMEM
|
||||||
|
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
// interrupt handler and related code must be in RAM on ESP8266,
|
||||||
|
// according to issue #46.
|
||||||
|
#define RECEIVE_ATTR ICACHE_RAM_ATTR
|
||||||
|
#define VAR_ISR_ATTR
|
||||||
|
#elif defined(ESP32)
|
||||||
|
#define RECEIVE_ATTR IRAM_ATTR
|
||||||
|
#define VAR_ISR_ATTR DRAM_ATTR
|
||||||
|
#else
|
||||||
|
#define RECEIVE_ATTR
|
||||||
|
#define VAR_ISR_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Format for protocol definitions:
|
||||||
|
* {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal}
|
||||||
|
*
|
||||||
|
* pulselength: pulse length in microseconds, e.g. 350
|
||||||
|
* Sync bit: {1, 31} means 1 high pulse and 31 low pulses
|
||||||
|
* (perceived as a 31*pulselength long pulse, total length of sync bit is
|
||||||
|
* 32*pulselength microseconds), i.e:
|
||||||
|
* _
|
||||||
|
* | |_______________________________ (don't count the vertical bars)
|
||||||
|
* "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
|
||||||
|
* and 3 low pulses, total length (1+3)*pulselength, i.e:
|
||||||
|
* _
|
||||||
|
* | |___
|
||||||
|
* "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
|
||||||
|
* ___
|
||||||
|
* | |_
|
||||||
|
*
|
||||||
|
* These are combined to form Tri-State bits when sending or receiving codes.
|
||||||
|
*/
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
static const VAR_ISR_ATTR RCSwitch::Protocol proto[] = {
|
||||||
|
#else
|
||||||
|
static const RCSwitch::Protocol PROGMEM proto[] = {
|
||||||
|
#endif
|
||||||
|
{ 350, { 1, 31}, { 1, 3}, { 3, 1}, false }, // protocol 1
|
||||||
|
{ 650, { 1, 10}, { 1, 2}, { 2, 1}, false }, // protocol 2
|
||||||
|
{ 100, { 30, 71}, { 4, 11}, { 9, 6}, false }, // protocol 3
|
||||||
|
{ 380, { 1, 6}, { 1, 3}, { 3, 1}, false }, // protocol 4
|
||||||
|
{ 500, { 6, 14}, { 1, 2}, { 2, 1}, false }, // protocol 5
|
||||||
|
{ 450, { 23, 1}, { 1, 2}, { 2, 1}, true }, // protocol 6 (HT6P20B)
|
||||||
|
{ 150, { 2, 62}, { 1, 6}, { 6, 1}, false }, // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote)
|
||||||
|
{ 200, { 3, 130}, { 7, 16}, { 3, 16}, false }, // protocol 8 Conrad RS-200 RX
|
||||||
|
{ 200, { 130, 7}, { 16, 7}, { 16, 3}, true }, // protocol 9 Conrad RS-200 TX
|
||||||
|
{ 365, { 18, 1}, { 3, 1}, { 1, 3}, true }, // protocol 10 (1ByOne Doorbell)
|
||||||
|
{ 270, { 36, 1}, { 1, 2}, { 2, 1}, true }, // protocol 11 (HT12E)
|
||||||
|
{ 320, { 36, 1}, { 1, 2}, { 2, 1}, true } // protocol 12 (SM5212)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
numProto = sizeof(proto) / sizeof(proto[0])
|
||||||
|
};
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
volatile unsigned long RCSwitch::nReceivedValue = 0;
|
||||||
|
volatile unsigned int RCSwitch::nReceivedBitlength = 0;
|
||||||
|
volatile unsigned int RCSwitch::nReceivedDelay = 0;
|
||||||
|
volatile unsigned int RCSwitch::nReceivedProtocol = 0;
|
||||||
|
int RCSwitch::nReceiveTolerance = 60;
|
||||||
|
const unsigned int VAR_ISR_ATTR RCSwitch::nSeparationLimit = 4300;
|
||||||
|
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
|
||||||
|
// according to discussion on issue #14 it might be more suitable to set the separation
|
||||||
|
// limit to the same time as the 'low' part of the sync signal for the current protocol.
|
||||||
|
unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RCSwitch::RCSwitch()
|
||||||
|
{
|
||||||
|
this->nTransmitterPin = -1;
|
||||||
|
this->setRepeatTransmit(10);
|
||||||
|
this->setProtocol(1);
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
this->nReceiverInterrupt = -1;
|
||||||
|
this->setReceiveTolerance(60);
|
||||||
|
RCSwitch::nReceivedValue = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the protocol to send.
|
||||||
|
*/
|
||||||
|
void RCSwitch::setProtocol(Protocol protocol)
|
||||||
|
{
|
||||||
|
this->protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the protocol to send, from a list of predefined protocols
|
||||||
|
*/
|
||||||
|
void RCSwitch::setProtocol(int nProtocol)
|
||||||
|
{
|
||||||
|
if (nProtocol < 1 || nProtocol > numProto) {
|
||||||
|
nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ???
|
||||||
|
}
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
this->protocol = proto[nProtocol - 1];
|
||||||
|
#else
|
||||||
|
memcpy_P(&this->protocol, &proto[nProtocol - 1], sizeof(Protocol));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the protocol to send with pulse length in microseconds.
|
||||||
|
*/
|
||||||
|
void RCSwitch::setProtocol(int nProtocol, int nPulseLength)
|
||||||
|
{
|
||||||
|
setProtocol(nProtocol);
|
||||||
|
this->setPulseLength(nPulseLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets pulse length in microseconds
|
||||||
|
*/
|
||||||
|
void RCSwitch::setPulseLength(int nPulseLength)
|
||||||
|
{
|
||||||
|
this->protocol.pulseLength = nPulseLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets Repeat Transmits
|
||||||
|
*/
|
||||||
|
void RCSwitch::setRepeatTransmit(int nRepeatTransmit)
|
||||||
|
{
|
||||||
|
this->nRepeatTransmit = nRepeatTransmit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Receiving Tolerance
|
||||||
|
*/
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
void RCSwitch::setReceiveTolerance(int nPercent)
|
||||||
|
{
|
||||||
|
RCSwitch::nReceiveTolerance = nPercent;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable transmissions
|
||||||
|
*
|
||||||
|
* @param nTransmitterPin Arduino Pin to which the sender is connected to
|
||||||
|
*/
|
||||||
|
void RCSwitch::enableTransmit(int nTransmitterPin)
|
||||||
|
{
|
||||||
|
this->nTransmitterPin = nTransmitterPin;
|
||||||
|
pinMode(this->nTransmitterPin, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable transmissions
|
||||||
|
*/
|
||||||
|
void RCSwitch::disableTransmit()
|
||||||
|
{
|
||||||
|
this->nTransmitterPin = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type D REV)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (A,B,C,D)
|
||||||
|
* @param nDevice Number of the switch itself (1..3)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(char sGroup, int nDevice)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordD(sGroup, nDevice, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type D REV)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (A,B,C,D)
|
||||||
|
* @param nDevice Number of the switch itself (1..3)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(char sGroup, int nDevice)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordD(sGroup, nDevice, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type C Intertechno)
|
||||||
|
*
|
||||||
|
* @param sFamily Familycode (a..f)
|
||||||
|
* @param nGroup Number of group (1..4)
|
||||||
|
* @param nDevice Number of device (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordC(sFamily, nGroup, nDevice, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type C Intertechno)
|
||||||
|
*
|
||||||
|
* @param sFamily Familycode (a..f)
|
||||||
|
* @param nGroup Number of group (1..4)
|
||||||
|
* @param nDevice Number of device (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordC(sFamily, nGroup, nDevice, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type B with two rotary/sliding switches)
|
||||||
|
*
|
||||||
|
* @param nAddressCode Number of the switch group (1..4)
|
||||||
|
* @param nChannelCode Number of the switch itself (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(int nAddressCode, int nChannelCode)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordB(nAddressCode, nChannelCode, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type B with two rotary/sliding switches)
|
||||||
|
*
|
||||||
|
* @param nAddressCode Number of the switch group (1..4)
|
||||||
|
* @param nChannelCode Number of the switch itself (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(int nAddressCode, int nChannelCode)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordB(nAddressCode, nChannelCode, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead!
|
||||||
|
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param nChannelCode Number of the switch itself (1..5)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(const char *sGroup, int nChannel)
|
||||||
|
{
|
||||||
|
const char *code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||||
|
this->switchOn(sGroup, code[nChannel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead!
|
||||||
|
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param nChannelCode Number of the switch itself (1..5)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(const char *sGroup, int nChannel)
|
||||||
|
{
|
||||||
|
const char *code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||||
|
this->switchOff(sGroup, code[nChannel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(const char *sGroup, const char *sDevice)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordA(sGroup, sDevice, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(const char *sGroup, const char *sDevice)
|
||||||
|
{
|
||||||
|
this->sendTriState(this->getCodeWordA(sGroup, sDevice, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a char[13], representing the code word to be send.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *RCSwitch::getCodeWordA(const char *sGroup, const char *sDevice, bool bStatus)
|
||||||
|
{
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = bStatus ? '0' : 'F';
|
||||||
|
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding for type B switches with two rotary/sliding switches.
|
||||||
|
*
|
||||||
|
* The code word is a tristate word and with following bit pattern:
|
||||||
|
*
|
||||||
|
* +-----------------------------+-----------------------------+----------+------------+
|
||||||
|
* | 4 bits address | 4 bits address | 3 bits | 1 bit |
|
||||||
|
* | switch group | switch number | not used | on / off |
|
||||||
|
* | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 |
|
||||||
|
* +-----------------------------+-----------------------------+----------+------------+
|
||||||
|
*
|
||||||
|
* @param nAddressCode Number of the switch group (1..4)
|
||||||
|
* @param nChannelCode Number of the switch itself (1..4)
|
||||||
|
* @param bStatus Whether to switch on (true) or off (false)
|
||||||
|
*
|
||||||
|
* @return char[13], representing a tristate code word of length 12
|
||||||
|
*/
|
||||||
|
char *RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus)
|
||||||
|
{
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like getCodeWord (Type C = Intertechno)
|
||||||
|
*/
|
||||||
|
char *RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus)
|
||||||
|
{
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
int nFamily = (int)sFamily - 'a';
|
||||||
|
if (nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// encode the family into four bits
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0';
|
||||||
|
|
||||||
|
// encode the device and group
|
||||||
|
sReturn[nReturnPos++] = ((nDevice - 1) & 1) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = ((nDevice - 1) & 2) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = ((nGroup - 1) & 1) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = ((nGroup - 1) & 2) ? 'F' : '0';
|
||||||
|
|
||||||
|
// encode the status code
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding for the REV Switch Type
|
||||||
|
*
|
||||||
|
* The code word is a tristate word and with following bit pattern:
|
||||||
|
*
|
||||||
|
* +-----------------------------+-------------------+----------+--------------+
|
||||||
|
* | 4 bits address | 3 bits address | 3 bits | 2 bits |
|
||||||
|
* | switch group | device number | not used | on / off |
|
||||||
|
* | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 |
|
||||||
|
* +-----------------------------+-------------------+----------+--------------+
|
||||||
|
*
|
||||||
|
* Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
|
||||||
|
*
|
||||||
|
* @param sGroup Name of the switch group (A..D, resp. a..d)
|
||||||
|
* @param nDevice Number of the switch itself (1..3)
|
||||||
|
* @param bStatus Whether to switch on (true) or off (false)
|
||||||
|
*
|
||||||
|
* @return char[13], representing a tristate code word of length 12
|
||||||
|
*/
|
||||||
|
char *RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus)
|
||||||
|
{
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
// sGroup must be one of the letters in "abcdABCD"
|
||||||
|
int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A';
|
||||||
|
if (nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 3; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = bStatus ? '1' : '0';
|
||||||
|
sReturn[nReturnPos++] = bStatus ? '0' : '1';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sCodeWord a tristate code word consisting of the letter 0, 1, F
|
||||||
|
*/
|
||||||
|
void RCSwitch::sendTriState(const char *sCodeWord)
|
||||||
|
{
|
||||||
|
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||||
|
unsigned long code = 0;
|
||||||
|
unsigned int length = 0;
|
||||||
|
for (const char *p = sCodeWord; *p; p++) {
|
||||||
|
code <<= 2L;
|
||||||
|
switch (*p) {
|
||||||
|
case '0':
|
||||||
|
// bit pattern 00
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
// bit pattern 01
|
||||||
|
code |= 1L;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
// bit pattern 11
|
||||||
|
code |= 3L;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
length += 2;
|
||||||
|
}
|
||||||
|
this->send(code, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sCodeWord a binary code word consisting of the letter 0, 1
|
||||||
|
*/
|
||||||
|
void RCSwitch::send(const char *sCodeWord)
|
||||||
|
{
|
||||||
|
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||||
|
unsigned long code = 0;
|
||||||
|
unsigned int length = 0;
|
||||||
|
for (const char *p = sCodeWord; *p; p++) {
|
||||||
|
code <<= 1L;
|
||||||
|
if (*p != '0')
|
||||||
|
code |= 1L;
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
this->send(code, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit the first 'length' bits of the integer 'code'. The
|
||||||
|
* bits are sent from MSB to LSB, i.e., first the bit at position length-1,
|
||||||
|
* then the bit at position length-2, and so on, till finally the bit at position 0.
|
||||||
|
*/
|
||||||
|
void RCSwitch::send(unsigned long code, unsigned int length)
|
||||||
|
{
|
||||||
|
if (this->nTransmitterPin == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
// make sure the receiver is disabled while we transmit
|
||||||
|
int nReceiverInterrupt_backup = nReceiverInterrupt;
|
||||||
|
if (nReceiverInterrupt_backup != -1) {
|
||||||
|
this->disableReceive();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
|
||||||
|
for (int i = length - 1; i >= 0; i--) {
|
||||||
|
if (code & (1L << i))
|
||||||
|
this->transmit(protocol.one);
|
||||||
|
else
|
||||||
|
this->transmit(protocol.zero);
|
||||||
|
}
|
||||||
|
this->transmit(protocol.syncFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable transmit after sending (i.e., for inverted protocols)
|
||||||
|
digitalWrite(this->nTransmitterPin, LOW);
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
// enable receiver again if we just disabled it
|
||||||
|
if (nReceiverInterrupt_backup != -1) {
|
||||||
|
this->enableReceive(nReceiverInterrupt_backup);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit a single high-low pulse.
|
||||||
|
*/
|
||||||
|
void RCSwitch::transmit(HighLow pulses)
|
||||||
|
{
|
||||||
|
uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH;
|
||||||
|
uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW;
|
||||||
|
|
||||||
|
digitalWrite(this->nTransmitterPin, firstLogicLevel);
|
||||||
|
delayMicroseconds(this->protocol.pulseLength * pulses.high);
|
||||||
|
digitalWrite(this->nTransmitterPin, secondLogicLevel);
|
||||||
|
delayMicroseconds(this->protocol.pulseLength * pulses.low);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
/**
|
||||||
|
* Enable receiving data
|
||||||
|
*/
|
||||||
|
void RCSwitch::enableReceive(int interrupt)
|
||||||
|
{
|
||||||
|
this->nReceiverInterrupt = interrupt;
|
||||||
|
this->enableReceive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCSwitch::enableReceive()
|
||||||
|
{
|
||||||
|
if (this->nReceiverInterrupt != -1) {
|
||||||
|
RCSwitch::nReceivedValue = 0;
|
||||||
|
RCSwitch::nReceivedBitlength = 0;
|
||||||
|
#if defined(RaspberryPi) // Raspberry Pi
|
||||||
|
wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt);
|
||||||
|
#else // Arduino
|
||||||
|
attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable receiving data
|
||||||
|
*/
|
||||||
|
void RCSwitch::disableReceive()
|
||||||
|
{
|
||||||
|
#if not defined(RaspberryPi) // Arduino
|
||||||
|
detachInterrupt(this->nReceiverInterrupt);
|
||||||
|
#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR
|
||||||
|
this->nReceiverInterrupt = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RCSwitch::available()
|
||||||
|
{
|
||||||
|
return RCSwitch::nReceivedValue != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCSwitch::resetAvailable()
|
||||||
|
{
|
||||||
|
RCSwitch::nReceivedValue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long RCSwitch::getReceivedValue()
|
||||||
|
{
|
||||||
|
return RCSwitch::nReceivedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RCSwitch::getReceivedBitlength()
|
||||||
|
{
|
||||||
|
return RCSwitch::nReceivedBitlength;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RCSwitch::getReceivedDelay()
|
||||||
|
{
|
||||||
|
return RCSwitch::nReceivedDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RCSwitch::getReceivedProtocol()
|
||||||
|
{
|
||||||
|
return RCSwitch::nReceivedProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int *RCSwitch::getReceivedRawdata()
|
||||||
|
{
|
||||||
|
return RCSwitch::timings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* helper function for the receiveProtocol method */
|
||||||
|
static inline unsigned int diff(int A, int B)
|
||||||
|
{
|
||||||
|
return abs(A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount)
|
||||||
|
{
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
const Protocol & pro = proto[p - 1];
|
||||||
|
#else
|
||||||
|
Protocol pro;
|
||||||
|
memcpy_P(&pro, &proto[p - 1], sizeof(Protocol));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned long code = 0;
|
||||||
|
//Assuming the longer pulse length is the pulse captured in timings[0]
|
||||||
|
const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high);
|
||||||
|
const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses;
|
||||||
|
const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100;
|
||||||
|
|
||||||
|
/* For protocols that start low, the sync period looks like
|
||||||
|
* _________
|
||||||
|
* _____________| |XXXXXXXXXXXX|
|
||||||
|
*
|
||||||
|
* |--1st dur--|-2nd dur-|-Start data-|
|
||||||
|
*
|
||||||
|
* The 3rd saved duration starts the data.
|
||||||
|
*
|
||||||
|
* For protocols that start high, the sync period looks like
|
||||||
|
*
|
||||||
|
* ______________
|
||||||
|
* | |____________|XXXXXXXXXXXXX|
|
||||||
|
*
|
||||||
|
* |-filtered out-|--1st dur--|--Start data--|
|
||||||
|
*
|
||||||
|
* The 2nd saved duration starts the data
|
||||||
|
*/
|
||||||
|
const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1);
|
||||||
|
|
||||||
|
for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) {
|
||||||
|
code <<= 1;
|
||||||
|
if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
|
||||||
|
// zero
|
||||||
|
} else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) {
|
||||||
|
// one
|
||||||
|
code |= 1;
|
||||||
|
} else {
|
||||||
|
// Failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise
|
||||||
|
RCSwitch::nReceivedValue = code;
|
||||||
|
RCSwitch::nReceivedBitlength = (changeCount - 1) / 2;
|
||||||
|
RCSwitch::nReceivedDelay = delay;
|
||||||
|
RCSwitch::nReceivedProtocol = p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RECEIVE_ATTR RCSwitch::handleInterrupt()
|
||||||
|
{
|
||||||
|
|
||||||
|
static unsigned int changeCount = 0;
|
||||||
|
static unsigned long lastTime = 0;
|
||||||
|
static unsigned int repeatCount = 0;
|
||||||
|
|
||||||
|
const long time = micros();
|
||||||
|
const unsigned int duration = time - lastTime;
|
||||||
|
|
||||||
|
if (duration > RCSwitch::nSeparationLimit) {
|
||||||
|
// A long stretch without signal level change occurred. This could
|
||||||
|
// be the gap between two transmission.
|
||||||
|
if ((repeatCount == 0) || (diff(duration, RCSwitch::timings[0]) < 200)) {
|
||||||
|
// This long signal is close in length to the long signal which
|
||||||
|
// started the previously recorded timings; this suggests that
|
||||||
|
// it may indeed by a a gap between two transmissions (we assume
|
||||||
|
// here that a sender will send the signal multiple times,
|
||||||
|
// with roughly the same gap between them).
|
||||||
|
repeatCount++;
|
||||||
|
if (repeatCount == 2) {
|
||||||
|
for (unsigned int i = 1; i <= numProto; i++) {
|
||||||
|
if (receiveProtocol(i, changeCount)) {
|
||||||
|
// receive succeeded for protocol i
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeatCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// detect overflow
|
||||||
|
if (changeCount >= RCSWITCH_MAX_CHANGES) {
|
||||||
|
changeCount = 0;
|
||||||
|
repeatCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCSwitch::timings[changeCount++] = duration;
|
||||||
|
lastTime = time;
|
||||||
|
}
|
||||||
|
#endif
|
182
433/433Utils/rc-switch/RCSwitch.h
Normal file
182
433/433Utils/rc-switch/RCSwitch.h
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
RCSwitch - Arduino libary for remote control outlet switches
|
||||||
|
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
- Andre Koehler / info(at)tomate-online(dot)de
|
||||||
|
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||||
|
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||||
|
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||||
|
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Max Horn / max(at)quendi(dot)de
|
||||||
|
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
|
||||||
|
Project home: https://github.com/sui77/rc-switch/
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef _RCSwitch_h
|
||||||
|
#define _RCSwitch_h
|
||||||
|
|
||||||
|
#if defined(ARDUINO) && ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
|
||||||
|
#include "Energia.h"
|
||||||
|
#elif defined(RPI) // Raspberry Pi
|
||||||
|
#define RaspberryPi
|
||||||
|
|
||||||
|
// Include libraries for RPi:
|
||||||
|
#include <string.h> /* memcpy */
|
||||||
|
#include <stdlib.h> /* abs */
|
||||||
|
#include <wiringPi.h>
|
||||||
|
#elif defined(SPARK)
|
||||||
|
#include "application.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// At least for the ATTiny X4/X5, receiving has to be disabled due to
|
||||||
|
// missing libm depencies (udivmodhi4)
|
||||||
|
#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ )
|
||||||
|
#define RCSwitchDisableReceiving
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Number of maximum high/Low changes per packet.
|
||||||
|
// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
|
||||||
|
#define RCSWITCH_MAX_CHANGES 67
|
||||||
|
|
||||||
|
class RCSwitch {
|
||||||
|
|
||||||
|
public:
|
||||||
|
RCSwitch();
|
||||||
|
|
||||||
|
void switchOn(int nGroupNumber, int nSwitchNumber);
|
||||||
|
void switchOff(int nGroupNumber, int nSwitchNumber);
|
||||||
|
void switchOn(const char *sGroup, int nSwitchNumber);
|
||||||
|
void switchOff(const char *sGroup, int nSwitchNumber);
|
||||||
|
void switchOn(char sFamily, int nGroup, int nDevice);
|
||||||
|
void switchOff(char sFamily, int nGroup, int nDevice);
|
||||||
|
void switchOn(const char *sGroup, const char *sDevice);
|
||||||
|
void switchOff(const char *sGroup, const char *sDevice);
|
||||||
|
void switchOn(char sGroup, int nDevice);
|
||||||
|
void switchOff(char sGroup, int nDevice);
|
||||||
|
|
||||||
|
void sendTriState(const char *sCodeWord);
|
||||||
|
void send(unsigned long code, unsigned int length);
|
||||||
|
void send(const char *sCodeWord);
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
void enableReceive(int interrupt);
|
||||||
|
void enableReceive();
|
||||||
|
void disableReceive();
|
||||||
|
bool available();
|
||||||
|
void resetAvailable();
|
||||||
|
|
||||||
|
unsigned long getReceivedValue();
|
||||||
|
unsigned int getReceivedBitlength();
|
||||||
|
unsigned int getReceivedDelay();
|
||||||
|
unsigned int getReceivedProtocol();
|
||||||
|
unsigned int *getReceivedRawdata();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void enableTransmit(int nTransmitterPin);
|
||||||
|
void disableTransmit();
|
||||||
|
void setPulseLength(int nPulseLength);
|
||||||
|
void setRepeatTransmit(int nRepeatTransmit);
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
void setReceiveTolerance(int nPercent);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of a single pule, which consists of a high signal
|
||||||
|
* whose duration is "high" times the base pulse length, followed
|
||||||
|
* by a low signal lasting "low" times the base pulse length.
|
||||||
|
* Thus, the pulse overall lasts (high+low)*pulseLength
|
||||||
|
*/
|
||||||
|
struct HighLow {
|
||||||
|
uint8_t high;
|
||||||
|
uint8_t low;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "protocol" describes how zero and one bits are encoded into high/low
|
||||||
|
* pulses.
|
||||||
|
*/
|
||||||
|
struct Protocol {
|
||||||
|
/** base pulse length in microseconds, e.g. 350 */
|
||||||
|
uint16_t pulseLength;
|
||||||
|
|
||||||
|
HighLow syncFactor;
|
||||||
|
HighLow zero;
|
||||||
|
HighLow one;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, interchange high and low logic levels in all transmissions.
|
||||||
|
*
|
||||||
|
* By default, RCSwitch assumes that any signals it sends or receives
|
||||||
|
* can be broken down into pulses which start with a high signal level,
|
||||||
|
* followed by a a low signal level. This is e.g. the case for the
|
||||||
|
* popular PT 2260 encoder chip, and thus many switches out there.
|
||||||
|
*
|
||||||
|
* But some devices do it the other way around, and start with a low
|
||||||
|
* signal level, followed by a high signal level, e.g. the HT6P20B. To
|
||||||
|
* accommodate this, one can set invertedSignal to true, which causes
|
||||||
|
* RCSwitch to change how it interprets any HighLow struct FOO: It will
|
||||||
|
* then assume transmissions start with a low signal lasting
|
||||||
|
* FOO.high*pulseLength microseconds, followed by a high signal lasting
|
||||||
|
* FOO.low*pulseLength microseconds.
|
||||||
|
*/
|
||||||
|
bool invertedSignal;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setProtocol(Protocol protocol);
|
||||||
|
void setProtocol(int nProtocol);
|
||||||
|
void setProtocol(int nProtocol, int nPulseLength);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *getCodeWordA(const char *sGroup, const char *sDevice, bool bStatus);
|
||||||
|
char *getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus);
|
||||||
|
char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus);
|
||||||
|
char *getCodeWordD(char group, int nDevice, bool bStatus);
|
||||||
|
void transmit(HighLow pulses);
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
static void handleInterrupt();
|
||||||
|
static bool receiveProtocol(const int p, unsigned int changeCount);
|
||||||
|
int nReceiverInterrupt;
|
||||||
|
#endif
|
||||||
|
int nTransmitterPin;
|
||||||
|
int nRepeatTransmit;
|
||||||
|
|
||||||
|
Protocol protocol;
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
static int nReceiveTolerance;
|
||||||
|
volatile static unsigned long nReceivedValue;
|
||||||
|
volatile static unsigned int nReceivedBitlength;
|
||||||
|
volatile static unsigned int nReceivedDelay;
|
||||||
|
volatile static unsigned int nReceivedProtocol;
|
||||||
|
const static unsigned int nSeparationLimit;
|
||||||
|
/*
|
||||||
|
* timings[0] contains sync timing, followed by a number of bits
|
||||||
|
*/
|
||||||
|
static unsigned int timings[RCSWITCH_MAX_CHANGES];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
42
433/433Utils/rc-switch/README.md
Normal file
42
433/433Utils/rc-switch/README.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# rc-switch
|
||||||
|
[![arduino-library-badge](https://www.ardu-badge.com/badge/rc-switch.svg?)](https://www.ardu-badge.com/rc-switch)
|
||||||
|
[![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch)
|
||||||
|
|
||||||
|
Use your Arduino or [Raspberry Pi](https://github.com/r10r/rcswitch-pi) to operate remote radio controlled devices
|
||||||
|
|
||||||
|
## Download
|
||||||
|
https://github.com/sui77/rc-switch/releases/latest
|
||||||
|
|
||||||
|
rc-switch is also listed in the arduino library manager.
|
||||||
|
|
||||||
|
## Wiki
|
||||||
|
https://github.com/sui77/rc-switch/wiki
|
||||||
|
|
||||||
|
## Info
|
||||||
|
### Send RC codes
|
||||||
|
|
||||||
|
Use your Arduino or Raspberry Pi to operate remote radio controlled devices.
|
||||||
|
This will most likely work with all popular low cost power outlet sockets. If
|
||||||
|
yours doesn't work, you might need to adjust the pulse length.
|
||||||
|
|
||||||
|
All you need is a Arduino or Raspberry Pi, a 315/433MHz AM transmitter and one
|
||||||
|
or more devices with one of the supported chipsets:
|
||||||
|
|
||||||
|
- SC5262 / SC5272
|
||||||
|
- HX2262 / HX2272
|
||||||
|
- PT2262 / PT2272
|
||||||
|
- EV1527 / RT1527 / FP1527 / HS1527
|
||||||
|
- Intertechno outlets
|
||||||
|
- HT6P20X
|
||||||
|
|
||||||
|
### Receive and decode RC codes
|
||||||
|
|
||||||
|
Find out what codes your remote is sending. Use your remote to control your
|
||||||
|
Arduino.
|
||||||
|
|
||||||
|
All you need is an Arduino, a 315/433MHz AM receiver (altough there is no
|
||||||
|
instruction yet, yes it is possible to hack an existing device) and a remote
|
||||||
|
hand set.
|
||||||
|
|
||||||
|
For the Raspberry Pi, clone the https://github.com/ninjablocks/433Utils project to
|
||||||
|
compile a sniffer tool and transmission commands.
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
Example for receiving
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
|
||||||
|
If you want to visualize a telegram copy the raw data and
|
||||||
|
paste it into http://test.sui.li/oszi/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (mySwitch.available()) {
|
||||||
|
output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
|
||||||
|
mySwitch.resetAvailable();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
static const char* bin2tristate(const char* bin);
|
||||||
|
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength);
|
||||||
|
|
||||||
|
void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) {
|
||||||
|
|
||||||
|
const char* b = dec2binWzerofill(decimal, length);
|
||||||
|
Serial.print("Decimal: ");
|
||||||
|
Serial.print(decimal);
|
||||||
|
Serial.print(" (");
|
||||||
|
Serial.print( length );
|
||||||
|
Serial.print("Bit) Binary: ");
|
||||||
|
Serial.print( b );
|
||||||
|
Serial.print(" Tri-State: ");
|
||||||
|
Serial.print( bin2tristate( b) );
|
||||||
|
Serial.print(" PulseLength: ");
|
||||||
|
Serial.print(delay);
|
||||||
|
Serial.print(" microseconds");
|
||||||
|
Serial.print(" Protocol: ");
|
||||||
|
Serial.println(protocol);
|
||||||
|
|
||||||
|
Serial.print("Raw data: ");
|
||||||
|
for (unsigned int i=0; i<= length*2; i++) {
|
||||||
|
Serial.print(raw[i]);
|
||||||
|
Serial.print(",");
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* bin2tristate(const char* bin) {
|
||||||
|
static char returnValue[50];
|
||||||
|
int pos = 0;
|
||||||
|
int pos2 = 0;
|
||||||
|
while (bin[pos]!='\0' && bin[pos+1]!='\0') {
|
||||||
|
if (bin[pos]=='0' && bin[pos+1]=='0') {
|
||||||
|
returnValue[pos2] = '0';
|
||||||
|
} else if (bin[pos]=='1' && bin[pos+1]=='1') {
|
||||||
|
returnValue[pos2] = '1';
|
||||||
|
} else if (bin[pos]=='0' && bin[pos+1]=='1') {
|
||||||
|
returnValue[pos2] = 'F';
|
||||||
|
} else {
|
||||||
|
return "not applicable";
|
||||||
|
}
|
||||||
|
pos = pos+2;
|
||||||
|
pos2++;
|
||||||
|
}
|
||||||
|
returnValue[pos2] = '\0';
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
|
||||||
|
static char bin[64];
|
||||||
|
unsigned int i=0;
|
||||||
|
|
||||||
|
while (Dec > 0) {
|
||||||
|
bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0';
|
||||||
|
Dec = Dec >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j< bitLength; j++) {
|
||||||
|
if (j >= bitLength - i) {
|
||||||
|
bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
|
||||||
|
} else {
|
||||||
|
bin[j] = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bin[bitLength] = '\0';
|
||||||
|
|
||||||
|
return bin;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Simple example for receiving
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (mySwitch.available()) {
|
||||||
|
|
||||||
|
Serial.print("Received ");
|
||||||
|
Serial.print( mySwitch.getReceivedValue() );
|
||||||
|
Serial.print(" / ");
|
||||||
|
Serial.print( mySwitch.getReceivedBitlength() );
|
||||||
|
Serial.print("bit ");
|
||||||
|
Serial.print("Protocol: ");
|
||||||
|
Serial.println( mySwitch.getReceivedProtocol() );
|
||||||
|
|
||||||
|
mySwitch.resetAvailable();
|
||||||
|
}
|
||||||
|
}
|
57
433/433Utils/rc-switch/examples/SendDemo/SendDemo.ino
Normal file
57
433/433Utils/rc-switch/examples/SendDemo/SendDemo.ino
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Example for different sending methods
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// Transmitter is connected to Arduino Pin #10
|
||||||
|
mySwitch.enableTransmit(10);
|
||||||
|
|
||||||
|
// Optional set protocol (default is 1, will work for most outlets)
|
||||||
|
// mySwitch.setProtocol(2);
|
||||||
|
|
||||||
|
// Optional set pulse length.
|
||||||
|
// mySwitch.setPulseLength(320);
|
||||||
|
|
||||||
|
// Optional set number of transmission repetitions.
|
||||||
|
// mySwitch.setRepeatTransmit(15);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
/* See Example: TypeA_WithDIPSwitches */
|
||||||
|
mySwitch.switchOn("11111", "00010");
|
||||||
|
delay(1000);
|
||||||
|
mySwitch.switchOff("11111", "00010");
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
/* Same switch as above, but using decimal code */
|
||||||
|
mySwitch.send(5393, 24);
|
||||||
|
delay(1000);
|
||||||
|
mySwitch.send(5396, 24);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
/* Same switch as above, but using binary code */
|
||||||
|
mySwitch.send("000000000001010100010001");
|
||||||
|
delay(1000);
|
||||||
|
mySwitch.send("000000000001010100010100");
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
/* Same switch as above, but tri-state code */
|
||||||
|
mySwitch.sendTriState("00000FFF0F0F");
|
||||||
|
delay(1000);
|
||||||
|
mySwitch.sendTriState("00000FFF0FF0");
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
delay(20000);
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Example for outlets which are configured with a 10 pole DIP switch.
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Transmitter is connected to Arduino Pin #10
|
||||||
|
mySwitch.enableTransmit(10);
|
||||||
|
|
||||||
|
// Optional set pulse length.
|
||||||
|
// mySwitch.setPulseLength(320);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Switch on:
|
||||||
|
// The first parameter represents the setting of the first 5 DIP switches.
|
||||||
|
// In this example it's ON-ON-OFF-OFF-ON.
|
||||||
|
//
|
||||||
|
// The second parameter represents the setting of the last 5 DIP switches.
|
||||||
|
// In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF.
|
||||||
|
mySwitch.switchOn("11001", "01010");
|
||||||
|
|
||||||
|
// Wait a second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Switch off
|
||||||
|
mySwitch.switchOff("11001", "01010");
|
||||||
|
|
||||||
|
// Wait another second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
This is a minimal sketch without using the library at all but only works for
|
||||||
|
the 10 pole dip switch sockets. It saves a lot of memory and thus might be
|
||||||
|
very useful to use with ATTinys :)
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
*/
|
||||||
|
|
||||||
|
int RCLpin = 7;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(RCLpin, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
RCLswitch(0b010001000001); // DIPs an Steckdose: 0100010000 An:01
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
RCLswitch(0b010001000010); // DIPs an Steckdose: 0100010000 Aus:10
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCLswitch(uint16_t code) {
|
||||||
|
for (int nRepeat=0; nRepeat<6; nRepeat++) {
|
||||||
|
for (int i=4; i<16; i++) {
|
||||||
|
RCLtransmit(1,3);
|
||||||
|
if (((code << (i-4)) & 2048) > 0) {
|
||||||
|
RCLtransmit(1,3);
|
||||||
|
} else {
|
||||||
|
RCLtransmit(3,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RCLtransmit(1,31);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCLtransmit(int nHighPulses, int nLowPulses) {
|
||||||
|
digitalWrite(RCLpin, HIGH);
|
||||||
|
delayMicroseconds( 350 * nHighPulses);
|
||||||
|
digitalWrite(RCLpin, LOW);
|
||||||
|
delayMicroseconds( 350 * nLowPulses);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Example for outlets which are configured with two rotary/sliding switches.
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Transmitter is connected to Arduino Pin #10
|
||||||
|
mySwitch.enableTransmit(10);
|
||||||
|
|
||||||
|
// Optional set pulse length.
|
||||||
|
// mySwitch.setPulseLength(320);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Switch on:
|
||||||
|
// The first parameter represents the setting of the first rotary switch.
|
||||||
|
// In this example it's switched to "1" or "A" or "I".
|
||||||
|
//
|
||||||
|
// The second parameter represents the setting of the second rotary switch.
|
||||||
|
// In this example it's switched to "4" or "D" or "IV".
|
||||||
|
mySwitch.switchOn(1, 4);
|
||||||
|
|
||||||
|
// Wait a second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Switch off
|
||||||
|
mySwitch.switchOff(1, 4);
|
||||||
|
|
||||||
|
// Wait another second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Example for Intertechno outlets
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Transmitter is connected to Arduino Pin #10
|
||||||
|
mySwitch.enableTransmit(10);
|
||||||
|
|
||||||
|
// Optional set pulse length.
|
||||||
|
// mySwitch.setPulseLength(320);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Switch on:
|
||||||
|
// The first parameter represents the familycode (a, b, c, ... f)
|
||||||
|
// The second parameter represents the group number
|
||||||
|
// The third parameter represents the device number
|
||||||
|
//
|
||||||
|
// In this example it's family 'b', group #3, device #2
|
||||||
|
mySwitch.switchOn('b', 3, 2);
|
||||||
|
|
||||||
|
// Wait a second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Switch off
|
||||||
|
mySwitch.switchOff('b', 3, 2);
|
||||||
|
|
||||||
|
// Wait another second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
}
|
41
433/433Utils/rc-switch/examples/TypeD_REV/TypeD_REV.ino
Normal file
41
433/433Utils/rc-switch/examples/TypeD_REV/TypeD_REV.ino
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Example for REV outlets (e.g. 8342L)
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
|
||||||
|
Need help? http://forum.ardumote.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
// Transmitter is connected to Arduino Pin #10
|
||||||
|
mySwitch.enableTransmit(10);
|
||||||
|
|
||||||
|
// set pulse length.
|
||||||
|
mySwitch.setPulseLength(360);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
// Switch on:
|
||||||
|
// The first parameter represents the channel (a, b, c, d)
|
||||||
|
// The second parameter represents the device number
|
||||||
|
//
|
||||||
|
// In this example it's family 'd', device #2
|
||||||
|
mySwitch.switchOn('d', 2);
|
||||||
|
|
||||||
|
// Wait a second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// Switch off
|
||||||
|
mySwitch.switchOff('d', 2);
|
||||||
|
|
||||||
|
// Wait another second
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
}
|
154
433/433Utils/rc-switch/examples/Webserver/Webserver.ino
Normal file
154
433/433Utils/rc-switch/examples/Webserver/Webserver.ino
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
A simple RCSwitch/Ethernet/Webserver demo
|
||||||
|
|
||||||
|
https://github.com/sui77/rc-switch/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Ethernet.h>
|
||||||
|
#include <RCSwitch.h>
|
||||||
|
|
||||||
|
// Ethernet configuration
|
||||||
|
uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC Address
|
||||||
|
uint8_t ip[] = { 192,168,0, 2 }; // IP Address
|
||||||
|
EthernetServer server(80); // Server Port 80
|
||||||
|
|
||||||
|
// RCSwitch configuration
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
int RCTransmissionPin = 7;
|
||||||
|
|
||||||
|
// More to do...
|
||||||
|
// You should also modify the processCommand() and
|
||||||
|
// httpResponseHome() functions to fit your needs.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup
|
||||||
|
*/
|
||||||
|
void setup() {
|
||||||
|
Ethernet.begin(mac, ip);
|
||||||
|
server.begin();
|
||||||
|
mySwitch.enableTransmit( RCTransmissionPin );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop
|
||||||
|
*/
|
||||||
|
void loop() {
|
||||||
|
char* command = httpServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command dispatcher
|
||||||
|
*/
|
||||||
|
void processCommand(char* command) {
|
||||||
|
if (strcmp(command, "1-on") == 0) {
|
||||||
|
mySwitch.switchOn(1,1);
|
||||||
|
} else if (strcmp(command, "1-off") == 0) {
|
||||||
|
mySwitch.switchOff(1,1);
|
||||||
|
} else if (strcmp(command, "2-on") == 0) {
|
||||||
|
mySwitch.switchOn(1,2);
|
||||||
|
} else if (strcmp(command, "2-off") == 0) {
|
||||||
|
mySwitch.switchOff(1,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Response with homepage
|
||||||
|
*/
|
||||||
|
void httpResponseHome(EthernetClient c) {
|
||||||
|
c.println("HTTP/1.1 200 OK");
|
||||||
|
c.println("Content-Type: text/html");
|
||||||
|
c.println();
|
||||||
|
c.println("<html>");
|
||||||
|
c.println("<head>");
|
||||||
|
c.println( "<title>RCSwitch Webserver Demo</title>");
|
||||||
|
c.println( "<style>");
|
||||||
|
c.println( "body { font-family: Arial, sans-serif; font-size:12px; }");
|
||||||
|
c.println( "</style>");
|
||||||
|
c.println("</head>");
|
||||||
|
c.println("<body>");
|
||||||
|
c.println( "<h1>RCSwitch Webserver Demo</h1>");
|
||||||
|
c.println( "<ul>");
|
||||||
|
c.println( "<li><a href=\"./?1-on\">Switch #1 on</a></li>");
|
||||||
|
c.println( "<li><a href=\"./?1-off\">Switch #1 off</a></li>");
|
||||||
|
c.println( "</ul>");
|
||||||
|
c.println( "<ul>");
|
||||||
|
c.println( "<li><a href=\"./?2-on\">Switch #2 on</a></li>");
|
||||||
|
c.println( "<li><a href=\"./?2-off\">Switch #2 off</a></li>");
|
||||||
|
c.println( "</ul>");
|
||||||
|
c.println( "<hr>");
|
||||||
|
c.println( "<a href=\"https://github.com/sui77/rc-switch/\">https://github.com/sui77/rc-switch/</a>");
|
||||||
|
c.println("</body>");
|
||||||
|
c.println("</html>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Redirect to homepage
|
||||||
|
*/
|
||||||
|
void httpResponseRedirect(EthernetClient c) {
|
||||||
|
c.println("HTTP/1.1 301 Found");
|
||||||
|
c.println("Location: /");
|
||||||
|
c.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Response 414 error
|
||||||
|
* Command must not be longer than 30 characters
|
||||||
|
**/
|
||||||
|
void httpResponse414(EthernetClient c) {
|
||||||
|
c.println("HTTP/1.1 414 Request URI too long");
|
||||||
|
c.println("Content-Type: text/plain");
|
||||||
|
c.println();
|
||||||
|
c.println("414 Request URI too long");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process HTTP requests, parse first request header line and
|
||||||
|
* call processCommand with GET query string (everything after
|
||||||
|
* the ? question mark in the URL).
|
||||||
|
*/
|
||||||
|
char* httpServer() {
|
||||||
|
EthernetClient client = server.available();
|
||||||
|
if (client) {
|
||||||
|
char sReturnCommand[32];
|
||||||
|
int nCommandPos=-1;
|
||||||
|
sReturnCommand[0] = '\0';
|
||||||
|
while (client.connected()) {
|
||||||
|
if (client.available()) {
|
||||||
|
char c = client.read();
|
||||||
|
if ((c == '\n') || (c == ' ' && nCommandPos>-1)) {
|
||||||
|
sReturnCommand[nCommandPos] = '\0';
|
||||||
|
if (strcmp(sReturnCommand, "\0") == 0) {
|
||||||
|
httpResponseHome(client);
|
||||||
|
} else {
|
||||||
|
processCommand(sReturnCommand);
|
||||||
|
httpResponseRedirect(client);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nCommandPos>-1) {
|
||||||
|
sReturnCommand[nCommandPos++] = c;
|
||||||
|
}
|
||||||
|
if (c == '?' && nCommandPos == -1) {
|
||||||
|
nCommandPos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nCommandPos > 30) {
|
||||||
|
httpResponse414(client);
|
||||||
|
sReturnCommand[0] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nCommandPos!=-1) {
|
||||||
|
sReturnCommand[nCommandPos] = '\0';
|
||||||
|
}
|
||||||
|
// give the web browser time to receive the data
|
||||||
|
delay(1);
|
||||||
|
client.stop();
|
||||||
|
|
||||||
|
return sReturnCommand;
|
||||||
|
}
|
||||||
|
return '\0';
|
||||||
|
}
|
57
433/433Utils/rc-switch/keywords.txt
Normal file
57
433/433Utils/rc-switch/keywords.txt
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map For RCSwitch
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
RCSwitch KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
##########
|
||||||
|
#SENDS Begin
|
||||||
|
##########
|
||||||
|
switchOn KEYWORD2
|
||||||
|
switchOff KEYWORD2
|
||||||
|
sendTriState KEYWORD2
|
||||||
|
send KEYWORD2
|
||||||
|
##########
|
||||||
|
#SENDS End
|
||||||
|
##########
|
||||||
|
|
||||||
|
##########
|
||||||
|
#RECEIVE Begin
|
||||||
|
##########
|
||||||
|
enableReceive KEYWORD2
|
||||||
|
disableReceive KEYWORD2
|
||||||
|
available KEYWORD2
|
||||||
|
resetAvailable KEYWORD2
|
||||||
|
setReceiveTolerance KEYWORD2
|
||||||
|
getReceivedValue KEYWORD2
|
||||||
|
getReceivedBitlength KEYWORD2
|
||||||
|
getReceivedDelay KEYWORD2
|
||||||
|
getReceivedProtocol KEYWORD2
|
||||||
|
getReceivedRawdata KEYWORD2
|
||||||
|
##########
|
||||||
|
#RECEIVE End
|
||||||
|
##########
|
||||||
|
|
||||||
|
##########
|
||||||
|
#OTHERS Begin
|
||||||
|
##########
|
||||||
|
enableTransmit KEYWORD2
|
||||||
|
disableTransmit KEYWORD2
|
||||||
|
setPulseLength KEYWORD2
|
||||||
|
setProtocol KEYWORD2
|
||||||
|
setRepeatTransmit KEYWORD2
|
||||||
|
##########
|
||||||
|
#OTHERS End
|
||||||
|
##########
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
21
433/433Utils/rc-switch/library.json
Normal file
21
433/433Utils/rc-switch/library.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "rc-switch",
|
||||||
|
"description": "Use your Arduino or Raspberry Pi to operate remote radio controlled devices",
|
||||||
|
"keywords": "rf, radio, wireless",
|
||||||
|
"authors":
|
||||||
|
{
|
||||||
|
"name": "Suat Ozgur"
|
||||||
|
},
|
||||||
|
"repository":
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/sui77/rc-switch.git"
|
||||||
|
},
|
||||||
|
"version": "2.6.4",
|
||||||
|
"frameworks": [
|
||||||
|
"arduino",
|
||||||
|
"energia",
|
||||||
|
"wiringpi"
|
||||||
|
],
|
||||||
|
"platforms": "*"
|
||||||
|
}
|
10
433/433Utils/rc-switch/library.properties
Normal file
10
433/433Utils/rc-switch/library.properties
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
name=rc-switch
|
||||||
|
version=2.6.4
|
||||||
|
author=sui77
|
||||||
|
maintainer=sui77,fingolfin <noreply@sui.li>
|
||||||
|
sentence=Operate 433/315Mhz devices.
|
||||||
|
paragraph=Use your Arduino, ESP8266/ESP32 or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets.
|
||||||
|
category=Device Control
|
||||||
|
url=https://github.com/sui77/rc-switch
|
||||||
|
architectures=avr,esp8266,esp32,stm32,megaavr
|
||||||
|
includes=RCSwitch.h
|
16
433/rc-switch-pico/.gitignore
vendored
Normal file
16
433/rc-switch-pico/.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.DS_Store
|
||||||
|
CMakeFiles/
|
||||||
|
elf2uf2/
|
||||||
|
generated/
|
||||||
|
pico-sdk/
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeDoxyfile.in
|
||||||
|
CMakeDoxygenDefaults.cmake
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
*.bin
|
||||||
|
*.dis
|
||||||
|
*.elf
|
||||||
|
*.elf.map
|
||||||
|
*.hex
|
||||||
|
*.uf2
|
23
433/rc-switch-pico/CMakeLists.txt
Normal file
23
433/rc-switch-pico/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
|
# Pull in SDK (must be before project)
|
||||||
|
include(pico_sdk_import.cmake)
|
||||||
|
|
||||||
|
project(pico_examples C CXX ASM)
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
|
# Initialize the SDK
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
|
# Add blink example
|
||||||
|
add_subdirectory(examples/Transmit)
|
||||||
|
add_subdirectory(examples/Receive)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
21
433/rc-switch-pico/LICENSE
Normal file
21
433/rc-switch-pico/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 oshawa-connection
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
31
433/rc-switch-pico/examples/Receive/CMakeLists.txt
Normal file
31
433/rc-switch-pico/examples/Receive/CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
add_executable(receive
|
||||||
|
Receive.cc
|
||||||
|
../../radio-switch.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_compile_options(-Wall
|
||||||
|
-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
|
||||||
|
-Wno-unused-function # we have some for the docs that aren't called
|
||||||
|
-Wno-maybe-uninitialized
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull in our pico_stdlib which pulls in commonly used features
|
||||||
|
|
||||||
|
target_link_libraries(receive
|
||||||
|
pico_stdlib
|
||||||
|
hardware_adc
|
||||||
|
pico_multicore)
|
||||||
|
|
||||||
|
# enable usb output, disable uart output
|
||||||
|
pico_enable_stdio_usb(receive 1)
|
||||||
|
pico_enable_stdio_uart(receive 0)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(receive)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
235
433/rc-switch-pico/examples/Receive/Receive.cc
Normal file
235
433/rc-switch-pico/examples/Receive/Receive.cc
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "../../radio-switch.h"
|
||||||
|
#include "pico/stdio.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/multicore.h"
|
||||||
|
|
||||||
|
//#include "hardware/adc.h"
|
||||||
|
//#include <stdio.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define BUFFER_SIZ 1024
|
||||||
|
|
||||||
|
// 闪烁LED
|
||||||
|
void light()
|
||||||
|
{
|
||||||
|
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||||
|
gpio_init(LED_PIN);
|
||||||
|
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||||
|
gpio_put(LED_PIN, 1);
|
||||||
|
sleep_ms(100);
|
||||||
|
gpio_put(LED_PIN, 0);
|
||||||
|
sleep_ms(100);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int temperature() {
|
||||||
|
// 数模转换器为 0~3.3v 最大值为 12bit
|
||||||
|
const float conversion_factor = 3.3f / (1 << 12);
|
||||||
|
|
||||||
|
float v;
|
||||||
|
float t;
|
||||||
|
stdio_init_all();
|
||||||
|
printf("Use adc channel 4, measuring temptutre\n");
|
||||||
|
// ADC初始化
|
||||||
|
adc_init();
|
||||||
|
adc_set_temp_sensor_enabled(true);
|
||||||
|
adc_select_input(4);
|
||||||
|
|
||||||
|
// 数字转换为电压
|
||||||
|
v = adc_read() * conversion_factor;
|
||||||
|
t = 27 - (v - 0.706) / 0.001721;
|
||||||
|
printf("t:%.2f v:%.2f\n", t, v);
|
||||||
|
|
||||||
|
sleep_ms(100);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char pool[] = {
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 随即数
|
||||||
|
static int RAND()
|
||||||
|
{
|
||||||
|
int PASSWD_LEN = 3;
|
||||||
|
char password[BUFFER_SIZ];
|
||||||
|
int i = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
memset(password, 0, BUFFER_SIZ);
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
while (i != PASSWD_LEN) {
|
||||||
|
password[i++] = pool[rand() % sizeof(pool)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("%d\n", atoi(password));
|
||||||
|
return atoi(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SEND(const int ID)
|
||||||
|
{
|
||||||
|
const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚
|
||||||
|
const uint BUTTON = 21; // 按钮发射
|
||||||
|
|
||||||
|
const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED
|
||||||
|
const uint REPEAT_TRANSMIT = 4; // set this to whatever works best for you. // 重复发送
|
||||||
|
const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED
|
||||||
|
const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED
|
||||||
|
|
||||||
|
gpio_init(RADIO_TRANSMIT_PIN);
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
mySwitch.enableTransmit(RADIO_TRANSMIT_PIN);
|
||||||
|
mySwitch.setProtocol(PROTOCOL);
|
||||||
|
mySwitch.setPulseLength(PULSE_LENGTH);
|
||||||
|
mySwitch.setRepeatTransmit(REPEAT_TRANSMIT);
|
||||||
|
|
||||||
|
int RANDOM = 500;
|
||||||
|
int LOOP_NUM = 1; // 循环发送次数
|
||||||
|
|
||||||
|
for (int i = 0; i <= LOOP_NUM; i++) {
|
||||||
|
RANDOM = RAND();
|
||||||
|
light(); // 灯闪烁
|
||||||
|
|
||||||
|
sleep_ms(RANDOM * 2 / 3); // 等待随机时间
|
||||||
|
|
||||||
|
mySwitch.send(ID, BIT_LENGTH); // 第一次发射
|
||||||
|
sleep_ms(130);
|
||||||
|
|
||||||
|
mySwitch.send(ID + 1, BIT_LENGTH); // 第二次发射
|
||||||
|
sleep_ms(130);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int int_string(int val, char *string, int string_len, int *str_len, char *dest, int *dest_len)
|
||||||
|
{
|
||||||
|
char s[] = "55";
|
||||||
|
char d = '2';
|
||||||
|
|
||||||
|
snprintf(string, string_len, "%d", val);
|
||||||
|
*str_len = strlen(string);
|
||||||
|
|
||||||
|
if (0 == strncasecmp(string, s, 2)) {
|
||||||
|
dest[0] = d;
|
||||||
|
dest[1] = d;
|
||||||
|
strncpy(dest + 2, string + 2, (*str_len) - 2);
|
||||||
|
|
||||||
|
*dest_len = strlen(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 核心0发送数据到核心1, 核心1判断是否有数据到来, 然后打印.
|
||||||
|
void core1_main()
|
||||||
|
{
|
||||||
|
const uint RADIO_RECEIVER_PIN = 17;
|
||||||
|
gpio_init(RADIO_RECEIVER_PIN);
|
||||||
|
|
||||||
|
RCSwitch rcSwitch = RCSwitch();
|
||||||
|
rcSwitch.enableReceive(RADIO_RECEIVER_PIN);
|
||||||
|
|
||||||
|
char str[270];
|
||||||
|
char dest[270];
|
||||||
|
int str_len;
|
||||||
|
int dest_len;
|
||||||
|
memset(str, 0, 270);
|
||||||
|
memset(dest, 0, 270);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (rcSwitch.available()) {
|
||||||
|
light();
|
||||||
|
|
||||||
|
uint32_t val = rcSwitch.getReceivedValue();
|
||||||
|
//printf("核心1接收到的433MHZ数值%u\n", val);
|
||||||
|
|
||||||
|
int_string(val, str, 270, &str_len, dest, &dest_len);
|
||||||
|
|
||||||
|
if (val != 0) {
|
||||||
|
if (str[0] == '5' && str[1] == '5')
|
||||||
|
{
|
||||||
|
|
||||||
|
multicore_fifo_push_blocking(atoi(dest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rcSwitch.resetAvailable();
|
||||||
|
val = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rcSwitch.resetAvailable();
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (multicore_fifo_rvalid()) {
|
||||||
|
uint32_t i = multicore_fifo_pop_blocking();
|
||||||
|
printf("核心1接收到核心0的数值%u\n", i);
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
sleep_ms(130);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
multicore_reset_core1();
|
||||||
|
multicore_launch_core1(core1_main);
|
||||||
|
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
if (multicore_fifo_rvalid()) {
|
||||||
|
uint32_t i = multicore_fifo_pop_blocking(); // 读取核心1发送来的数据
|
||||||
|
//printf("核心0接收到核心1的数值%u\n", i);
|
||||||
|
|
||||||
|
//multicore_reset_core1(); // 关闭核心1
|
||||||
|
//SEND(i); // 433MHZ发送
|
||||||
|
//multicore_launch_core1(core1_main); // 开启核心1
|
||||||
|
//multicore_fifo_push_blocking(i); // 给核心1发送数据
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SEND(i);
|
||||||
|
printf("核心0转发433MHZ %u\n", i);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sleep_ms(130);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
21
433/rc-switch-pico/examples/Transmit/CMakeLists.txt
Normal file
21
433/rc-switch-pico/examples/Transmit/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
add_executable(transmit
|
||||||
|
Transmit.cc
|
||||||
|
../../radio-switch.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_compile_options(-Wall
|
||||||
|
-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
|
||||||
|
-Wno-unused-function # we have some for the docs that aren't called
|
||||||
|
-Wno-maybe-uninitialized
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull in our pico_stdlib which pulls in commonly used features
|
||||||
|
target_link_libraries(transmit pico_stdlib)
|
||||||
|
|
||||||
|
# enable usb output, disable uart output
|
||||||
|
pico_enable_stdio_usb(transmit 1)
|
||||||
|
pico_enable_stdio_uart(transmit 0)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(transmit)
|
101
433/rc-switch-pico/examples/Transmit/Transmit.cc
Normal file
101
433/rc-switch-pico/examples/Transmit/Transmit.cc
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "../../radio-switch.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define BUFFER_SIZ 1024
|
||||||
|
|
||||||
|
|
||||||
|
// 闪烁LED
|
||||||
|
static void light()
|
||||||
|
{
|
||||||
|
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
|
||||||
|
gpio_init(LED_PIN);
|
||||||
|
gpio_set_dir(LED_PIN, GPIO_OUT);
|
||||||
|
gpio_put(LED_PIN, 1);
|
||||||
|
sleep_ms(100);
|
||||||
|
gpio_put(LED_PIN, 0);
|
||||||
|
sleep_ms(100);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static char pool[] = {
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 随即数
|
||||||
|
static int RAND()
|
||||||
|
{
|
||||||
|
int PASSWD_LEN = 3;
|
||||||
|
char password[BUFFER_SIZ];
|
||||||
|
int i = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
|
||||||
|
memset(password, 0, BUFFER_SIZ);
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
while (i != PASSWD_LEN) {
|
||||||
|
password[i++] = pool[rand() % sizeof(pool)];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
printf("%d\n", atoi(password));
|
||||||
|
|
||||||
|
return atoi(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚
|
||||||
|
const uint BUTTON = 17; // 按钮发射
|
||||||
|
|
||||||
|
|
||||||
|
const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED
|
||||||
|
const uint REPEAT_TRANSMIT = 4; // set this to whatever works best for you. // 重复发送
|
||||||
|
const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED
|
||||||
|
const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED
|
||||||
|
|
||||||
|
stdio_init_all();
|
||||||
|
gpio_init(RADIO_TRANSMIT_PIN);
|
||||||
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
mySwitch.enableTransmit(RADIO_TRANSMIT_PIN);
|
||||||
|
mySwitch.setProtocol(PROTOCOL);
|
||||||
|
mySwitch.setPulseLength(PULSE_LENGTH);
|
||||||
|
mySwitch.setRepeatTransmit(REPEAT_TRANSMIT);
|
||||||
|
|
||||||
|
int RANDOM = 30;
|
||||||
|
int LOOP_NUM = 2; // 循环发送次数
|
||||||
|
|
||||||
|
|
||||||
|
const int but = 55001;
|
||||||
|
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
|
||||||
|
//if (1 == gpio_get(BUTTON)) { // 按钮按下
|
||||||
|
for (int i=0; i<=LOOP_NUM; i++) {
|
||||||
|
RANDOM = RAND();
|
||||||
|
light(); // 灯闪烁
|
||||||
|
|
||||||
|
sleep_ms(RANDOM * 2 / 3); // 等待随机时间
|
||||||
|
|
||||||
|
mySwitch.send(but, BIT_LENGTH); // 第一次发射
|
||||||
|
sleep_ms(130);
|
||||||
|
|
||||||
|
|
||||||
|
//mySwitch.send(but+1, BIT_LENGTH); // 第二次发射
|
||||||
|
//sleep_ms(130);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
|
sleep_ms(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
62
433/rc-switch-pico/pico_sdk_import.cmake
Normal file
62
433/rc-switch-pico/pico_sdk_import.cmake
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate this SDK
|
||||||
|
# It should be include()ed prior to project()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||||
|
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||||
|
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||||
|
|
||||||
|
if (NOT PICO_SDK_PATH)
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT)
|
||||||
|
include(FetchContent)
|
||||||
|
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||||
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG master
|
||||||
|
)
|
||||||
|
if (NOT pico_sdk)
|
||||||
|
message("Downloading Raspberry Pi Pico SDK")
|
||||||
|
FetchContent_Populate(pico_sdk)
|
||||||
|
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||||
|
endif ()
|
||||||
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||||
|
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||||
|
|
||||||
|
include(${PICO_SDK_INIT_CMAKE_FILE})
|
BIN
433/rc-switch-pico/pioasm/pioasm
Normal file
BIN
433/rc-switch-pico/pioasm/pioasm
Normal file
Binary file not shown.
728
433/rc-switch-pico/radio-switch.cc
Normal file
728
433/rc-switch-pico/radio-switch.cc
Normal file
@ -0,0 +1,728 @@
|
|||||||
|
/*
|
||||||
|
RCSwitch - Arduino libary for remote control outlet switches
|
||||||
|
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
- Andre Koehler / info(at)tomate-online(dot)de
|
||||||
|
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||||
|
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||||
|
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||||
|
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Andreas Steinel / A.<lastname>(at)gmail(dot)com
|
||||||
|
- Max Horn / max(at)quendi(dot)de
|
||||||
|
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Johann Richard / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo
|
||||||
|
- Matias Cuenca-Acuna
|
||||||
|
|
||||||
|
Project home: https://github.com/sui77/rc-switch/
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "radio-switch.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
|
#include "hardware/uart.h"
|
||||||
|
|
||||||
|
#ifdef _PICO_STDLIB_H
|
||||||
|
#define HIGH 1
|
||||||
|
#define LOW 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define PROGMEM
|
||||||
|
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
// interrupt handler and related code must be in RAM on ESP8266,
|
||||||
|
// according to issue #46.
|
||||||
|
#define RECEIVE_ATTR ICACHE_RAM_ATTR
|
||||||
|
#define VAR_ISR_ATTR
|
||||||
|
#elif defined(ESP32)
|
||||||
|
#define RECEIVE_ATTR IRAM_ATTR
|
||||||
|
#define VAR_ISR_ATTR DRAM_ATTR
|
||||||
|
#else
|
||||||
|
#define RECEIVE_ATTR
|
||||||
|
#define VAR_ISR_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Format for protocol definitions:
|
||||||
|
* {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal}
|
||||||
|
*
|
||||||
|
* pulselength: pulse length in microseconds, e.g. 350
|
||||||
|
* Sync bit: {1, 31} means 1 high pulse and 31 low pulses
|
||||||
|
* (perceived as a 31*pulselength long pulse, total length of sync bit is
|
||||||
|
* 32*pulselength microseconds), i.e:
|
||||||
|
* _
|
||||||
|
* | |_______________________________ (don't count the vertical bars)
|
||||||
|
* "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
|
||||||
|
* and 3 low pulses, total length (1+3)*pulselength, i.e:
|
||||||
|
* _
|
||||||
|
* | |___
|
||||||
|
* "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
|
||||||
|
* ___
|
||||||
|
* | |_
|
||||||
|
*
|
||||||
|
* These are combined to form Tri-State bits when sending or receiving codes.
|
||||||
|
*/
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
static const VAR_ISR_ATTR RCSwitch::Protocol proto[] = {
|
||||||
|
#else
|
||||||
|
static const RCSwitch::Protocol PROGMEM proto[] = {
|
||||||
|
#endif
|
||||||
|
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1
|
||||||
|
{ 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2
|
||||||
|
{ 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3
|
||||||
|
{ 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4
|
||||||
|
{ 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5
|
||||||
|
{ 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B)
|
||||||
|
{ 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false }, // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote)
|
||||||
|
{ 200, { 3, 130}, { 7, 16 }, { 3, 16}, false}, // protocol 8 Conrad RS-200 RX
|
||||||
|
{ 200, { 130, 7 }, { 16, 7 }, { 16, 3 }, true}, // protocol 9 Conrad RS-200 TX
|
||||||
|
{ 365, { 18, 1 }, { 3, 1 }, { 1, 3 }, true }, // protocol 10 (1ByOne Doorbell)
|
||||||
|
{ 270, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 11 (HT12E)
|
||||||
|
{ 320, { 36, 1 }, { 1, 2 }, { 2, 1 }, true } // protocol 12 (SM5212)
|
||||||
|
};
|
||||||
|
|
||||||
|
void RCSwitch::gpio_callback(unsigned int gpio, uint32_t events) {
|
||||||
|
RCSwitch::handleInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
numProto = sizeof(proto) / sizeof(proto[0])
|
||||||
|
};
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
volatile unsigned long RCSwitch::nReceivedValue = 0;
|
||||||
|
volatile unsigned int RCSwitch::nReceivedBitlength = 0;
|
||||||
|
volatile unsigned int RCSwitch::nReceivedDelay = 0;
|
||||||
|
volatile unsigned int RCSwitch::nReceivedProtocol = 0;
|
||||||
|
int RCSwitch::nReceiveTolerance = 60;
|
||||||
|
const unsigned int VAR_ISR_ATTR RCSwitch::nSeparationLimit = 4300;
|
||||||
|
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
|
||||||
|
// according to discussion on issue #14 it might be more suitable to set the separation
|
||||||
|
// limit to the same time as the 'low' part of the sync signal for the current protocol.
|
||||||
|
unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RCSwitch::RCSwitch() {
|
||||||
|
this->nTransmitterPin = -1;
|
||||||
|
this->setRepeatTransmit(10);
|
||||||
|
this->setProtocol(1);
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
this->nReceiverInterrupt = -1;
|
||||||
|
this->setReceiveTolerance(60);
|
||||||
|
RCSwitch::nReceivedValue = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the protocol to send.
|
||||||
|
*/
|
||||||
|
void RCSwitch::setProtocol(Protocol protocol) {
|
||||||
|
this->protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the protocol to send, from a list of predefined protocols
|
||||||
|
*/
|
||||||
|
void RCSwitch::setProtocol(int nProtocol) {
|
||||||
|
if (nProtocol < 1 || nProtocol > numProto) {
|
||||||
|
nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ???
|
||||||
|
}
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
this->protocol = proto[nProtocol-1];
|
||||||
|
#else
|
||||||
|
memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the protocol to send with pulse length in microseconds.
|
||||||
|
*/
|
||||||
|
void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
|
||||||
|
setProtocol(nProtocol);
|
||||||
|
this->setPulseLength(nPulseLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets pulse length in microseconds
|
||||||
|
*/
|
||||||
|
void RCSwitch::setPulseLength(int nPulseLength) {
|
||||||
|
this->protocol.pulseLength = nPulseLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets Repeat Transmits
|
||||||
|
*/
|
||||||
|
void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
|
||||||
|
this->nRepeatTransmit = nRepeatTransmit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Receiving Tolerance
|
||||||
|
*/
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
void RCSwitch::setReceiveTolerance(int nPercent) {
|
||||||
|
RCSwitch::nReceiveTolerance = nPercent;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable transmissions
|
||||||
|
*
|
||||||
|
* @param nTransmitterPin Arduino Pin to which the sender is connected to
|
||||||
|
*/
|
||||||
|
void RCSwitch::enableTransmit(int nTransmitterPin) {
|
||||||
|
this->nTransmitterPin = nTransmitterPin;
|
||||||
|
// pinMode(this->nTransmitterPin, OUTPUT);
|
||||||
|
gpio_set_dir(this->nTransmitterPin,GPIO_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable transmissions
|
||||||
|
*/
|
||||||
|
void RCSwitch::disableTransmit() {
|
||||||
|
this->nTransmitterPin = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type D REV)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (A,B,C,D)
|
||||||
|
* @param nDevice Number of the switch itself (1..3)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(char sGroup, int nDevice) {
|
||||||
|
this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type D REV)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (A,B,C,D)
|
||||||
|
* @param nDevice Number of the switch itself (1..3)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(char sGroup, int nDevice) {
|
||||||
|
this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type C Intertechno)
|
||||||
|
*
|
||||||
|
* @param sFamily Familycode (a..f)
|
||||||
|
* @param nGroup Number of group (1..4)
|
||||||
|
* @param nDevice Number of device (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
|
||||||
|
this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type C Intertechno)
|
||||||
|
*
|
||||||
|
* @param sFamily Familycode (a..f)
|
||||||
|
* @param nGroup Number of group (1..4)
|
||||||
|
* @param nDevice Number of device (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
|
||||||
|
this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type B with two rotary/sliding switches)
|
||||||
|
*
|
||||||
|
* @param nAddressCode Number of the switch group (1..4)
|
||||||
|
* @param nChannelCode Number of the switch itself (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
|
||||||
|
this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type B with two rotary/sliding switches)
|
||||||
|
*
|
||||||
|
* @param nAddressCode Number of the switch group (1..4)
|
||||||
|
* @param nChannelCode Number of the switch itself (1..4)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
|
||||||
|
this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead!
|
||||||
|
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param nChannelCode Number of the switch itself (1..5)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(const char* sGroup, int nChannel) {
|
||||||
|
const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||||
|
this->switchOn(sGroup, code[nChannel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead!
|
||||||
|
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param nChannelCode Number of the switch itself (1..5)
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(const char* sGroup, int nChannel) {
|
||||||
|
const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||||
|
this->switchOff(sGroup, code[nChannel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOn(const char* sGroup, const char* sDevice) {
|
||||||
|
this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||||
|
*
|
||||||
|
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||||
|
*/
|
||||||
|
void RCSwitch::switchOff(const char* sGroup, const char* sDevice) {
|
||||||
|
this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a char[13], representing the code word to be send.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) {
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = bStatus ? '0' : 'F';
|
||||||
|
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding for type B switches with two rotary/sliding switches.
|
||||||
|
*
|
||||||
|
* The code word is a tristate word and with following bit pattern:
|
||||||
|
*
|
||||||
|
* +-----------------------------+-----------------------------+----------+------------+
|
||||||
|
* | 4 bits address | 4 bits address | 3 bits | 1 bit |
|
||||||
|
* | switch group | switch number | not used | on / off |
|
||||||
|
* | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 |
|
||||||
|
* +-----------------------------+-----------------------------+----------+------------+
|
||||||
|
*
|
||||||
|
* @param nAddressCode Number of the switch group (1..4)
|
||||||
|
* @param nChannelCode Number of the switch itself (1..4)
|
||||||
|
* @param bStatus Whether to switch on (true) or off (false)
|
||||||
|
*
|
||||||
|
* @return char[13], representing a tristate code word of length 12
|
||||||
|
*/
|
||||||
|
char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) {
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like getCodeWord (Type C = Intertechno)
|
||||||
|
*/
|
||||||
|
char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) {
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
int nFamily = (int)sFamily - 'a';
|
||||||
|
if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode the family into four bits
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0';
|
||||||
|
|
||||||
|
// encode the device and group
|
||||||
|
sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0';
|
||||||
|
sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0';
|
||||||
|
|
||||||
|
// encode the status code
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = 'F';
|
||||||
|
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoding for the REV Switch Type
|
||||||
|
*
|
||||||
|
* The code word is a tristate word and with following bit pattern:
|
||||||
|
*
|
||||||
|
* +-----------------------------+-------------------+----------+--------------+
|
||||||
|
* | 4 bits address | 3 bits address | 3 bits | 2 bits |
|
||||||
|
* | switch group | device number | not used | on / off |
|
||||||
|
* | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 |
|
||||||
|
* +-----------------------------+-------------------+----------+--------------+
|
||||||
|
*
|
||||||
|
* Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
|
||||||
|
*
|
||||||
|
* @param sGroup Name of the switch group (A..D, resp. a..d)
|
||||||
|
* @param nDevice Number of the switch itself (1..3)
|
||||||
|
* @param bStatus Whether to switch on (true) or off (false)
|
||||||
|
*
|
||||||
|
* @return char[13], representing a tristate code word of length 12
|
||||||
|
*/
|
||||||
|
char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) {
|
||||||
|
static char sReturn[13];
|
||||||
|
int nReturnPos = 0;
|
||||||
|
|
||||||
|
// sGroup must be one of the letters in "abcdABCD"
|
||||||
|
int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A';
|
||||||
|
if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 3; i++) {
|
||||||
|
sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F';
|
||||||
|
}
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
sReturn[nReturnPos++] = '0';
|
||||||
|
|
||||||
|
sReturn[nReturnPos++] = bStatus ? '1' : '0';
|
||||||
|
sReturn[nReturnPos++] = bStatus ? '0' : '1';
|
||||||
|
|
||||||
|
sReturn[nReturnPos] = '\0';
|
||||||
|
return sReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sCodeWord a tristate code word consisting of the letter 0, 1, F
|
||||||
|
*/
|
||||||
|
void RCSwitch::sendTriState(const char* sCodeWord) {
|
||||||
|
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||||
|
unsigned long code = 0;
|
||||||
|
unsigned int length = 0;
|
||||||
|
for (const char* p = sCodeWord; *p; p++) {
|
||||||
|
code <<= 2L;
|
||||||
|
switch (*p) {
|
||||||
|
case '0':
|
||||||
|
// bit pattern 00
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
// bit pattern 01
|
||||||
|
code |= 1L;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
// bit pattern 11
|
||||||
|
code |= 3L;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
length += 2;
|
||||||
|
}
|
||||||
|
this->send(code, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sCodeWord a binary code word consisting of the letter 0, 1
|
||||||
|
*/
|
||||||
|
void RCSwitch::send(const char* sCodeWord) {
|
||||||
|
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||||
|
unsigned long code = 0;
|
||||||
|
unsigned int length = 0;
|
||||||
|
for (const char* p = sCodeWord; *p; p++) {
|
||||||
|
code <<= 1L;
|
||||||
|
if (*p != '0')
|
||||||
|
code |= 1L;
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
this->send(code, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit the first 'length' bits of the integer 'code'. The
|
||||||
|
* bits are sent from MSB to LSB, i.e., first the bit at position length-1,
|
||||||
|
* then the bit at position length-2, and so on, till finally the bit at position 0.
|
||||||
|
*/
|
||||||
|
void RCSwitch::send(unsigned long code, unsigned int length) {
|
||||||
|
if (this->nTransmitterPin == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
// make sure the receiver is disabled while we transmit
|
||||||
|
int nReceiverInterrupt_backup = nReceiverInterrupt;
|
||||||
|
if (nReceiverInterrupt_backup != -1) {
|
||||||
|
this->disableReceive();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
|
||||||
|
for (int i = length-1; i >= 0; i--) {
|
||||||
|
if (code & (1L << i))
|
||||||
|
this->transmit(protocol.one);
|
||||||
|
else
|
||||||
|
this->transmit(protocol.zero);
|
||||||
|
}
|
||||||
|
this->transmit(protocol.syncFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable transmit after sending (i.e., for inverted protocols)
|
||||||
|
// digitalWrite(this->nTransmitterPin, LOW);
|
||||||
|
gpio_put(this->nTransmitterPin, LOW);
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
// enable receiver again if we just disabled it
|
||||||
|
if (nReceiverInterrupt_backup != -1) {
|
||||||
|
this->enableReceive(nReceiverInterrupt_backup);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit a single high-low pulse.
|
||||||
|
*/
|
||||||
|
void RCSwitch::transmit(HighLow pulses) {
|
||||||
|
uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH;
|
||||||
|
uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW;
|
||||||
|
|
||||||
|
// digitalWrite(this->nTransmitterPin, firstLogicLevel);
|
||||||
|
// delayMicroseconds( this->protocol.pulseLength * pulses.high);
|
||||||
|
// digitalWrite(this->nTransmitterPin, secondLogicLevel);
|
||||||
|
// delayMicroseconds( this->protocol.pulseLength * pulses.low);
|
||||||
|
gpio_put(this->nTransmitterPin, firstLogicLevel);
|
||||||
|
sleep_us(this->protocol.pulseLength * pulses.high);
|
||||||
|
gpio_put(this->nTransmitterPin, secondLogicLevel);
|
||||||
|
sleep_us(this->protocol.pulseLength * pulses.low);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
/**
|
||||||
|
* Enable receiving data
|
||||||
|
*/
|
||||||
|
void RCSwitch::enableReceive(int interrupt) {
|
||||||
|
this->nReceiverInterrupt = interrupt;
|
||||||
|
this->enableReceive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCSwitch::enableReceive() {
|
||||||
|
if (this->nReceiverInterrupt != -1) {
|
||||||
|
RCSwitch::nReceivedValue = 0;
|
||||||
|
RCSwitch::nReceivedBitlength = 0;
|
||||||
|
gpio_set_irq_enabled_with_callback(this->nReceiverInterrupt, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
|
||||||
|
// attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable receiving data
|
||||||
|
*/
|
||||||
|
void RCSwitch::disableReceive() {
|
||||||
|
#if not defined(RaspberryPi) // Arduino
|
||||||
|
// detachInterrupt(this->nReceiverInterrupt);
|
||||||
|
#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR
|
||||||
|
this->nReceiverInterrupt = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RCSwitch::available() {
|
||||||
|
return RCSwitch::nReceivedValue != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RCSwitch::resetAvailable() {
|
||||||
|
RCSwitch::nReceivedValue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long RCSwitch::getReceivedValue() {
|
||||||
|
return RCSwitch::nReceivedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RCSwitch::getReceivedBitlength() {
|
||||||
|
return RCSwitch::nReceivedBitlength;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RCSwitch::getReceivedDelay() {
|
||||||
|
return RCSwitch::nReceivedDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int RCSwitch::getReceivedProtocol() {
|
||||||
|
return RCSwitch::nReceivedProtocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int* RCSwitch::getReceivedRawdata() {
|
||||||
|
return RCSwitch::timings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* helper function for the receiveProtocol method */
|
||||||
|
static inline unsigned int diff(int A, int B) {
|
||||||
|
return abs(A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
|
||||||
|
#if defined(ESP8266) || defined(ESP32)
|
||||||
|
const Protocol &pro = proto[p-1];
|
||||||
|
#else
|
||||||
|
Protocol pro;
|
||||||
|
memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned long code = 0;
|
||||||
|
//Assuming the longer pulse length is the pulse captured in timings[0]
|
||||||
|
const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high);
|
||||||
|
const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses;
|
||||||
|
const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100;
|
||||||
|
|
||||||
|
/* For protocols that start low, the sync period looks like
|
||||||
|
* _________
|
||||||
|
* _____________| |XXXXXXXXXXXX|
|
||||||
|
*
|
||||||
|
* |--1st dur--|-2nd dur-|-Start data-|
|
||||||
|
*
|
||||||
|
* The 3rd saved duration starts the data.
|
||||||
|
*
|
||||||
|
* For protocols that start high, the sync period looks like
|
||||||
|
*
|
||||||
|
* ______________
|
||||||
|
* | |____________|XXXXXXXXXXXXX|
|
||||||
|
*
|
||||||
|
* |-filtered out-|--1st dur--|--Start data--|
|
||||||
|
*
|
||||||
|
* The 2nd saved duration starts the data
|
||||||
|
*/
|
||||||
|
const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1);
|
||||||
|
|
||||||
|
for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) {
|
||||||
|
code <<= 1;
|
||||||
|
if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance &&
|
||||||
|
diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
|
||||||
|
// zero
|
||||||
|
} else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance &&
|
||||||
|
diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) {
|
||||||
|
// one
|
||||||
|
code |= 1;
|
||||||
|
} else {
|
||||||
|
// Failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise
|
||||||
|
RCSwitch::nReceivedValue = code;
|
||||||
|
RCSwitch::nReceivedBitlength = (changeCount - 1) / 2;
|
||||||
|
RCSwitch::nReceivedDelay = delay;
|
||||||
|
RCSwitch::nReceivedProtocol = p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void RECEIVE_ATTR RCSwitch::handleInterrupt() {
|
||||||
|
|
||||||
|
static unsigned int changeCount = 0;
|
||||||
|
static unsigned long lastTime = 0;
|
||||||
|
static unsigned int repeatCount = 0;
|
||||||
|
|
||||||
|
// const long time = micros();
|
||||||
|
const long time = to_us_since_boot(get_absolute_time());
|
||||||
|
const unsigned int duration = time - lastTime;
|
||||||
|
|
||||||
|
if (duration > RCSwitch::nSeparationLimit) {
|
||||||
|
|
||||||
|
// A long stretch without signal level change occurred. This could
|
||||||
|
// be the gap between two transmission.
|
||||||
|
if ((repeatCount==0) || (diff(duration, RCSwitch::timings[0]) < 200)) {
|
||||||
|
|
||||||
|
// This long signal is close in length to the long signal which
|
||||||
|
// started the previously recorded timings; this suggests that
|
||||||
|
// it may indeed by a a gap between two transmissions (we assume
|
||||||
|
// here that a sender will send the signal multiple times,
|
||||||
|
// with roughly the same gap between them).
|
||||||
|
repeatCount++;
|
||||||
|
if (repeatCount == 2) {
|
||||||
|
for(unsigned int i = 1; i <= numProto; i++) {
|
||||||
|
if (receiveProtocol(i, changeCount)) {
|
||||||
|
// receive succeeded for protocol i
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeatCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// detect overflow
|
||||||
|
if (changeCount >= RCSWITCH_MAX_CHANGES) {
|
||||||
|
changeCount = 0;
|
||||||
|
repeatCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCSwitch::timings[changeCount++] = duration;
|
||||||
|
lastTime = time;
|
||||||
|
}
|
||||||
|
#endif
|
170
433/rc-switch-pico/radio-switch.h
Normal file
170
433/rc-switch-pico/radio-switch.h
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
RCSwitch - Arduino libary for remote control outlet switches
|
||||||
|
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
- Andre Koehler / info(at)tomate-online(dot)de
|
||||||
|
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||||
|
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||||
|
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||||
|
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
- Max Horn / max(at)quendi(dot)de
|
||||||
|
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||||
|
|
||||||
|
Project home: https://github.com/sui77/rc-switch/
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef _RCSwitch_h
|
||||||
|
#define _RCSwitch_h
|
||||||
|
|
||||||
|
|
||||||
|
// #define RaspberryPi
|
||||||
|
|
||||||
|
// Include libraries for RPi:
|
||||||
|
#include <string.h> /* memcpy */
|
||||||
|
#include <stdlib.h> /* abs */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Number of maximum high/Low changes per packet.
|
||||||
|
// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
|
||||||
|
#define RCSWITCH_MAX_CHANGES 67
|
||||||
|
|
||||||
|
class RCSwitch {
|
||||||
|
|
||||||
|
public:
|
||||||
|
RCSwitch();
|
||||||
|
|
||||||
|
void switchOn(int nGroupNumber, int nSwitchNumber);
|
||||||
|
void switchOff(int nGroupNumber, int nSwitchNumber);
|
||||||
|
void switchOn(const char* sGroup, int nSwitchNumber);
|
||||||
|
void switchOff(const char* sGroup, int nSwitchNumber);
|
||||||
|
void switchOn(char sFamily, int nGroup, int nDevice);
|
||||||
|
void switchOff(char sFamily, int nGroup, int nDevice);
|
||||||
|
void switchOn(const char* sGroup, const char* sDevice);
|
||||||
|
void switchOff(const char* sGroup, const char* sDevice);
|
||||||
|
void switchOn(char sGroup, int nDevice);
|
||||||
|
void switchOff(char sGroup, int nDevice);
|
||||||
|
|
||||||
|
void sendTriState(const char* sCodeWord);
|
||||||
|
void send(unsigned long code, unsigned int length);
|
||||||
|
void send(const char* sCodeWord);
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
void enableReceive(int interrupt);
|
||||||
|
void enableReceive();
|
||||||
|
void disableReceive();
|
||||||
|
bool available();
|
||||||
|
void resetAvailable();
|
||||||
|
|
||||||
|
unsigned long getReceivedValue();
|
||||||
|
unsigned int getReceivedBitlength();
|
||||||
|
unsigned int getReceivedDelay();
|
||||||
|
unsigned int getReceivedProtocol();
|
||||||
|
unsigned int* getReceivedRawdata();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void enableTransmit(int nTransmitterPin);
|
||||||
|
void disableTransmit();
|
||||||
|
void setPulseLength(int nPulseLength);
|
||||||
|
void setRepeatTransmit(int nRepeatTransmit);
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
void setReceiveTolerance(int nPercent);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of a single pule, which consists of a high signal
|
||||||
|
* whose duration is "high" times the base pulse length, followed
|
||||||
|
* by a low signal lasting "low" times the base pulse length.
|
||||||
|
* Thus, the pulse overall lasts (high+low)*pulseLength
|
||||||
|
*/
|
||||||
|
struct HighLow {
|
||||||
|
uint8_t high;
|
||||||
|
uint8_t low;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A "protocol" describes how zero and one bits are encoded into high/low
|
||||||
|
* pulses.
|
||||||
|
*/
|
||||||
|
struct Protocol {
|
||||||
|
/** base pulse length in microseconds, e.g. 350 */
|
||||||
|
uint16_t pulseLength;
|
||||||
|
|
||||||
|
HighLow syncFactor;
|
||||||
|
HighLow zero;
|
||||||
|
HighLow one;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, interchange high and low logic levels in all transmissions.
|
||||||
|
*
|
||||||
|
* By default, RCSwitch assumes that any signals it sends or receives
|
||||||
|
* can be broken down into pulses which start with a high signal level,
|
||||||
|
* followed by a a low signal level. This is e.g. the case for the
|
||||||
|
* popular PT 2260 encoder chip, and thus many switches out there.
|
||||||
|
*
|
||||||
|
* But some devices do it the other way around, and start with a low
|
||||||
|
* signal level, followed by a high signal level, e.g. the HT6P20B. To
|
||||||
|
* accommodate this, one can set invertedSignal to true, which causes
|
||||||
|
* RCSwitch to change how it interprets any HighLow struct FOO: It will
|
||||||
|
* then assume transmissions start with a low signal lasting
|
||||||
|
* FOO.high*pulseLength microseconds, followed by a high signal lasting
|
||||||
|
* FOO.low*pulseLength microseconds.
|
||||||
|
*/
|
||||||
|
bool invertedSignal;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setProtocol(Protocol protocol);
|
||||||
|
void setProtocol(int nProtocol);
|
||||||
|
void setProtocol(int nProtocol, int nPulseLength);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void gpio_callback(unsigned int gpio, uint32_t events);
|
||||||
|
char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus);
|
||||||
|
char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus);
|
||||||
|
char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus);
|
||||||
|
char* getCodeWordD(char group, int nDevice, bool bStatus);
|
||||||
|
void transmit(HighLow pulses);
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
static void handleInterrupt();
|
||||||
|
static bool receiveProtocol(const int p, unsigned int changeCount);
|
||||||
|
int nReceiverInterrupt;
|
||||||
|
#endif
|
||||||
|
int nTransmitterPin;
|
||||||
|
int nRepeatTransmit;
|
||||||
|
|
||||||
|
Protocol protocol;
|
||||||
|
|
||||||
|
#if not defined( RCSwitchDisableReceiving )
|
||||||
|
static int nReceiveTolerance;
|
||||||
|
volatile static unsigned long nReceivedValue;
|
||||||
|
volatile static unsigned int nReceivedBitlength;
|
||||||
|
volatile static unsigned int nReceivedDelay;
|
||||||
|
volatile static unsigned int nReceivedProtocol;
|
||||||
|
const static unsigned int nSeparationLimit;
|
||||||
|
/*
|
||||||
|
* timings[0] contains sync timing, followed by a number of bits
|
||||||
|
*/
|
||||||
|
static unsigned int timings[RCSWITCH_MAX_CHANGES];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
23
433/rc-switch-pico/readme.md
Normal file
23
433/rc-switch-pico/readme.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# RcSwitch
|
||||||
|
A port of the brilliant [RC-Switch](https://github.com/sui77/rc-switch) library to the raspberry pi pico.
|
||||||
|
|
||||||
|
It allows you to send and recieve radio signals from 433/315Mhz devices like radio controlled power sockets, using cheap radio modules.
|
||||||
|
|
||||||
|
This works for both recieving and transmitting. Check out the examples for code for both of these.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
This library can be developed on any platform that the pico-sdk works on, through cmake.
|
||||||
|
|
||||||
|
In the root directory, make sure that the pico-sdk is on your path and run
|
||||||
|
```bash
|
||||||
|
cmake .
|
||||||
|
```
|
||||||
|
|
||||||
|
then change directory into `examples/recieve`, then run
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
which will spit out your uf2 file.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
If you experience an error while using this library, please raise an issue here on Github and I'll try to help out. Pull requests are also very welcome!
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user