проблемы с таймером
- Войдите на сайт для отправки комментариев
Добый вечер! пишу код для астротрекера... подскажите как можно решить следующую задачу? Необходимо запрограммировать включение мотора от кнопки ровно на опред время в этот промежуток времени ведется съемка, не используя функцию delay(), т.е. цикл loop не должен останавливаться... фишка в следующем, есть установка времени работы 60 сек 70 сек и т.д. все написал, циклическое меню простенькое, установка времени работы, установка скорости вращения шагового двигателя, вращает двигатель... загвостка в том как отмерять время... воспользовался фонкцией MsTimer2, но не особо понял ее принцип работы... у меня не получается 1 сек - это 1000мс((( загвостка в том что я хочу еще выводить на экран отсчет секунд...
#include <AccelStepper.h> #include <LiquidCrystal.h> #include <MsTimer2.h> #define HALFSTEP 8 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int adc_key_val[5] ={50, 200, 400, 600, 800 }; //матрица значений каждой кнопки int k,x,go; unsigned long s, t, t2, t3; // переменные для отсчета времени // Motor pin definitions #define motorPin1 3 // IN1 on the ULN2003 driver 1 #define motorPin2 4 // IN2 on the ULN2003 driver 1 #define motorPin3 5 // IN3 on the ULN2003 driver 1 #define motorPin4 6 // IN4 on the ULN2003 driver 1 int NUM_KEYS = 5; // кол-во ключей int adc_key_in; //переменная хранит входящее напряжение с кнопок int key=-1; int isRun; double speeds = 271.6; //переменная скорости int maxspeed = 1245; //максимальная скорость AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4); void setExposure() // функция устанвоки экспозиции { if (key >= 0) // если нажатие обнаружено { if (key == 1) { //если нажата кнопка 1 s=s+10; delay(200); } if (key == 2) { //если нажата кнопка 2 s=s-10; delay(200); } if (s>200) {s=60; lcd.clear();} if (s<60) {s=200;lcd.clear();} } lcd.clear(); lcd.setCursor(0,0); //ставим курсор на ноль lcd.print("Set Exposure"); lcd.setCursor(0, 1); //переходим на вторую строку lcd.print("sec. "); //печатаем "скорость" lcd.setCursor(5, 1); //переходим на вторую строку lcd.print(s); // печатаем занчение скорости lcd.setCursor(13, 1); lcd.print("< >"); t=s*1000; // переводим в милисекунды } void setSpeeds() //функция устанвоки скорости мотора {if (key >= 0) // если нажатие обнаружено { if (key == 1) { //если нажата кнопка 0 speeds += 10; //увеличить скорость на 10 } if (key == 2) { //если нажата кнопка 3 speeds -= 10; //уменьшить скорость на 10 } if (speeds>maxspeed) { //если скорость больше максимальной скорость 1245 speeds = maxspeed; //то принудительно ограничить скорость значение макс.скорости } if (speeds<-maxspeed) { //если скорость меньше максимальной скорость -1245 speeds = -maxspeed; // //то принудительно ограничить скорость значение -макс.скорости } lcd.clear(); lcd.setCursor(0,0); //ставим курсор на ноль lcd.print("Set Speed"); lcd.setCursor(0, 1); //переходим на вторую строку lcd.print(speeds); lcd.setCursor(13, 1); lcd.print("< >"); } } void setMiliSpeeds() //функция установки скорости мотора до десятых {if (key >= 0) // если нажатие обнаружено { if (key == 1) { //если нажата кнопка 1 speeds += 0.1; //скорость вращения увеличить на 0.1 delay(200); } if (key == 2 && speeds > 0) { //если нажата кнопка 2 и скорость больше 0 speeds -= 0.1; //уменьщаем скорость 0.1 delay(200); } if (speeds>maxspeed) { //если скорость больше максимальной скорость 1245 speeds = maxspeed; //то принудительно ограничить скорость значение макс.скорости } if (speeds<-maxspeed) { //если скорость меньше максимальной скорость -1245 speeds = -maxspeed; // //то принудительно ограничить скорость значение -макс.скорости } lcd.clear(); lcd.setCursor(0,0); //ставим курсор на ноль lcd.print("Set miliSpeed"); lcd.setCursor(0, 1); //переходим на вторую строку lcd.print(speeds); lcd.setCursor(13, 1); lcd.print("< >"); } } void goTo() // функция делаем кадр { lcd.clear(); if (isRun !=1){lcd.setCursor(2,0); lcd.print("Press SELECT"); //проверяем значение переменной и выводим что нам нужно нажать для начала программы lcd.setCursor(3,1); lcd.print("for runnig!"); digitalWrite(1, LOW); //фукусировка отлючена digitalWrite(2, LOW); //затвор в положение выкл MsTimer2::stop();} // таймре остановлен if (key == 4) {delay(50);} if (key==4) {isRun =!isRun;} if (isRun == 1) { //если 1 MsTimer2::start(); //запускаем таймер lcd.setCursor(0,0);lcd.print("+++++Runnig+++++"); //выводим на экран что процесс заппущен t2++; //счтиаем милисекунды t3=t2/1000; //считаем секунды lcd.setCursor(0,1);lcd.print(t2); //выводим на экран секунды lcd.setCursor(3,1);lcd.print("sec."); stepper1.setSpeed(speeds);stepper1.runSpeed(); //считываем указанную скорость вращения двигателя и запускаем двигатель с этой скоростью } if (t==t2) {isRun=0; //проверяем сколько прошло времени и совпадает ли оно с установленным, если да MsTimer2::stop(); //останавливаем таймер lcd.setCursor(0,1); lcd.print("------STOP------"); //выводим на экран процесс остановлен delay(5000); //ждем 5 сек t2=0;t3=0;} //обнуляем счетчики милисекунд и секунд if (t2>0 & isRun==0) { //проверяем была нажата кнопка 4, то по условию isrun должен инвертивораться, т.е. если он равен 0 и прошло какое то время с момента запуска, что говорит о запущенном процессе //другими словами прервал процесс съемки кадра кнопкой MsTimer2::stop(); lcd.setCursor(0,1); lcd.print("------STOP------"); delay(5000); t2=0;t3=0;} } void flash() { //функция сделат кадр static boolean output = LOW; digitalWrite(1, output); digitalWrite(2, output); output = !output; } void setup() { pinMode(1, OUTPUT); pinMode(2, OUTPUT); lcd.clear(); lcd.begin(16, 2); lcd.setCursor(0,0); lcd.setCursor(0,1); isRun = 0; x=0; go=0; s=60;t2=0;t=0;t3=0; stepper1.setMaxSpeed(maxspeed); stepper1.setSpeed(speeds); MsTimer2::set(t, flash); MsTimer2::start(); } void loop() { adc_key_in = analogRead(0); // прочитать значение от датчика key = get_key(adc_key_in); // конвертировать в нажатия клавиши if (key == 0) {go++;} // листаем меню вправо delay(100); if (go >3) {go=0;} // с 4 страницы на 1 if (key == 3) {go--;} //листаем меню слева if (go <0) {go=3;} //с 1 страницы на 4 delay(100); switch(go) { case 0: setExposure(); break; case 1: setSpeeds(); break; case 2: setMiliSpeeds(); break; case 3: goTo(); break; } } int get_key(unsigned int input) //функиця { int k; for (k = 0; k < NUM_KEYS; k++) //перебираем значения k до тех пор пока k меньше значения NUM_KEYS { if (input < adc_key_val[k]) //если занчение меньше значения массива, т.е. тем самым узнаем какая кнопка нажата, k должно быть меньше одного из числе этого ряда: 50, 200, 400, 600, 800 return k; // прирвать цикл } if (k >= NUM_KEYS) //если k больше либо равно 5 k = -1; // Не будет нажата ни одна действительный ключ return k; }
Конкретно по
MsTimer2
посоветовать не могу. Я бы просто с ним не стал связываться но это исключительно дело вкуса.Таймер можно набросать самому. У Вас есть счётчик millis(); (который видимо и использует
MsTimer2
).отсчитывать время можно примерно следующим образом:
Объявляется глобальная переменная размером 4 байта и беззаковая типа unsigned long.
В теле setup ей присваевается текущее значение millis(), а дальще в основном цикле сравниваются значения переменной и millis() и как только их разность становится равной или проивышает 1000, плюс секунда и прировнять переменную к millis();
Визуально это что то типо такого
Польшой минус такой затеи в том что отсчёт времени не будет точный, т.к. плюс ко всему у вас в коде много "делеек". Хотя можно подогнать код под максимальную точность. Так же не лишним будет продумать момент переполнения значения millis() а это обязательно произойдёт "приблизительно через 50 дней."
Если строку 12 чаще вставлять, так же увеличится точность.
В остальном по коду:
Мне не понятно зачем Вы опускаете переменную key ниже нуля. Может я что то пропустил но при 0 у Вас ничего не происходит и при -1 так же ничего не происходит. может инициализировать нулём и в конце никла присвоить 0 и тогда все строки
можно записать как
Хотя ,как мне кажется, эта команда вобще лишняя.