Не получается добиться правильной работы модуля на TM1637 Задача: Включаем, "timer_val" работает как обратный отсчет 2 мин, после того как будет нуль запускается "timer_val1", то же обратный отсчет и так поочереди. Но у меня после окончания счета "timer_val1" опять и опять запускается "timer_val1". Что-то я совсем запутался, как это исправить После исправления будет еще добавлена работа pin2 при работе "timer_val" - pin2,HIGH при работе "timer_val1" - pin2,LOW Код (C++): #include "TM1637.h" // подключение библиотеки #define CLK A0 #define DIO A1 #define Pulse 2 // Выход для сигнализации int timer_val=2; // Обратный отсчет в минутах int timer_val1=1; // Обратный отсчет в минутах int timer_seconds=00; // Отображение секунд // Переменные для хранения индивидуальных номеров int firstnum=0; int secondnum=0; int thirdnum=0; int fournum=0; TM1637 tm1637(CLK,DIO); // Настройка индикатора void setup(){ pinMode(Pulse, OUTPUT); digitalWrite(Pulse, LOW); tm1637.init(); // Сброс дисплея tm1637.set(BRIGHT_TYPICAL); // Уровень яркости // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2; tm1637.point(POINT_ON); // Активация точки посредине delay(1000); // Задержка 1 секунда } void loop() { // Проверка, запустился ли таймер while (timer_val == 0 && timer_seconds == 0) { // Распределяем минуты и сикунды по отдельным сегментам if (timer_val1 > 9) { firstnum = timer_val1/10%10; secondnum = timer_val1%10; } else { secondnum = timer_val1; } if (timer_seconds > 9) { thirdnum = timer_seconds/10%10; fournum = timer_seconds%10; } else { thirdnum = 0; fournum = timer_seconds; } // Отображаем обратный отсчет tm1637.clearDisplay(); // Очистка дисплея if (timer_val1 > 9) { tm1637.display(0,firstnum); } if (timer_val1 > 0) { tm1637.display(1,secondnum); } if (timer_seconds > 9 || timer_val1 > 0) { tm1637.display(2,thirdnum); } tm1637.display(3,fournum); // Decrease seconds timer_seconds=timer_seconds-1; delay(1000); // Delay of 1 second // Decrease timer if (timer_seconds == -1) { timer_val1=timer_val1-1; timer_seconds=59; } } // Распределяем минуты и сикунды по отдельным сегментам if (timer_val > 9) { firstnum = timer_val/10%10; secondnum = timer_val%10; } else { secondnum = timer_val; } if (timer_seconds > 9) { thirdnum = timer_seconds/10%10; fournum = timer_seconds%10; } else { thirdnum = 0; fournum = timer_seconds; } // Отображаем обратный отсчет tm1637.clearDisplay(); // Очистка дисплея if (timer_val > 9) { tm1637.display(0,firstnum); } if (timer_val > 0) { tm1637.display(1,secondnum); } if (timer_seconds > 9 || timer_val > 0) { tm1637.display(2,thirdnum); } tm1637.display(3,fournum); // Decrease seconds timer_seconds=timer_seconds-1; delay(1000); // Delay of 1 second // Decrease timer if (timer_seconds == -1) { timer_val=timer_val-1; timer_seconds=59; } }
Что-то в коде запутаться можно слишком просто... Я бы сделал так: 1) Вывод на дисплей в виде отдельного метода 2) Сделать переменную, которая отвечает за время начала интервала (вдумайтесь и поймите эту фразу), сделать переменную, которая отвечает за то, какой сейчас таймер запущен (может быть булевого типа, если два варианта работы таймера или enum, byte, int в других случаях, как удобно). 3) Хранить массив, в котором будет указано время выполнения каждого периода в секундах. И по итогу получим: Запускаем, определяем через millis() время начала интервала, пока оно меньше продолжительности интервала - выводим время. Как только стало больше или равно, время начала интервала - текущее, счётчик Код (C++): int currentInterval = 0; int intervals[] = {120,60}; ulong startInterval = 0; int currentTime = 0; void setup() { startInterval = millis(); //last line } void loop() { currentTime = (millis() - startInterval) / 1000; while(currentTime < intervals[currentInterval]) { showTime(currentTime); //метод отображения времени delay(1000); //не уверен на счёт секунды } currentInterval = (currentInterval + 1 == intervals.length()) ? 0 : currentInterval + 1; startInterval = millis(); } P.S. код писал на коленке
Спойлер: мой код Код (C++): unsigned long mill; // переменная под millis() //-----Cl_Manager--------------------------- // класс менеджер задач struct task_t { void (*Do)(); unsigned long past; unsigned int time; struct task_t (*next); }; class Cl_Manager { protected: struct task_t (*start) = NULL; public: void run() { for (struct task_t (**i) = &start; (*i) != NULL; ) { if (mill - (**i).past >= (**i).time) { struct task_t (*_new) = (*i); (*i) = (**i).next; (*_new).Do(); delete _new; } else i = &(**i).next; } } void Task(unsigned int time, void (*Do)()) { struct task_t (*_new) = new struct task_t; (*_new).Do = Do; (*_new).past = mill; (*_new).time = time; (*_new).next = start; start = _new; } }; Cl_Manager Manager; //---Компоновка----------------------- // --serial void serial_1() { Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_2); Serial.println("1-one"); } void serial_2() { Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_3); Serial.println("2-two"); } void serial_3() { Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_4); Serial.println("3-three"); } void serial_4() { Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_5); Serial.println("4-four"); } void serial_5() { Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serial_1); Serial.println("5-five"); } //---main----------------------------- void setup() { Serial.begin(9600); serial_1(); } void loop() { mill = millis(); Manager.run(); } /*Скетч использует 2400 байт (7%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 236 байт (11%) динамической памяти, оставляя 1812 байт для локальных переменных. Максимум: 2048 байт. */
Не совсем понял, как запустить два таймера, а так же значение в последней строке intervals.length()) ? 0 :
попробовал с использованием библиотеки <Thread.h> , то же не корректная работа, здесь таймеры работают одновременно Код (C++): #include "TM1637.h" // подключение библиотеки #define CLK A0 #define DIO A1 #define Pulse 2 // Выход для сигнализации int timer_val=2; // Обратный отсчет в минутах int timer_val1=1; // Обратный отсчет в минутах int timer_seconds=00; // Отображение секунд // Переменные для хранения индивидуальных номеров int firstnum=0; int secondnum=0; int thirdnum=0; int fournum=0; TM1637 tm1637(CLK,DIO); // Настройка индикатора #include <Thread.h> // подключение библиотеки ArduinoThread const int soundPin = 3; // переменная с номером пина пьезоэлемента const int ledPin = 13; // переменная с номером пина светодиода Thread valThread = Thread(); // создаём поток управления светодиодом Thread valThread1 = Thread(); // создаём поток управления сиреной void setup() { pinMode(soundPin, OUTPUT); // объявляем пин 3 как выход. pinMode(ledPin, OUTPUT); // объявляем пин 13 как выход. valThread.onRun(RAD); // назначаем потоку задачу valThread.setInterval(2000); // задаём интервал срабатывания, мсек valThread1.onRun(NoRAD); // назначаем потоку задачу valThread1.setInterval(1000); // задаём интервал срабатывания, мсек tm1637.init(); // Сброс дисплея tm1637.set(BRIGHT_TYPICAL); // Уровень яркости // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2; tm1637.point(POINT_ON); // Активация точки посредине } void loop() { // Проверим, пришло ли время переключиться светодиоду: if (valThread.shouldRun()) valThread.run(); // запускаем поток // Проверим, пришло ли время сменить тональность сирены: if (valThread1.shouldRun()) valThread1.run(); // запускаем поток } void RAD() { // Распределяем минуты и сикунды по отдельным сегментам if (timer_val > 9) { firstnum = timer_val/10%10; secondnum = timer_val%10; } else { secondnum = timer_val; } if (timer_seconds > 9) { thirdnum = timer_seconds/10%10; fournum = timer_seconds%10; } else { thirdnum = 0; fournum = timer_seconds; } // Отображаем обратный отсчет tm1637.clearDisplay(); // Очистка дисплея if (timer_val > 9) { tm1637.display(0,firstnum); } if (timer_val > 0) { tm1637.display(1,secondnum); } if (timer_seconds > 9 || timer_val > 0) { tm1637.display(2,thirdnum); } tm1637.display(3,fournum); // Decrease seconds timer_seconds=timer_seconds-1; delay(1000); // Delay of 1 second // Decrease timer if (timer_seconds == -1) { timer_val=timer_val-1; timer_seconds=59; } } void NoRAD() { // Распределяем минуты и сикунды по отдельным сегментам if (timer_val1 > 9) { firstnum = timer_val1/10%10; secondnum = timer_val1%10; } else { secondnum = timer_val1; } if (timer_seconds > 9) { thirdnum = timer_seconds/10%10; fournum = timer_seconds%10; } else { thirdnum = 0; fournum = timer_seconds; } // Отображаем обратный отсчет tm1637.clearDisplay(); // Очистка дисплея if (timer_val1 > 9) { tm1637.display(0,firstnum); } if (timer_val1 > 0) { tm1637.display(1,secondnum); } if (timer_seconds > 9 || timer_val1 > 0) { tm1637.display(2,thirdnum); } tm1637.display(3,fournum); // Decrease seconds timer_seconds=timer_seconds-1; delay(1000); // Delay of 1 second // Decrease timer if (timer_seconds == -1) { timer_val1=timer_val1-1; timer_seconds=59; } }
Вот код на 2 последовательно работающих таймера, разумеется с использованием менеджера. Спойлер: код Код (C++): unsigned long mill; // переменная под millis() //-----Cl_Manager--------------------------- // класс менеджер задач struct task_t { void (*Do)(); unsigned long past; unsigned int time; struct task_t (*next); }; class Cl_Manager { protected: struct task_t (*start) = NULL; public: void run() { for (struct task_t (**i) = &start; (*i) != NULL; ) { if (mill - (**i).past >= (**i).time) { struct task_t (*_new) = (*i); (*i) = (**i).next; (*_new).Do(); delete _new; } else i = &(**i).next; } } void Task(unsigned int time, void (*Do)()) { struct task_t (*_new) = new struct task_t; (*_new).Do = Do; (*_new).past = mill; (*_new).time = time; (*_new).next = start; start = _new; } }; Cl_Manager Manager; //---Компоновка----------------------- // --serial byte Timer1, Timer2; void Timer1Run() { Serial.print("Timer1:"); Serial.print(Timer1); Serial.println(); --Timer1; if (Timer1 > 0) { Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&Timer1Run); } else { Timer2 = 10; Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&Timer2Run); } } void Timer2Run() { Serial.print("Timer2:"); Serial.print(Timer2); Serial.println(); --Timer2; if (Timer2 > 0) Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&Timer2Run); else { Timer1 = 10; Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&Timer1Run); } } //---main----------------------------- void setup() { Serial.begin(9600); Timer1 = 10; Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&Timer1Run); } void loop() { mill = millis(); Manager.run(); } /*Скетч использует 2610 байт (8%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 220 байт (10%) динамической памяти, оставляя 1828 байт для локальных переменных. Максимум: 2048 байт. */
А зачем самому придумывать какие-то переменные для времени, почему не использовать функцию time? https://www.arduino.cc/en/Reference/Millis Запускаете таймер - записываете время запуска, а в цикле проверяете прошло ли нужное время. Точность этих строк очень сомнительна, будет явно больше секунды Код (C++): timer_seconds=timer_seconds-1; delay(1000);
У вас же два таймера работают последовательно? Сначала первый отрабатывает, потом второй, верно? Последняя строка - это тернарный оператор. Можно расписать, как if else. Код (C++): #include "TM1637.h" // подключение библиотеки #define CLK A0 #define DIO A1 #define Pulse 2 // Выход для сигнализации TM1637 tm1637(CLK,DIO); // Настройка индикатора int currentInterval =0; //номер текущего интервала int intervals[]={120,60}; //длина интервалов в секундах, в массиве ulong startInterval =0; //время начала текущего интервала int currentTime =0; // прошедшее время с начала текущего интервала в секундах void setup(){ pinMode(Pulse, OUTPUT); digitalWrite(Pulse, LOW); tm1637.init(); // Сброс дисплея tm1637.set(BRIGHT_TYPICAL); // Уровень яркости // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2; tm1637.point(POINT_ON); // Активация точки посредине delay(1000); // Задержка 1 секунда } void loop() { currentTime =(millis()- startInterval)/1000; while(currentTime < intervals[currentInterval]) { showTime();//метод отображения времени delay(1000);//не уверен на счёт секунды currentTime =(millis()- startInterval)/1000; } currentInterval =(currentInterval +1== intervals.length())?0: currentInterval +1; startInterval = millis(); } void showTime() { tm1637.clearDisplay();// Очистка дисплея int seconds = currentTime % 60; //количество секунд int mins = currentTime / 60; //количество минут tm1637.display(0,seconds%10); //не уверен на счёт индексов в самих модулях, возможно нужно использовать не 0, а 3. Ну и в других также if(seconds > 9) tm1637.display(1,seconds/10); if(mins > 0) tm1637.display(2,mins%10); if(mins > 9) tm1637.display(3,mins/10); }
Код (C++): } currentInterval =(currentInterval +1== intervals.length())?0: currentInterval +1; startInterval = millis(); } Ну вот как и в первый раз выдает ошибку sketch_oct27a.ino: In function 'void loop()': sketch_oct27a:30: error: request for member 'length' in 'intervals', which is of non-class type 'int [2]' request for member 'length' in 'intervals', which is of non-class type 'int [2]'
С чего вы взяли, что так можно вызывать - intervals.length() ? Что это за метод length() вдруг у массива появился? Вы с питоном или перлом не попутали случаем? И вообще, вся эта строка - это попытка исполнить тройной прыжок тем, кто вчера на коньки встал. Если вы не чувствуете кода - не лезте в дебри, пишите простыми операторами. И поправьте заголовк. Ваш вопрос к дисплею не имеет ни малейшего отношения.
Да, не чувствовать кода это зло. Я не супер програмист переделал код как я его понимаю и он почти работает, но есть большое НО, при запуске светодиод включается и выключается по заданному времени как надо, на дисплее 2 мин отсчитываются как надо, потом идет пауза 10 сек на дисплее (11:11), и вот когда таймер запускается второй раз (он отсчитывает установленные 2 мин), но на дисплее горят только секунды (3-й и 4- сигменты). Где у меня ошибка в отображении на дисплее? Код (C++): #include "TM1637.h" // подключение библиотеки #define CLK 11 #define DIO 12 int ledPin = 13; // номер пина со светодиодом int ledState = LOW; // состояние светодиода int timer_val1=2; // Обратный отсчет в минутах int timer_seconds1=00; // Отображение секунд // Переменные для хранения индивидуальных номеров int firstnum=0; int secondnum=0; int thirdnum=0; int fournum=0; TM1637 tm1637(CLK,DIO); // Настройка индикатора unsigned long previousMillis = 0; long OnTime = 120000; // длительность свечения светодиода (в миллисекундах) long OffTime = 10000; // светодиод не горит (в миллисекундах) void setup(){ pinMode(ledPin, OUTPUT); tm1637.init(); // Сброс дисплея tm1637.set(BRIGHT_TYPICAL); // Уровень яркости // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2; tm1637.point(POINT_ON); // Активация точки посредине delay(1000); // Задержка 1 секунда } void loop() { Blinck(); timer(); clining(); } void Blinck(){ // выясняем не настал ли момент сменить состояние светодиода unsigned long currentMillis = millis(); // текущее время в миллисекундах // если светодиод включен и светится больше чем надо if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // выключаем previousMillis = currentMillis; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // выключаем previousMillis = currentMillis ; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } } void timer(){ if (ledState == HIGH) { // Распределяем минуты и сикунды по отдельным сегментам if (timer_val1 > 9) { firstnum = timer_val1/10%10; secondnum = timer_val1%10; } else { secondnum = timer_val1; } if (timer_seconds1 > 9) { thirdnum = timer_seconds1/10%10; fournum = timer_seconds1%10; } else { thirdnum = 0; fournum = timer_seconds1; } // Отображаем обратный отсчет tm1637.clearDisplay(); // Очистка дисплея if (timer_val1 > 9) { tm1637.display(0,firstnum); } if (timer_val1 > 0) { tm1637.display(1,secondnum); } if (timer_seconds1 > 9 || timer_val1 > 0) { tm1637.display(2,thirdnum); } tm1637.display(3,fournum); // Decrease seconds timer_seconds1=timer_seconds1-1; delay(1000); // Decrease timer if (timer_seconds1 == -1) { timer_val1=timer_val1-1; timer_seconds1=59; } } } void clining(){ // Проверка, запустился ли таймер if (ledState == LOW) { tm1637.clearDisplay(); // Очистка дисплея tm1637.display(0,1); tm1637.display(1,1); tm1637.display(2,1); tm1637.display(3,1); delay(300); tm1637.clearDisplay(); // Очистка дисплея delay(300); } } .
Что же такого гипер сложного в этой строке? Код (C++): currentInterval =(currentInterval +1== sizeof(intervals)/sizeof(int)) ? 0 : currentInterval +1; Окей, да, мой косяк, метода length нет. Писал не в arduinoIDE, а в браузере и не смогу проверить все ошибки. Если текущий интервал +1 = размеру массива, то текущий интервал 0, иначе текущий интервал +1. Если бы у меня были все необходимые модули, я бы обязательно проверил перед отправкой, а так это просто интерес. Код (C++): #include "TM1637.h" // подключение библиотеки #define CLK A0 #define DIO A1 #define Pulse 2 // Выход для сигнализации TM1637 tm1637(CLK,DIO); // Настройка индикатора int currentInterval =0; //номер текущего интервала int intervals[]={120,60}; //длина интервалов в секундах, в массиве ulong startInterval =0; //время начала текущего интервала int currentTime =0; // прошедшее время с начала текущего интервала в секундах void setup(){ pinMode(Pulse, OUTPUT); digitalWrite(Pulse, LOW); tm1637.init(); // Сброс дисплея tm1637.set(BRIGHT_TYPICAL); // Уровень яркости // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2; tm1637.point(POINT_ON); // Активация точки посредине delay(1000); // Задержка 1 секунда } void loop() { currentTime =(millis()- startInterval)/1000; while(currentTime < intervals[currentInterval]) { if(currentInterval % 2 == 0) { showTime(); //метод отображения времени } currentTime =(millis()- startInterval)/1000; delay(200); } tm1637.clearDisplay(); // Очистка дисплея currentInterval =(currentInterval + 1 == sizeof(intervals)/sizeof(int)) ? 0 : currentInterval +1; startInterval = millis(); } void showTime() { tm1637.clearDisplay();// Очистка дисплея int seconds = currentTime % 60; //количество секунд int mins = currentTime / 60; //количество минут tm1637.display(0,seconds%10); //не уверен на счёт индексов в самих модулях, возможно нужно использовать не 0, а 3. Ну и в других также if(seconds > 9) tm1637.display(1,seconds/10); if(mins > 0) tm1637.display(2,mins%10); if(mins > 9) tm1637.display(3,mins/10); }
Тогда метод сделать такой: Код (C++): void showTime() { tm1637.clearDisplay();// Очистка дисплея int showingTime = intervals[currentInterval] - currentTime; //добавил эту строку. Берём время текущего интервала и вычитаем время прошедшее с начала интервала. int seconds = showingTime % 60; //количество секунд int mins = showingTime / 60; //количество минут tm1637.display(0,seconds%10); //не уверен на счёт индексов в самих модулях, возможно нужно использовать не 0, а 3. Ну и в других также if(seconds > 9) tm1637.display(1,seconds/10); if(mins > 0) tm1637.display(2,mins%10); if(mins > 9) tm1637.display(3,mins/10); } Вообще в код будет вести обратный отсчёт для каждого четного элемента в intervals и ничего не отображать для каждого нечетного. Т.е. если intervals = {60,30,120,60}; - то будет отсчёт с 60 до 0, потом 30 сек тишины, потом отсчёт с 120 до 0, потом 60 сек тишины и заново.
В ответе №11 я описал что не корректно работает в моем коде, кто подскажет как исправить, буду благодарен. Код Орленка по работе дисплея после мелких исправление отлично работает, осталось только прицепить светодиод.
Может быть криво-косо, но код работает, спасибо все кто помог словом-делом Код (C++): #include "TM1637.h" // подключение библиотеки #define CLK 11 #define DIO 12 int ledPin = 13; // номер пина со светодиодом int ledState = LOW; // состояние светодиода TM1637 tm1637(CLK,DIO); // Настройка индикатора int currentInterval =0; //номер текущего интервала int intervals[]={120,10,60,5}; //длина интервалов в секундах, в массиве long startInterval =0; //время начала текущего интервала int currentTime =0; // прошедшее время с начала текущего интервала в секундах unsigned long previousMillis = 0; long OnTime = 10; // длительность свечения светодиода (в миллисекундах) long OffTime = 10; // светодиод не горит (в миллисекундах) void setup(){ pinMode(ledPin, OUTPUT); tm1637.init(); // Сброс дисплея tm1637.set(BRIGHT_TYPICAL); // Уровень яркости // BRIGHT_DARKEST = 0,BRIGHTEST = 7 BRIGHT_TYPICAL = 2; tm1637.point(POINT_ON); // Активация точки посредине delay(1000); // Задержка 1 секунда } void loop() { Blinck(); currentTime =(millis()- startInterval)/1000; while(currentTime < intervals[currentInterval]) { if(currentInterval % 2 == 0) { showTime(); //метод отображения времени } currentTime =(millis()- startInterval)/1000; delay(200); } tm1637.clearDisplay(); // Очистка дисплея currentInterval =(currentInterval + 1 == sizeof(intervals)/sizeof(int)) ? 0 : currentInterval +1; startInterval = millis(); } void showTime() { tm1637.clearDisplay();// Очистка дисплея int showingTime = intervals[currentInterval] - currentTime; int seconds = showingTime % 60; //количество секунд int mins = showingTime / 60; //количество минут tm1637.display(3,seconds%10); if(seconds > 9) tm1637.display(2,seconds/10); if(mins > 0) tm1637.display(1,mins%10); if(mins > 9) tm1637.display(0,mins/10); } void Blinck(){ // выясняем не настал ли момент сменить состояние светодиода unsigned long currentMillis = millis(); // текущее время в миллисекундах // если светодиод включен и светится больше чем надо if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // выключаем previousMillis = currentMillis; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // включаем previousMillis = currentMillis ; // запоминаем момент времени digitalWrite(ledPin, ledState); // реализуем новое состояние } }