Программа мигания светодиодами. Вопрос по таймерам и функции прерывания.

yaap89
Offline
Зарегистрирован: 04.12.2014

Доброго всем!

Имеется задача: 1. Разработать программу управления 5-ю светодиодными индикаторами (СД) с помощью двух кнопок, по следующему алгоритму: при нажатии на первую кнопку («Старт») (через каждые 5 сек) зажигаются СД, при этом каждый предыдущий СД не гаснет при включении последующего. Гашение СД происходит одновременно через 5 сек после того как будут гореть все 5 СД. Прекращение работы происходит только после нажатия на кнопку («Стоп»).
 
Я подключил к цифровым выводам с 5-9 диоды, на pin 2,3 кнопки.
 
int x=1;
 
void setup()
{
  pinMode(5, OUTPUT);   pinMode(6, OUTPUT);    pinMode(7, OUTPUT);    pinMode(8, OUTPUT);    pinMode(9, OUTPUT);   
  attachInterrupt(0, blink, CHANGE); // привязываем 0-е прерывание к функции blink(). Это будет кнопка стоп pin 2
}
 
void loop() {
if (x==1) 
{
digitalWrite(5, HIGH);
delay(5000);
digitalWrite(6, HIGH)
delay(5000);
digitalWrite(7, HIGH);
delay(5000);
digitalWrite(8, HIGH);
delay(5000);
digitalWrite(9, HIGH);
}
 
else
{
digitalWrite(5,LOW);
digitalWrite(6, LOW)
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
}
}
 
void blink()
{
 x = 0;                    // Должно выключить все диоды
}

Этот кусок программы работает, но не по заданию. При нажатии на кнопку х=о, но пока цикл загорания всех светодиодов не завершится они не тухнут.

Знакомый предложил сделать таймер не  через delay, а просто создать какой-то цикл и подсчитать время одного цикла тогда программа будет при каждом цикле проверять условие if (x==1) и при его не выполнении сразу же выключать все диоды.

А подскажите, может как-то более точно можно реализовать это или есть еще какие-то внутренние таймеры. Заранее благодарен за помощь. Просто даже нет мыслей в каком направлении смотреть. 

vov4ik
Offline
Зарегистрирован: 10.09.2013

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

[code]
bool _tim1I = 0;
bool _tim1O = 0;
unsigned long _tim1P = 0UL;
bool _trgs1 = 0;
bool _tim2I = 0;
bool _tim2O = 0;
unsigned long _tim2P = 0UL;
bool _tim3I = 0;
bool _tim3O = 0;
unsigned long _tim3P = 0UL;
bool _tim4I = 0;
bool _tim4O = 0;
unsigned long _tim4P = 0UL;
bool _bounseInput2S = 0;
bool _bounseInput2O = 0;
unsigned long _bounseInput2P = 0UL;
bool _bounseInput3S = 0;
bool _bounseInput3O = 0;
unsigned long _bounseInput3P = 0UL;
void setup()
{
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);

_bounseInput2O =  digitalRead(2);
_bounseInput3O =  digitalRead(3);
}
void loop()
{
bool  _bounceTmp2 =  (digitalRead (2));

if (_bounseInput2S) 
    {
     if (millis() >= (_bounseInput2P + 40)) 
         {_bounseInput2O= _bounceTmp2; _bounseInput2S=0;}
     }
else
    {
     if (_bounceTmp2 != _bounseInput2O )
         {_bounseInput2S=1; _bounseInput2P = millis();} 
      } 
bool  _bounceTmp3 =  (digitalRead (3));

if (_bounseInput3S) 
    {
     if (millis() >= (_bounseInput3P + 40)) 
         {_bounseInput3O= _bounceTmp3; _bounseInput3S=0;}
     }
else
    {
     if (_bounceTmp3 != _bounseInput3O )
         {_bounseInput3S=1; _bounseInput3P = millis();} 
      } 



if(_bounseInput2O) _trgs1 = 1;
if(_bounseInput3O) _trgs1 = 0;
if (_trgs1)
{
_tim1O  = 1;
_tim1I  = 1;
}
else
{
if (_tim1I)
{
_tim1I = 0;
_tim1P = millis();
}
else
{
if (_tim1O)
{if ( _isTimer(_tim1P, 5000)) _tim1O = 0;
}
}
} 
if (_tim1O)
{
_tim2O  = 1;
_tim2I  = 1;
}
else
{
if (_tim2I)
{
_tim2I = 0;
_tim2P = millis();
}
else
{
if (_tim2O)
{if ( _isTimer(_tim2P, 5000)) _tim2O = 0;
}
}
} 
if (_tim2O)
{
_tim3O  = 1;
_tim3I  = 1;
}
else
{
if (_tim3I)
{
_tim3I = 0;
_tim3P = millis();
}
else
{
if (_tim3O)
{if ( _isTimer(_tim3P, 5000)) _tim3O = 0;
}
}
} 
if (_tim3O)
{
_tim4O  = 1;
_tim4I  = 1;
}
else
{
if (_tim4I)
{
_tim4I = 0;
_tim4P = millis();
}
else
{
if (_tim4O)
{if ( _isTimer(_tim4P, 5000)) _tim4O = 0;
}
}
} 
digitalWrite(5, _trgs1);
digitalWrite(6, _tim1O);
digitalWrite(7, _tim2O);
digitalWrite(8, _tim3O);
digitalWrite(9, _tim4O);



}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long endTime;
  endTime = startTime+period;
  return (millis() >= endTime);
  }

[/code]

 

yaap89
Offline
Зарегистрирован: 04.12.2014

Спасибо. Буду разбираться, что тут написано. может пойму. 

vov4ik
Offline
Зарегистрирован: 10.09.2013

Для понимания упростил и добавил комментарии, поищите в нете что такое RS триггер и таймер с задержкой включения.

[code]
bool Q_RS = 0; // выход RS триггера
bool _tim1I = 0;
bool Q_tim_1 = 0; // выход таймера №1
unsigned long _tim1P = 0UL;
bool _tim2I = 0;
bool Q_tim_2 = 0; // выход таймера №2
unsigned long _tim2P = 0UL;
bool _tim3I = 0;
bool Q_tim_3 = 0; // выход таймера №3
unsigned long _tim3P = 0UL;
bool _tim4I = 0;
bool Q_tim_4 = 0; // выход таймера №4
unsigned long _tim4P = 0UL;
void setup()
{  // тут всё понятно
pinMode(2, INPUT); 
pinMode(3, INPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
}
void loop()
{
if( (digitalRead (2))) Q_RS = 1; // проверяем состояние кнопки пин 2
if( (digitalRead (3))) Q_RS = 0; // проверяем состояние кнопки пин 3
if (Q_RS) // если состояние Q_RS истинно начинаем выполнять: запуск первого таймера; также Q_RS служит для выхода пин 5 (см внизу кода)
{
Q_tim_1  = 1;
_tim1I  = 1;
}
else
{
if (_tim1I)
{
_tim1I = 0;
_tim1P = millis();
}
else
{
if (Q_tim_1) 
{if ( _isTimer(_tim1P, 5000)) Q_tim_1 = 0; // сравниваем миллес Q_RS - истинна через 5 сек Q_tim_1 истинна, до этого лож
}
}
} 
if (Q_tim_1)// если состояние Q_tim_1 истинно начинаем выполнять: запуск второго таймера; также Q_tim_1 служит для выхода пин 6 (см внизу кода)
{
Q_tim_2  = 1;
_tim2I  = 1;
}
else
{
if (_tim2I)
{
_tim2I = 0;
_tim2P = millis();
}
else
{
if (Q_tim_2)
{if ( _isTimer(_tim2P, 5000)) Q_tim_2 = 0;
}
}
} 
if (Q_tim_2)
{
Q_tim_3  = 1;
_tim3I  = 1;
}
else
{
if (_tim3I)
{
_tim3I = 0;
_tim3P = millis();
}
else
{
if (Q_tim_3)
{if ( _isTimer(_tim3P, 5000)) Q_tim_3 = 0;
}
}
} 
if (Q_tim_3)
{
Q_tim_4  = 1;
_tim4I  = 1;
}
else
{
if (_tim4I)
{
_tim4I = 0;
_tim4P = millis();
}
else
{
if (Q_tim_4)
{if ( _isTimer(_tim4P, 5000)) Q_tim_4 = 0;
}
}
} 
digitalWrite(5, Q_RS);
digitalWrite(6, Q_tim_1);
digitalWrite(7, Q_tim_2);
digitalWrite(8, Q_tim_3);
digitalWrite(9, Q_tim_4);
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long endTime;
  endTime = startTime+period;
  return (millis() >= endTime);
  }

[/code]

 

yaap89
Offline
Зарегистрирован: 04.12.2014

спасибо!

Sergivan
Offline
Зарегистрирован: 11.09.2014

Здравствуйте, Вовчик!

Я не могу реализовать программу по управлению машинкой с использованием эхолокационного дальномера.

Думаю, что дело в delay. Если встретит препятствие, то должно повернуть.

Не могли бы вы мне сделать набросок программы?

 

 

vov4ik
Offline
Зарегистрирован: 10.09.2013

Модет сначало распиновку, какие девайсы задействованы и вашу програмку.

yaap89
Offline
Зарегистрирован: 04.12.2014

vov4ik, может быть сможете подсказать по моей программе.  Программа управления двумя светодиодными индикаторами (СД1 и СД2)с помощью 2х кнопок, по следующему алгоритму: Кнопка нажата – СД1 и СД2 переключаются попеременно через 20 сек, отпускание кнопки не приводит к прекращению работы СД. СД гаснут только при нажатии второй кнопки.

У меня получилось написать программу, время между диодами заменил на 5сек. Первый вариант программы получился таким, используется вн.таймер, при нажатии на кнопку старт есть пауза в 5 секунд потом загораются свеодиоды. При нажатии на кнопку стоп все диоды тухнут.

Теперь есть одна проблема, хотел сделать так чтоб при нажатии на кнопку Старт, диод начал гореть 5 секунд без всяких пауз. Добавил в цикл условие, если y==1 оно выполнится один раз после нажатия на кнопку и далее будет отсчитвыться 5 секунд и менять состояние диодов на противоположное. Сейчас ни как не могу понять, почему из этого цика  не выходится ни как. при нажатии на кн. стоп программа не останавливается. 

// Вар.12 Программа управления двумя светодиодными индикаторами (СД1 и СД2)с помощью 2х кнопок,
// по следующему алгоритму: Кнопка нажата – СД1 и СД2 переключаются попеременно через 20 сек,
// отпускание кнопки не приводит к прекращению работы СД. СД гаснут только при нажатии второй кнопки.




int ledPin1 = 10;  // LED подсоединен к выводу 10
int ledPin2 = 9;   // LED подсоединен к выводу 9

unsigned long currentTime;  // Текшее время
unsigned long loopTime;   //  Время цикла

int state =  0; // Статус LED. 1-переменно мигают, 0-не горят

void setup()
{  
   pinMode(ledPin1, OUTPUT);      // устанавливаем вывод 10 как выход
   pinMode(ledPin2, OUTPUT);      // устанавливаем вывод 9 как выход
   pinMode(1, OUTPUT);
   
   
  currentTime = millis();       // считываем время, прошедшее с момента запуска программы
  loopTime = currentTime;  
 
  attachInterrupt(0, button1, CHANGE); // привязываем 0-е прерывание к функции blink().  Кнопка Старт. Pin2. При нажатии выполняется функция button1
  attachInterrupt(1, button2, CHANGE); // привязываем 1-е прерывание к функции blink().  Кнопка Стоп. Pin3
}

void loop(){
 
if (state==1) // проверка была ли нажата кнопка старт
{
  currentTime = millis();   // считываем время, прошедшее с момента запуска программы
   
  if(currentTime >= (loopTime + 5000)){              // сравниваем текущий таймер с переменной loopTime + 5 секунд
    digitalWrite(ledPin1, !digitalRead(ledPin1));   
    digitalWrite(ledPin2, !digitalRead(ledPin1));                 // включаем/выключаем LED
    loopTime = currentTime;                         // в loopTime записываем новое значение
 }   
}


else {
digitalWrite(ledPin1, LOW); 
digitalWrite(ledPin2, LOW); 
 }   
} 
 
 

void button1()
{
state=1;  // условие для зажигания диодов
 }
 
 
void button2()
{
state=0;
 }

 

Вот код с добавленным условием 

// Вар.12 Программа управления двумя светодиодными индикаторами (СД1 и СД2)с помощью 2х кнопок,
// по следующему алгоритму: Кнопка нажата – СД1 и СД2 переключаются попеременно через 20 сек,
// отпускание кнопки не приводит к прекращению работы СД. СД гаснут только при нажатии второй кнопки.




int ledPin1 = 10;  // LED подсоединен к выводу 10
int ledPin2 = 9;   // LED подсоединен к выводу 9

unsigned long currentTime;  // Текшее время
unsigned long loopTime;   //  Время цикла

int state =  0; // Статус LED. 1-переменно мигают, 0-не горят
int y =  0;
void setup()
{  
   pinMode(ledPin1, OUTPUT);      // устанавливаем вывод 10 как выход
   pinMode(ledPin2, OUTPUT);      // устанавливаем вывод 9 как выход
   pinMode(1, OUTPUT);
   
   
  currentTime = millis();       // считываем время, прошедшее с момента запуска программы
  loopTime = currentTime;  
 
  attachInterrupt(0, button1, CHANGE); // привязываем 0-е прерывание к функции blink().  Кнопка Старт. Pin2. При нажатии выполняется функция button1
  attachInterrupt(1, button2, CHANGE); // привязываем 1-е прерывание к функции blink().  Кнопка Стоп. Pin3
}

void loop(){
 
if (state==1) // проверка была ли нажата кнопка старт
{
  currentTime = millis();   // считываем время, прошедшее с момента запуска программы
   
  if(currentTime >= (loopTime + 5000) || y==1){              // сравниваем текущий таймер с переменной loopTime + 5 секунд
    digitalWrite(ledPin1, !digitalRead(ledPin1));   
    digitalWrite(ledPin2, !digitalRead(ledPin1));                 // включаем/выключаем LED
    loopTime = currentTime;                         // в loopTime записываем новое значение
    y=0;
 }   
}


else {
digitalWrite(ledPin1, LOW); 
digitalWrite(ledPin2, LOW); 
 }   
} 
 
 

void button1()
{
state=1;  // условие для зажигания диодов
y=1;
 }
 
 
void button2()
{
state=0;
 }





 

vov4ik
Offline
Зарегистрирован: 10.09.2013

Вот нравится вам кидать программу туда сюда, ведь написал как работает RS триггер

if( (digitalRead (2))) Q_RS = 1; // проверяем состояние кнопки пин 2

if( (digitalRead (3))) Q_RS = 0; // проверяем состояние кнопки пин 3

сдесь всё просто приоритет у кнопки 3, в вашем случае при нажатии одновременно двух кнопок что будет выполнено button1() или button2()

 простая мигалка

boolean v1 = 1;boolean v2 = 0;boolean v3 = 0;unsigned long v4 = 0;
boolean v5(unsigned long v6,unsigned long v7){unsigned long v8;v8=v6+v7;
return (millis()>=v8);}
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
if (v1){if(!v2){v2=1;v3=1;v4=millis();}}else{v2=0;v3=0;}if(v2){if(v3){if(v5(v4,500)){v4=millis();v3=0;}}
else{if(v5(v4,500)){v4=millis();v3=1;}}}digitalWrite(13,v3);
 }

в вашем случае мигалку поставить под истинность Q_RSdigitalWrite(13,v3); заменить на digitalWrite(10,v3); с инверсией digitalWrite(9,!v3); 500 заменить на ваши 20000

 

yaap89
Offline
Зарегистрирован: 04.12.2014

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