Задержки в Arduino

Здесь обсуждаем Arduino
Аватара пользователя
GhostX
Сообщения: 1110
Зарегистрирован: 07 дек 2015, 14:40
Откуда: Рязань

Задержки в Arduino

Сообщение GhostX » 17 дек 2015, 00:49

Искал выход из ситуации с delay().
для простого моргания диодом, эта функция хороша, НО для более сложных задач, она становится недостатком.
Познакомился с millis() и понял, что с ее помощью можно написать намного практичнее вещи.
Вопрос: Какое требуется время, для прокрутки одного круга loop()?
Понятно, что чем больше кода тем дольше, но к чему привязываться?
Тактовая частота, так же известна.
Нужен широко развернутый ответ. :)

Аватара пользователя
GhostX
Сообщения: 1110
Зарегистрирован: 07 дек 2015, 14:40
Откуда: Рязань

Re: Задержки в Arduino

Сообщение GhostX » 17 дек 2015, 15:35

Практика показала, что медленно... слишком медленно, для моих нужд. :)
вот отрезок кода. Отрезано обращение к датчикам вывод на lcd информации итд, но все строки без delay()
постарался прокомментировать максимально доступно.
Как ускорить и вообще контролировать скорость поворотов? и в целом как сократить код?
for, while нельзя или осторожно с ключами на время одного поворота как то, так как interval будет 2-3 часа, а смотреть температуру и др. данные, нужно каждую минуту ну или хотя бы 5 мин.

Код: Выделить всё

#include <Servo.h>
int pos = 0;    // переменная для хранения позиции сервы 
int key = 0; //ключ для направления смены позиций сервы, с лева на право и наоборот
int time1 = 0; //ключ для времени интервала 1
int time2 = 0; //ключ для времени интервала 2
long previousMillis1 = 0;  // здесь будет храниться время последнего изменения состояния сервы против часовой
long previousMillis2 = 0;  // здесь будет храниться время последнего изменения состояния сервы по часовой
long interval = 5000;      // интервал паузы сервы в миллисекундах
void setup()
{
key = 1; //выставляем стартовую позицию ключем
}
void loop() 
{
//serva
    if (pos < 100 && key == 1){          //сравниваем позицию и направление
	   if (pos == 55 && time1 == 0){ //если позиция сервы равна 55градусов и ключ выключен
		   previousMillis1 = millis(); //засекаем таймер и включаем ключ
		   time1 = 1;
	   }
		 if (millis() - previousMillis1 < interval && time1 == 1){ //смотрим на таймер, если ключ включен и 
                                                                                        //  время не вышло выходим. ключ вкл			 
			 return;
		 }
		  else                                                                 // время вышло ключ выключаем
		    {
			  time1 = 0;
	        }
	 pos += 1;
     myservo.write(pos);              // добавляем градус и поворачиваем серву
     //delay(20); 	//старая версия. ждём 20ms пока серва займёт новое положение
     return;                                //на новый круг если не досчитали до 100  
	}
	  else                                // досчитали, переключили ключ, чтоб крутить обратно.
	   { 
        key = 0;
       }
    if (pos > 0 && key == 0){             // тут все тоже самое, только позиция остановки другая 
       if (pos == 47 && time2 == 0){    // обе позиции держат горизонт просто учтены корректировки механических
		previousMillis2 = millis();   // недочетов.
		      time2 = 1;
	    }
		    if (millis() - previousMillis2 < interval && time2 == 1){
			    
			    return;
		    }
	          else 
			  {
				time2 = 0;  
			  }
	  pos -= 1;
      myservo.write(pos);              // опять считаем до 0 
      //delay(20);                      // старая версия. ждём 20ms пока серва займёт новое положение 
      return;                               //возвращаемся, пока не будет 0 и меняем ключ. далее снова по кругу.
	}
      else 
	   { 
        key = 1;
       }
}

Аватара пользователя
gurvinok
Сообщения: 1476
Зарегистрирован: 02 мар 2013, 09:18
Откуда: Москва

Re: Задержки в Arduino

Сообщение gurvinok » 17 дек 2015, 16:52

Если нужны точные интервалы и независимые от хода программы, то добро пожаловать в мир регистров и прерываний. Для точного отсчета времени нужны прерывания от аппаратных таймеров. Вот тут я про них писал.
Если долго мучиться, может быть получится.

Аватара пользователя
GhostX
Сообщения: 1110
Зарегистрирован: 07 дек 2015, 14:40
Откуда: Рязань

Re: Задержки в Arduino

Сообщение GhostX » 17 дек 2015, 17:05

прям сейчас перелопачиваю весь код. сейчас когда закончу, придет понимание, того что нужно.
голова маленько распухла, от объема новой информации.
но возможно мир регистров именно мне и светит. опыт набираю. :) :) :)

Аватара пользователя
GhostX
Сообщения: 1110
Зарегистрирован: 07 дек 2015, 14:40
Откуда: Рязань

Re: Задержки в Arduino

Сообщение GhostX » 17 дек 2015, 17:43

Что то глянул в таймеры и понимаю, что там совсем не про Ардуино речь идет, а об AVR для взрослых дядей.))
Мне то куда, я то в яслях на ардуине!
Такое в работе с ардуиной, вообще доступно?

Аватара пользователя
gurvinok
Сообщения: 1476
Зарегистрирован: 02 мар 2013, 09:18
Откуда: Москва

Re: Задержки в Arduino

Сообщение gurvinok » 17 дек 2015, 18:55

Я думаю нет. Я сам с Ардуино досконально не разбирался. Надо почитать маны, но скорее всего там нет такого.
Если долго мучиться, может быть получится.

Аватара пользователя
GhostX
Сообщения: 1110
Зарегистрирован: 07 дек 2015, 14:40
Откуда: Рязань

Re: Задержки в Arduino

Сообщение GhostX » 17 дек 2015, 21:09

Вот и я такого не встречал ни в одном справочнике или статье, что на глаза попадались.
но да и ладно. Я маленько переделал код.
И вот вопрос. я его на данный момент больше сам понимал, чем для реальной практики использовать.
И задача была перемещение сервы в 3 положения, крайние и горизонт. При этом в этих положениях должна она была долго стоять, а код выполнятся. Изначально все было на delay(). работало. с новыми условиями сейчас тоже работает. хоть и немного громоздко получилось, но работает именно так как было поставлено в задаче.
теперь новое условие. при наступлении события, серва из любого положения должна с той же скоростью встать в горизонт и стоять так до отмены этого события, но код по прежнему должен выполняться. После отмены, вернутся на старое место и продолжить старое направление или стояние в ожидании, все с той же скоростью. Так же delay() не желателен.
Код условно разделен на 4 части 2 по 2. и вся суть ясна из 1/4 кода.
нужно кнопу (событие) прикрутить и как то, точно понимаю, что можно уменьшить его в 3 раза как минимум.
Я еще подумаю конечно, но Как это сделать?

Код: Выделить всё

//serva
    if (key == 1){             //проверяем позицию и ключ направления вращения сервы
	  if (time == 1 && pos <= 55 ) goto printervalch;      //проверяем первичность следующего цикла
	  if (time == 1 && pos >55) goto printervalch2;      //проверяем из какого диапазона градусов и если не первой половины, то идем во вторую половину
		for(pos = 0; pos < 55; pos += 1)    // крутим серву до горизонтального положения
	    {
		  myservo.write(pos);              // процесс перемещения
          delay(P);                      // ждём 20ms пока серва займёт новое положение 
	    }   
		if (pos == 55 && time == 0){   //останавливаем серву в горизонтальном положении
		      previousMillis1 = millis();   //присваеваем переменной последнего замера времени настоящее время 
		      time = 1;                    //ставим ключ для определения первичности цикла и необходимости измерения времени.   
	    }
		printervalch:   //метка перехода, для пропуска повторяющихся движений сервы.
	    if (millis() - previousMillis1 < intervalGorizonta && time == 1){  //сравниваем прошедшее время с заданным интервалом
			 
			return;    //если мало прошло крутим все с начало
		}
		else    //время прошло достаточно выключаем таймер
		{
		     time = 0;
	    }		
	  printervalch2:  	
	  if (time == 1 && pos >55) goto printervalvch;  //проверяем так же как в первой половине.
	    for(pos = 55; pos < 100; pos += 1)
		{
		    myservo.write(pos);              // 
            delay(P);                      // ждём 20ms пока серва займёт новое положение 
	    }
		if (pos == 100 && time == 0){
		    previousMillis1 = millis();
		    time = 1;
	    }
		printervalvch:
		if (millis() - previousMillis1 < interval && time == 1){
			 
		    return;
		}
		else
		{ 
			time = 0;
            key = 0;			
		}
		
	}
		   
	if (key == 0){             //проверяем позицию и ключ направления вращения сервы
	  if (time == 1 && pos >= 47 ) goto lvintervalch;      //проверяем первичность следующего цикла
		if (time == 1 && pos <47) goto lvintervalch2;      //проверяем из какого диапазона градусов и если не первой половины, то идем во вторую половину
		for(pos = 100; pos > 47; pos -= 1)    // крутим серву до горизонтального положения
	    {
		  myservo.write(pos);              // процесс перемещения
          delay(P);                      // ждём 20ms пока серва займёт новое положение 
	    }   
		if (pos == 47 && time == 0){   //останавливаем серву в горизонтальном положении
		      previousMillis1 = millis();   //присваеваем переменной последнего замера времени настоящее время 
		      time = 1;                    //ставим ключ для определения первичности цикла и необходимости измерения времени.   
	    }
		lvintervalch:   //метка перехода, для пропуска повторяющихся движений сервы.
	    if (millis() - previousMillis1 < intervalGorizonta && time == 1){  //сравниваем прошедшее время с заданным интервалом
			 
			return;    //если мало прошло крутим все сначало
		}
		else    //время прошло достаточно выключаем таймер
		{
		     time = 0;
	    }		
	  lvintervalch2:  	
	  if (time == 1 && pos < 47) goto lvintervalvch;  //проверяем так же как в первой половине.
	    for(pos = 47; pos > 0; pos -= 1)
		{
		    myservo.write(pos);              // 
            delay(P);                      // ждём 20ms пока серва займёт новое положение 
	    }
		if (pos == 0 && time == 0){
		    previousMillis1 = millis();
		    time = 1;
	    }
		lvintervalvch:
		if (millis() - previousMillis1 < interval && time == 1){
			 
		    return;
		}
		else
		{ 
			time = 0;
            key = 1;			
		}
		
	} 	

Аватара пользователя
gurvinok
Сообщения: 1476
Зарегистрирован: 02 мар 2013, 09:18
Откуда: Москва

Re: Задержки в Arduino

Сообщение gurvinok » 18 дек 2015, 21:12

goto printervalch;
Эту гадость нужно убрать!!! Ни каких го в жопу ту. Это закон. Пока в программе есть такие переходы, программа нормально работать не будет.
Если долго мучиться, может быть получится.

Аватара пользователя
GhostX
Сообщения: 1110
Зарегистрирован: 07 дек 2015, 14:40
Откуда: Рязань

Re: Задержки в Arduino

Сообщение GhostX » 18 дек 2015, 21:32

чем то заменить, или вообще переписать все иначе как то?
и как? :?
у меня еще, в целом, смутное представление, как надо заставлять ее работать, чтоб результат получить... :?

Аватара пользователя
gurvinok
Сообщения: 1476
Зарегистрирован: 02 мар 2013, 09:18
Откуда: Москва

Re: Задержки в Arduino

Сообщение gurvinok » 18 дек 2015, 22:33

Я щя пью пиво и играю на гитаре. Поэтому в двух словах без лирики.

Код: Выделить всё

goto метка

метка:
Это жопа!!!.
Тоже самое, но правильно.

Код: Выделить всё

void function(void);

void main()
{
   while(1)
   {
      function();
    }
}

void function(void)
{
  // Какие-то дейсвия
}
Если долго мучиться, может быть получится.

Ответить