47 Commits

Author SHA1 Message Date
AlexGyver 6c91bf4e80 Update library.properties
2.1.1
2024-04-11 16:55:23 +03:00
AlexGyver 102beca9f5 edit badge 2024-04-11 16:38:21 +03:00
AlexGyver c4a9822af4 english readme 2023-12-22 23:51:58 +03:00
AlexGyver b7b2f840da english readme 2023-12-22 23:49:46 +03:00
AlexGyver f0a5bdad5b english readme 2023-12-22 23:39:32 +03:00
AlexGyver a73d2f6bbc Update README.md 2023-08-15 10:26:42 +03:00
AlexGyver 9e7e75ffe5 edit workflow 2023-04-12 14:36:06 +03:00
AlexGyver 1700798c90 edit workflow 2023-04-11 17:37:22 +03:00
AlexGyver 463158e667 edit badge 2022-09-03 14:08:14 +03:00
AlexGyver a2265e1aae edit badge 2022-07-20 13:58:34 +03:00
AlexGyver 17fa4047f9 edit workflow 2022-06-29 15:06:41 +03:00
AlexGyver 17d9e91111 edit readme 2022-06-27 23:48:54 +03:00
AlexGyver f97e26411f edit readme 2022-06-27 23:46:28 +03:00
AlexGyver fe49edcfa6 edit readme 2022-06-27 23:44:23 +03:00
AlexGyver 3587e96247 edit readme 2022-06-27 23:41:04 +03:00
AlexGyver fc967f7554 edit readme 2022-06-27 23:36:34 +03:00
AlexGyver 2d1566ace2 edit readme 2022-06-27 23:34:09 +03:00
AlexGyver a0dd1f6aee edit readme 2022-06-27 23:28:39 +03:00
AlexGyver 035596d252 create workflow 2022-06-27 23:20:36 +03:00
AlexGyver 5a467a1c93 edit readme 2022-06-27 19:36:36 +03:00
AlexGyver e987107e6e issues 2022-06-27 14:52:39 +03:00
AlexGyver f3a861ecd1 update 2022-05-24 12:03:59 +03:00
Alex 8f40368bdf english readme 2022-05-04 04:43:34 +03:00
Alex 83e3903f88 english readme 2022-05-04 04:33:47 +03:00
Alex 33477745b2 Update README.md 2022-05-03 03:26:00 +03:00
Alex 52277d98e8 Update README.md 2022-01-28 02:37:40 +03:00
Alex 9c10e644db Update README.md 2022-01-25 02:38:34 +03:00
Alex 03525ebe93 Merge branch 'main' of https://github.com/GyverLibs/Gyver433 2022-01-06 00:50:23 +03:00
Alex 9d18b80bb6 upd 2022-01-06 00:50:15 +03:00
Alex 415de7a97a Update README.md 2021-12-16 01:45:57 +03:00
Alex 970e454920 Update README.md 2021-12-15 15:40:41 +03:00
Alex b416ae981a Update README.md 2021-12-11 14:34:17 +03:00
Alex e66a74de62 upd 2021-12-11 14:33:29 +03:00
Alex 48c3ee21a4 upd 2021-09-09 17:57:11 +03:00
Alex e6f45643b9 upd 2021-09-09 17:54:30 +03:00
Alex 96520e1b3b upd 2021-08-24 01:30:02 +03:00
Alex 8196c8e583 v1.4 2021-07-17 23:04:48 +03:00
Alex f4c573bf88 Update Gyver433.h 2021-06-20 22:01:08 +03:00
Alex 060fcbb9ce v1.3 2021-06-20 12:05:51 +03:00
Alex d10b64cbe6 upd 2021-06-17 17:24:48 +03:00
Alex 48e1fa1e98 v1.2 2021-06-17 12:49:46 +03:00
Alex bd9e4b19ae Update README.md 2021-06-14 21:55:30 +03:00
Alex ecfcdf1bf9 v1.1 2021-06-14 21:53:39 +03:00
Alex 1e37f86364 Update README.md 2021-06-14 18:38:06 +03:00
Alex cb09165d3e v1.1 2021-06-14 18:36:58 +03:00
Alex ef9eca0f9f Update Gyver433.h 2021-05-26 01:09:20 +03:00
Alex a06be3a93e Update README.md 2021-05-25 00:05:07 +03:00
23 changed files with 838 additions and 320 deletions
+20
View File
@@ -0,0 +1,20 @@
name: Telegram Message
on:
release:
types: [published]
jobs:
build:
name: Send Message
runs-on: ubuntu-latest
steps:
- name: send telegram message on push
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_TO }}
token: ${{ secrets.TELEGRAM_TOKEN }}
disable_web_page_preview: true
message: |
${{ github.event.repository.name }} v${{ github.event.release.tag_name }}
${{ github.event.release.body }}
https://github.com/${{ github.repository }}
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2021 Alex Copyright (c) 2021 AlexGyver
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+140 -40
View File
@@ -1,16 +1,29 @@
![License: MIT](https://img.shields.io/badge/License-MIT-green.svg) [![latest](https://img.shields.io/github/v/release/GyverLibs/Gyver433.svg?color=brightgreen)](https://github.com/GyverLibs/Gyver433/releases/latest/download/Gyver433.zip)
![author](https://img.shields.io/badge/author-AlexGyver-informational.svg) [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/Gyver433.svg)](https://registry.platformio.org/libraries/gyverlibs/Gyver433)
# Gyver433_TX [![arduino-library](https://www.ardu-badge.com/badge/Gyver433.svg?)](https://www.ardu-badge.com/Gyver433)
[![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/)
[![Foo](https://img.shields.io/badge/%E2%82%BD$%E2%82%AC%20%D0%9D%D0%B0%20%D0%BF%D0%B8%D0%B2%D0%BE-%D1%81%20%D1%80%D1%8B%D0%B1%D0%BA%D0%BE%D0%B9-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/)
[![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/Gyver433?_x_tr_sl=ru&_x_tr_tl=en)
[![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs)
# Gyver433
Библиотека для радиомодулей 433 МГц и Arduino Библиотека для радиомодулей 433 МГц и Arduino
- Не использует прерывания и таймеры (кроме нулевого, читает micros()) - **Передача данных с модуля на модуль по собственному интерфейсу связи**, т.е. не работает с китайскими пультами и шлагбаумами!
- Поддержка кривых китайских модулей
- Встроенный CRC контроль целостности - Встроенный CRC контроль целостности
- Ускоренный алгоритм IO для AVR Arduino - Ускоренный алгоритм IO для AVR Arduino
- Асинхронный приём в прерывании
- Супер лёгкая либа, заведётся даже на тини13
### Совместимость ### Совместимость
Совместима со всеми Arduino платформами (используются Arduino-функции) Совместима со всеми Arduino платформами (используются Arduino-функции)
- При подключении прерывания на esp8266 не забудь аттрибут `IRAM_ATTR`
## Содержание ## Содержание
- [Установка](#install) - [Установка](#install)
- [Интерфейс](#interface)
- [Подключение](#wiring)
- [Инициализация](#init) - [Инициализация](#init)
- [Использование](#usage) - [Использование](#usage)
- [Пример](#example) - [Пример](#example)
@@ -19,96 +32,183 @@
<a id="install"></a> <a id="install"></a>
## Установка ## Установка
- Библиотеку можно найти по названию **Gyver433_TX** и установить через менеджер библиотек в: - Библиотеку можно найти по названию **Gyver433** и установить через менеджер библиотек в:
- Arduino IDE - Arduino IDE
- Arduino IDE v2 - Arduino IDE v2
- PlatformIO - PlatformIO
- [Скачать библиотеку](https://github.com/GyverLibs/Gyver433_TX/archive/refs/heads/main.zip) .zip архивом для ручной установки: - [Скачать библиотеку](https://github.com/GyverLibs/Gyver433/archive/refs/heads/main.zip) .zip архивом для ручной установки:
- Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64)
- Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32)
- Распаковать и положить в *Документы/Arduino/libraries/* - Распаковать и положить в *Документы/Arduino/libraries/*
- (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив
- Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
### Обновление
- Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
- Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
- Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!
<a id="interface"></a>
## Интерфейс
- Перед отправкой данных идёт синхронизирующий импульс, *TRAIN* мс
- Далее старт импульс, *START* мс, LOW
- Данные кодируются длиной импульса
- Завершает отправку стоп импульс, *TRAIN* мс
![scheme](/doc/interface.png)
![scheme](/doc/timing.png)
<a id="wiring"></a>
## Подключение
![scheme](/doc/radio433.png)
Передатчики:
- SYN115, маленький чип: 1.8-3.6V, макс. скорость 8000
- FS1000A: 3-12V, макс. скорость 10000
- WL102-341: 2.0-3.6V, макс. скорость 6000
Приёмники:
- SYN480R, крупный чип: 3.3-5.5V
- MX-RM-5V (RF-5V): 5V
- RX470 (WL101-341): 3-5V
![scheme](/doc/scheme.jpg)
![scheme](/doc/radio.png)
<a id="init"></a> <a id="init"></a>
## Инициализация ## Инициализация
```cpp ```cpp
// указать пин // === ПЕРЕДАТЧИК ===
Gyver433_RX rx(2); Gyver433_TX<пин> tx;
Gyver433_TX tx(2); Gyver433_TX<пин, CRC> tx;
// === ПРИЁМНИК ===
Gyver433_RX<пин> rx;
Gyver433_RX<пин, буфер> rx;
Gyver433_RX<пин, буфер, CRC> rx;
// пин: цифровой пин
// буфер: размер буфера в байтах, по умолч. 64
// CRC: проверка целостности данных: G433_CRC8 (надёжный), G433_XOR (лёгкий), G433_NOCRC (отключено). По умолч. G433_CRC8
``` ```
<a id="usage"></a> <a id="usage"></a>
## Использование ## Использование
```cpp ```cpp
// ========= Gyver433_TX ========= // ========= Gyver433_TX =========
void sendData(T &data); // отправить данные любого типа void sendData(T &data); // отправить данные любого типа (CRC добавляется автоматически)
void write(uint8_t* buf, uint8_t size); // отправить массив байт указанного размера (CRC не добавляется)
// ========= Gyver433_RX ========= // ========= Gyver433_RX =========
uint8_t tick(); // неблокирующий приём, вернёт кол-во успешно принятых байт // приём в прерывании
uint8_t tickWait(); // блокирующий приём, вернёт кол-во успешно принятых байт void tickISR(); // тикер приёма для вызова в прерывании по CHANGE
uint8_t tickISRraw(); // ручной приём в прерывании по CHANGE. Вернёт 1 (начало приёма), 2 (принят байт), 3 (конец пакета)
// приём в loop
uint16_t tick(); // неблокирующий приём. Вернёт количество успешно принятых байт
uint16_t tickWait(); // блокирующий приём. Вернёт количество успешно принятых байт
bool readData(T &data); // прочитает буфер в любой тип данных (в указанную переменную) bool readData(T &data); // прочитает буфер в любой тип данных (в указанную переменную)
int getSize(); // получить размер принятых данных uint16_t getSize(); // получить размер принятых данных
uint16_t gotData(); // вернёт количество успешно принятых в tickISR() байт (см. пример isr_rx)
uint8_t getRSSI(); // получить качество приёма (процент успешных передач 0.. 100)
uint8_t buffer[]; // доступ к буферу приёма
uint8_t byteBuf; // доступ к буферу принятого байта
// ============= CRC =============
// можно использовать встроенные функции для генерации байта CRC для ручной упаковки пакетов
uint8_t G433_crc8(uint8_t *buffer, uint8_t size); // ручной CRC8
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size); // ручной CRC XOR
// ====== ДЕФАЙНЫ-НАСТРОЙКИ ======
// вызывать перед подключением библиотеки
#define G433_FAST // [TX] короткая синхронизация для зелёных модулей
#define G433_MEDIUM // [TX] средняя синхронизация при отправке на SYN480R ЧАЩЕ 400мс (активно по умолчанию)
#define G433_SLOW // [TX] длинная синхронизация при отправке на SYN480R РЕЖЕ 400мс
#define G433_SPEED 1000 // [RX/TX] скорость, должна быть одинакова на RX и TX, 100-10000 бит/с, по умолч. 2000 бит/с
#define G433_RSSI_COUNT 8 // [RX] количество успешно принятых пакетов для расчёта RSSI (по умолч. 8)
#define G433_CUT_RSSI // [RX] убрать расчёт RSSI из кода (сэкономит чуть памяти)
``` ```
### Работа приёмника без прерываний
Для приёма данных достаточно вызывать в основном цикле метод `tick()`, он сам опрашивает пин радио.
- Если в программе есть блокирующие места и loop() выполняется с задержками - будет потеря данных
- Для более надёжного приёма рекомендуется вызывать `tickWait()`, она блокирует выполнение кода на время приёма.
### Работа приёмника с прерываниями
Рекомендуется использовать приём в прерывании по CHANGE, для этого нужно вызывать в нём `tickISR()`.
Тогда приём будет асинхронный и будет работать даже в загруженной программе.
- Если стандартных пинов прерываний не хватает, можно задействовать PCINT. Вручную или с помощью библиотеки https://github.com/NicoHood/PinChangeInterrupt
<a id="example"></a> <a id="example"></a>
## Пример ## Примеры
Остальные примеры смотри в **examples**! Остальные примеры смотри в **examples**!
### Отправка ### Отправка
```cpp ```cpp
// мелкий передатчик 3.6V SYN115
#define G433_BUFSIZE 50 // размер буфера
#define G433_SPEED 2000 // скорость бит/сек (минимальная)
#include <Gyver433.h> #include <Gyver433.h>
Gyver433_TX tx(2); // указали пин Gyver433_TX<2> tx; // указали пин
void setup() { void setup() {
} }
char data[] = "Hello from #xx"; char data[] = "Hello from #xx"; // строка для отправки
byte count = 0; byte count = 0; // счётчик для отправки
void loop() { void loop() {
// добавляем счётчик в строку
data[12] = (count / 10) + '0'; data[12] = (count / 10) + '0';
data[13] = (count % 10) + '0'; data[13] = (count % 10) + '0';
if (++count >= 100) count = 0; if (++count >= 100) count = 0;
tx.sendData(data); tx.sendData(data);
delay(100); delay(100);
} }
``` ```
### Приём ### Приём в прерывании
```cpp ```cpp
// крупный приёмник 5.0 SYN480R
#define G433_BUFSIZE 50 // размер буфера
#define G433_SPEED 2000 // скорость бит/сек (минимальная)
#include <Gyver433.h> #include <Gyver433.h>
Gyver433_RX rx(2); Gyver433_RX<2, 20> rx; // указали пин и размер буфера
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
attachInterrupt(0, isr, CHANGE); // прерывание пина радио по CHANGE
} }
// спец. тикер вызывается в прерывании
void isr() {
rx.tickISR();
}
void loop() { void loop() {
// tick принимает асинхронно, но может ловить ошибки при загруженном коде if (rx.gotData()) { // если успешно принято больше 0
// tickWait блокирует выполнение, но принимает данные чётко Serial.write(rx.buffer, rx.size); // выводим
if (rx.tickWait()) { Serial.println();
byte buf[64]; }
rx.readData(buf); delay(50); // имитация загруженного кода
for (byte i = 0; i < rx.size; i++) Serial.write(buf[i]);
}
} }
``` ```
<a id="versions"></a> <a id="versions"></a>
## Версии ## Версии
- v1.0 - v1.0
- v1.1 - оптимизация, новый интерфейс, поддержка дешёвых синих модулей, работа в прерывании
- v1.2 - улучшение качества связи, оптимизация работы в прерывании
- v1.3 - добавлен вывод RSSI
- v1.4 - переделан FastIO
- v1.4.1 - убран FastIO, CRC вынесен отдельно
- v2.0 - убран буфер на отправку, убран манчестер, полностью переделан и оптимизирован интерфейс связи
- v2.0.1 - fix compiler warnings
<a id="feedback"></a> <a id="feedback"></a>
## Баги и обратная связь ## Баги и обратная связь
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru)
Библиотека открыта для доработки и ваших **Pull Request**'ов! Библиотека открыта для доработки и ваших **Pull Request**'ов!
При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:
- Версия библиотеки
- Какой используется МК
- Версия SDK (для ESP)
- Версия Arduino IDE
- Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
- Какой код загружался, какая работа от него ожидалась и как он работает в реальности
- В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код
+206
View File
@@ -0,0 +1,206 @@
This is an automatic translation, may be incorrect in some places. See sources and examples!
# Gyver433
Library for Radio Modules 433 MHz and Arduino
- ** Data transfer from the module to the module on your own communication interface **, i.e.Does not work with Chinese remote controls and barriers!
- Support for crooked Chinese modules
- Built -in CRC Control of integrity
- Accelerated IO algorithm for AVR Arduino
- asynchronous reception in interruption
- Super lightly Liba, will even start on Tini13
## compatibility
Compatible with all arduino platforms (used arduino functions)
- When connecting an interruption on the ESP8266, do not forget the Attricbut `IRAM_ATTR`
## Content
- [installation] (# Install)
- [interface] (#interface)
- [connection] (#wiring)
- [initialization] (#init)
- [use] (#usage)
- [Example] (# Example)
- [versions] (#varsions)
- [bugs and feedback] (#fedback)
<a id="install"> </a>
## Installation
- The library can be found by the name ** Gyver433 ** and installed through the library manager in:
- Arduino ide
- Arduino ide v2
- Platformio
- [download the library] (https://github.com/gyverlibs/gyver433/archive/refs/heads/main.zip) .Zip archive for manual installation:
- unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64)
- unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32)
- unpack and put in *documents/arduino/libraries/ *
- (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive
- Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA)
### Update
- I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added
- through the IDE library manager: find the library how to install and click "update"
- Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors!
<a Id="INterFace"> </a>
## Interface
- Before sending the data, there is a synchronizing pulse, * train * ms
- Next, start impulse, * Start * ms, Low
- Data is encoded by pulse length
- completes the sending of the stop impulse, * train * ms
! [Scheme] (/doc/interface.png)
! [Scheme] (/doc/timing.png)
<a id="wiring"> </a>
## connection
! [Scheme] (/doc/radio433.png)
Transmitters:
- SYN115, small chip: 1.8-3.6V, max.speed 8000
- FS1000A: 3-12V, Max.speed of 10,000
-WL102-341: 2.0-3.6V, max.speed 6000
Receivers:
- SYN480R, large chip: 3.3-5.5V
-MX-RM-5V (RF-5V): 5V
-RX470 (WL101-341): 3-5V
! [Scheme] (/doc/scheme.jpg)
! [Scheme] (/doc/radio.png)
<a id="init"> </a>
## initialization
`` `CPP
// === transmitter ===
Gyver433_TX <PIN> TX;
Gyver433_TX <PIN, CRC> TX;
// === The receiver ====
Gyver433_rx <PIN> RX;
Gyver433_rx <pin, buffer> rx;
Gyver433_rx <pin, buffer, CRC> rx;
// PIN: Digital PIN
// buffer: the size of the buffer in bytes, by the silence.64
// CRC: Statement of data integrity: G433_CRC8 (reliable), G433_XOR (Light), G433_NOCRC (disconnected).By the silence.G433_CRC8
`` `
<a id="usage"> </a>
## Usage`` `CPP
// ========= gyver433_TX ============
VOID SendData (T & Data);// Send data any type (CRC is added automatically)
VOID Write (uint8_t* buf, uint8_t size);// Send an array of byte of the specified size (CRC is not added)
// ========= gyver433_rx ============
// Reception in interruption
VOID Tickisr ();// Take of reception for calling in interruption by Change
uint8_t TickisrRaw ();// manual reception in the interruption in Change.Return 1 (beginning of reception), 2 (Baite adopted), 3 (end of the package)
// Reception in Loop
uint16_t tick ();// Neboking technique.Will return the number of successfully accepted bytes
uint16_t tickwait ();// blocking reception.Will return the number of successfully accepted bytes
Bool Readdata (T & Data);// read the buffer in any type of data (in the specified variable)
uint16_t getsize ();// Get the amount of data accepted
uint16_t gotdata ();// will return the number of byte successfully accepted in Tickisr () (see ISR_RX example)
uint8_t getrssi ();// get the quality of the reception (percentage of successful gears 0 .. 100)
uint8_t buffer [];// Access to the reception buffer
uint8_t bytebuf;// Access to the Baita Boofer
// ============== CRC ==================
// you can use the built -in functions for generating the CRC byt for manual packages
uint8_t g433_crc8 (uint8_t *buffer, uint8_t size);// manual CRC8
uint8_t g433_crc_xor (uint8_t *buffer, uint8_t size);// manual CRC XOR
// ====== Defain-settings ==========
// Call before connecting the library
#define g433_fast // [tx] short synchronization for green modules
#define g433_Medium // [tx] average synchronization when sending to SYN480R more than 400MS (actively by default)
#define g433_slow // [tx] Long synchronization when sending to SYN480R less often 400ms
#define G433_Speed 1000 // [RX/TX] Speed, should be the same on RX and TX, 100-10,000 bits/s, silent.2000 bits/s
#define g433_rssi_count 8 // [RX] The number of successfully accepted packets for RSSI calculation (according to default. 8)
#define g433_cut_rssi // [rx] Remove the RSSI calculation from the code (save a little memory)
`` `
### Work of the receiver without interruption
To receive data, it is enough to cause a basic cycle of the `tick ()` method, he himself interviews a pin of the radio.
- If the program has blocking places and Loop () is performed with delays - there will be a loss of data
- For more reliable reception, it is recommended to call `tickwait ()`, it blocks the performance of the code during the reception.
### Work of the receiver with interruptions
It is recommended to use the technique in the interrupt on Change, for this you need to call `Tickisr ()` in it.
Then the reception will be asynchronous and will work even in a loaded program.
- If the standard pins of interruptions are not enough, you can use PCINT.Manually or with the help of the library https://github.com/nicohood/pinchangeinterrapt
<a id="EXAMPLE"> </a>
## Examples
The rest of the examples look at ** Examples **!
### Sending
`` `CPP
#include <gyver433.h>
Gyver433_tx <2> tx;// indicated the pin
VOID setup () {
}
Char Data [] = "Hello from #xx";// line for sending
Byte count = 0;// counter for sending
VOID loop () {
// Add the counter to the line
Data [12] = (Count / 10) + '0';
Data [13] = (Count % 10) + '0';
if (++ count> = 100) count = 0;
TX.SendData (Data);
DELAY (100);
}
`` `
### Reception in interruption
`` `CPP
#include <gyver433.h>
Gyver433_rx <2, 20> rx;// indicated the pin and size of the buffer
VOID setup () {
Serial.Begin (9600);
Attachinterrupt (0, Isr, Change);// Interruption of Pina Radio on Change
}
// Special.The ticer is called in interruption
VOID isr () {
rx.tickisr ();
}
VOID loop () {
if (rx.gotdata ()) {// If more than 0 successfully accepted
Serial.write (rx.buffer, rx.size);// Display
Serial.println ();
}
DELAY (50);// imitation of a loaded code
}
`` `
<a id="versions"> </a>
## versions
- V1.0
- V1.1 - optimization, new interface, support for cheap blue modules, work in interruption
- V1.2 -improvement in communication quality, optimization of work in interruption
- v1.3 - added RSSI withdrawal
- V1.4 - Redeled Fastio
- v1.4.1 - removed Fastio, CRC is taken separately
- V2.0 - removed the buffer for sending, removed Manchester, completely redone and optimized the communication interface
- V2.0.1 - FIX Compiler Warnings
<a id="feedback"> </a>
## bugs and feedback
Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru)
The library is open for refinement and your ** pull Request ** 'ow!
When reporting about bugs or incorrect work of the library, it is necessary to indicate:
- The version of the library
- What is MK used
- SDK version (for ESP)
- version of Arduino ide
- whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code
- what code has been loaded, what work was expected from it and how it works in reality
- Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 KiB

After

Width:  |  Height:  |  Size: 172 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+53
View File
@@ -0,0 +1,53 @@
// демо-пример приёма в прерывании
// SYN480R, крупный чип: 3.3-5.5V
// MX-RM-5V (RF-5V): 5V
// RX470 (WL101-341): 3-5V
// дефайны перед подключением библиотеки
//#define G433_SPEED 2000 // скорость 100-10000 бит/с, по умолч. 2000 бит/с
#include <Gyver433.h>
//Gyver433_RX<пин> rx;
//Gyver433_RX<пин, буфер> rx;
// пин: цифровой пин
// буфер: размер приёмного буфера в байтах. По умолч. 64
#include <Gyver433.h>
Gyver433_RX<2, 20> rx;
void setup() {
Serial.begin(9600);
// взводим прерывания по CHANGE
attachInterrupt(0, isr, CHANGE);
}
// тикер вызывается в прерывании
void isr() {
rx.tickISR();
}
void loop() {
// gotData() вернёт количество удачно принятых байт
if (rx.gotData()) { // если больше 0
// ЧИТАЕМ. СПОСОБ 1
// я знаю, что передатчик отправляет char[15]
char data[15];
// читаем принятые данные в data
// если данные совпадают по размеру - ок
if (rx.readData(data)) Serial.print(data);
else Serial.print("Data error");
// ЧИТАЕМ. СПОСОБ 2
// вывести сырые данные из буфера в порт
//Serial.write(rx.buffer, rx.size);
// выведем также качество соединения
Serial.print(", RSSI: ");
Serial.println(rx.getRSSI());
}
// имитация загруженного кода. Не влияет на приём
delay(50);
}
+33
View File
@@ -0,0 +1,33 @@
// демо-пример отправки
// SYN115, маленький чип: 1.8-3.6V
// FS1000A: 3-12V
// WL102-341: 2.0-3.6V
// дефайны перед подключением библиотеки
//#define G433_FAST // короткая синхронизация для зелёных модулей
//#define G433_MEDIUM // средняя синхронизация для SYN480R при отправке ЧАЩЕ 400мс (активно по умолчанию)
//#define G433_SLOW // длинная синхронизация для SYN480R при отправке РЕЖЕ 400мс
//#define G433_SPEED 2000 // скорость 100-10000 бит/с, по умолч. 2000 бит/с
#include <Gyver433.h>
//Gyver433_RX<пин> tx;
Gyver433_TX<2> tx;
void setup() {
}
char data[] = "Hello from #xx"; // строка для отправки
byte count = 0; // счётчик для отправки
void loop() {
// добавляем счётчик в строку
data[12] = (count / 10) + '0';
data[13] = (count % 10) + '0';
if (++count >= 100) count = 0;
// отправка данных любого типа
tx.sendData(data);
// отправка 10 раз в сек
delay(100);
}
+22
View File
@@ -0,0 +1,22 @@
// обмен сырыми данными без CRC
// отправляет пример raw_tx
// принимаем без прерывания! для примера
//#define G433_SPEED 1000 // скорость 100-10000 бит/с, по умолч. 2000 бит/с
#include <Gyver433.h>
Gyver433_RX<2, 20, G433_NOCRC> rx; // буфер 20 байт
void setup() {
Serial.begin(9600);
}
void loop() {
// этот тикер нужно вызывать как можно чаще
// лучше принимать в прерывании, см. пример demo
if (rx.tick()) {
// выводим сырые байты в порт
Serial.write(rx.buffer, rx.size);
Serial.println();
}
}
+26
View File
@@ -0,0 +1,26 @@
// обмен сырыми данными без CRC
// принимает пример raw_rx
//#define G433_SPEED 1000 // скорость 100-10000 бит/с, по умолч. 2000 бит/с
#include <Gyver433.h>
Gyver433_TX<2, G433_NOCRC> tx;
void setup() {
}
char data[] = "Hello from #xx"; // строка для отправки
byte count = 0; // счётчик для отправки
void loop() {
// добавляем счётчик в строку
data[12] = (count / 10) + '0';
data[13] = (count % 10) + '0';
if (++count >= 100) count = 0;
// отправка данных типа byte*
tx.write((byte*)data, sizeof(data));
// отправка 10 раз в сек
delay(100);
}
-22
View File
@@ -1,22 +0,0 @@
// крупный приёмник 5.0 SYN480R
#define G433_BUFSIZE 50 // размер буфера
#define G433_SPEED 2000 // скорость бит/сек (минимальная)
#include <Gyver433.h>
Gyver433_RX rx(2);
void setup() {
Serial.begin(9600);
}
void loop() {
// tick принимает асинхронно, но может ловить ошибки при загруженном коде
// tickWait блокирует выполнение, но принимает данные чётко
if (rx.tickWait()) {
byte buf[64];
rx.readData(buf);
for (byte i = 0; i < rx.size; i++) Serial.write(buf[i]);
}
}
+6 -13
View File
@@ -1,28 +1,21 @@
// крупный приёмник 5.0V SYN480R // выводим данные на дисплей. Отправляет пример demo_tx
#define G433_BUFSIZE 50 // размер буфера //#define G433_SPEED 1000 // скорость 100-10000 бит/с, по умолч. 1500 бит/с
#define G433_SPEED 2000 // скорость бит/сек (минимальная)
#include <Gyver433.h> #include <Gyver433.h>
Gyver433_RX rx(2); // указали пин Gyver433_RX<2> rx; // указали пин
#include <Wire.h>
#include <LiquidCrystal_I2C.h> #include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f, 16, 2); // или 0x27 LiquidCrystal_I2C lcd(0x3f, 16, 2); // или 0x27
void setup() { void setup() {
Serial.begin(9600);
lcd.init(); lcd.init();
lcd.backlight(); lcd.backlight();
} }
void loop() { void loop() {
// tick принимает асинхронно, но может ловить ошибки при загруженном коде
// tickWait блокирует выполнение, но принимает данные чётко
if (rx.tick()) { if (rx.tick()) {
byte buf[64];
rx.readData(buf); // прочитать в buf
lcd.clear(); lcd.clear();
lcd.home(); lcd.home();
for (byte i = 0; i < rx.size; i++) lcd.write(buf[i]); for (byte i = 0; i < rx.size; i++) lcd.write(rx.buffer[i]);
} }
} }
+16 -17
View File
@@ -1,13 +1,12 @@
// передача структуры данных // приём структуры данных
// крупный приёмник 5.0V SYN480R
#define G433_BUFSIZE 50 // размер буфера //#define G433_SPEED 1000 // скорость 100-10000 бит/с, по умолч. 2000 бит/с
#define G433_SPEED 2000 // скорость бит/сек (минимальная)
#include <Gyver433.h> #include <Gyver433.h>
Gyver433_RX rx(2); // указали пин Gyver433_RX<2, 12> rx; // указали пин и размер буфера
// формат пакета для приёма (такой же как отправляется) // формат пакета для приёма (такой же как отправляется)
struct dataPack { struct DataPack {
byte counter; byte counter;
byte randomNum; byte randomNum;
int analog; int analog;
@@ -19,17 +18,17 @@ void setup() {
} }
void loop() { void loop() {
// tick принимает асинхронно, но может ловить ошибки при загруженном коде
// tickWait блокирует выполнение, но принимает данные чётко
if (rx.tick()) { if (rx.tick()) {
dataPack data; DataPack data; // "буферная" структура
rx.readData(data); // прочитать в buf if (rx.readData(data)) { // переписываем данные в неё
// если данные подходят - выводим
Serial.println("Received:"); Serial.println(data.counter);
Serial.println(data.counter); Serial.println(data.randomNum);
Serial.println(data.randomNum); Serial.println(data.analog);
Serial.println(data.analog); Serial.println(data.time);
Serial.println(data.time); Serial.println();
Serial.println(); } else {
Serial.println("Wrong data");
}
} }
} }
-18
View File
@@ -1,18 +0,0 @@
// мелкий передатчик 3.6V SYN115
#define G433_BUFSIZE 50 // размер буфера
#define G433_SPEED 2000 // скорость бит/сек (минимальная)
#include <Gyver433.h>
Gyver433_TX tx(2); // указали пин
void setup() {
}
char data[] = "Hello from #xx";
byte count = 0;
void loop() {
data[12] = (count / 10) + '0';
data[13] = (count % 10) + '0';
if (++count >= 100) count = 0;
tx.sendData(data);
delay(100);
}
+9 -9
View File
@@ -1,19 +1,19 @@
// передача структуры данных // передача структуры данных
// мелкий передатчик 3.6V SYN115
#define G433_BUFSIZE 50 // размер буфера //#define G433_SPEED 1000 // скорость 100-10000 бит/с, по умолч. 2000 бит/с
#define G433_SPEED 2000 // скорость бит/сек (минимальная) #define G433_SLOW // отправляю раз в секунду на SYN480R
#include <Gyver433.h> #include <Gyver433.h>
Gyver433_TX tx(2); // указали пин Gyver433_TX<2> tx; // указали пин
// формат пакета для отправки // формат пакета для отправки
struct dataPack { struct DataPack {
byte counter; byte counter = 0;
byte randomNum; byte randomNum;
int analog; int analog;
uint32_t time; uint32_t time;
}; };
dataPack data; DataPack data;
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
@@ -24,14 +24,14 @@ void loop() {
data.randomNum = random(256); // случайное число data.randomNum = random(256); // случайное число
data.analog = analogRead(0); // тут ацп data.analog = analogRead(0); // тут ацп
data.time = millis(); // тут миллис data.time = millis(); // тут миллис
tx.sendData(data);
Serial.println("Transmit:"); Serial.println("Transmitted:");
Serial.println(data.counter); Serial.println(data.counter);
Serial.println(data.randomNum); Serial.println(data.randomNum);
Serial.println(data.analog); Serial.println(data.analog);
Serial.println(data.time); Serial.println(data.time);
Serial.println(); Serial.println();
tx.sendData(data);
delay(1000); delay(1000);
} }
+16 -1
View File
@@ -13,14 +13,29 @@ Gyver433_RX KEYWORD1
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
####################################### #######################################
sendData KEYWORD2 sendData KEYWORD2
write KEYWORD2
tick KEYWORD2 tick KEYWORD2
tickWait KEYWORD2 tickWait KEYWORD2
tickISR KEYWORD2
tickISRraw KEYWORD2
readData KEYWORD2 readData KEYWORD2
size KEYWORD2 size KEYWORD2
buffer KEYWORD2
getSize KEYWORD2 getSize KEYWORD2
gotData KEYWORD2
G433_crc8 KEYWORD2
G433_crc_xor KEYWORD2
getRSSI KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
G433_CLI LITERAL1
G433_CRC8 LITERAL1
G433_XOR LITERAL1
G433_NOCRC LITERAL1
G433_FAST LITERAL1
G433_MEDIUM LITERAL1
G433_SLOW LITERAL1
G433_SPEED LITERAL1 G433_SPEED LITERAL1
G433_BUFSIZE LITERAL1 G433_CUT_RSSI LITERAL1
+2 -2
View File
@@ -1,9 +1,9 @@
name=Gyver433 name=Gyver433
version=1.0 version=2.1.1
author=AlexGyver <alex@alexgyver.ru> author=AlexGyver <alex@alexgyver.ru>
maintainer=AlexGyver <alex@alexgyver.ru> maintainer=AlexGyver <alex@alexgyver.ru>
sentence=Simple library for 433 MHz radio sentence=Simple library for 433 MHz radio
paragraph=Simple library for 433 MHz radio paragraph=Simple library for 433 MHz radio
category=Device Control category=Device Control
url=https://github.com/GyverLibs/Gyver433 url=https://github.com/GyverLibs/Gyver433
architectures=* architectures=*
+41
View File
@@ -0,0 +1,41 @@
#include "G433_crc.h"
void G433_crc8_byte(uint8_t &crc, uint8_t data) {
#if defined (__AVR__)
// резкий алгоритм для AVR
uint8_t counter;
uint8_t buffer;
asm volatile (
"EOR %[crc_out], %[data_in] \n\t"
"LDI %[counter], 8 \n\t"
"LDI %[buffer], 0x8C \n\t"
"_loop_start_%=: \n\t"
"LSR %[crc_out] \n\t"
"BRCC _loop_end_%= \n\t"
"EOR %[crc_out], %[buffer] \n\t"
"_loop_end_%=: \n\t"
"DEC %[counter] \n\t"
"BRNE _loop_start_%="
: [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer)
: [crc_in]"0" (crc), [data_in]"r" (data)
);
#else
// обычный для всех остальных
uint8_t i = 8;
while (i--) {
crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1);
data >>= 1;
}
#endif
}
uint8_t G433_crc8(uint8_t *buffer, uint8_t size) {
uint8_t crc = 0;
for (uint8_t i = 0; i < size; i++) G433_crc8_byte(crc, buffer[i]);
return crc;
}
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size) {
uint8_t crc = 0;
for (uint8_t i = 0; i < size; i++) crc ^= buffer[i];
return crc;
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef G433_crc_h
#define G433_crc_h
#include <Arduino.h>
uint8_t G433_crc8(uint8_t *buffer, uint8_t size); // ручной CRC8
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size); // ручной CRC XOR
void G433_crc8_byte(uint8_t &crc, uint8_t data); // crc8 один байт
#endif
+240 -197
View File
@@ -3,9 +3,11 @@
Документация: Документация:
GitHub: https://github.com/GyverLibs/Gyver433 GitHub: https://github.com/GyverLibs/Gyver433
Возможности: Возможности:
- Не использует прерывания и таймеры (кроме нулевого, читает micros()) - Поддержка кривых китайских модулей
- Встроенный CRC контроль целостности - Встроенный CRC контроль целостности
- Ускоренный алгоритм IO для AVR Arduino - Ускоренный алгоритм IO для AVR Arduino
- Асинхронный приём в прерывании
- Супер лёгкая либа, заведётся даже на тини13
AlexGyver, alex@alexgyver.ru AlexGyver, alex@alexgyver.ru
https://alexgyver.ru/ https://alexgyver.ru/
@@ -13,247 +15,288 @@
Версии: Версии:
v1.0 - релиз v1.0 - релиз
v1.1 - оптимизация, новый интерфейс, поддержка дешёвых синих модулей, работа в прерывании
v1.2 - улучшение качества связи, оптимизация работы в прерывании
v1.3 - добавлен вывод RSSI
v1.4 - переделан FastIO
v1.4.1 - убран FastIO, CRC вынесен отдельно
v2.0 - убран буфер на отправку, убран манчестер, полностью переделан и оптимизирован интерфейс связи
v2.0.1 - fix compiler warnings
*/ */
#ifndef Gyver433_h #ifndef _Gyver433_h
#define Gyver433_h #define _Gyver433_h
#include <Arduino.h> #include <Arduino.h>
#include "G433_crc.h"
/* #define TRAINING_TIME_SLOW (500000) // время синхронизации для SLOW_MODE
Передатчик:
Gyver433_TX tx(пин) - создать объект
sendData(data) - отправить, любой тип данных
Приёмник:
Gyver433_RX rx(пин) - создать объект
tick() - вызывать постоянно для чтения. Асинхронный. Вернёт количество принятых байт
tickWait() - тож самое, но блокирует выполнение, принимает более четко
readData(data) - прочитать, любой тип данных
size - количество принятых байтов
*/
// =========================================================================
#ifndef G433_SPEED #ifndef G433_SPEED
#define G433_SPEED 2000 // скорость бит/сек (минимальная) #define G433_SPEED 2000
#endif
#ifndef G433_BUFSIZE
#define G433_BUFSIZE 64 // размер буфера приёма и отправки
#endif #endif
// тайминги интерфейса (компилятор посчитает) #ifndef G433_RSSI_COUNT
#define HIGH_PULSE (1000000ul/G433_SPEED) #define G433_RSSI_COUNT 8
#define LOW_PULSE (HIGH_PULSE/2) #endif
#define START_PULSE (HIGH_PULSE*2)
#define PULSE_HYST (LOW_PULSE/2)
#define START_MIN (START_PULSE-PULSE_HYST)
#define START_MAX (START_PULSE+PULSE_HYST)
#define LOW_MIN (LOW_PULSE-PULSE_HYST)
#define LOW_MAX (LOW_PULSE+PULSE_HYST)
#define HIGH_MIN (HIGH_PULSE-PULSE_HYST)
#define HIGH_MAX (HIGH_PULSE+PULSE_HYST)
// crc // тайминги интерфейса
uint8_t G433_crc(uint8_t *buffer, uint8_t size); #define G433_HIGH (1000000ul / G433_SPEED) // время HIGH
void G433_crc_byte(uint8_t &crc, uint8_t data); #define G433_LOW (G433_HIGH / 2) // время LOW
#define G433_START (G433_HIGH * 2) // стартовый импульс
#define G433_TRAIN (G433_HIGH * 3 / 2) // синхроимпульс
// ============ ПЕРЕДАТЧИК ============ #define G433_WINDOW (G433_HIGH / 4)
#define G433_EDGE_L (G433_LOW - G433_WINDOW)
#define G433_EDGE_LH (G433_HIGH - G433_WINDOW)
#define G433_EDGE_HT (G433_HIGH + G433_WINDOW)
#define G433_EDGE_TS (G433_TRAIN + G433_WINDOW)
#define G433_EDGE_S (G433_START + G433_WINDOW)
// жоский delay для avr
#ifdef _delay_us
#define G433_DELAY(x) _delay_us(x)
#else
#define G433_DELAY(x) delayMicroseconds(x)
#endif
// режимы CRC
#define G433_NOCRC 0
#define G433_CRC8 1
#define G433_XOR 2
// количество синхроимпульсов
#if defined(G433_FAST)
#define TRAINING_TIME 10000
#elif defined(G433_MEDIUM)
#define TRAINING_TIME 100000
#elif defined(G433_SLOW)
#define TRAINING_TIME (TRAINING_TIME_SLOW)
#else
#define TRAINING_TIME 100000
#endif
// =================================== ПЕРЕДАТЧИК ===================================
template <uint8_t TX_PIN, uint8_t CRC_MODE = G433_CRC8>
class Gyver433_TX { class Gyver433_TX {
public: public:
Gyver433_TX(uint8_t pin) : _pin(pin) { Gyver433_TX() {
#if defined(__AVR__) pinMode(TX_PIN, OUTPUT);
_port_reg = portOutputRegister(digitalPinToPort(pin));
_bit_mask = digitalPinToBitMask(pin);
#endif
pinMode(pin, OUTPUT);
} }
// отправка, блокирующая. Кушает любой тип данных // отправка, блокирующая. Кушает любой тип данных
template <typename T> template <typename T>
void sendData(T &data) { void sendData(T &data) {
const uint8_t *ptr = (const uint8_t*) &data; uint8_t *ptr = (uint8_t*) &data;
for (uint16_t i = 0; i < sizeof(T); i++) buffer[i] = *ptr++; write(ptr, sizeof(T));
buffer[sizeof(T)] = G433_crc(buffer, sizeof(T)); // CRC последним байтом }
bool flag = 0; // флаг дрыга
for (uint8_t i = 0; i < 30; i++) { // 30 импульсов для синхронизации // отправка сырого набора байтов
flag = !flag; void write(uint8_t* buf, uint16_t size) {
fastDW(flag); uint8_t crc;
delayMicroseconds(HIGH_PULSE); if (CRC_MODE == G433_CRC8) crc = G433_crc8(buf, size);
else if (CRC_MODE == G433_XOR) crc = G433_crc_xor(buf, size);
// раскачка радио
flag = 0;
for (uint16_t i = 0; i < (TRAINING_TIME / G433_TRAIN / 2) * 2 + 1; i++) {
fastWrite(TX_PIN, flag = !flag);
G433_DELAY(G433_TRAIN);
} }
fastDW(1); // старт бит
delayMicroseconds(START_PULSE); // старт бит // старт бит
for (int n = 0; n < sizeof(T) + 1; n++) { // буфер + CRC fastWrite(TX_PIN, 0); // старт
for (uint8_t b = 0; b < 8; b++) { G433_DELAY(G433_START); // ждём
fastDW(flag); fastWrite(TX_PIN, 1); // старт бит
flag = !flag;
if (bitRead(buffer[n], b)) delayMicroseconds(HIGH_PULSE); for (uint16_t i = 0; i < size; i++) write(buf[i]); // дата
else delayMicroseconds(LOW_PULSE); if (CRC_MODE) write(crc); // CRC
} G433_DELAY(G433_TRAIN);
fastWrite(TX_PIN, flag = !flag); // стоп
}
// отправить байт (без старт бита!)
void write(uint8_t data) {
for (uint8_t b = 0; b < 8; b++) {
if (data & 1) G433_DELAY(G433_HIGH);
else G433_DELAY(G433_LOW);
fastWrite(TX_PIN, flag = !flag);
data >>= 1;
} }
fastDW(0); // передача окончена }
}
private: private:
void fastDW(bool state) { // быстрый IO
#if defined(__AVR__) void fastWrite(const uint8_t pin, bool val) {
if (state) *_port_reg |= _bit_mask; // HIGH #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
else *_port_reg &= ~_bit_mask; // LOW if (pin < 8) bitWrite(PORTD, pin, val);
#else else if (pin < 14) bitWrite(PORTB, (pin - 8), val);
digitalWrite(_pin, state); else if (pin < 20) bitWrite(PORTC, (pin - 14), val);
#endif #elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
} bitWrite(PORTB, pin, val);
uint8_t buffer[G433_BUFSIZE]; #else
const uint8_t _pin; digitalWrite(pin, val);
#if defined(__AVR__) #endif
volatile uint8_t *_port_reg;
volatile uint8_t _bit_mask;
#endif
};
// ============ ПРИЁМНИК ============
class Gyver433_RX {
public:
Gyver433_RX(uint8_t pin){
#if defined(__AVR__)
_pin_reg = portInputRegister(digitalPinToPort(pin));
_bit_mask = digitalPinToBitMask(pin);
#endif
} }
// неблокирующий приём, вернёт кол-во успешно принятых байт bool flag = 0;
uint8_t tick() { };
bool newState = fastDR(); // читаем пин
if (newState != prevState) { // ловим изменение сигнала
uint32_t thisUs = micros();
uint32_t thisPulse = thisUs - tmr;
if (parse == 1) { // в прошлый раз поймали фронт
if (thisPulse > START_MIN && thisPulse < START_MAX) { // старт бит?
parse = 2; // ключ на старт
tmr = thisUs;
byteCount = 0;
bitCount = 0;
size = 0;
for (uint8_t i = 0; i < G433_BUFSIZE; i++) buffer[i] = 0;
} else { // не старт бит
parse = 0;
}
} else if (parse == 2) { // идёт парсинг
if (thisPulse > LOW_MIN && thisPulse < LOW_MAX) { // low бит
// просто пропускаем (в буфере уже нули)
tmr = thisUs;
bitCount++;
if (bitCount == 8) {
bitCount = 0;
byteCount++;
if (byteCount > G433_BUFSIZE) parse = 0; // оверфлоу
}
} else if (thisPulse > HIGH_MIN && thisPulse < HIGH_MAX) { // high бит
bitSet(buffer[byteCount], bitCount); // ставим бит единичку
tmr = thisUs;
bitCount++;
if (bitCount == 8) {
bitCount = 0;
byteCount++;
if (byteCount > G433_BUFSIZE) parse = 0; // оверфлоу
}
} else { // ошибка или конец передачи
tmr = thisUs;
parse = 0;
// проверяем, есть ли данные и целые ли они
if (byteCount > 0 && G433_crc(buffer, byteCount) == 0) {
size = byteCount - 2; // длина даты (минус crc)
return size;
}
else return 0;
}
}
if (newState && !prevState && parse == 0) { // ловим фронт // =================================== ПРИЁМНИК ===================================
parse = 1; // в следующий раз ждём флаг template <uint8_t RX_PIN, uint16_t RX_BUF = 64, uint8_t CRC_MODE = G433_CRC8>
tmr = thisUs; class Gyver433_RX {
public:
Gyver433_RX() {
pinMode(RX_PIN, INPUT);
}
// неблокирующий приём. Вернёт количество успешно принятых байт
uint16_t tick() {
if (pinChanged()) tickISR();
return gotData();
}
// блокирующий приём. Вернёт количество успешно принятых байт
uint16_t tickWait() {
do {
if (pinChanged()) tickISR();
} while (state == 1);
return gotData();
}
// ручной приём в прерывании по CHANGE. Вернёт 1 (начало приёма), 2 (принят байт), 3 (конец пакета)
// принятый байт можно прочитать в byteBuf
uint8_t tickISRraw() {
uint32_t pulse = micros() - tmr; // время импульса
tmr += pulse; // сброс таймера. Равносильно tmr = micros()
if (pulse <= G433_EDGE_L) return parse = 0; // импульс слишком короткий
trains <<= 1; // счётчик train импульсов (0b11111111 << 1)
if (pulse <= G433_EDGE_HT && parse) { // окно LOW/HIGH и идёт парсинг
byteBuf >>= 1; // двигаем байт-буфер
if (pulse > G433_EDGE_LH) byteBuf |= (1 << 7); // пишем бит, если это HIGH
if (!(++bits & 0x7)) return 2; // 2: ПРИНЯТ БАЙТ: собрали байт (каждые 8 бит, 0x7 == 0b111)
} else if (pulse <= G433_EDGE_TS) { // окно START
trains |= 1; // добавляем 1 справа к trains
if (parse) { // был парсинг, а это стоп бит
parse = 0; // стоп машина
return 3; // 3: ПРИНЯТ ПАКЕТ: принят стоп-бит
} }
prevState = newState; } else if (pulse <= G433_EDGE_S) { // окно STOP/TRAINING
} if (trains == 0xFE) { // было 7 train импульсов (0xFE == 0b11111110)
bits = 0; // прерываем парсинг, если он был
parse = 1; // старт бит, начинаем парсинг
return 1; // 1: СТАРТ ПРИЁМА
}
} else return parse = 0; // слишком длинный импульс, выходим
return 0; return 0;
} }
// блокирующий приём, вернёт кол-во успешно принятых байт // тикер приёма для вызова в прерывании по CHANGE
uint8_t tickWait() { void tickISR() {
do { switch (tickISRraw()) {
tick(); case 1: // СТАРТ БИТ
} while (parse == 2); if (!state) { // старта не было
if (byteCount > 0) { state = 1; // старт
byteCount = 0; bytes = 0; // сброс
return size; } // старт был - ошибка приёма
} else return 0; break;
case 2: // ПРИНЯТ БАЙТ
if (state == 1) { // парсинг идёт
buffer[bytes] = byteBuf; // пишем в буфер
bytes++; // счётчик принятых
if (bytes > sizeof(buffer)) { // буфер переполнен
state = 3; // флаг на чтение
}
}
break;
case 3: // КОНЕЦ ПАКЕТА
if (state == 1) state = 2; // флаг на чтение
break;
}
} }
// если пакет прочитан успешно - вернёт количество байт в нём
uint16_t gotData() {
if (state >= 2) { // флаг на чтение
size = 0; // обнуляем размер
if (state != 3 && bytes != 0) { // если буфер не переполнен, проверяем CRC
if (CRC_MODE == G433_CRC8) { // CRC8
if (!G433_crc8(buffer, bytes)) size = bytes - 1;
} else if (CRC_MODE == G433_XOR) { // CRC XOR
if (!G433_crc_xor(buffer, bytes)) size = bytes - 1;
} else size = bytes; // без CRC
}
#ifndef G433_CUT_RSSI
if (!size) errCount++; // принято 0 байт - ошибка
if (++rcCount >= G433_RSSI_COUNT) {
RSSI = 100 - errCount * 100 / G433_RSSI_COUNT;
errCount = rcCount = 0;
}
#endif
state = 0;
return size;
}
return 0;
}
// прочитает буфер в любой тип данных // прочитает буфер в любой тип данных
template <typename T> template <typename T>
bool readData(T &data) { bool readData(T &data) {
if (sizeof(T) > G433_BUFSIZE) return false; if (sizeof(T) > RX_BUF) return false; // великовато для буфера
uint8_t *ptr = (uint8_t*) &data; if (sizeof(T) != size) return false; // данные не соответствуют
uint8_t *ptr = (uint8_t*) &data;
for (uint16_t i = 0; i < sizeof(T); i++) *ptr++ = buffer[i]; for (uint16_t i = 0; i < sizeof(T); i++) *ptr++ = buffer[i];
return true; return true;
} }
// получить качество приёма (процент успешных передач)
uint8_t getRSSI() {
#ifndef G433_CUT_RSSI
return RSSI;
#endif
}
// получить размер принятых данных // получить размер принятых данных
int getSize() { uint16_t getSize() {
return size; return size;
} }
int size = 0; // размер принятых данных
uint16_t size = 0;
// доступ к буферу
uint8_t buffer[RX_BUF + !!CRC_MODE];
uint8_t byteBuf;
private: private:
bool fastDR() { bool fastRead(const uint8_t pin) {
#if defined(__AVR__) #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
return bool(*_pin_reg & _bit_mask); if (pin < 8) return bitRead(PIND, pin);
#else else if (pin < 14) return bitRead(PINB, pin - 8);
return digitalRead(_pin); else if (pin < 20) return bitRead(PINC, pin - 14);
#endif #elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
return bitRead(PINB, pin);
#else
return digitalRead(pin);
#endif
return 0;
} }
uint8_t buffer[G433_BUFSIZE];
bool prevState; bool pinChanged() {
uint8_t parse = 0; if (prevBit != fastRead(RX_PIN)) {
uint32_t tmr = 0; prevBit = !prevBit;
uint8_t bitCount = 0, byteCount = 0; return 1;
#if defined(__AVR__) } return 0;
volatile uint8_t *_pin_reg; }
volatile uint8_t _bit_mask;
bool prevBit;
volatile uint8_t state = 0;
volatile uint8_t parse = 0, trains = 0;
volatile uint32_t tmr = 0;
uint8_t bits = 0, bytes = 0;
#ifndef G433_CUT_RSSI
uint8_t errCount = 0, rcCount = 0, RSSI = 100;
#endif #endif
}; };
void G433_crc_byte(uint8_t &crc, uint8_t data) {
#if defined (__AVR__)
// резкий алгоритм для AVR
uint8_t counter;
uint8_t buffer;
asm volatile (
"EOR %[crc_out], %[data_in] \n\t"
"LDI %[counter], 8 \n\t"
"LDI %[buffer], 0x8C \n\t"
"_loop_start_%=: \n\t"
"LSR %[crc_out] \n\t"
"BRCC _loop_end_%= \n\t"
"EOR %[crc_out], %[buffer] \n\t"
"_loop_end_%=: \n\t"
"DEC %[counter] \n\t"
"BRNE _loop_start_%="
: [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer)
: [crc_in]"0" (crc), [data_in]"r" (data)
);
#else
// обычный для всех остальных
uint8_t i = 8;
while (i--) {
crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1);
data >>= 1;
}
#endif
}
uint8_t G433_crc(uint8_t *buffer, uint8_t size) {
uint8_t crc = 0;
for (uint8_t i = 0; i < size; i++) G433_crc_byte(crc, buffer[i]);
return crc;
}
#endif #endif