add rf433mhz component to extras, for using antenna modules with esp

This commit is contained in:
Felix5721 2019-01-14 14:53:15 +01:00
parent a721fb0bc7
commit 01e9c1b98e
No known key found for this signature in database
GPG key ID: 6512C30DD8E017B5
7 changed files with 359 additions and 0 deletions

View file

@ -0,0 +1,4 @@
PROGRAM = rf-send-recieve
EXTRA_COMPONENTS = extras/rf433mhz
include ../../common.mk

View 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
View 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.

View 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
View 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;
}

View 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
View 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