проблемы с таймером

neid86@gmail.com
Offline
Зарегистрирован: 28.10.2014

Добый вечер! пишу код для астротрекера... подскажите как можно решить следующую задачу? Необходимо запрограммировать включение мотора от кнопки ровно на опред время в этот промежуток времени ведется съемка, не используя функцию 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;
}

 

hugoboss317
Offline
Зарегистрирован: 21.03.2013

Конкретно по  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 и тогда все строки 

if (key >= 0)   // если нажатие обнаружено

можно записать как 

if (key)   // если нажатие обнаружено

Хотя ,как мне кажется, эта команда вобще лишняя.