Respect!
Я свой стаж считаю с 1982, когда я закончил факультет прикладной математики ВГУ.
Respect!
Если для коммерческого использования, то да. Но тогда нужно не Arduino, а Atmega в самом маленьком корпусе (если речь об AVR).roman.com писал(а): Пн июн 22, 2026 16:02:02 По теме.
Нужно малогабаритные устройство.
Чтобы можно было вмонтировать в дверной проем. Точно так же как простой дверной замок.
Отметили.
Просверлили.
Установили.
Угу. Мы видим эти "40 с лишним лет"Massaraksh7 писал(а): Пн июн 22, 2026 15:32:55 . У автора за спиной 40 с лишним лет программирования.
Я писал по теме - автор не понял написанного в силу плохого владения языком программирования. И теперь обвиняет в этом меняroman.com писал(а): Пн июн 22, 2026 16:02:02 Я заметил на этом сайте пишут про все что угодно но только не по теме...
Тоже - 40 лет??? Мдааа... А чеж до сих пор в трех березах то не разобрались?
А это тема про замки чтоль? Почему картинки врезного замка то показываете?
Если имеются в виду три березы другой ветки, то:Rapra писал(а): Пн июн 22, 2026 16:53:41 Тоже - 40 лет??? Мдааа... А чеж до сих пор в трех березах то не разобрались?
Эту я прочитал в самом начале, середину большей частью пропустил (сложно читать всё, особенно с картинками каких-то замков). Причины особенности конструкции были автором объяснены. Потом глянул, что всё успешно. А потом, зайдя уже от скуки, увидел, что автор, оказывается, всё сделал плохо, но не увидел, почему.Rapra писал(а): Пн июн 22, 2026 17:11:37 Не знаю, про какую соседнюю ветку речь, но я говорю именно об этой ветке.
А вот что, имея "40 лет опыта за плечами" - так сложно чтоль не копипастить, а написать именно подходящую к конкретному проекту версию? Объем работы - несколько строчек.Zapolyarny писал(а): Пн июн 22, 2026 17:19:03 Посегментное могло прийти из другого проекта, где оно было актуально.
А это уже другой алгоритм. Потому что ноги у человека две. И сенсор может зафиксировать две ноги, одну или ни одной, в зависимости от случайной постановки ног при шаге
Посмотрел. Так же глянул и Ваши замечания.Rapra писал(а): Пн июн 22, 2026 17:22:21 Ну так если у вас так же "40 лет опыта программирования" - просто посмотрите код. Ардуиновские функции типа digitalWrite можно не читать.
0x04 и 1 << 2 - где здесь увеличение листинга? К тому же, запись 1 << 2 логически показывает, что это позиция бита, а не какое-то число.
Вовсе нет. Они отличаются только объемом кода и/или сложностью задачи. А вот говнокод от "кода здорового человека" как раз и отличается тем, что рассматривается в этой теме.
Хорошо, когда ничего не надо менять. А вот у топикстартера сейчас начнутся изменения из-за нового места установки датчиков.Zapolyarny писал(а): Пн июн 22, 2026 17:44:09 Работает? Работает. (... "тогда ничего не трогай и не меняй!")
вот я написал на днях (тоже работа с индикатором и подсчёт):
Код: Выделить всё
// Получение сегментов соответственно цифрам:
uint8_t seg3 = Segments[d3];
uint8_t seg2 = Segments[d2];
uint8_t seg1 = Segments[d1];
// Добавление точки к нужному разряду:
#ifdef DISPLAY_COMMON_CATHODE
if (dot == 2) seg3 |= 0x02;
if (dot == 1) seg2 |= 0x02;
if (dot == 0) seg1 |= 0x02;
#else
if (dot == 2) seg3 &= ~0x02;
if (dot == 1) seg2 &= ~0x02;
if (dot == 0) seg1 &= ~0x02;
#endif
// Обновление массива дисплея новыми данными:
cli();
display[pos + 2] = seg1;
display[pos + 1] = seg2;
display[pos + 0] = seg3;
sei();Код: Выделить всё
// Обновление буфера дисплея новыми данными из массива сегментов;
//добавление точки, если разряд совпадает:
cli();
#ifdef DISPLAY_COMMON_CATHODE
display[pos + 2] = Segments[d1] | ((dot == 0) << 1);
display[pos + 1] = Segments[d2] | ((dot == 1) << 1);
display[pos + 0] = Segments[d3] | ((dot == 2) << 1);
#else
display[pos + 2] = Segments[d1] & ~((dot == 0) << 1);
display[pos + 1] = Segments[d2] & ~((dot == 1) << 1);
display[pos + 0] = Segments[d3] & ~((dot == 2) << 1);
#endif
sei();А вот для возможности перепиновки индикатора - очень даже нужно. То есть, если сегменты по пинам распределены не последовательно. Это может быть необходимо для разводки платы.
Так это связано. Тогда время прерывания таймера0 делаем 30мкс, и в обработчике по каждому прерыванию генерируем меандр, скажем, на на ноге D7, которую подключаем к IR-светодиоду + резистор (номинал?) + на землю. А в каждом 10 прерывании занимаемся обработкой, как было.roman.com писал(а): Пн июн 22, 2026 19:12:35 Рано вы занялись кодом. У вас ещё схемы нормальной нет.
Сначала передатчик подключите к мк.
А для этого один таймер освободите.
Значит, во всех бытовых устройствах пульты работают от случая к случаю. Кому как повезёт.roman.com писал(а): Пн июн 22, 2026 21:42:16 и не настолько мощного чтобы приёмник ловил отраженный сигнал от стен и других посторонних объектов ))
Зачем? В подобной задаче достаточно вообще одного таймера на всё. Или даже ноль таймеров.roman.com писал(а): Пн июн 22, 2026 21:42:16 Таймер... Я бы выделил отдельный таймер для передатчика.
Да без проблем.roman.com писал(а): Пн июн 22, 2026 21:42:16 Таймер... Я бы выделил отдельный таймер для передатчика. А программу бы всю переписал ))
Код: Выделить всё
//
// Shirokov V.V. aka Massaraksh7, 23.06.2026
//
#define IN1 2
#define IN2 3
#define FIRE 4
#define FB1 5
#define FB2 6
#define IR 7
#define R_WAIT 0
#define R_DIR 1
#define R_BACK 2
#define R_DO_DIR 3
#define R_DO_BACK 4
#define MAX_VIS 3 //---Максимальное число посетителей
#define DEL 700
byte count,rate,gen;
volatile byte sign1,sign2; //---Сигнал 0 или 1
volatile byte imp1,imp2; //---Число импульсов
volatile int tim0; //---счётчик основного цикла
//---Прочитать состояние входов
void ReadSignals() {
if (imp1<3) sign1=1; else sign1=0; imp1=0;
if (imp2<3) sign2=1; else sign2=0; imp2=0;
if (sign1==0) digitalWrite(FB1,LOW); else digitalWrite(FB1,HIGH);
if (sign2==0) digitalWrite(FB2,LOW); else digitalWrite(FB2,HIGH);
}
//---Подключить нагрузку
void fireON() {
digitalWrite(FIRE,HIGH);
}
//---Отключить нагрузку
void fireOFF() {
digitalWrite(FIRE,LOW);
}
//---Прерывание по переднему фронту 1 канала
void cannal_1() {
imp1++;
}
//---Прерывание по переднему фронту 2 канала
void cannal_2() {
imp2++;
}
//---1 мс - основной цикл
void startTimer0() {
cli();
TCCR0A = 0;
TCCR0B = 0;
TCNT0 = 0;
TCCR0A |= (1 << WGM01);
TCCR0B |= (1 << CS01) | (1 << CS00);
OCR0A = 249;
TIMSK0 |= (1 << OCIE0A);
sei();
}
//---25 мкс - генератор
void startTimer1() {
cli(); // Отключаем прерывания на время настройки
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11) | (1 << CS10);
OCR1A = 399;
TIMSK1 |= (1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect) {
if (gen==0) digitalWrite(IR,LOW); else digitalWrite(IR,HIGH);
gen=1-gen;
}
//---Инициализация
void setup() {
pinMode(IN1,INPUT);pinMode(IN2,INPUT);
pinMode(FIRE,OUTPUT);pinMode(FB1,OUTPUT);pinMode(FB2,OUTPUT);
pinMode(IR,OUTPUT);
digitalWrite(FIRE,LOW);digitalWrite(FB1,LOW);digitalWrite(FB2,LOW);
count=0;rate=R_WAIT;
sign1=1;sign2=1;gen=0;
//---Запустить таймеры
tim0=1;imp1=0;imp2=0;
startTimer0();
startTimer1();
//---Запустить внешние прерывания
attachInterrupt(digitalPinToInterrupt(IN1),cannal_1,RISING);
attachInterrupt(digitalPinToInterrupt(IN2),cannal_2,RISING);
}
//---Основной цикл по таймеру 0
ISR(TIMER0_COMPA_vect) {
tim0--;if (tim0!=0) return;
tim0=1;
if (rate==R_WAIT) //---Режим ожидания основной
{
ReadSignals();
if (sign1==0 && sign2==1){rate=R_BACK;return;}
if (sign1==1 && sign2==0){rate=R_DIR;return;}
return;
}
if (rate==R_DIR) //---Режим возможного пересечения вперёд
{
ReadSignals();
if (sign1==0 && sign2==0){rate=R_WAIT;return;}
if (sign1==1 && sign2==1){rate=R_DO_DIR;return;}
return;
}
if (rate==R_BACK) //---Режим возможного пересечения назад
{
ReadSignals();
if (sign1==0 && sign2==0){rate=R_WAIT;return;}
if (sign1==1 && sign2==1){rate=R_DO_BACK;return;}
return;
}
if (rate==R_DO_DIR) //---Точно пересечение вперёд
{
if (count<MAX_VIS) count++;
if (count==1) fireON();
tim0=DEL;
rate=R_WAIT;
return;
}
if (rate==R_DO_BACK) //---Точно пересечение назад
{
if (count>0) count--;
if (count==0) fireOFF();
tim0=DEL;
rate=R_WAIT;
return;
}
}
void loop() {
while (0==0) {};
}