В вашем случае условие не выполнится, если в момент сравнения millis() вернёт не 10000, а например 10004.
Подскажите, как я могу привязаться не к запуску системы, а к часам?
У меня на LCD секунды не отображаются, и я хочу, чтобы обновление минут происходило один раз в минуту, когда секунды 00, чтобы не отвлекать ардуину слушать эфир.
В Ардуино нет часов, потому только к запуску системы.
Вместо 10000 напишите 60000 :) будет раз в минуту, это число количество миллисекунд. 1сек == 1000мс.
Но по мне всё это блаж... к примеру в моём проекте вызов отрисовки раз в секунду не влияет на приём сигналов с четырёх датчиков практически никак. Часики у меня с секундами... )
В Ардуино нет часов, потому только к запуску системы.
Вместо 10000 напишите 60000 :) будет раз в минуту, это число количество миллисекунд. 1сек == 1000мс.
Но по мне всё это блаж... к примеру в моём проекте вызов отрисовки раз в секунду не влияет на приём сигналов с четырёх датчиков практически никак. Часики у меня с секундами... )
Вас понял, значит будет раз в секунду.
Подскажите, а в void loop () я могу любые условия добавлять и они будут проверяться в обязательном порядке?
Вот например будет ли работать это условие:
if (time.Hours==0){ // Полночь
lcd.setCursor(10,0);
lcd.print (time.gettime("d/m/Y")); // выводим дату
Ясно. А с какой частотой повторяется выполнение цикла loop?
Я правильно понимаю, что я не могу приостановить выполнение только одной функции в цикле?
void loop(){
if 1....
{ ......
delay(10000);
}
if 2.......
{.......
Если у меня в первом if стоит задержка delay(10000), то пока эта задержка не пройдёт, не будет выполняться дальше и соответственно if 2 не выполниться пока не пройдёт задержка у первого if?
Ну, это потому как там "за время пути собачка успевает подрости"... и его надо чуток видоизменить, но идейно он более правильный, он срабатывает в любой момент после наступления события, а указанный выше только в конкретный момент времени, и этот момент может вообще не случиться ;) хоть и случается достаточно часто... )))
Ну, это потому как там "за время пути собачка успевает подрости"... и его надо чуток видоизменить, но идейно он более правильный, он срабатывает в любой момент после наступления события, а указанный выше только в конкретный момент времени, и этот момент может вообще не случиться ;) хоть и случается достаточно часто... )))
Вас понял.
Но случается он действительно часто. У себя пропусков не заметил, смотрел внималельно)))
Отсутствие пропусков компенсируется глуховатостью... )
Время передачи Орегон пакета в эфире где-то ~190мс, пакетов обычно два. Если ваш код успевает отработать (в смысле опросить часы реального времени, вывести это на экран, и так далее) за это время, то это даст ошибку приёма только в одном пакете, и второй будет спокойненько принят и обработан. Вероятность попасть сразу на два пакета - мала, но тоже есть.
Так что всё зависит от времени выполнения вашего кода.
У меня вот так успевает, и по радио передать на экран вывести, вставлял куда написано автором, тут и преобразования в char и обратно (иначе не догадался как на ESP передавать, разрядность что ли у нах разная, ереданный массив из INT - доходит бред, буковки доходят нормально, надо только в 128 уместиться, для этого давление вычитаю, на той стороне прибавляю), и дисплей и nrf'кой есть, но ведь тут можно хоть на 40 секунд задержаться, всё равно передача поймается.
//////////////////////////////////////////////////////////////////////
//Здесь записываются остальные процедуры, например те, которые выполняются ежесекундно
//////////////////////////////////////////////////////////////////////
if ((millis() - timer_mark) > 1000) { timer_mark=millis();
// { if (!reciever_status) Serial.println("RECEIVING..."); reciever_status = 1; }
reciever_ctrl = 0; lastTime=lastTime+1;
// digitalWrite(13, !digitalRead(13));
Serial.print(".");
}
if (lastTime > 10) { lastTime = 0;
pres = (bmp.readPressure()/133.33)-600;
datadat[5]=char(dht.readTemperature());datadat[6]=char(dht.readHumidity()); datadat[7]=char(pres);
display.clearDisplay(); display.setTextSize(3);
display.setCursor(0,0); display.print(int(datadat[2])); display.print(char(247));
display.setCursor(0,25); display.print(int(datadat[5])); display.print(char(247));
display.setTextSize(1);
display.setCursor(65,3); display.print(int(datadat[3])); display.print("%");
display.setCursor(53,13); display.print(pres+600); display.print("mm");
display.setCursor(65,25); display.print(int(datadat[6])); display.print("%");
display.setCursor(63,40); if (int(datadat[4]) != 1 ) display.print(char(31)); //батарея разряжена
display.setCursor(77,40); display.print(datadat[1]); //сердечко - свой канал
if (radio.write(&datadat, sizeof(datadat))) Serial.print ("Send");
else {Serial.print ("NoSend"); display.setCursor(70,40); display.print(char(18));} //стрелочки - передача не удалась
display.display();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Завернул свой скетч в библиотеку. Попутно всплыли некоторые весьма критические ошибки при работе с памятью. Теперь всё вроде нормально. По крайней мере, скетч по отправке данных на народмон с этой библиотекой уже неделю работает без падений. Раньше перезагружался регулярно.
Oregon_NR.h
#include <Arduino.h>
#ifndef Oregon_NR_h
#define Oregon_NR_h
#define READ_BITS 96
#define READ_BITS2 192
#define PACKET_LENGTH 20
#define THGN132 0x1D20
#define THN132 0xEC40
#define GAS 0xAA00
#define FIND_PACKET 1
#define ANALIZE_PACKETS 2
#define PER_LENGTH 976
#define THR_LENGTH 615
#define LENGTH_TOLERANCE 20
static int RECEIVER_PIN;
class Oregon_NR
{
public:
//Данные датчика
word sens_type; //Sensor type
float sens_tmp, //Temperature
sens_tmp2; //Temperature2 (for GASv2 sensor)
byte sens_CO, //CO (ppm*10) (for GASv2 sensor)
sens_CH, //CH4 (ppm*100)(ppm)
sens_hmdty, //Humidity
sens_chnl, //Channel number
sens_id, //ID
sens_battery; //Battery status
bool crc_c = 0; //CRC check result. Сбрасывается при захвате. Выставляется при приёме корректного пакета.
bool captured = 0; //Capture data flag. Выставляется, если были считанны данные в память.
bool maybe_packet = 0; //Флаг, что возможно был пакет, но мы его потеряли...
unsigned long work_time; //Capture time
byte packet[PACKET_LENGTH]; //Result packet
byte valid_p[PACKET_LENGTH]; //Validity mask
byte packets_received = 0; //Number of received packets in block (0...2)
Oregon_NR(int, int); //Конструктор. Параметры:
Oregon_NR(int, int, byte, bool); //(вывод приёмника, номер прерывания, вывод светодиода, pull up)
void start(); //Star listening receiver
void stop(); //Stop listening receiver. Чтобы не занимал процессор, когда не нужен
void capture(bool); //Capture packet. if parameter is true function dumps capture data to Serial.
bool consist_synchro = false; //При поиске синхронибла опираться подтверждённые или сомнительные данные?
byte empty_space = 5; //Какое количество "пустых" тактов нужно для определения конца посылки?
//Параметр определяется уровнем сигнала и скоростью АРУ приёмника.
//Чем они лучше, тем меньше число. НО меньше двух не рекомендуется
bool is_assemble = true; //Assemble data from both packets in block or decode it separately.
private:
byte read_tacts, read_tacts2, result_size;
byte LED = 0xFF; //вывод светодиода, который мигает при приёме
bool PULL_UP; //куда подключён светодиод
byte packet_number = 0; //Количесвто принятых пакетов в посылке
int INT_NO; //Номер прерывания приёмника
//bool reciever_ctrl = true; //Флаг контроля ресивера (выставляется при приходе импулься, сбрасывается в таймере)
//Массивы данных для записи данных с канала и полученных битов
byte decode_tacts[READ_BITS2]; //Массив тактов. значения
// 0=ноль
// 1=единица
// 2=неизвестен
// 3=переход+
// 4=переход-
byte collect_data[READ_BITS2], collect_data2[READ_BITS2];
//А когда становится массивом полученных битов, то значения такие:
// 128 - неизвестен
// >128 - единица
// <128 - ноль
byte receive_status = FIND_PACKET;
byte start_pulse_cnt = 0;
unsigned long pulse_length, timer_marklong;
unsigned long pulse_marker, right_pulse_marker, last_premarker;
unsigned long pre_marker[4]; // Для хранения временных меток преамбулы ()
unsigned long first_packet_end;
int data_val, data_val2; // Качество пакетов
byte synchro_pos, synchro_pos2; // Позиции синхрониблов в записи
byte get_gas_CH(byte* gas_data);
byte get_gas_CO(byte* gas_data);
byte get_gas_hmdty(byte* gas_data);
float get_gas_temperature_in(byte* gas_data);
float get_gas_temperature_out(byte* gas_data);
byte get_gas_channel(byte* gas_data);
void restore_data(byte* oregon_data, word sensor_type);
bool check_CRC(byte* oregon_data, word sensor_type);
byte get_id(byte* oregon_data);
byte get_humidity(byte* oregon_data);
byte get_battery(byte* oregon_data);
byte get_channel(byte* oregon_data);
word get_sensor(byte* oregon_data);
float get_temperature(byte* oregon_data);
byte get_info_data(byte* code, byte* result, byte* valid);
void assemble_data(byte* s1, byte* s2, int shift);
int correlate_data(byte* ser1, byte* ser2);
byte collect(byte* cdptr);
int get_data(int btt, byte* cdptr);
void get_bits(byte* cdptr);
byte get_synchro_pos(byte* code);
void led_light(bool);
};
#endif
Oregon_NR.cpp
#include "Oregon_NR.h"
//Всё, что относится к прерыванию/////////////////////////////////////
#ifndef Oregon_NR_int
#define Oregon_NR_int
static volatile unsigned long pm;
static volatile unsigned long pl, timer_mark;
void receiver_interruption(void) {
if(digitalRead(RECEIVER_PIN)){
//Начало импульса
pl = 0;
pm = micros();
}
else{
//Конец импульса
//Вычисляется время окончания и длина
pl = micros() - pm;
pm += pl;
}
//yield();
}
#endif
//////////////////////////////////////////////////////////////////////
Oregon_NR::Oregon_NR(int MHZ, int MHZ_INT)
{
INT_NO = MHZ_INT;
RECEIVER_PIN = MHZ;
pinMode(MHZ, INPUT); // Вывод, на который подключён приёмник
}
Oregon_NR::Oregon_NR(int MHZ, int MHZ_INT, byte led, bool pull_up)
{
INT_NO = MHZ_INT;
LED = led;
PULL_UP = pull_up;
RECEIVER_PIN = MHZ;
pinMode(MHZ, INPUT); // Вывод, на который подключён приёмник
pinMode(LED, OUTPUT); // Вывод светодиода
}
//////////////////////////////////////////////////////////////////////
void Oregon_NR::start()
{
packet_number = 0;
packets_received = 0;
start_pulse_cnt = 0;
receive_status = FIND_PACKET;
led_light(false);
attachInterrupt(INT_NO, receiver_interruption, CHANGE);
}
//////////////////////////////////////////////////////////////////////
void Oregon_NR::stop()
{
detachInterrupt(INT_NO);
}
//////////////////////////////////////////////////////////////////////
//Захват и анализ пакета
//DEBUG_INFO - в Serial выводится информация о захвате данных
//////////////////////////////////////////////////////////////////////
void Oregon_NR::capture(bool DEBUG_INFO)
{
////////////////////////////////////////////////////////
// Возвращаемся к исходному состоянию
maybe_packet = 0;
packets_received = 0;
sens_type = 0;
crc_c = 0;
captured = 0;
data_val = 0;
data_val2 = 0;
////////////////////////////////////////////////////////
//Чтение данных с приёмника
noInterrupts();
pulse_length = pl;
pl = 0;
pulse_marker = pm;
interrupts();
////////////////////////////////////////////////////////
//Пришёл импульс
if (pulse_length != 0 && receive_status == FIND_PACKET){
if (start_pulse_cnt == 0){
////////////////////////////////////////////////////////
//Найдена первый "правильный" импульс - длинная единица!
if (pulse_length < (PER_LENGTH) && pulse_length > (THR_LENGTH) ) {
start_pulse_cnt = 1;
pre_marker[start_pulse_cnt] = pulse_marker;
pulse_length = 0;
}
}
else{
///////////////////////////////////////////////////////////
//Найдена следующий "правильный" импульс - длинная единица!
if (pulse_length <= (PER_LENGTH) && pulse_length >= (THR_LENGTH)) {
///////////////////////////////////////////////////////////
//Если импульс в правильном месте, то добавляем счётчик найденых стартовых импульсов
if(pulse_marker - pre_marker[start_pulse_cnt] > (PER_LENGTH*2-LENGTH_TOLERANCE) && pulse_marker - pre_marker[start_pulse_cnt] < (PER_LENGTH * 2 + LENGTH_TOLERANCE)){
start_pulse_cnt++;
pre_marker[start_pulse_cnt] = pulse_marker;
pulse_length = 0;
}
///////////////////////////////////////////////////////////
//Следующий импульс находится в неправильном месте
//Назначаем его первым
else{
start_pulse_cnt = 1;
pre_marker[start_pulse_cnt] = pulse_marker;
pulse_length = 0;
}
}
else{
///////////////////////////////////////////////////////////
//Если импульс неправильной длины, то стоит проверить,
//а не вышло ли время ожидания правильного импульса
if (pulse_marker - pre_marker[start_pulse_cnt] < (PER_LENGTH * 2 + LENGTH_TOLERANCE)){
///////////////////////////////////////////////////////////
//Время ещё не вышло, скорее всего это помеха. Пропускаем...
pulse_length = 0;
}
else{
///////////////////////////////////////////////////////////
//Время вышло, начинаем искать заново
start_pulse_cnt = 0;
pulse_length = 0;
}
}
}
}
/////////////////////////////////////////////////////////////////////
// Если найден первый пакет и вышло вермя ожидания второго
// Не ждём второго, а переходм в режим анализа
// Или если отключён режим сращивания пакетов
if (packet_number == 1 && (millis() - first_packet_end) > 200) receive_status = ANALIZE_PACKETS;
if (packet_number == 1 && !is_assemble) receive_status = ANALIZE_PACKETS;
//////////////////////////////////////////////////////////////////////
//Если Найдены три длинных единицы и два длинных нуля. Вероятнее всего это начало посылки...
// Начинаем СБОР ДАННЫХ
if (start_pulse_cnt == 3 && receive_status == FIND_PACKET) {
work_time = millis();
last_premarker = pre_marker[3];
start_pulse_cnt = 0;
if (packet_number == 0){
read_tacts = collect(collect_data);
first_packet_end = millis();
packet_number = 1;
}
else{
read_tacts2 = collect(collect_data2);
packet_number = 2;
receive_status = ANALIZE_PACKETS;
}
}
//////////////////////////////////////////////////////////////////////
// Анализ данных////////////////////////////////////////////////////////
if (receive_status == ANALIZE_PACKETS) {
//////////////////////////////////////////////////////////////////////
//Отключаем прерывание, чтобы сократить время обработки
detachInterrupt(INT_NO);
led_light(true);
/* //Дамп собранных данных
if (DEBUG_INFO){
for(int bt = 0; bt < 180; bt++){
Serial.print(collect_data[bt], HEX);
Serial.print(' ');
}
Serial.println(" ");
for(int bt = 0; bt < 180; bt++){
Serial.print(collect_data2[bt],HEX);
Serial.print(' ');
}
Serial.println(" ");
}
*/
//////////////////////////////////////////////
//Обработка первой записи
//Расшифровываем запись. Данные сохраянем в decode_tacts[]
get_bits(collect_data);
bool halfshift;
if (get_data(0, collect_data) > get_data(1, collect_data)){
data_val = get_data(0, collect_data);
halfshift = 0;
}
else {
data_val = get_data(1, collect_data);
halfshift = 1;
}
//////////////////////////////////////////////
//Ищем позицию синхронибла
synchro_pos = get_synchro_pos(collect_data);
//////////////////////////////////////////////
//Выводим посылку
if (DEBUG_INFO){
Serial.print("1) ");
for(int bt = 0; bt < READ_BITS; bt++) {
if (bt <= read_tacts / 2){
if (collect_data[bt] > 128 + 1) Serial.print('I');
if (collect_data[bt] < 128 - 1) Serial.print('O');
if (collect_data[bt] == 128 + 1) Serial.print('i');
if (collect_data[bt] == 128 - 1) Serial.print('o');
if (collect_data[bt] == 128) Serial.print('.');
}
else Serial.print(' ');
}
Serial.print(" SIZE:");
Serial.print(read_tacts);
Serial.print(" VAL:");
Serial.print(data_val);
Serial.print(" SYN:");
Serial.print(synchro_pos);
Serial.print(" SHIFT:");
Serial.println(halfshift);
}
//////////////////////////////////////////////
//Аналогично обрабатываем вторую запись
if (packet_number == 2){
get_bits(collect_data2);
if (get_data(0, collect_data2) > get_data(1, collect_data2)) {
data_val2 = get_data(0, collect_data2);
halfshift = 0;
}
else {
data_val2 = get_data(1, collect_data2);
halfshift = 1;
}
synchro_pos2 = get_synchro_pos(collect_data2);
if (DEBUG_INFO){
Serial.print("2) ");
for(int bt = 0; bt < READ_BITS; bt++) {
if (bt <= read_tacts2 / 2){
if (collect_data2[bt] > 128 + 1) Serial.print('I');
if (collect_data2[bt] < 128 - 1) Serial.print('O');
if (collect_data2[bt] == 128 + 1) Serial.print('i');
if (collect_data2[bt] == 128 - 1) Serial.print('o');
if (collect_data2[bt] == 128) Serial.print('.');
}
else Serial.print(' ');
}
Serial.print(" SIZE:");
Serial.print(read_tacts2);
Serial.print(" VAL:");
Serial.print(data_val2);
Serial.print(" SYN:");
Serial.print(synchro_pos2);
Serial.print(" SHIFT:");
Serial.print(halfshift);
}
}
byte* result_data, result_data_start, aux_data;
int correlation;
//////////////////////////////////////////////
//СОПОСТАВЛЕНИЕ ПАКЕТОВ
//Если пакет один, то и сопоставлять не из чего
if (packet_number == 1) result_data = collect_data;
//////////////////////////////////////////////
//А вот если два, то нужна СБОРКА ПАКЕТА
//вычисляем оптимальное "смещение" пакетов друг относительно друга
if (packet_number == 2) {
correlation = correlate_data(collect_data, collect_data2);
if (DEBUG_INFO){
Serial.print(" COR: ");
Serial.println(correlation);
}
//////////////////////////////////////////////
//Собираем данные в пакет, где синхронибл найден раньше
//////////////////////////////////////////////
if (synchro_pos >= synchro_pos2)
{
result_size = read_tacts2;
result_data = collect_data2;
correlation = -correlation;
assemble_data(collect_data2, collect_data, correlation);
}
else
{
result_size = read_tacts;
result_data = collect_data;
assemble_data(collect_data, collect_data2, correlation);
}
}
//////////////////////////////////////////////
//Вывод готовой посылки
if (DEBUG_INFO && packet_number == 2){
Serial.print("RESULT ");
byte* rdt = result_data;
for(int bt = 0; bt < READ_BITS; bt++){
if (bt <= result_size / 2){
if (*rdt > 128 + 1) Serial.print('I');
if (*rdt < 128 - 1) Serial.print('O');
if (*rdt == 128 + 1) Serial.print('i');
if (*rdt == 128 - 1) Serial.print('o');
if (*rdt == 128) Serial.print('.');
}
else Serial.print(' ');
rdt++;
}
Serial.println(" ");
}
//////////////////////////////////////////////
//Извлекаем из тактовой последовательности биты
sens_type = 0;
if (get_info_data(result_data, packet, valid_p)){
sens_type = get_sensor(packet); //Определяем тип пакета по типу датчика
restore_data(packet, sens_type); // Восстанавливаем данные по типу датчика
crc_c = check_CRC(packet, sens_type); // Проверяем CRC, если оно верно, то все сомнительные биты делаем уверенными
//Если не все байты определены уверенно, нельзя считать, что пакет корректный
byte secresingV;
if (sens_type == THGN132 || (sens_type & 0xFF00) == GAS) secresingV = PACKET_LENGTH - 4;
if (sens_type == THN132) secresingV = PACKET_LENGTH - 6;
for (byte www = 0; www < (PACKET_LENGTH - secresingV + 2); www++)
if (valid_p[www] < 0x0f) crc_c = false;
//Захват пакета происходит тольок в случае, если найдена стартовая последовательность (нибл синхронизации)
captured = 1;
}
else if (data_val >=64 || data_val2 >=64) maybe_packet = 1;
////////////////////////////////////////////////////////////////////////////////////////////////////
//Расшифровка датчиков Орегон
////////////////////////////////////////////////////////////////////////////////////////////////////
if ((sens_type == THGN132 || sens_type == THN132) && crc_c){
sens_tmp2 = 404;
sens_CO = 255;
sens_CH = 255;
sens_id = get_id(packet);
sens_chnl = get_channel(packet);
sens_battery = get_battery(packet);
sens_tmp = get_temperature(packet);
if (sens_type == THGN132)
sens_hmdty = get_humidity(packet);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//Расшифровка комплексных газовых датчиков
////////////////////////////////////////////////////////////////////////////////////////////////////
if ((sens_type & 0xFF00) == GAS && crc_c){
sens_id = 0;
sens_battery = 0;
sens_chnl = get_gas_channel(packet);
sens_tmp = get_gas_temperature_out(packet);
if (packet[9] == 0x0F) sens_tmp = 404;
sens_tmp2 = get_gas_temperature_in(packet);
if (packet[12] == 0x0F) sens_tmp2 = 404;
sens_hmdty = get_gas_hmdty(packet);
sens_CO = get_gas_CO(packet);
sens_CH = get_gas_CH(packet);
}
////////////////////////////////////////////////////////////////////////////////
//Остальные вычисления
//Возвращаем всё в исходное состояние и включаем прослушивание приёмника
work_time = millis() - work_time;
packets_received = 0;
if (data_val >= 64 && synchro_pos != 255) packets_received++;
if (data_val2 >= 64 && synchro_pos2 != 255) packets_received++;
receive_status = FIND_PACKET;
start_pulse_cnt = 0;
packet_number = 0;
led_light(false);
//Serial.print("LED = ");
//Serial.println(LED);
attachInterrupt(INT_NO, receiver_interruption, CHANGE);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Извлекает из тактовой последовательности - битовую
//Параметры: cdptr - указатель на записанную тактовую последовательность
////////////////////////////////////////////////////////////////////////////////////////////////////
void Oregon_NR::get_bits(byte* cdptr){
//Сброс массивов
byte* cdp=cdptr;
for(int bt=0 ; bt<READ_BITS*2; bt++) decode_tacts[bt]=2;
for(int bt=0 ; bt<READ_BITS*2; bt++){
if ((*cdp&0xf0)>0x20 && (*cdp&0x0f)>0x04) decode_tacts[bt]=1;
if ((*cdp&0xf0)<0x30 && (*cdp&0x0f)<0x05) decode_tacts[bt]=0;
if ((*cdp&0xf0)<0x20 && (*cdp&0x0f)>0x04) decode_tacts[bt]=4;
if ((*cdp&0xf0)>0x40 && (*cdp&0x0f)<0x02) decode_tacts[bt]=3;
*cdp++;
}
return;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Извлекает из записи канала тактовую последовательность
//Параметры: cdptr - указатель на записанные данные
// btt - смещение в тактах. Смещение на такт при анализе может поммочь восстановить пакет, у которого разрушено начало
// Функция вовзращает качество или "годность" расшифровки - количесвто уверенно узнаных тактов.
// Сравнивая годность с btt=0 и btt=1 выбираем лучшую
////////////////////////////////////////////////////////////////////////////////////////////////////
int Oregon_NR::get_data(int btt, byte* cdptr){ //btt - смещение на такт при анализе может поммочь восстановить пакет, у которого разрушено начало
byte* cdp=cdptr;
for(int bt=0 ; bt<READ_BITS; bt++){
*cdp=128;
cdp++;
}
cdp=cdptr;
*cdp=(128+2);
cdp++;
int packet_validity=0;
for(int bt=1 ; bt<READ_BITS; bt++){
if(decode_tacts[bt*2-btt]==0) *cdp-=1;
if(decode_tacts[bt*2-btt]==1) *cdp+=1;
if(decode_tacts[bt*2-2-btt]==1 && decode_tacts[bt*2-1-btt]==4) *cdp-=1;
if(decode_tacts[bt*2-2-btt]==0 && decode_tacts[bt*2-1-btt]==3) *cdp+=1;
if(decode_tacts[bt*2-2-btt]==0 && decode_tacts[bt*2-1-btt]==1) *cdp-=1;
if(decode_tacts[bt*2-2-btt]==1 && decode_tacts[bt*2-1-btt]==0) *cdp+=1;
if(decode_tacts[bt*2+2-btt]==1 && decode_tacts[bt*2+1-btt]==3) *cdp-=1;
if(decode_tacts[bt*2+2-btt]==0 && decode_tacts[bt*2+1-btt]==4) *cdp+=1;
if(decode_tacts[bt*2+2-btt]==0 && decode_tacts[bt*2+1-btt]==1) *cdp-=1;
if(decode_tacts[bt*2+2-btt]==1 && decode_tacts[bt*2+1-btt]==0) *cdp+=1;
//Подсчитываем кол-во достоверных бит в пакете
if (*cdp>(128+1) ) packet_validity+=*cdp-128;
if (*cdp<(128-1)) packet_validity+=128-*cdp;
cdp++;
}
return packet_validity;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Прослушивание канала с частотой дискретизации 16384Гц
//cdptr - указатель на область памяти, куда записываются сигнал
//dtl - указатель на количество считанных тактов
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::collect(byte* cdptr){
bool cdp_prev_null;
byte* cdp = cdptr;
byte nulls_found = 0;
//////////////////////////////////////////////////////
//Запись начинаем с этого момента (конец последнего импулься зацепки + 1/16 такта)
unsigned long tmp_marker = last_premarker+PER_LENGTH/32;
byte bt2 = 0;
//////////////////////////////////////////////////////
//Первые два такта - единицы. Мы же поймали импульс!
*cdp = 0x88;
cdp++;
while (micros() <= tmp_marker);
//////////////////////////////////////////////////////
//Начинаем читать данные в память
// Читаем максимум ПО 90 БИТ
// ПОСЫЛКА thgn - 96БИТ, THN - 76 бИТ + как минимум 3 бита 111, которые мы уже нашли
byte bt;
for (bt = 0 ; bt < READ_BITS2; bt++) {
*cdp = 0;
for (byte ckl = 0; ckl < 8; ckl++) { // Читаем 8 раз за полутакт
if (digitalRead(RECEIVER_PIN)) *cdp += 0x10; // Измерения запиываем в старший полубайт
tmp_marker += PER_LENGTH / 16;
while (micros() < tmp_marker);
}
last_premarker += PER_LENGTH / 2;
tmp_marker = last_premarker + PER_LENGTH / 32;
for (byte ckl = 0; ckl < 8; ckl++) {
if (digitalRead(RECEIVER_PIN)) *cdp += 1; // В следующий полутакт измерения запиываем в младший полубайт. Это экономит память.
tmp_marker += PER_LENGTH / 16;
while (micros() < tmp_marker);
}
last_premarker += PER_LENGTH / 2;
bt2++;
// Каждые 8 тактов добавлять 5мкс для выравнивания периода с 976мкс до 976.56мкс
if (bt2 == 8) {
last_premarker += 5;
bt2 = 0;
}
tmp_marker = last_premarker + PER_LENGTH / 32;
cdp++;
/////////////////////////////////////////////
//Есть время до прихода следующего полутакта
//Можно проверить, а не закончилась ли посылка
//Если в канале последнее время пустота, то это надо отметить
//if ((*cdp&0xf0)<0x30 && (*cdp&0x0f)<0x05) decode_tacts[bt]=0;
//if (*cdp == 0 && (*(cdp - 1) == 0)) nulls_found++;
yield();
if ((*cdp & 0xf0) < 0x30 && (*cdp & 0x0f) < 0x05 && ((*(cdp - 1) & 0xf0) < 0x30 && (*(cdp - 1) & 0x0f) < 0x05)) nulls_found++;
else nulls_found = 0;
/////////////////////////////////////////////
//Если более empty_space пустых полей в записи, то
//это вероятнее всего конец посылки. Дальше читать нет смысла
//empty_space - число эмпирическое, зависит от типа приёмника и уровня сигнала
//Если уменьшить, возможно спутать с повреждением пакета
//Если увеличить, то можно не прекратить чтение и начать записывать помехи
if (nulls_found > empty_space ) return bt;
/////////////////////////////////////////////
//Ждём прихода времени следующего полутакта
while (micros() < last_premarker);
}
return bt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Определение смещения пакетов друг относительно друга
//В качестве параметров передаются указатели на массивы данных
// Возваращаяется смещение
// >0 - второй пакет начался раньше, <0 - Первый пакет начался раньше
////////////////////////////////////////////////////////////////////////////////////////////////////
int Oregon_NR::correlate_data(byte* ser1, byte* ser2){
byte best_correl = 0;
int best_shift = 0;
byte best_correl_back = 0;
int best_shift_back = 0;
byte shift_score[READ_BITS];
byte* s1;
byte* s2;
byte* s2t = ser2;
//смещаем первый пакет относительно второго
for (byte sht = 0; sht < READ_BITS; sht++){
s1 = ser1;
s2 = s2t;
shift_score[sht] = 0;
for(byte sp = 0; sp < READ_BITS - sht; sp++){
if ((*s1 > (128+1) && *s2 > (128+1))||(*s1 < (128-1) && *s2 < (128-1)) ) shift_score[sht]++;
s2++;
s1++;
}
yield();
s2t++;
}
for (int i = 0; i < READ_BITS; i++){
if (shift_score[i] > best_correl){
best_correl = shift_score[i];
best_shift = i;
}
}
//Теперь наоборот -втрой пакет относительно первого
byte* s1t = ser1;
for (byte sht = 0; sht < READ_BITS; sht++){
s2 = ser2;
s1 = s1t;
shift_score[sht] = 0;
for (byte sp = 0; sp < READ_BITS-sht; sp++){
if ((*s1 > (128+1) && *s2 > (128+1))||(*s1 < (128-1) && *s2 < (128-1)) ) shift_score[sht]++;
s2++;
s1++;
}
yield();
s1t++;
}
// Ищем наилучшее совпадение для обоих вариантов
for (int i = 0; i < READ_BITS; i++){
if (shift_score[i] > best_correl_back){
best_correl_back = shift_score[i];
best_shift_back = i;
}
}
//И возвращаем самое лучшее из двух
if (best_correl_back > best_correl) return -best_shift_back;
else return best_shift;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Сборка из двух пакетов
//В качестве параметров передаются указатели на массивы данных
// Причём первым должен идти результирующий пакет, т.е. тот который имеет более длинную преамбулу.
//shift - смещение втрого пакета относительного первого
////////////////////////////////////////////////////////////////////////////////////////////////////
void Oregon_NR::assemble_data(byte* s1, byte* s2, int shift){
if (shift >= 0) {
for (int g = 0; g < shift; g++) s2++;
for (int i = 0; i < READ_BITS - shift; i++){
if(*s1 < (128 + 2) && *s1 > (128 - 2) && (*s2 > (128 + 1) || *s2 < (128 - 1))) {
*s1 = *s2;
}
s1++;
s2++;
}
}
else {
for (int g = 0; g < -shift; g++) s1++;
for (int i = 0; i < READ_BITS + shift; i++){
if(*s1 < (128 + 2) && *s1 > (128 - 2) && (*s2 > (128 + 1) || *s2 < (128 - 1))) {
*s1 = *s2;
}
s1++;
s2++;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает позицию синхронибла в посылке
// 0xFF - нет синхронибла
//code - указатель на расшифрованную битовую последовательность
//result - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_synchro_pos(byte* code){
bool syn_found = false;
byte* cp = code;
int i = 0;
for (i = 0; i < READ_BITS - 8; i++){
if (!consist_synchro && (*cp < 128 && *(cp + 1) > 128 && *(cp + 2) < 128 && *(cp + 3) > 128)) {
syn_found = true;
break;
}
if (consist_synchro && (*cp < 127 && *(cp + 1) > 129 && *(cp + 2) < 127 && *(cp + 3) > 129)) {
syn_found = true;
break;
}
cp++;
}
if (!syn_found) return 0xFF;
//Последовательность нашли, но надо убедиться, что перед этим идёт перамбула, т. е. либо уверенные единицы, либо неразборчивый сигнал
//Преамбулу надо просматривать на 16-3 = 13 битов назад. Ну хотя бы на 10!!!
for (byte g = i; i - g < 10 && g > 0; g --){
cp --;
if (*cp < 127) return 0xFF; // Перед синхрониблом в преамбуле не может быть уверенного нуля. Нет тут синхронибла!
}
return (byte) i;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Создаёт кодовую посылку
//code - указатель на расшифрованную битовую последовательность
//result - указатель на кодовую посылку
//valid - указатель на карту достоверности кодовой посылки
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_info_data(byte* code, byte* result, byte* valid){
byte* rd = result;
byte* vd = valid;
//Чистим массивы
for (int l = 0; l < PACKET_LENGTH; l++){
*vd = 0;
*rd = 0;
vd++;
rd++;
}
rd = result;
vd = valid;
int csm;
for (csm = 0; csm < 30; csm++){
if ( !consist_synchro && (*code < 128 && *(code + 1) > 128 && *(code + 2) < 128 && *(code + 3) > 128)) break; //Найдена последовательность 0101
if ( consist_synchro && (*code < 127 && *(code + 1) > 129 && *(code + 2) < 127 && *(code + 3) > 129)) break;
code++;
}
// Стартовая последовательность в первых 20 битах не найдена, такой пакет этим методом не расшифруешь
if (csm > 22) return 0;
//Переходим на начало считывания
code += 4;
int ii = 0;
for (int i = 0; i < READ_BITS - csm; i++)
{
// Чтобы не выйти за пределы
if (i >= PACKET_LENGTH * 4) break;
byte multipl;
switch (ii){
case 0: {multipl = 0x01; break;}
case 1: {multipl = 0x02; break;}
case 2: {multipl = 0x04; break;}
case 3: {multipl = 0x08; break;}
}
if (*code == 129 ) *rd += multipl;
if (*code > 129 ) {
*rd += multipl;
*vd += multipl;
}
if (*code < 127 ) *vd += multipl;
code ++;
ii ++;
if (ii == 4) {
ii = 0;
vd++;
rd++;
}
}
return 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение температуры
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
float Oregon_NR::get_temperature(byte* oregon_data){
float tmprt;
oregon_data+=8;
//исправляем возможные ошибки:
for (int g=0;g<4; g++) if (*(oregon_data+g)>9) *(oregon_data+g)=*(oregon_data+g)-8;
tmprt+=*(oregon_data)*0.1;
tmprt+=*(oregon_data+1);
tmprt+=*(oregon_data+2)*10;
return (*(oregon_data+3)) ? -tmprt : tmprt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает тип сенсора
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
word Oregon_NR::get_sensor(byte* oregon_data){
return (word)(*(oregon_data))*0x1000 + (*(oregon_data+1))*0x0100 + (*(oregon_data+2))*0x10 + *(oregon_data+3);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение канала
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_channel(byte* oregon_data){
byte channel;
switch (*(oregon_data+4))
{
case 1:
channel = 1;
break;
case 2:
channel = 2;
break;
case 4:
channel = 3;
break;
}
return channel;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_battery(byte* oregon_data){
return (*(oregon_data+7) & 0x4) ? 0 : 1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает значение влажности
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_humidity(byte* oregon_data){
byte tmprt;
oregon_data+=12;
//исправляем возможные ошибки:
for (int g=0;g<2; g++) if (*(oregon_data+g)>9) *(oregon_data+g)=*(oregon_data+g)-8;
tmprt=*(oregon_data);
tmprt+=*(oregon_data+1)*10;
return tmprt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Возвращает id датчика
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_id(byte* oregon_data){
byte tmprt;
oregon_data+=5;
tmprt=*(oregon_data)*0x10;
tmprt+=*(oregon_data+1);
return tmprt;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Проверка CRC
//oregon_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Oregon_NR::check_CRC(byte* oregon_data, word sensor_type){
byte* pp=oregon_data;
byte crc, resived_crc;
crc=0;
if (sensor_type==THGN132 || (sensor_type & 0xFF00) == GAS ){
for(int x=0; x<15; x++){
crc+=*pp;
pp++;
}
resived_crc=(*(oregon_data+15))+(*(oregon_data+16))*0x10;
return (resived_crc==crc)? 1 : 0;
}
if (sensor_type==THN132){
for(int x=0; x<12; x++){
crc+=*pp;
pp++;
}
resived_crc=(*(oregon_data+12))+(*(oregon_data+13))*0x10;
return (resived_crc==crc)? 1 : 0;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Востановление данных по типу датчика
////////////////////////////////////////////////////////////////////////////////////////////////////
void Oregon_NR::restore_data(byte* oregon_data, word sensor_type){
byte* pp=oregon_data;
if (sensor_type==THGN132){
pp+=8;
for(int x=0; x<6; x++){
if(*pp>9 && x!=3) *pp-=8;
pp++;
}
}
if (sensor_type==THN132){
pp+=8;
for(int x=0; x<3; x++){
if(*pp>9) *pp-=8;
pp++;
}
}
return;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//Функции расшифровки данных датчиков GAS
//gas_data - указатель на кодовую посылку
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_gas_channel(byte* gas_data){
return gas_data[2];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Oregon_NR::get_gas_temperature_out(byte* gas_data){
int temperat = gas_data[9] * 0x0100 + gas_data[8] * 0x0010 + gas_data[7];
return ((float)(-1000 + temperat)) / 10;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
float Oregon_NR::get_gas_temperature_in(byte* gas_data){
int temperat = gas_data[12] * 0x0100 + gas_data[11] * 0x0010 + gas_data[10];
return ((float)(-1000 + temperat)) / 10;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_gas_hmdty(byte* gas_data){
return gas_data[14] * 0x10 + gas_data[13];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_gas_CO(byte* gas_data){
return gas_data[6] * 0x10 + gas_data[5];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
byte Oregon_NR::get_gas_CH(byte* gas_data){
return gas_data[4] * 0x10 + gas_data[3];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Oregon_NR::led_light(bool led_on) {
if (LED != 0xFF) {
if (PULL_UP && led_on) digitalWrite(LED, LOW);
if (PULL_UP && !led_on) digitalWrite(LED, HIGH);
if (!PULL_UP && led_on) digitalWrite(LED, HIGH);
if (!PULL_UP && !led_on) digitalWrite(LED, LOW);
}
}
Пример:
#include <Oregon_NR.h>
#define WEMOS_D1
//#define UNO
#ifdef UNO
Oregon_NR oregon(2, 0, 13, false); // Для Arduino UNO/Nano - датчик на выводе D2, Прерывание 0, Светодиод приёма на вывод 13
//Oregon_NR oregon(2, 0); // Если светодиод не нужен
#endif
#ifdef WEMOS_D1
Oregon_NR oregon(4, 4, 2, true); // для Wemos D1 - датчик на выводе D4 (GPIO2), Светодиод на D2 подтянут к +пит.
#endif
void setup() {
Serial.begin(115200);
//вкючение прослушивания радиоканала
oregon.start();
}
void loop() {
//////////////////////////////////////////////////////////////////////
//Захват пакета,//////////////////////////////////////////////
oregon.capture(1);
//Захваченные данные годны до следующего вызова capture
//ОБработка полученного пакета//////////////////////////////////////////////
if (oregon.captured) {
//Вывод информации в Serial
if ((oregon.sens_type == THGN132 || oregon.sens_type == THN132) && oregon.crc_c){
Serial.print("PERIOD:\t");
Serial.print(millis()/40000);
Serial.print("\t");
if (oregon.sens_type == THGN132) for (int q = 0;q < PACKET_LENGTH - 2; q++) Serial.print(oregon.packet[q], HEX);
if (oregon.sens_type == THN132) for (int q = 0;q < PACKET_LENGTH - 4; q++) Serial.print(oregon.packet[q], HEX);
Serial.print(" TYPE: ");
if (oregon.sens_type == THGN132) Serial.print("THGN132N");
if (oregon.sens_type == THN132) Serial.print("THN132N ");
Serial.print(" CHNL: ");
Serial.print(oregon.sens_chnl);
if (oregon.sens_tmp > 0 && oregon.sens_tmp < 10) Serial.print(" TMP: ");
if (oregon.sens_tmp < 0 && oregon.sens_tmp >-10) Serial.print(" TMP: ");
if (oregon.sens_tmp <= -10) Serial.print(" TMP:");
if (oregon.sens_tmp >= 10) Serial.print(" TMP: ");
Serial.print(oregon.sens_tmp, 1);
Serial.print("C ");
if (oregon.sens_type == THGN132) {
Serial.print("HUM: ");
Serial.print(oregon.sens_hmdty, 1);
Serial.print("%");
}
Serial.print(" BAT: ");
if (oregon.sens_battery) Serial.print("F "); else Serial.print("e ");
Serial.print("ID: ");
Serial.print(oregon.sens_id, HEX);
Serial.print(" PROC. TIME: ");
Serial.print(oregon.work_time);
Serial.print("ms ");
Serial.println("");
}
}
}
Завернул свой скетч в библиотеку. Попутно всплыли некоторые весьма критические ошибки при работе с памятью. Теперь всё вроде нормально. По крайней мере, скетч по отправке данных на народмон с этой библиотекой уже неделю работает без падений. Раньше перезагружался регулярно.
Спасибо за труд. Завтра на работе буду разбираться.
Планируете ли выложить полный скетч ( экран, narodmon,…) в теме своего проекта?
Да не знаю даже что и ответить... ОБычный текст... Сохраняем в файлы любым текстовым редактором. Файлы помещаем к остальным библиртекам. У меня, например, это c:\Program Files (x86)\Arduino\libraries\Oregon_NR\
Да не знаю даже что и ответить... ОБычный текст... Сохраняем в файлы любым текстовым редактором. Файлы помещаем к остальным библиртекам. У меня, например, это c:\Program Files (x86)\Arduino\libraries\Oregon_NR\
Мой косяк, забыл в отдельную папку убрать)))
Спасибо.
Подскажите, что нужно подправить в вашей библиотеке, чтобы другие модели датчиков Oregon "ловил"?
Ну я уже говорил. Будет у меня датчик 3-ей версиии, будет и поддержка. Можно, конечно, и без датчика попробовать что-то написать, но удачный исход маловероятен.
У меня тут сейчас другая проблема. Даже не знаю, относиться она к этой теме. Железо: wemos D1, LCD2004 I2C, приёмник 433Мгц. Если Wemos не подключён к компьютеру и порт не мониторится, то прерывания от приёмника не обрабатываются! Это какой-то адский ребус. Два вечера убил, пока не понял, кто перебивает прерывание. До прописывания в скетч библиотек, связанных с дисплеем и I2C всё работало. Есть подозрения на конфликт класса Serial и библиотеки Wire.h. Никто с таким не сталкивался?
Ну я уже говорил. Будет у меня датчик 3-ей версиии, будет и поддержка. Можно, конечно, и без датчика попробовать что-то написать, но удачный исход маловероятен.
В том то и дело, что датчики второй версии не работают.
У меня тут сейчас другая проблема. Даже не знаю, относиться она к этой теме. Железо: wemos D1, LCD2004 I2C, приёмник 433Мгц. Если Wemos не подключён к компьютеру и порт не мониторится, то прерывания от приёмника не обрабатываются! Это какой-то адский ребус. Два вечера убил, пока не понял, кто перебивает прерывание. До прописывания в скетч библиотек, связанных с дисплеем и I2C всё работало. Есть подозрения на конфликт класса Serial и библиотеки Wire.h. Никто с таким не сталкивался?
Уфф. Разобрался. Сам дурак, называется. Подключил приёмник на D3 (GPIO0). А туда, оказывается, разведён вывод DTR конвертера UART-USB. Перевёл приёмник на D8. Всё заработало.
P.S. Твою так.... На D8 тоже нельзя. Случаются проблемы с запуском и программированием. Прижилось окончательно вроде на D7 (GPIO13). Половина выводов GPIO ESP8266 очень специфичны, нужно двадцать раз подумать, прежде, чем чего то туда подключать...
Можно нескромный вопрос, если у вас уверенно и хорошо работает местный код, с чего такая тяга к коду тов. Porosenok ? ;) Тем более что он не универсальный, тяжёлый, кушает сильно больше памяти...
что-то и я уже потерялся, использую уже код тов. Porosenok, 1 версию, без библиотек, вроде всё отлично работает, но вот с индикацией, nrf'кой уже упираюсь в память, поверезал половину, но всё равно, надо ещё штук добавить всяких, а места нет. Покажите ссылку на лёгкий код, а то в теме их много, какой стабильный - не ясно, я уже заблудился, помню, работал какой-то, пробовал, но нет сил ветку перечитывать заново.
зы nrf'ку использую, чтобы передавать готовую температуру на esp, которая передаёт в инет, хотел сделать всё в одном, но невозможно, тк прерывание выполняется постоянно, тк с приёмника идёт шум (я-то наивный думал, что прерывание будет раз в 40 сек (ну или чуть чаще, если в округе несколько датчиков), ан нет, всегда крутится декодер, шансов не оставляет чего-то ещё полноценно делать (мне ещё надо звонковую кнопку прослушивать и домофон).
Покажите ссылку на лёгкий код, а то в теме их много, какой стабильный - не ясно, я уже заблудился, помню, работал какой-то, пробовал, но нет сил ветку перечитывать заново.
посмотрите код в 114 посте.
Я пошел по другому пути, одна ардуина занимается погодой, вторая всем остальным в том числе и отправкой погодных данных в Blynk, ардуины соединил через Tx->Rx.
хотел сделать всё в одном, но невозможно, тк прерывание выполняется постоянно, тк с приёмника идёт шум (я-то наивный думал, что прерывание будет раз в 40 сек (ну или чуть чаще, если в округе несколько датчиков), ан нет, всегда крутится декодер, шансов не оставляет чего-то ещё полноценно делать (мне ещё надо звонковую кнопку прослушивать и домофон).
В одном флаконе собрать можно все на wemos или nodmcu. Там и памяти, хоть ложкой ешь, и процессор пободрее, все слушать успевает. У меня туда повешено прослушивание радио, пожарой сигнализации, вывод на дисплей и передача на народмон. Пока тянет.
Подумал, что в идеале надо бы и "лёгкий код" в класс завернуть и привести всё к единому интерфейсу, чтобы простой заменой "ашника" можно было выбрать тип программного декодера.
Я пошел по другому пути, одна ардуина занимается погодой, вторая всем остальным в том числе и отправкой погодных данных в Blynk, ардуины соединил через Tx->Rx.
вспомнил, тот код не поддерживает THGN132N (без G поддерживает, но надо с влажностью), вроде тут находил попроще, который поддерживал, но он с балкона ловил двтчик через раз, а код Porosenok - всегда.
вот в итоге у меня одна и занимается погодой, отправкой на esp через радиоканал и выводом на 5110 индикатор (ну чтоб уж коробочка зря не стояла, а где-то в комнате), esp принимает погоду через irf, и отправляет на narodmon, плюс в неё надо перенести функции той ардуины, что висит в прихожей (отображение погоды на улице, автооткрывание домофона, дверной звонок на разные нажатия разными мелодиями (mp3 модулем), ну и там сбор о протечке воды и датчика газа с кухни). rx-tx на esp будет занят дисплеем, опять же serial нужен и для управления mp3 проигрывателем, на ESP-12, просто выводов не хватает, для портов я поставлю расширитель через i2c, а вот с serial всё сложно.
Porosenok пишет:
класс завернуть и привести всё к единому интерфейсу, чтобы простой заменой "ашника" можно было выбрать тип программного декодера.
Вот это хорошо, я так понимаю, код уменьшится, и, если можно, возможность не использовать индикатор без лазанья в код библиотеки, тк выводов, как у меня, совсем не осталось, я убрал просто в коде, а теперь бибилиотека, хочется уже упростить вид кода, подключив бибилиотеку.
вспомнил, тот код не поддерживает THGN132N (без G поддерживает, но надо с влажностью), вроде тут находил попроще, который поддерживал, но он с балкона ловил двтчик через раз, а код Porosenok - всегда.
В вашем случае условие не выполнится, если в момент сравнения millis() вернёт не 10000, а например 10004.
Подскажите, как я могу привязаться не к запуску системы, а к часам?
У меня на LCD секунды не отображаются, и я хочу, чтобы обновление минут происходило один раз в минуту, когда секунды 00, чтобы не отвлекать ардуину слушать эфир.
В Ардуино нет часов, потому только к запуску системы.
Вместо 10000 напишите 60000 :) будет раз в минуту, это число количество миллисекунд. 1сек == 1000мс.
Но по мне всё это блаж... к примеру в моём проекте вызов отрисовки раз в секунду не влияет на приём сигналов с четырёх датчиков практически никак. Часики у меня с секундами... )
В Ардуино нет часов, потому только к запуску системы.
Вместо 10000 напишите 60000 :) будет раз в минуту, это число количество миллисекунд. 1сек == 1000мс.
Но по мне всё это блаж... к примеру в моём проекте вызов отрисовки раз в секунду не влияет на приём сигналов с четырёх датчиков практически никак. Часики у меня с секундами... )
Подскажите, а в void loop () я могу любые условия добавлять и они будут проверяться в обязательном порядке?
Вот например будет ли работать это условие:
да, любые.
да, любые.
Ясно. А с какой частотой повторяется выполнение цикла loop?
Я правильно понимаю, что я не могу приостановить выполнение только одной функции в цикле?
Если у меня в первом if стоит задержка delay(10000), то пока эта задержка не пройдёт, не будет выполняться дальше и соответственно if 2 не выполниться пока не пройдёт задержка у первого if?
Зависит от кода и частоты процессора, ну допустим миллион раз в секунду может... )
Да, будет ждать пока delay() не кончится.
Зависит от кода и частоты процессора, ну допустим миллион раз в секунду может... )
Да, будет ждать пока delay() не кончится.
Вас понял, значит моё обновление часов раз в секунду не особо тормозит приём сигнала с орегоновских датчиков?
Я точно не знаю как именно работает код приёма, но если вдруг будет плохо ловить, сдвиньте отрисовку окрана на 100-300мс...
millis()%1000 == 300
или используетй код предложенный Porosenok
Я точно не знаю как именно работает код приёма, но если вдруг будет плохо ловить, сдвиньте отрисовку окрана на 100-300мс...
millis()%1000 == 300
или используетй код предложенный Porosenok
Если использовать код от Porosenok, то при выставлении 1000, наблюдается пропуск секунд.
Ну, это потому как там "за время пути собачка успевает подрости"... и его надо чуток видоизменить, но идейно он более правильный, он срабатывает в любой момент после наступления события, а указанный выше только в конкретный момент времени, и этот момент может вообще не случиться ;) хоть и случается достаточно часто... )))
Ну, это потому как там "за время пути собачка успевает подрости"... и его надо чуток видоизменить, но идейно он более правильный, он срабатывает в любой момент после наступления события, а указанный выше только в конкретный момент времени, и этот момент может вообще не случиться ;) хоть и случается достаточно часто... )))
Вас понял.
Но случается он действительно часто. У себя пропусков не заметил, смотрел внималельно)))
Отсутствие пропусков компенсируется глуховатостью... )
Время передачи Орегон пакета в эфире где-то ~190мс, пакетов обычно два. Если ваш код успевает отработать (в смысле опросить часы реального времени, вывести это на экран, и так далее) за это время, то это даст ошибку приёма только в одном пакете, и второй будет спокойненько принят и обработан. Вероятность попасть сразу на два пакета - мала, но тоже есть.
Так что всё зависит от времени выполнения вашего кода.
У меня вот так успевает, и по радио передать на экран вывести, вставлял куда написано автором, тут и преобразования в char и обратно (иначе не догадался как на ESP передавать, разрядность что ли у нах разная, ереданный массив из INT - доходит бред, буковки доходят нормально, надо только в 128 уместиться, для этого давление вычитаю, на той стороне прибавляю), и дисплей и nrf'кой есть, но ведь тут можно хоть на 40 секунд задержаться, всё равно передача поймается.
Завернул свой скетч в библиотеку. Попутно всплыли некоторые весьма критические ошибки при работе с памятью. Теперь всё вроде нормально. По крайней мере, скетч по отправке данных на народмон с этой библиотекой уже неделю работает без падений. Раньше перезагружался регулярно.
Oregon_NR.h
Oregon_NR.cpp
Пример:
Завернул свой скетч в библиотеку. Попутно всплыли некоторые весьма критические ошибки при работе с памятью. Теперь всё вроде нормально. По крайней мере, скетч по отправке данных на народмон с этой библиотекой уже неделю работает без падений. Раньше перезагружался регулярно.
Спасибо за труд. Завтра на работе буду разбираться.
Планируете ли выложить полный скетч ( экран, narodmon,…) в теме своего проекта?
Porosenok
Подскажите, как сохранить код в библиотеку Oregon_NR.h и Oregon_NR.cpp.
Вроде в Notepad++ сохраняю как надо, а Arduino не воспринимает как библиотеку.
Да не знаю даже что и ответить... ОБычный текст... Сохраняем в файлы любым текстовым редактором. Файлы помещаем к остальным библиртекам. У меня, например, это c:\Program Files (x86)\Arduino\libraries\Oregon_NR\
Да не знаю даже что и ответить... ОБычный текст... Сохраняем в файлы любым текстовым редактором. Файлы помещаем к остальным библиртекам. У меня, например, это c:\Program Files (x86)\Arduino\libraries\Oregon_NR\
Мой косяк, забыл в отдельную папку убрать)))
Спасибо.
Подскажите, что нужно подправить в вашей библиотеке, чтобы другие модели датчиков Oregon "ловил"?
Porosenok
Жаль, что ваша библиотека только под два типа датчика((
И как её научить работать с другими датчиками Oregon не знаю.
Ну я уже говорил. Будет у меня датчик 3-ей версиии, будет и поддержка. Можно, конечно, и без датчика попробовать что-то написать, но удачный исход маловероятен.
У меня тут сейчас другая проблема. Даже не знаю, относиться она к этой теме. Железо: wemos D1, LCD2004 I2C, приёмник 433Мгц. Если Wemos не подключён к компьютеру и порт не мониторится, то прерывания от приёмника не обрабатываются! Это какой-то адский ребус. Два вечера убил, пока не понял, кто перебивает прерывание. До прописывания в скетч библиотек, связанных с дисплеем и I2C всё работало. Есть подозрения на конфликт класса Serial и библиотеки Wire.h. Никто с таким не сталкивался?
Подскажите, что нужно подправить в вашей библиотеке, чтобы другие модели датчиков Oregon "ловил"?
Да так же, как Вы и раньше это делали. Если делали, конечно...
Ну я уже говорил. Будет у меня датчик 3-ей версиии, будет и поддержка. Можно, конечно, и без датчика попробовать что-то написать, но удачный исход маловероятен.
В том то и дело, что датчики второй версии не работают.
- THGN122N
- THN132N
-RTGN318
THN132N точно должен работать. На нём проверялась библиотека. И все датчики типа 1D20h и EC40h должны работать.
THN132N точно должен работать. На нём проверялась библиотека
Приёмник на PWM 2?
Если так, то в Serial тишина, белый лист.
Это как настроите. В примере всё описано
Это как настроите. В примере всё описано
Это я понимаю, я не трогал строку.
Да, но для того, чтобы эта строка "работала", нужно определить тип устройства выше.
Да, но для того, чтобы эта строка "работала", нужно определить тип устройства выше.
Теперь ясно.
Serial ожил.
Что за датчик у вас на 1-ом канале, который показывает -4.8С 61%?
Что за датчик у вас на 1-ом канале, который показывает -4.8С 61%?
-RTGN318
Канал 1.
-RTGN318
Канал 2.
- THGN122N
Serial (несколько раз нажимал reset на датчике THGN122N, чтобы он больше засветился).
Я вижу два датчика на первом канале. На одном около -5С, на другом +25.2С
Я вижу два датчика на первом канале. На одном около -5С, на другом +25.2С
Это из самого первого serial.
Датчик на котором +25,2 это был тестовый THN132N, т.к. вы сказали, что на нём проверялась библиотека.
На работе обычно подключены только эти:
Канал 1 -RTGN318
Канал 2 - THGN122N
Сейчас первый раз появилась информация с THGN122N, она выдалась как THGN132N.
Странно, но ваш 122-датчик какое-то время выдавал бердовый заголовок с корректной температурой и CRC.
Странно, но ваш 122-датчик какое-то время выдавал бердовый заголовок с корректной температурой и CRC.
С чем это может быть связано?
Понятия не имею. Однажды наблюдал похожую вещь на одном из своих датчиков. Его даже оригинальная погодная станция не видела. Потом прошло...
Понятия не имею. Однажды наблюдал похожую вещь на одном из своих датчиков. Его даже оригинальная погодная станция не видела. Потом прошло...
Ясно.
Не могли бы вы в свою библиотеку внести мои датчики, если показания смогли с них определить?
Заранее спасибо.
Porosenok
С кодом из этого поста, датчик THGN122N работает нормально, показания приходят раз в минуту.
http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-s...
А с кодом из вашей библиотеки, в Serial данные расшифровались только один раз.
Мне почему-то кажется, что ветку мы уже сильно загадили и остальным наш диалог не особо интересен. Надо что-то менять. Перед людьми неудобно...
Мне почему-то кажется, что ветку мы уже сильно загадили и остальным наш диалог не особо интересен. Надо что-то менять. Перед людьми неудобно...
Согласен. Флуд прекращаю. Перед людьми извиняюсь.
Согласен. Флуд прекращаю. Перед людьми извиняюсь.
Если будет совсем тяжко с моей библиотекой, в скайпе я invandy, только скажите, чтобы я запросы включил...
У меня тут сейчас другая проблема. Даже не знаю, относиться она к этой теме. Железо: wemos D1, LCD2004 I2C, приёмник 433Мгц. Если Wemos не подключён к компьютеру и порт не мониторится, то прерывания от приёмника не обрабатываются! Это какой-то адский ребус. Два вечера убил, пока не понял, кто перебивает прерывание. До прописывания в скетч библиотек, связанных с дисплеем и I2C всё работало. Есть подозрения на конфликт класса Serial и библиотеки Wire.h. Никто с таким не сталкивался?
Уфф. Разобрался. Сам дурак, называется. Подключил приёмник на D3 (GPIO0). А туда, оказывается, разведён вывод DTR конвертера UART-USB. Перевёл приёмник на D8. Всё заработало.
P.S. Твою так.... На D8 тоже нельзя. Случаются проблемы с запуском и программированием. Прижилось окончательно вроде на D7 (GPIO13). Половина выводов GPIO ESP8266 очень специфичны, нужно двадцать раз подумать, прежде, чем чего то туда подключать...
Завернул свой скетч в библиотеку.
Круто, жаль нельзя вынести в шапку.
В эмуляции в шапке тоже есть бага, в постах ее нашли и поправили, но искать сложно...
Не могли бы вы в свою библиотеку внести мои датчики, если показания смогли с них определить?
Можно нескромный вопрос, если у вас уверенно и хорошо работает местный код, с чего такая тяга к коду тов. Porosenok ? ;)
Тем более что он не универсальный, тяжёлый, кушает сильно больше памяти...
Не могли бы вы в свою библиотеку внести мои датчики, если показания смогли с них определить?
Можно нескромный вопрос, если у вас уверенно и хорошо работает местный код, с чего такая тяга к коду тов. Porosenok ? ;)
Тем более что он не универсальный, тяжёлый, кушает сильно больше памяти...
Всё просто, мне понравился его проект http://arduino.ru/forum/proekty/pogodnaya-stantsiya-na-datchikakh-oregon-scientific-v21 , а со своими нулевыми знаниями я не могу сделать так же. Хотя это всё баловство))
зы nrf'ку использую, чтобы передавать готовую температуру на esp, которая передаёт в инет, хотел сделать всё в одном, но невозможно, тк прерывание выполняется постоянно, тк с приёмника идёт шум (я-то наивный думал, что прерывание будет раз в 40 сек (ну или чуть чаще, если в округе несколько датчиков), ан нет, всегда крутится декодер, шансов не оставляет чего-то ещё полноценно делать (мне ещё надо звонковую кнопку прослушивать и домофон).
Покажите ссылку на лёгкий код, а то в теме их много, какой стабильный - не ясно, я уже заблудился, помню, работал какой-то, пробовал, но нет сил ветку перечитывать заново.
посмотрите код в 114 посте.
Я пошел по другому пути, одна ардуина занимается погодой, вторая всем остальным в том числе и отправкой погодных данных в Blynk, ардуины соединил через Tx->Rx.
хотел сделать всё в одном, но невозможно, тк прерывание выполняется постоянно, тк с приёмника идёт шум (я-то наивный думал, что прерывание будет раз в 40 сек (ну или чуть чаще, если в округе несколько датчиков), ан нет, всегда крутится декодер, шансов не оставляет чего-то ещё полноценно делать (мне ещё надо звонковую кнопку прослушивать и домофон).
В одном флаконе собрать можно все на wemos или nodmcu. Там и памяти, хоть ложкой ешь, и процессор пободрее, все слушать успевает. У меня туда повешено прослушивание радио, пожарой сигнализации, вывод на дисплей и передача на народмон. Пока тянет.
Подумал, что в идеале надо бы и "лёгкий код" в класс завернуть и привести всё к единому интерфейсу, чтобы простой заменой "ашника" можно было выбрать тип программного декодера.
Я пошел по другому пути, одна ардуина занимается погодой, вторая всем остальным в том числе и отправкой погодных данных в Blynk, ардуины соединил через Tx->Rx.
вспомнил, тот код не поддерживает THGN132N (без G поддерживает, но надо с влажностью), вроде тут находил попроще, который поддерживал, но он с балкона ловил двтчик через раз, а код Porosenok - всегда.
вот в итоге у меня одна и занимается погодой, отправкой на esp через радиоканал и выводом на 5110 индикатор (ну чтоб уж коробочка зря не стояла, а где-то в комнате), esp принимает погоду через irf, и отправляет на narodmon, плюс в неё надо перенести функции той ардуины, что висит в прихожей (отображение погоды на улице, автооткрывание домофона, дверной звонок на разные нажатия разными мелодиями (mp3 модулем), ну и там сбор о протечке воды и датчика газа с кухни). rx-tx на esp будет занят дисплеем, опять же serial нужен и для управления mp3 проигрывателем, на ESP-12, просто выводов не хватает, для портов я поставлю расширитель через i2c, а вот с serial всё сложно.
вспомнил, тот код не поддерживает THGN132N (без G поддерживает, но надо с влажностью), вроде тут находил попроще, который поддерживал, но он с балкона ловил двтчик через раз, а код Porosenok - всегда.
А если этот попробовать
http://arduino.ru/forum/proekty/chtenie-i-emulyatsiya-datchikov-oregon-s...
Что такого странного в THGN132N что его не ловил код с поста #113 ?