• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Подружить ESP8266 и приемник 433МГц

Sr.FatCat

Member
Ясновидящие редкость это понятно, как и внимательно читающие. От D1 Wi-Fi Uno до обычной esp.
Так может рискнете уже написать правильный код для какого-нибудь пина, а такой нуб как я уже просто изменит одну циферку или буковку, или ручками воткнет датчик в нужный пин
Я уже расписал все выше - подробнее некуда, @tretyakov_sa, с завидным терпением, все повторил и разжевал. Где какие GPIO на незнакомой D1 Wi-Fi Uno мне не понятно, поэтому насчет какую циферку вписать вам в mySwitch.enableReceive(0) не скажет никто, кроме Вас.
Кстати, думаю, особых проблем ни с 0, ни с 2 не будет, при старте ESP-шка отрабатывает прижатие их к земле, а шум приемника он к питанию. Но неожиданности могут быть.

Абсолютно согласен, но с одной оговоркой. Если есть 100% уверенность в работоспособности данной библиотеки на esp8266.
В противном случае, лезть придется.
Это одна из лучших в плане мультиплатформенности библиотек. В коде препроцессора ESP поддерживается явнее некуда. Мне в код библиотеки пришлось лезть только по одной причине - для совместного использования обработчика прерывания, ибо интерфейса для наследников там не предусмотрено, к сожалению.

По теме вопроса. Дальнейшие исследования показали, что при совместном подключении UNO и ESP к приемнику - есть очень любопытные нюансы. А именно, если на UNO не подавать питания, то никаких сигналов к ESP не проходит. Похоже вход выключенной UNO шунтирует выход приемника. А при включенной UNO - ESPшка ловит манчестер в 3-5 раз лучше, чем если просто подключена одна, но все равно хуже в 2-3 раза, чем UNO. Даже предположить не могу, что там такого может быть на входе уны, что так благотворно влияет на прием есп-шкой. Пробывал подтягивать вход есп-шки (при отключеной уно) разными номиналами к земле и снимать с приемника через делитель, но эффекта 0 - ESPшка очень печально раскодирует манчестер и очень уверено RC_Switch. Хотя все это больше склоняет меня к борьбе аппаратной проблемой.
Вчера под вечер ситуация усугубилась. Похоже сильно прибавилось шумов в эфире, есп-шка стала хреновее работать как UDP-сервер и переодически вылетать с Exception(9). Закоментировал в обработчике прерывания мой декодер манчестера - вылетать перестала. Подозреваю, что идут слишком частые обращения к прерыванию и сравнительно тяжелый код манчестера вместе с лагающим UDP провоцируют злобную сторожевую собаку на soft reset...
 

kab

New member
@Sr.FatCat
Может в процедуре прерывания ввести принудительный интервал между "рабочими" приемами информации - пропуская без обработки пришедшие слишком "рано"? И вопрос к специалистам - а что вообще происходит, если процедура прерывания еще не завершена, а наступает новое условие прерывания?
 

roiksv

Member
Т.е в mySwitch.enableReceive(N) для Uno N=0 >pin2, N=1 >pin3, для Mega N=2 > pin21, N=3 > pin20, N=4 > pin19, N=5 > pin18, а для esp N=0 >gpio0, N=1 >gpio1 и так далее?
 

Sr.FatCat

Member
@roiksv именно так

@Sr.FatCat
Может в процедуре прерывания ввести принудительный интервал между "рабочими" приемами информации - пропуская без обработки пришедшие слишком "рано"? И вопрос к специалистам - а что вообще происходит, если процедура прерывания еще не завершена, а наступает новое условие прерывания?
Ну там и так отбрасывается, все, что меньше 200мкс, в эту сторону не отптимизируешь. Буду медитировать над кодом, чтобы придумать условия чтобы как можно раньше обрывать обработку.

Что касается именно этих прерываний у ESP - не знаю, а обычно вложенные прерывания могут быть разрешены и обработчик должен это учитывать, либо запрещать вложенность, либо запрещать вообще все прерывания на время обработки.
 

kab

New member
вложенные прерывания могут быть разрешены
может здесь собака и порылась? Т. е. во время выполнения "тяжелого" кода наступает новое прерывание и новый процесс сбивает какие-то значения глобальных переменных от старого процесса? И из-за этого всё путается?
 

Sr.FatCat

Member
@kab я сделал более кондово: я запрещал в обработчике прерывания :), гарантируя что мне ничего не помешает. Качество распознавания манчестера ни сколько не улучшилось :(
 

Sr.FatCat

Member
Выкинул из обработчика прерывания процедуру декодирования манчестера и сделал буфер на 256 таймингов. Буфер копирую с запретом прерывания и разбираю, по возможности, в основном цикле. Сторожевая собака довольна, хотя переполнение буфера происходит переодически и часть сигналов теряется.
Вставил это безобразие в основной проект, распознавание манчестера ухудшилось еще сильнее - теперь в среднем не более 4 распознаных посылок за час.

Тем не менее, у меня картинка сложилась, может не до конца правильная, но думаю дело в этом. Часть кода в ESP8266 отвечающая за обслуживание WiFi, естественно имеет более высокий приоритет, а потому прерывание от приемника 433 выполняется не всегда или с задержкой. Для RC_switch это не так критично, хотя более внимательное рассмотрение показывает, что оно тоже страдает, пропуск посылок на реальном проете все-таки и там происходит, но редко - в 5-7% случаев примерно, а вот для манчестера - да, беда, беда.

Программное решение тут почти не вижу. То, что могу придумать - довольно сложно, с массой ограничений и работать будет не идеально.
Аппаратных решений вижу 2: использовать в качестве приемника что-типа RFM69 или сделать свой бридж RF433->OneWire/I2C на какой-нибудь тиньке или мини про. Думаю тему можно закрывать.
 
  • Like
Реакции: kab

fm96

New member
Не очень надеюсь, что кто-то сможет чем-то помочь, поэтому скетч пока выкладывать не буду. Опишу словами:
Есть NodeMCU к выводу D1 (GPIO5) которого подключен примитивный приемник 433МГц (сейчас RXB6, как самый хваленый, но картина не сильно отличается и с SRX882 и даже с RF-5V) - задача принять и расшифровать сигналы от стандартного RC_Switch устройства и датчиков Oregon Scientific.
Реализация довольно примитивная: сигнал с приемника вызывает прерывание на D1 - там определяется его длинна (от предыдущего прерывания) и по известным алгоритмам переводится в байты RCSwitch или манчестерский код.
Велосипед не изобретался. была взята известная библиотека RCSwitch и в ее процедуру обработки прерывания вкостылена еще и функция обсчета манчестерского кода известным классом DecodeOOK.

Вся математика в прерывании. В теле loop проверяется только флаг прочитанного кода и если он выставлен - результат выводится в Serial.

Теперь интрига.
Сначала все это опробывал на Arduino UNO (с подключением к 2-му цифровому, прерывание 0) - работает как часы. Просто отлично.
Поменял в скетче только номер прерывания. Загрузил в ESP и облом. RCSwitch - все так же выдает как часы, данные от Oregon получаются расшифровать в среднем в 1 из 7-10 посылок. При этом еще и куча ложняков приходит (это при том, что 6/8 байт манчестерского кода проверяются по CRC !!!)
Погрешил на шумность ESP - смонтировал UNO и NodeMCU на одной макетке c одним приемником, выход которого подключил без всякой развязки к 2 и D1 выводов МК сответственно. Питание пробывал подавать и от уны и от ноды. Запускаю скетчи одновременно - смотрю в разных терминалах. Результат - тот же. Все прекрасно работает на уне, но на esp только RCSwitch работает отлично, по Орегону очень редко и ложняки.
Хотя бы понять с чем это связано может быть? Аппаратно или программно?
У меня работает н RC_Switch, но не работает на RemoteReceiver
 

fm96

New member
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RCSwitch.h>
LiquidCrystal_I2C _lcd1(0x27, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;
extern "C" {
#include "user_interface.h";
}
float out1;
float out2;
RCSwitch mySwitch= RCSwitch();
float tempout=0,Hr=0;
#define key1 11000 // датчик температуры
#define key2 12000 // датчик влажность
extern "C" {
#include "user_interface.h"
}
os_timer_t watchDogTimer;
int _PWDC = 0;
int _disp1oldLength = 0;
int _disp2oldLength = 0;
void setup()
{
Wire.pins(4, 5);
Wire.begin();
delay(10);
satrtWachDogTimer();
_lcd1.init();
_lcd1.backlight();
mySwitch.enableReceive(0); // Receiver on inerrupt 0 => that is pin #2 // иницилизация.Используется вывод м/к с прерыванием под номером 0.
Serial.begin(9600);
mySwitch.enableReceive(0);
}
void loop()
{if (_isNeedClearDisp1) {_lcd1.clear(); _isNeedClearDisp1= 0;}
_PWDC = 0;


//Плата:1
{

if (mySwitch.available()) {

unsigned long receivedCode= mySwitch.getReceivedValue();
if (receivedCode == 0) {
// обработка:не верный формат данных
} else {
if (key1<=receivedCode && key1+999>receivedCode) tempout=(int)(receivedCode-key1-500);
else if (key2<=receivedCode && key2+999>receivedCode)Hr=(int)(receivedCode-key2);
else tempout = (float)(receivedCode); //пример для влажности
// нужно делить на 10,если отправляем через езернет на компьютер- разделить можно там.

}
mySwitch.resetAvailable(); // сброс данных.
} // end available
out1 = tempout;
out2 = Hr;
Serial.println(tempout);
delay(1000);
Serial.println(Hr);
delay(1000);
// тут могут выводится данные tempout и tempin на лсд экран или отправлятся через езернет.
}
if (1) {
_dispTempLength1 = ((( _floatToStringWitRaz((out2)/(10.00),2)))).length();
if (_disp2oldLength > _dispTempLength1) {_isNeedClearDisp1 = 1;}
_disp2oldLength = _dispTempLength1;
_lcd1.setCursor(0, 1);
_lcd1.print((( _floatToStringWitRaz((out2)/(10.00),2))));
} else {
if (_disp2oldLength > 0) {_isNeedClearDisp1 = 1; _disp2oldLength = 0;}
}
if (1) {
_dispTempLength1 = ((( _floatToStringWitRaz((out1)/(10.00),2)))).length();
if (_disp1oldLength > _dispTempLength1) {_isNeedClearDisp1 = 1;}
_disp1oldLength = _dispTempLength1;
_lcd1.setCursor(0, 0);
_lcd1.print((( _floatToStringWitRaz((out1)/(10.00),2))));
} else {
if (_disp1oldLength > 0) {_isNeedClearDisp1 = 1; _disp1oldLength = 0;}
}


}
String _floatToStringWitRaz(float value, int raz)
{

return String(value,raz);
}
bool _isTimer(unsigned long startTime, unsigned long period )
{
unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
}
void wachDogTimerTick(void *pArg) {
if (_PWDC >= 100){ ESP.reset(); }else{_PWDC = _PWDC+1;}
}
void satrtWachDogTimer(void ) {
os_timer_setfn(&watchDogTimer, wachDogTimerTick, NULL);
os_timer_arm(&watchDogTimer, 100, true);
}
 
Сверху Снизу