Вот продолжение проектирование программы.Но там еще куча нюансов полезло. Так например надо сбрасывать кнопкой не только звук зуммера, но и взод датчиков сеялки
И это я еще не начал писать код и просто вырабатываю структуру программы и уточняю ТЗ
ПС: А еще для решения задачи банально не хватает пинов. И надо переходить на Мегу или аппаратно расширять количество ног. В последнем случае придется писать класс посредник.
Про экран, табло и прочее думал. Если бы лично я сеял, то без раздумий бы сделал выход на LSD экран, или табо. Но трактором я уже не кправляю, а нанимаю тракториста. В большинстве своем они уже пожилого возраста, плохо видят близко, да и тяжеловато им электроника дается. Поэтому решил сделать все просто и сердито. Тракторист сеет, у него все внимаение вперед на гон, запищал зуммер!!!!!!, он глянул на светодиод и порядковый номер - остановился для устранения причин.
Откулючать зуммер я не намерен, он будет пищать - пока проблема не будет устранена или не выключена система. Единственное подумываю о регуляторе громкости.
Зная психологию трактористов - это сделано специально, так как если он попищит да перестанет, тракторист будет устранять проблему только на конце гона или на заправке семенами - проходили через это.
Откулючать зуммер я не намерен, он будет пищать - пока проблема не будет устранена или не выключена система. Единственное подумываю о регуляторе громкости.
Вот попробуем представить . Вы тракторист. Запищало. Тракторист глянул.Остановил трактор. Влез, прочистил. Но как система узнает что там чисто. И как тракторист узнает, система узнала, что там чисто. Где находится система. Ведь место тракториста и сопло на чистке это разные места. Вы думаете что пожилой тракторист будет бегать в кабину и на место чистки . Опять же если трактор стоит, он не сеит. Но система работает. А зерна нет. Значит система думает, что все сопла забиты. А раз все сопла забиты, то звенеть и чистить сопла.
А так человек почистил, зумер звенит,сел завел трактор , поехал, сделал сброс системы . И дальше сеит.
Модуль будет находится по правую руку механизатора. Расстояние от модуля до датчиков примерно 3 метра. Модуль прекрасно виден через заднее стекло от датчиков. Да и в любом месте его можо воткнуть, вся кабина прекрасно наблюдается снаружи. В механичеких сеялках привод высева идет от колеса сеялки. Зерно будет сыпаться только во время движения. Для визуального контроля сыпи семян, сеялка приподымается гидравликой в транспортное положение, при полном поднятии на 30 см от земли приводные колеса оторваны от земли, тракторист рукой делает оборот колеса и все прекрасно видно где сыпится где нет.
И так я тракторист .
1 вариант забился семяпровод, загорелся красный светодиод. Запищало. Остановился. Сеялка перестала работать, зерно не сыпется. Загорелось дополнительно 16 желтых светодиодов красный горит один. Я подымаю гидравликой сеялку, так как засор 90%% в лапе. Я устранил причину затора, зерно высыпалось из семяпровода на землю - датчик не получает сигнал, красный погас.Зуммер пищит, так как горят желтые.Моем руки, Садимся в кабину - тронулся, пошел поток зерна, желтые светодиоды сразу гаснут после первого зернышка. Зуммер затух. В моей криворуко чайниковской версии алгоритма на эмуляторе все так и происходит. При желании можно крутануть приводное колесо блок сразу весь затухнет.
2 вариант затор в бункере перед высевающим аппаратом. Зерно перестало сыпаться через датчик, загорелся желтый имнно того высевающего аппарата где нет потока семян, запищал зуммер. Запомнил номер высевающего. СТоп машина! Устраняем причину засора в нужном высевающем. Прокручиваем приводное колесо, смотрим на блок, можно и слушать, если открыть боковое окно. ВИзуально наблюдаем сыпь семян в нужном отсеке, отсутствие сигнала на блоке. Моем руки, садимя в кабину и сеем дальше.
В моем кривом алгоритме нет ни каких сбросов. В эмуляторе все работает и без них. Есть сыпь - молчим, нет сигнала - желтый, непрерывный сигнал красный.
В алгоритм проверки датчика не стал углубляться, так как не понял как один датчик отслеживает два засора.
Набросал скетч с двумя наборами датчиков (RED и YELLOW), пины и прочее объединил в массивы:
arduinec У ТС один датчик на сопло- зерносып . Просто желтый загорается если перестало сыпаться, а красный если перестало сыпаться через 1 секунду. Зумер если загорелся хоть один ЖЕЛТЫЙ !!!!. Правильно или неправильно это кто его знает. Этот проект надо создавать лично, а не со слов на форуме.
arduinec У ТС один датчик на сопло- зерносып . Просто желтый загорается если перестало сыпаться, а красный если перестало сыпаться через 1 секунду. Зумер если загорелся хоть один ЖЕЛТЫЙ !!!!. Правильно или неправильно это кто его знает. Этот проект надо создавать лично, а не со слов на форуме.
немного не так.
Датчик один в сопло зерносыпе (воронке). - Верно
Желтый загорается если перестало сыпаться, нес сингнала к примеру 3 секунды - Верно
Красный загорается, если сопло наполнилось зерном и закрыло сам датчик, и он подает непрерывный с сигнал.
В рабочем состоянии датчик производит примерно 150 в секунду - по количеству пролетающих зерен. + - может что-то пропуститью
Пищалка срабатывает в обеих случаях, хоть при загорании красного, хоть желтого светодиода.
Смоделируем ситуацию: человек работае загорелсяк примеру 5й - водитель (запомнил не запомнил)остановился а у него все горит, или пока вылез взял ключи, кто то отвлек, (опять забыл), сами же пишете что люди пожылые.
Решение: установить кнопку на коробку передач - передачу включили кн-вк. выключили кн-вык. в прграме записать что только при включеной кнопке (тоесть при движении) делать проверку.
Выгода: 1) При остановке будет гореть только поломка.
2) Если все нормально и человек остановился на перекур - ничего не пищит
2) Вы как роботодатель можете в любое время остановить и проверит - не халурит ли он
Водила будет всегда халтурить, а поэтому надо прикрутить GSM модуль и слать либо смс либо че мелочиться сразу на сервер пакеты о состоянии системы в релтайм
ну или хотябы карту памяти прилепить с записью логов, что бы потом с водилы бабок за лень содрать.
а еще можно GPS модуль прикрутить чтобы мониторить когда стоит и откключать мониторинг , заодно и скорость конролировать и по превышению тлже штрафовать, да и если слишком медленно также лишать премии.
Смоделируем ситуацию: человек работае загорелсяк примеру 5й - водитель (запомнил не запомнил)остановился а у него все горит, или пока вылез взял ключи, кто то отвлек, (опять забыл), сами же пишете что люди пожылые.
Решение: установить кнопку на коробку передач - передачу включили кн-вк. выключили кн-вык. в прграме записать что только при включеной кнопке (тоесть при движении) делать проверку.
Выгода: 1) При остановке будет гореть только поломка.
2) Если все нормально и человек остановился на перекур - ничего не пищит
2) Вы как роботодатель можете в любое время остановить и проверит - не халурит ли он
ВОдитель остановился, загорятся только желтые. После остановки по любой причине водитель поднимает комплекс, чтобы вывести из зацепления с почвой (при трогании сцепление меньше палишь). Если он забыл № Первым делом он крутанет приводное колесо и визуально все и сразу увидит и показания датчика и реальное положение дел.
Идея правильная, но думаю на первый сезон надо сделать проще некуда, а на следующий год доработать имеющиеся неджочеты.
Датчиков и диодов у Вас МНОГО, на обработку каждого - необходимо какоето время, для того чтобы сократить время обработки ГУРУ советуют работать с портами на прямую. Вот пример на три датчика
// Датчики 8-9-10
// Светодиод Желтый = 2, 4, 6
// Светодиод Красный = 3, 5, 7
uint8_t dat_portB;
uint8_t temp_portB;
uint8_t rezult_portB;
uint8_t zumer;
void setup(){
DDRB = B00000000; // PORTB, подключенный- как выход,
DDRD = DDRD | B11111100; // PORTD, подключенный как выход 0й и 1й не трогаем
}
//Переменные функции паузы или дребезга, с разным временем опроса
unsigned long currentPause[16]; //массив данных. Количество элементов - количеству таймеров
bool fl_pause[16];//массив данных. Количество элементов - количеству таймеров
//Функция дребезга или паузы (time-время задержки, nomer-номер таймера)
boolean my_pausa(unsigned long time, byte nomer){
bool x = 0;
if (fl_pause[nomer] == 0)currentPause[nomer] = millis(), fl_pause[nomer] = 1;
if (millis() - currentPause[nomer] >= time) x = 1, fl_pause[nomer] = 0;
return x;
}
void loop(){
static uint8_t j;
dat_portB = PINB;
rezult_portB = dat_portB ^ temp_portB;
temp_portB = dat_portB;
zumer = PIND; // Проверяем порт если диоды не горят
if(!zumer) PORTB &= ~(1<<5); // Звук выключаем
else PORTB |= (1<<5); // Звук включаем
for(uint8_t i=0;i<3;i++)
{
if(!i) j=2;
else j+=2;
if (rezult_portB & (1 << i)){ // Если все нормально
fl_pause[i] = 0; //Сброс таймера
PORTD &= ~(1<<j); // Выключаем желтый
PORTD &= ~(1<<(j+1)); // Выключаем красный
}
else{ //Чтото пошло не так!!!
if (dat_portB & (1 << i)){
if (my_pausa(1000, i))PORTD |= (1<<j); // Включаем желтый
}
if (~(dat_portB) & (1 << i)){
if (my_pausa(500, i))PORTD |= (1<<(j+1)); // Включаем красный
}
}
}
}
Вот продолжение проектирование программы.Но там еще куча нюансов полезло. Так например надо сбрасывать кнопкой не только звук зуммера, но и взод датчиков сеялки
/*зерносеялка*/ unsigned long mill; // переменная под millis() typedef (*pDo)();// тип - обработчик //-------------------------------- // класс зуммер class Cl_Zoomer { protected: byte pin; /*пин зуммера*/ public: /*конструктор*/ Cl_Zoomer(byte p): pin(p) {} /*инициализация*/ void init() {} /*работа*/ void run() {} /*вкл*/ void ON() {} /*выкл*/ void OFF() {} }; //------------------------------ // класс сопло сеялки class Cl_DrillNozzle { protected: pDo Do; byte pin1, pin2, pin3; /*пины красный,желтой,датчика*/ public: /*конструктор*/ Cl_DrillNozzle(byte p1, byte p2, byte p3, pDo D) : pin1(p1), pin2(p2), pin3(p3), Do(D) {} /*инициализация*/ void init() {} /*работа*/ void run() {} }; //----------------------------------- // класс кнопкa class Cl_Btn { protected: byte pin; /*кнопки*/ pDo Do; public: /*конструктор*/ Cl_Btn(byte p, pDo D) : pin(p), Do(D) {} /*инициализация*/ void init() {} /*работа*/ void run() {} }; //---Компоновка----------------------------- Cl_Zoomer Zoomer(/*пин зуммера*/10); void DoDR() { Zoomer.ON(); } Cl_DrillNozzle DR1(/*пин красный*/6,/*пин желтый*/A0,/*датчик*/2,/*обработчик аварии*/& DoDR); Cl_DrillNozzle DR2(/*пин красный*/7,/*пин желтый*/A1,/*датчик*/3,/*обработчик аварии*/& DoDR); Cl_DrillNozzle DR3(/*пин красный*/8,/*пин желтый*/A2,/*датчик*/4,/*обработчик аварии*/& DoDR); Cl_DrillNozzle DR4(/*пин красный*/9,/*пин желтый*/A3,/*датчик*/5,/*обработчик аварии*/& DoDR); void DoBtn1() { Zoomer.OFF(); } Cl_Btn Btn1(/*пин кнопки*/11,/**/&DoBtn1); //---main----------------------------- void setup() { Zoomer.init(); DR1.init(); DR2.init(); DR3.init(); DR4.init(); Btn1.init(); } void loop() { mill = millis(); Zoomer.run(); DR1.run(); DR2.run(); DR3.run(); DR4.run(); Btn1.run(); } /*Скетч использует 630 байт (2%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 37 байт (1%) динамической памяти, оставляя 2011 байт для локальных переменных. Максимум: 2048 байт. */И это я еще не начал писать код и просто вырабатываю структуру программы и уточняю ТЗ
ПС: А еще для решения задачи банально не хватает пинов. И надо переходить на Мегу или аппаратно расширять количество ног. В последнем случае придется писать класс посредник.
Доброго вечера!
Про экран, табло и прочее думал. Если бы лично я сеял, то без раздумий бы сделал выход на LSD экран, или табо. Но трактором я уже не кправляю, а нанимаю тракториста. В большинстве своем они уже пожилого возраста, плохо видят близко, да и тяжеловато им электроника дается. Поэтому решил сделать все просто и сердито. Тракторист сеет, у него все внимаение вперед на гон, запищал зуммер!!!!!!, он глянул на светодиод и порядковый номер - остановился для устранения причин.
Откулючать зуммер я не намерен, он будет пищать - пока проблема не будет устранена или не выключена система. Единственное подумываю о регуляторе громкости.
Зная психологию трактористов - это сделано специально, так как если он попищит да перестанет, тракторист будет устранять проблему только на конце гона или на заправке семенами - проходили через это.
Оффтоп
LSD экран
Такой можно программировать? Я думал это случайный неконтролируемый процесс
Вот попробуем представить . Вы тракторист. Запищало. Тракторист глянул.Остановил трактор. Влез, прочистил. Но как система узнает что там чисто. И как тракторист узнает, система узнала, что там чисто. Где находится система. Ведь место тракториста и сопло на чистке это разные места. Вы думаете что пожилой тракторист будет бегать в кабину и на место чистки . Опять же если трактор стоит, он не сеит. Но система работает. А зерна нет. Значит система думает, что все сопла забиты. А раз все сопла забиты, то звенеть и чистить сопла.
А так человек почистил, зумер звенит,сел завел трактор , поехал, сделал сброс системы . И дальше сеит.
А так человек почистил, зумер звенит,сел завел трактор , поехал, сделал сброс системы . И дальше сеит.
В предложеном мной коде сброс происходит автоматически - поехал - семена покатились и все потухло, система вошла в рабочее состояние!
Вот мой комплекс - один в один.
Модуль будет находится по правую руку механизатора. Расстояние от модуля до датчиков примерно 3 метра. Модуль прекрасно виден через заднее стекло от датчиков. Да и в любом месте его можо воткнуть, вся кабина прекрасно наблюдается снаружи. В механичеких сеялках привод высева идет от колеса сеялки. Зерно будет сыпаться только во время движения. Для визуального контроля сыпи семян, сеялка приподымается гидравликой в транспортное положение, при полном поднятии на 30 см от земли приводные колеса оторваны от земли, тракторист рукой делает оборот колеса и все прекрасно видно где сыпится где нет.
И так я тракторист .
1 вариант забился семяпровод, загорелся красный светодиод. Запищало. Остановился. Сеялка перестала работать, зерно не сыпется. Загорелось дополнительно 16 желтых светодиодов красный горит один. Я подымаю гидравликой сеялку, так как засор 90%% в лапе. Я устранил причину затора, зерно высыпалось из семяпровода на землю - датчик не получает сигнал, красный погас.Зуммер пищит, так как горят желтые.Моем руки, Садимся в кабину - тронулся, пошел поток зерна, желтые светодиоды сразу гаснут после первого зернышка. Зуммер затух. В моей криворуко чайниковской версии алгоритма на эмуляторе все так и происходит. При желании можно крутануть приводное колесо блок сразу весь затухнет.
2 вариант затор в бункере перед высевающим аппаратом. Зерно перестало сыпаться через датчик, загорелся желтый имнно того высевающего аппарата где нет потока семян, запищал зуммер. Запомнил номер высевающего. СТоп машина! Устраняем причину засора в нужном высевающем. Прокручиваем приводное колесо, смотрим на блок, можно и слушать, если открыть боковое окно. ВИзуально наблюдаем сыпь семян в нужном отсеке, отсутствие сигнала на блоке. Моем руки, садимя в кабину и сеем дальше.
В моем кривом алгоритме нет ни каких сбросов. В эмуляторе все работает и без них. Есть сыпь - молчим, нет сигнала - желтый, непрерывный сигнал красный.
Ну где то так. Скетч не проверял. Может где-то что надо подправить.
/*зерносеялка*/ unsigned long mill; // переменная под millis() //-------------------------------- // класс зуммер class Cl_Zoomer { protected: byte pin; /*пин зуммера*/ public: /*конструктор*/ Cl_Zoomer(byte p): pin(p) {} /*инициализация*/ void init() {} /*вкл*/ void ON() { tone(pin, 262); } /*выкл*/ void OFF() { noTone(pin); } /*работа*/ void run() {} }; //------------------------------ // класс сопло сеялки const unsigned long MINTIMEHIGH = 1000;// время сработки class Cl_DrillNozzle { protected: Cl_Zoomer Zoomer; byte redPin, yellowPin, sensPin; /*пины красный,желтой,датчика*/ unsigned long past; byte state ; // 0 - идет поток / 1 временно пропал / 2 совсем пропал /*установить в состояние*/ void stand(byte s) { state = s; past = mill; switch (state) { case 0:/* идут семена*/ digitalWrite(yellowPin, 0); digitalWrite(redPin, 0); Zoomer.OFF(); break; case 1:/*пропали семена*/ digitalWrite(yellowPin, 1); Zoomer.ON(); break; case 2:/*долго нет семян*/ digitalWrite(redPin, 1); break; } } public: /*конструктор*/ Cl_DrillNozzle(byte p1, byte p2, byte p3, Cl_Zoomer &Z) : redPin(p1), yellowPin(p2), sensPin(p3), Zoomer(Z) {} /*инициализация*/ void init() { pinMode(redPin, OUTPUT); pinMode(yellowPin, OUTPUT); pinMode(sensPin, INPUT); stand(0); } /*работа*/ void run() { bool value = digitalRead(sensPin);/*0 - нет семян /1 есть*/ if (state != 0 && value == 1) {// если посыпались семена stand(0); } if (state == 0 && value == 0) {// если пропали семена stand(1); } if (state == 1 && value == 0 && mill - past > MINTIMEHIGH) { // если пропали семена надолго stand(2); } } }; //---Компоновка----------------------------- Cl_Zoomer Zoomer(/*пин зуммера*/10); Cl_DrillNozzle DR1(/*пин красный*/6,/*пин желтый*/A0,/*датчик*/2,/*зуммер*/Zoomer); Cl_DrillNozzle DR2(/*пин красный*/7,/*пин желтый*/A1,/*датчик*/3,/*зуммер*/Zoomer); Cl_DrillNozzle DR3(/*пин красный*/8,/*пин желтый*/A2,/*датчик*/4,/*зуммер*/Zoomer); Cl_DrillNozzle DR4(/*пин красный*/9,/*пин желтый*/A3,/*датчик*/5,/*зуммер*/Zoomer); //---main----------------------------- void setup() { Zoomer.init(); DR1.init(); DR2.init(); DR3.init(); DR4.init(); } void loop() { mill = millis(); Zoomer.run(); DR1.run(); DR2.run(); DR3.run(); DR4.run(); } /*Скетч использует 2206 байт (7%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 73 байт (3%) динамической памяти, оставляя 1975 байт для локальных переменных. Максимум: 2048 байт. */"Хлеб - Родине!" (из лозунгов СССР)
В алгоритм проверки датчика не стал углубляться, так как не понял как один датчик отслеживает два засора.
Набросал скетч с двумя наборами датчиков (RED и YELLOW), пины и прочее объединил в массивы:
#define NUM_D 4 // количество датчиков #define PIN_ZUM 9 // пин зуммера byte pin_datchik_red[NUM_D] = {11, 12, 13, 14}; // пины датчиков RED byte pin_datchik_yel[NUM_D] = {15, 16, 17, 18}; // пины датчиков YEL byte pin_led_red[NUM_D] = {21, 22, 23, 24}; // пины светодиодов RED byte pin_led_yel[NUM_D] = {25, 26, 27, 28}; // пины светодиодов YEL byte zator_red[NUM_D], zator_yel[NUM_D]; // запоминание заторов byte sum_red, sum_yel; // для запуска зуммера int i; void setup() { for(i=0; i<NUM_D; i++) pinMode(pin_datchik_red[i], INPUT); for(i=0; i<NUM_D; i++) pinMode(pin_datchik_yel[i], INPUT); for(i=0; i<NUM_D; i++) pinMode(pin_led_red[i], OUTPUT); for(i=0; i<NUM_D; i++) pinMode(pin_led_yel[i], OUTPUT); pinMode(PIN_ZUM, OUTPUT); } void loop() { for(i=0; i<NUM_D; i++) { // проверка датчиков RED //if (датчик сработал) { if (digitalRead(pin_datchik_red[i]) == LOW) { zator_red[i] = 1; } else zator_red[i] = 0; } for(i=0; i<NUM_D; i++) { // проверка датчиков YEL //if (датчик сработал) { if (digitalRead(pin_datchik_yel[i]) == LOW) { zator_yel[i] = 1; } else zator_yel[i] = 0; } sum_red = 0; sum_yel = 0; for(i=0; i<NUM_D; i++) { // зажигаем светодиоды RED if (zator_red[i]) { digitalWrite(pin_led_red[i], HIGH); sum_red++; } else digitalWrite(pin_led_red[i], LOW); } for(i=0; i<NUM_D; i++) { // зажигаем светодиоды YEL if (zator_yel[i]) { digitalWrite(pin_led_yel[i], HIGH); sum_yel++; } else digitalWrite(pin_led_yel[i], LOW); } if ((sum_red > 0) || (sum_yel > 0)) { // включаем зуммер digitalWrite(PIN_ZUM, HIGH); } else digitalWrite(PIN_ZUM, LOW); }arduinec У ТС один датчик на сопло- зерносып . Просто желтый загорается если перестало сыпаться, а красный если перестало сыпаться через 1 секунду. Зумер если загорелся хоть один ЖЕЛТЫЙ !!!!. Правильно или неправильно это кто его знает. Этот проект надо создавать лично, а не со слов на форуме.
arduinec У ТС один датчик на сопло- зерносып . Просто желтый загорается если перестало сыпаться, а красный если перестало сыпаться через 1 секунду. Зумер если загорелся хоть один ЖЕЛТЫЙ !!!!. Правильно или неправильно это кто его знает. Этот проект надо создавать лично, а не со слов на форуме.
немного не так.
Датчик один в сопло зерносыпе (воронке). - Верно
Желтый загорается если перестало сыпаться, нес сингнала к примеру 3 секунды - Верно
Красный загорается, если сопло наполнилось зерном и закрыло сам датчик, и он подает непрерывный с сигнал.
В рабочем состоянии датчик производит примерно 150 в секунду - по количеству пролетающих зерен. + - может что-то пропуститью
Пищалка срабатывает в обеих случаях, хоть при загорании красного, хоть желтого светодиода.
Плохо виде не выкладывается :-((
А вот когда семена сыпятся то тоже идет таже полнота. Ну чуть посветлее. Тогда надо использовать аналоговые выходы cенсоров.
Круче рацуха.
Водила будет всегда халтурить, а поэтому надо прикрутить GSM модуль и слать либо смс либо че мелочиться сразу на сервер пакеты о состоянии системы в релтайм
ну или хотябы карту памяти прилепить с записью логов, что бы потом с водилы бабок за лень содрать.
а еще можно GPS модуль прикрутить чтобы мониторить когда стоит и откключать мониторинг , заодно и скорость конролировать и по превышению тлже штрафовать, да и если слишком медленно также лишать премии.
блин, чем-то мне РЖД начинает навевать
И дефибриллятор к водителю подключить. Чтоб шустрее ездил. Без перекуров.
ВОдитель остановился, загорятся только желтые. После остановки по любой причине водитель поднимает комплекс, чтобы вывести из зацепления с почвой (при трогании сцепление меньше палишь). Если он забыл № Первым делом он крутанет приводное колесо и визуально все и сразу увидит и показания датчика и реальное положение дел.
Идея правильная, но думаю на первый сезон надо сделать проще некуда, а на следующий год доработать имеющиеся неджочеты.
А вот когда семена сыпятся то тоже идет таже полнота. Ну чуть посветлее. Тогда надо использовать аналоговые выходы cенсоров.
Когда сыпется идет не полнота, а колебания, свнтодиод постоянно мерцает, и релюшка трещит.
Скинь почту я видео вышлю
del
// Датчики 8-9-10 // Светодиод Желтый = 2, 4, 6 // Светодиод Красный = 3, 5, 7 uint8_t dat_portB; uint8_t temp_portB; uint8_t rezult_portB; uint8_t zumer; void setup(){ DDRB = B00000000; // PORTB, подключенный- как выход, DDRD = DDRD | B11111100; // PORTD, подключенный как выход 0й и 1й не трогаем } //Переменные функции паузы или дребезга, с разным временем опроса unsigned long currentPause[16]; //массив данных. Количество элементов - количеству таймеров bool fl_pause[16];//массив данных. Количество элементов - количеству таймеров //Функция дребезга или паузы (time-время задержки, nomer-номер таймера) boolean my_pausa(unsigned long time, byte nomer){ bool x = 0; if (fl_pause[nomer] == 0)currentPause[nomer] = millis(), fl_pause[nomer] = 1; if (millis() - currentPause[nomer] >= time) x = 1, fl_pause[nomer] = 0; return x; } void loop(){ static uint8_t j; dat_portB = PINB; rezult_portB = dat_portB ^ temp_portB; temp_portB = dat_portB; zumer = PIND; // Проверяем порт если диоды не горят if(!zumer) PORTB &= ~(1<<5); // Звук выключаем else PORTB |= (1<<5); // Звук включаем for(uint8_t i=0;i<3;i++) { if(!i) j=2; else j+=2; if (rezult_portB & (1 << i)){ // Если все нормально fl_pause[i] = 0; //Сброс таймера PORTD &= ~(1<<j); // Выключаем желтый PORTD &= ~(1<<(j+1)); // Выключаем красный } else{ //Чтото пошло не так!!! if (dat_portB & (1 << i)){ if (my_pausa(1000, i))PORTD |= (1<<j); // Включаем желтый } if (~(dat_portB) & (1 << i)){ if (my_pausa(500, i))PORTD |= (1<<(j+1)); // Включаем красный } } } }