add rf433mhz component to extras, for using antenna modules with esp
This commit is contained in:
parent
a721fb0bc7
commit
01e9c1b98e
7 changed files with 359 additions and 0 deletions
4
examples/rf433mhz/Makefile
Normal file
4
examples/rf433mhz/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
PROGRAM = rf-send-recieve
|
||||||
|
EXTRA_COMPONENTS = extras/rf433mhz
|
||||||
|
include ../../common.mk
|
||||||
|
|
88
examples/rf433mhz/rf-send-recieve.c
Normal file
88
examples/rf433mhz/rf-send-recieve.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
//esp sdk
|
||||||
|
#include "espressif/esp_common.h"
|
||||||
|
#include "esp/uart.h"
|
||||||
|
|
||||||
|
//rtos
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
|
//rf 433mhz
|
||||||
|
#include <rf433mhz/rf_433mhz.h>
|
||||||
|
|
||||||
|
#define TRANSMITTER_PIN 5
|
||||||
|
#define RECIEVER_PIN 4
|
||||||
|
|
||||||
|
reciever_433mhz* reciever;
|
||||||
|
QueueHandle_t decode_queue;
|
||||||
|
|
||||||
|
void rf433mhz_transmit(void *pvParameters) {
|
||||||
|
gpio_enable(TRANSMITTER_PIN, GPIO_OUTPUT);
|
||||||
|
message_433mhz msg;
|
||||||
|
msg.code_lenght=24;
|
||||||
|
msg.repeat=2;
|
||||||
|
msg.pulse_length = 312;
|
||||||
|
protocol_433mhz proto = protocols_433mhz[PROTO1];
|
||||||
|
msg.protocol = &proto;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
msg.data=1364;
|
||||||
|
send_message_433mhz(TRANSMITTER_PIN, &msg);
|
||||||
|
vTaskDelay(1000);
|
||||||
|
msg.data=1361;
|
||||||
|
send_message_433mhz(TRANSMITTER_PIN, &msg);
|
||||||
|
vTaskDelay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void recieve_interrupt_handler(uint8_t gpio_num) {
|
||||||
|
BaseType_t xHigerPriorityTaskTriggerd = pdFALSE;
|
||||||
|
UBaseType_t uxSavedInterruptStatus;
|
||||||
|
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
||||||
|
recieve_on_interrupt(reciever);
|
||||||
|
if (reciever->repeatCount < 2) {
|
||||||
|
taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//printf("Function recieve_interrupt_handler recieved going enter critical \n");
|
||||||
|
reciever_433mhz* old_reciever = reciever;
|
||||||
|
reciever = create_reciever_buffer();
|
||||||
|
taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
|
||||||
|
xQueueSendFromISR(decode_queue, &old_reciever, &xHigerPriorityTaskTriggerd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rf433mhz_recieve(void *pvParameters) {
|
||||||
|
//enable reception on recieve pin
|
||||||
|
gpio_enable(RECIEVER_PIN, GPIO_INPUT);
|
||||||
|
reciever = create_reciever_buffer();
|
||||||
|
gpio_set_interrupt(RECIEVER_PIN, GPIO_INTTYPE_EDGE_ANY, recieve_interrupt_handler);
|
||||||
|
|
||||||
|
reciever_433mhz* recv;
|
||||||
|
message_433mhz msg;
|
||||||
|
while(1) {
|
||||||
|
if(xQueueReceive(decode_queue, &recv, 0) == pdTRUE){
|
||||||
|
//try to decode recieved data
|
||||||
|
bool recieved = false;
|
||||||
|
for(int i=0; i < PROTOCOL_COUNT ; i++) {
|
||||||
|
if(decode_recieved(recv, &protocols_433mhz[i], &msg)) {
|
||||||
|
recieved = true;
|
||||||
|
printf("Recieved message with data: %d\n", msg.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//no protcol found to decode data
|
||||||
|
}
|
||||||
|
free(recv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_init(void) {
|
||||||
|
uart_set_baud(0, 115200);
|
||||||
|
|
||||||
|
decode_queue = xQueueCreate(2, sizeof(reciever_433mhz*));
|
||||||
|
|
||||||
|
//start tasks
|
||||||
|
xTaskCreate(rf433mhz_transmit, "transmitter_rf", 256, NULL, 1, NULL);
|
||||||
|
xTaskCreate(rf433mhz_recieve, "reciever_rf", 256, NULL, 1, NULL);
|
||||||
|
|
||||||
|
}
|
35
extras/rf433mhz/README.md
Normal file
35
extras/rf433mhz/README.md
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
rf433hmz - A Copyright (c) 2018 Felix Richter <judge@felixrichter.tech>
|
||||||
|
|
||||||
|
# About
|
||||||
|
|
||||||
|
This is a simple c library which implements encoding and decoding of various rf protocols for sending and recieving rf transmissions.
|
||||||
|
It is heavly based on the RC Switch library. It is designed to be used with the esp8266 using open rtos, but it should be very easy to port
|
||||||
|
to other platforms.
|
||||||
|
|
||||||
|
# Issues
|
||||||
|
|
||||||
|
If you find any bugs, please report them at: https://github.com/Felix5721/rf433mhz
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
rf433hmz is published under the MIT license.
|
||||||
|
|
||||||
|
Copyright © 2018 Felix Richter <judge@felixrichter.tech>
|
||||||
|
|
||||||
|
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.
|
9
extras/rf433mhz/component.mk
Normal file
9
extras/rf433mhz/component.mk
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Component makefile for extras/rf433mhz
|
||||||
|
|
||||||
|
# expected anyone using this driver includes it as 'rf433mhz/rf_433mhz.h'
|
||||||
|
INC_DIRS += $(rf433mhz_ROOT)..
|
||||||
|
|
||||||
|
# args for passing into compile rule generation
|
||||||
|
rf433mhz_SRC_DIR = $(rf433mhz_ROOT)
|
||||||
|
|
||||||
|
$(eval $(call component_compile_rules,rf433mhz))
|
126
extras/rf433mhz/rf_433mhz.c
Normal file
126
extras/rf433mhz/rf_433mhz.c
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#include "rf_433mhz.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
protocol_433mhz protocols_433mhz[] = {
|
||||||
|
{ { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1
|
||||||
|
{ { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2
|
||||||
|
{ { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3
|
||||||
|
{ { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4
|
||||||
|
{ { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5
|
||||||
|
{ { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B)
|
||||||
|
{ { 2, 62 }, { 1, 6 }, { 6, 1 }, false } // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote)
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline unsigned int diff(int A, int B) {
|
||||||
|
return abs(A - B);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Transmit single pulse meaning 1 or 0 or sync
|
||||||
|
void transmit(uint8_t pin, protocol_433mhz* proto, pulse_t pulse_params, uint16_t pulse_length) {
|
||||||
|
bool firstLogicLevel = proto->inverted ? 0 : 1;
|
||||||
|
bool secondLogicLevel = proto->inverted ? 1 : 0;
|
||||||
|
|
||||||
|
setPinDigital(pin, firstLogicLevel);
|
||||||
|
delayMicroSec(pulse_length * pulse_params.high_time);
|
||||||
|
setPinDigital(pin, secondLogicLevel);
|
||||||
|
delayMicroSec(pulse_length * pulse_params.low_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_message_433mhz(uint8_t pin, message_433mhz* msg) {
|
||||||
|
disableInterrupts();
|
||||||
|
for (uint8_t n_repeat=0; n_repeat < msg->repeat; n_repeat++) {
|
||||||
|
for(int i = msg->code_lenght-1; i>=0; i--) {
|
||||||
|
if ( msg->data & (1L << i) ) {
|
||||||
|
transmit(pin, msg->protocol, msg->protocol->one, msg->pulse_length);
|
||||||
|
} else {
|
||||||
|
transmit(pin, msg->protocol, msg->protocol->zero, msg->pulse_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transmit(pin, msg->protocol, msg->protocol->sync, msg->pulse_length);
|
||||||
|
}
|
||||||
|
//make sure antenna is powered off
|
||||||
|
setPinDigital(pin, 0);
|
||||||
|
enableInterrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void recieve_on_interrupt(reciever_433mhz* reciever) {
|
||||||
|
long time = getMicroSec();
|
||||||
|
unsigned int duration = time - reciever->last_time;
|
||||||
|
|
||||||
|
if (duration > reciever->seperation_limit) {
|
||||||
|
//long stretch without change -> might be gap between transmittions
|
||||||
|
if ( diff(duration, reciever->timeings[0]) < 200 ) {
|
||||||
|
//this long singal is close in length to the previous recorded signals
|
||||||
|
reciever->repeatCount++;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
reciever->changeCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( reciever->changeCount >= RECIEVE_MAX_BUFFER_LEN ) {
|
||||||
|
reciever->changeCount = 0;
|
||||||
|
reciever->repeatCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
reciever->timeings[reciever->changeCount++] = duration;
|
||||||
|
reciever->last_time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool decode_recieved(reciever_433mhz* reciever, protocol_433mhz* proto, message_433mhz* msg) {
|
||||||
|
msg->data = 0;
|
||||||
|
unsigned int sync_len = (proto->sync.low_time > proto->sync.high_time) ? proto->sync.low_time : proto->sync.high_time;
|
||||||
|
unsigned int delay = reciever->timeings[0]/sync_len;
|
||||||
|
unsigned int delay_tolerance = delay * reciever->recieve_tolerance /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
|
||||||
|
*/
|
||||||
|
unsigned int firstdata = proto->inverted ? 2 : 1;
|
||||||
|
for (unsigned int i = firstdata; i < reciever->changeCount-1; i+=2) {
|
||||||
|
msg->data <<= 1;
|
||||||
|
if ( diff(reciever->timeings[i], delay*proto->zero.high_time) < delay_tolerance &&
|
||||||
|
diff(reciever->timeings[i+1], delay*proto->zero.low_time) < delay_tolerance ){
|
||||||
|
//recieved zero
|
||||||
|
} else if ( diff(reciever->timeings[i], delay*proto->one.high_time) < delay_tolerance &&
|
||||||
|
diff(reciever->timeings[i+1], delay*proto->one.low_time) < delay_tolerance ) {
|
||||||
|
//recieved one
|
||||||
|
msg->data |= 1;
|
||||||
|
} else {
|
||||||
|
//Failed to decode data with given protocol
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reciever->changeCount > 7) {
|
||||||
|
msg->code_lenght = (reciever->changeCount -1)/2;
|
||||||
|
msg->protocol = proto;
|
||||||
|
msg->pulse_length = delay;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reciever_433mhz* create_reciever_buffer() {
|
||||||
|
reciever_433mhz* reciever = malloc(sizeof(reciever_433mhz));
|
||||||
|
reciever->recieve_tolerance = RECIEVE_TOLERANCE_433MHZ;
|
||||||
|
reciever->seperation_limit = SEPERATION_LIMIT_433MHZ;
|
||||||
|
reciever->changeCount = 0;
|
||||||
|
reciever->repeatCount = 0;
|
||||||
|
reciever->last_time = getMicroSec();
|
||||||
|
reciever->recieve_len = 0;
|
||||||
|
memset(&reciever->timeings, 0, RECIEVE_MAX_BUFFER_LEN);
|
||||||
|
return reciever;
|
||||||
|
}
|
66
extras/rf433mhz/rf_433mhz.h
Normal file
66
extras/rf433mhz/rf_433mhz.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef rf_h_INCLUDED
|
||||||
|
#define rf_h_INCLUDED
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define RECIEVE_MAX_BUFFER_LEN 67
|
||||||
|
#define SEPERATION_LIMIT_433MHZ 5000
|
||||||
|
#define RECIEVE_TOLERANCE_433MHZ 60
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a pure c reimplemnation of the rc swich library, it was build to be used with open rtos
|
||||||
|
* Copyright: Felix Richter 2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint8_t high_time;
|
||||||
|
uint8_t low_time;
|
||||||
|
} pulse_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
pulse_t sync;
|
||||||
|
pulse_t zero;
|
||||||
|
pulse_t one;
|
||||||
|
bool inverted;
|
||||||
|
} protocol_433mhz;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint32_t data;
|
||||||
|
unsigned int code_lenght;
|
||||||
|
protocol_433mhz* protocol;
|
||||||
|
uint16_t pulse_length;
|
||||||
|
uint8_t repeat;
|
||||||
|
} message_433mhz;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint16_t recieve_len;
|
||||||
|
unsigned long last_time;
|
||||||
|
unsigned int changeCount;
|
||||||
|
unsigned int repeatCount;
|
||||||
|
unsigned int seperation_limit;
|
||||||
|
unsigned int recieve_tolerance;
|
||||||
|
unsigned int timeings[RECIEVE_MAX_BUFFER_LEN];
|
||||||
|
} reciever_433mhz;
|
||||||
|
|
||||||
|
void send_message_433mhz(uint8_t pin, message_433mhz* msg);
|
||||||
|
void recieve_on_interrupt(reciever_433mhz* reciever);
|
||||||
|
bool decode_recieved(reciever_433mhz* reciever, protocol_433mhz* proto, message_433mhz* msg);
|
||||||
|
reciever_433mhz* create_reciever_buffer();
|
||||||
|
|
||||||
|
extern protocol_433mhz protocols_433mhz[];
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PROTO1,
|
||||||
|
PROTO2,
|
||||||
|
PROTO3,
|
||||||
|
PROTO4,
|
||||||
|
PROTO5,
|
||||||
|
PROTO6,
|
||||||
|
PROTO7,
|
||||||
|
PROTOCOL_COUNT
|
||||||
|
} protocol_name_433mhz;
|
||||||
|
|
||||||
|
#endif // rf_h_INCLUDED
|
||||||
|
|
31
extras/rf433mhz/util.h
Normal file
31
extras/rf433mhz/util.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef util_h_INCLUDED
|
||||||
|
#define util_h_INCLUDED
|
||||||
|
|
||||||
|
#include "espressif/esp_common.h"
|
||||||
|
#include "espressif/esp_misc.h"
|
||||||
|
#include "esp8266.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
void delayMicroSec(uint16_t us) {
|
||||||
|
sdk_os_delay_us(us);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPinDigital(uint8_t pin, bool value) {
|
||||||
|
gpio_write(pin, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long getMicroSec() {
|
||||||
|
return sdk_system_get_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableInterrupts() {
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableInterrupts() {
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // util_h_INCLUDED
|
||||||
|
|
Loading…
Reference in a new issue