Дмитрий МВ 0 26 августа, 2023 Опубликовано 26 августа, 2023 · Жалоба Добрый день. Хочу сделать привод для ворот. Имеется вот такой приемник и сигнал который он принимает. Микроконтроллер атмега 8. Предполагается использовать таймер для принятия сигнала, он будет отслеживать что приходит на ножку и заносить в массив, затем сохранять его и сравнивать в будущем. timer2_init{}; masive_signal[]; masive_open[]; masive_close[]; //PIND5 нога куда заведена антена //PIND2 нога записи сигнала открыть //PIND3 нога записи сигнала закрыть while(1) { int size = 10; //по сути ширина сигнала ISR(timer2_compa_vect) { int j = 0; masive_signal[j] = PIND5; j++; if(PIND2==1)//если нажата кнопка открыть { masive_open = new int ; //записываем сигнал как открыть for (int i = 0; i<size; i++) {masive_open = masive_signal;} //заносим в память EEPROM.write(0,masive_open); delet[]masive_open; } if(PIND3==1)//если нажата кнопка закрыть { masive_cloze = new int ; //записываем сигнал как открыть for (int i = 0; i<size; i++) {masive_cloze = masive_signal;} //заносим в память); EEPROM.write(1,masive_close); delet[]masive_cloze; } } if(masive_signal == masive_open) команда открыть; if(masive_signal == masive_close) комана закыть; Вот осциллограммы 1 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Дмитрий МВ 0 26 августа, 2023 Опубликовано 26 августа, 2023 · Жалоба За что минус? Ну не разобрался как код вставлять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 79 26 августа, 2023 Опубликовано 26 августа, 2023 · Жалоба Работает, определяет? Хорошо. Хотя конечно лучше декодировать сигнал в двоичную форму (0/1) на основе измеренных длительностей, а потом просто сравнивать получившийся двоичный код в виде некоего числа. Ну и в EEPROM лучше не писать каждый раз принятый сигнал. Достаточно одного раза, при "обучении" приемника. поставил + для нейтрализации. Если человек не умеет, это еще не повод его гнобить и минусовать. 5 часов назад, Дмитрий МВ сказал: if(PIND2==1)//если нажата кнопка открыть { masive_open = new int ; //записываем сигнал как открыть for (int i = 0; i<size; i++) {masive_open = masive_signal;} //заносим в память EEPROM.write(0,masive_open); delet[]masive_open; } При нажатой кнопке эти действия будут повторяться мильён раз в секунду безостановочно, до тех пор, пока кнопка остается нажатой. Нужно внести дополнительную переменную-флаг ("триггер"), которая будет устанавливаться при первом заходе в это условие и сбрасываться только при отпускании кнопки. А это условие дополнить еще одной проверкой типа if(flag == 0) , то есть, чтобы вход в эту часть кода был только при значении флага = 0, то есть только один раз. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 79 26 августа, 2023 Опубликовано 26 августа, 2023 · Жалоба В остальном, конечно же нужно учиться программированию. Потому что написана, в целом, ерунда. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vasily_ 50 26 августа, 2023 Опубликовано 26 августа, 2023 · Жалоба 5 часов назад, Дмитрий МВ сказал: Хочу сделать привод для ворот. https://vorotnet.ru/aksesuary/priemniki/radiopriemnik-vneshnij-dlya-vorot-i-shlagbaumov-furniteh-ge-rcv1 https://profipult.ru/product-category/priemniki-dlya-vorot/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 48 26 августа, 2023 Опубликовано 26 августа, 2023 · Жалоба 1 час назад, Vasily_ сказал: https://profipult.ru/product-category/priemniki-dlya-vorot/ Ну может чел. просто хочет подучить программирование, а это реле та, под руку попалось))))))))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Дмитрий МВ 0 12 сентября, 2023 Опубликовано 12 сентября, 2023 (изменено) · Жалоба извиняюсь за долгое отсутствие, долгий больничный, куча работы накопилось. вот набросок но куча варнингов, проблемы с записью и чтением из EEPROM. видимо я что то не понимаю. 10 minutes ago, Дмитрий МВ said: извиняюсь за долгое отсутствие, долгий больничный, куча работы накопилось. вот набросок но куча варнингов, проблемы с записью и чтением из EEPROM. видимо я что то не понимаю. #include <avr/io.h> #define F_CPU 1000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <avr/eeprom.h> #include "main.h" void port_ini (void) { DDRD &=~ (1<<2)|(1<<3)|(1<<5)|(1<<6); DDRD |= (1<<7); PORTD &=~ (1<<2)|(1<<3)|(1<<7); PORTD |= (1<<5)|(1<<6); DDRB &=~ (1<<0)|(1<<7); DDRB |= (1<<1); PORTB &=~ (1<<0); PORTB |= (1<<1)|(1<<7); DDRC |= (1<<2)|(1<<3)|(1<<5); PORTC &=~ (1<<2)|(1<<3)|(1<<5); } void timer_ini(void) { TCCR1A = 0x00; TCCR1B |= (1<<WGM12)// устанавливаем режим СТС (сброс по совпадению) |(1<<CS10); // делитель TCNT1 = 0x00; // Обнуляем счетный регистр OCR1A=833; // Настраиваем регистр сравнения 1000000/833=1200 //CS12 CS11 CS10 //0 0 0 нет тактирования //0 0 1 /1 //0 1 0 /8 //0 1 1 /64 //1 0 0 /256 //1 0 1 /1024 //1 1 0 External clock source on T1 pin. Clock on falling edge. //1 1 1 1 External clock source on T1 pin. Clock on rising edge. // Разрешаем прерывание таймера по совпадению с OCR1A TIMSK |= (1<<OCIE1A); } //заносим в массив входящий сигнал ISR (TIMER1_COMPA_vect) { massive_signal[i]=data_input; i++; } int main(void) { timer_ini(); port_ini(); sei(); while (1) { if (button_open) { flag_button_open; } if (button_close) { flag_button_close; } if (flag_button_open) { //копируем массив memccpy(massive_open,massive_signal,'@',10); //заносим массив в память eeprom_write_block(massive_open,0,10); flag_button_open = false; } if (flag_button_close) { memccpy(massive_close,massive_signal,'@',10); eeprom_write_block(massive_close,1,10); flag_button_close = false; } unsigned int massive_open_memories[10]; unsigned int massive_close_memories[10]; eeprom_read_block(massive_open_memories, 0,10); eeprom_read_block(massive_close_memories, 1,10); if (memcmp (massive_open_memories, massive_signal, 10) == 0) { open; } if (memcmp (massive_close_memories, massive_signal, 10) == 0) { close; } if (alarm) { stop; } } } Изменено 12 сентября, 2023 пользователем Дмитрий МВ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба Несколько замечаний. Сам алгоритм не пытался понять, чисто визуально. 1) вы не приложили main.h, в котором, подозреваю, определены переменные. В заголовочных файлах в 99% случаев нужно делать только объявления (declaration) с префиксом extern, а не определения (definition). Ваш подход приведёт к "непонятным" проблемам, если проект разрастётся до нескольких .c файлов. 2) в обработчике прерывания таймера вы записываете значения (не очень понятно, какие, ну да ладно) в массив без проверки значения 'i'. Это может закончится порчей памяти и очень странными ошибками. 3) eeprom_read_block, eeprom_write_block, memcmp в качестве последнего аргумента используют размер в байтах. 'unsigned int massive[10]' в случае AVR имеет размер 20 байт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Дмитрий МВ 0 13 сентября, 2023 Опубликовано 13 сентября, 2023 (изменено) · Жалоба 17 minutes ago, esaulenka said: Несколько замечаний. Сам алгоритм не пытался понять, чисто визуально. 1) вы не приложили main.h, в котором, подозреваю, определены переменные. В заголовочных файлах в 99% случаев нужно делать только объявления (declaration) с префиксом extern, а не определения (definition). Ваш подход приведёт к "непонятным" проблемам, если проект разрастётся до нескольких .c файлов. 2) в обработчике прерывания таймера вы записываете значения (не очень понятно, какие, ну да ладно) в массив без проверки значения 'i'. Это может закончится порчей памяти и очень странными ошибками. 3) eeprom_read_block, eeprom_write_block, memcmp в качестве последнего аргумента используют размер в байтах. 'unsigned int massive[10]' в случае AVR имеет размер 20 байт. 1) почему dec а не def? В примерах на микроконтроллер везде пишут def. 2) согласен у меня размер массива 10, нужно внести изменения 3) размер в байтах? Спасибо внесу поправку Изменено 13 сентября, 2023 пользователем Дмитрий МВ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба 24 minutes ago, Дмитрий МВ said: 1) почему dec а не def? В примерах на микроконтроллер везде пишут def. Потому что заголовочный файл может include'иться в несколько .c файлов одновременно. Ваш подход приведёт к образованию нескольких копий переменных, и благоприятный исход всего этого - линкер при компиляции выдаст ошибку (неблагоприятный - накомпилирует чёрт знает что). 24 minutes ago, Дмитрий МВ said: 3) размер в байтах? Разве не размер массива? Размер массива в байтах, в документации вполне явно написано. Ну и это не с++, компилятор не сможет узнать размер одного элемента. У вас, кстати, с этими eeprom read/write ещё одна ошибка. Надо указывать адреса так, чтобы они не перекрывались. Сейчас massive_open состоит из одного байта, принятого при открытии и "хвоста" из massive_close. Ещё одно "темное" место: if (button_open) { flag_button_open; } ... if (flag_button_open) { ... Что такое flag_button_open ? если это переменная типа bool, то что происходит в начале? И ещё. Что за магия с memccpy ? Вы точно хотите использовать это вместо обычного memcpy ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Дмитрий МВ 0 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба 8 minutes ago, esaulenka said: заголовочный файл может include'иться в несколько .c файлов одновременно Это как? На мониторе один файл .с и один .h 10 minutes ago, esaulenka said: документации вполне явно написано. Да точно, не внимательный был. 15 minutes ago, esaulenka said: У вас, кстати, с этими eeprom read/write ещё одна ошибка. Надо указывать адреса так, чтобы они не перекрывались. Сейчас massive_open состоит из одного байта, принятого при открытии и "хвоста" из massive_close. Это где так? eeprom_write_block(название массива, адрес в памяти куда записать, размер массива в байтах) 18 minutes ago, esaulenka said: Что такое flag_button_open ? если это переменная типа bool, то что происходит в начале? Да bool, вначале она объявлена значит равна нулю. 19 minutes ago, esaulenka said: if (button_open) { flag_button_open; } Здесь она приравнивается к единице. 20 minutes ago, esaulenka said: Что за магия с memccpy ? Сравнить два массива. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба 17 minutes ago, Дмитрий МВ said: Это как? На мониторе один файл .с и один .h А у меня два монитора и несколько проектов, в каждом из которых по полсотни исходных файлов. Вы уж определитесь - у вас всё хорошо, или "куча варнингов, проблемы, я не понимаю". 20 minutes ago, Дмитрий МВ said: Здесь она приравнивается к единице. "приравнивается к единице" записывается как "var = 1;", а тут, с высокой вероятностью, написана ерунда. 26 minutes ago, Дмитрий МВ said: Это где так? eeprom_write_block(название массива, адрес в памяти куда записать, размер массива в байтах) В вашем коде ДВА вызова eeprom_write_block. Найдите оба и сравните адреса, которые вы туда передаёте. 21 minutes ago, Дмитрий МВ said: 41 minutes ago, esaulenka said: Что за магия с memccpy ? Сравнить два массива. Ну ок. Вы даже читать не пытаетесь. Вопросов больше не имею. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 79 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба Цитата if (button_open) { flag_button_open; } Неясно, что такое flag_button_open. Если это переменная, вы должны явно написать flag_button_open = 1; или flag_button_open = true; 17 часов назад, Дмитрий МВ сказал: но куча варнингов, Какого рода они, что написано, на что указывают? Полагаю, что как минимум, на flag_button_open без правой части - пишется statement has no effect - выражение не имеет эффекта. В операторе if() можно не указывать явно, чему равен flag_button_open, поскольку любое значение, отличное от нуля, будет истинным (true). А в других случаях нужно явно указывать, какое значение будет присвоено переменной. То есть, обязательна как левая, так и правая (после знака = ) часть выражения. Ну и я уже выше писал - логика работы должна быть триггерной, то есть: if(button_open && !flag_button_open) // если нажата кнопка и нет флага триггера { flag_button_open = true; // установить триггер // Выполнить открытие двери } if(!button_open) // если кнопка отпущена { flag_button_open = false; // сбросить триггер } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 79 14 сентября, 2023 Опубликовано 14 сентября, 2023 · Жалоба Вообще, если это приемник, то тогда зачем в нем нужна обработка кнопок? Разве что это дополнительные кнопки местного открывания изнутри. В целом, программа может выглядеть следующим образом: bool isReceiveCommlete; // флаг завершения приема пакета #define NUM_TEMPL_PACKS 3 // число известных шаблонов пакета #define NUM_ELEM_IN_PACK 5 // число элементов в пакете bool templates[NUM_TEMPL_PACKS][NUM_ELEM_IN_PACK] = {{0, 0, 0, 0, 1}, {0, 1, 0, 1, 0}, {1, 0, 0, 0, 1}}; // массив шаблонов пакета bool receivePacket[NUM_ELEM_IN_PACK]; // буфер для приема пакета /** * Инит хардвара (аппаратных модулей) */ void HardwareInit() { // Аппаратные модули инициализованы и настроены } /** * @brief Сравнение принятого пакета с известными шаблонами. * @return Номер шаблона, которому соответствует принятый пакет, * либо, если соответствие не найдено, значение, большее чем * число пакетов */ int CompareReceivePacet() { int id = 0; /* Сравнение принятого пакета с одним из шаблонов: * повторять инкремент id (номера шаблона) до тех пор, пока * не будет найден совпадающий или не проверятся все шаблоны */ while((memcmp(receivePacket, templates[id], sizeof(receivePacket))) && (id < NUM_TEMPL_PACKS)) { id++; } return id; } /** * @brief */ int main(void) { /* Инициализация аппаратных модулей */ HardwareInit(); /* Основной цикл работы */ while(true) { // Если завершен прием полного пакета по радиоканалу, if(isReceiveCommlete) { // ...сравнить полученный пакет с набором шаблонов // и выполнить соответствующее действие switch(CompareReceivePacet()) { case 0: // команда "Стоп!", остановить дверь break; case 1: // команда "Открыть дверь", выполнить открытие break; case 2: // команда "Закрыть дверь", выполнить закрытие break; default: // Неизвестная команда, ничего не делать break; } isReceiveCommlete = false; // сбросить флаг принятого пакета } } } Запись в EEPROM не нужна, я ж уже ранее писал - это лишние действия. Вам нужно просто посмотреть лог. анализатором все принимаемые пакеты, декодировать их по длительностям уровней и внести шаблоны в таблицу в виде последовательностей единиц и нулей. Декодировать пакета можно делать, изменяя интервалы между изменениями уровня сигнала и определяя, в какой диапазон они попадают. Исходя из этого, присваивать 0 или 1 очередному биту в пакете. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 14 сентября, 2023 Опубликовано 14 сентября, 2023 · Жалоба 3 hours ago, EdgeAligned said: Вообще, если это приемник, то тогда зачем в нем нужна обработка кнопок? Мой хрустальный шар подсказывает, что это кнопки для "запоминания" магической последовательности, и пользователь их должен нажимать примерно один раз в жизни устройства - когда меняет пульт. Насколько это надёжно работает - я не знаю. Скорее всего, не очень. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться