проблемы с таймером
- Войдите на сайт для отправки комментариев
Добый вечер! пишу код для астротрекера... подскажите как можно решить следующую задачу? Необходимо запрограммировать включение мотора от кнопки ровно на опред время в этот промежуток времени ведется съемка, не используя функцию 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();
Визуально это что то типо такого
unsigned long var; int time = 60; // или 70 void setup(){ var = millis(); } void loop(){ ...... ...... ...... if(millis() - var >= 1000) {time --; var = millis();} //тут же печатаем секунды if(!var) {.........} //если прошло 60 sec и т.д.}Польшой минус такой затеи в том что отсчёт времени не будет точный, т.к. плюс ко всему у вас в коде много "делеек". Хотя можно подогнать код под максимальную точность. Так же не лишним будет продумать момент переполнения значения millis() а это обязательно произойдёт "приблизительно через 50 дней."
Если строку 12 чаще вставлять, так же увеличится точность.
В остальном по коду:
Мне не понятно зачем Вы опускаете переменную key ниже нуля. Может я что то пропустил но при 0 у Вас ничего не происходит и при -1 так же ничего не происходит. может инициализировать нулём и в конце никла присвоить 0 и тогда все строки
можно записать как
Хотя ,как мне кажется, эта команда вобще лишняя.