Задать вопрос
@Vlad0ss_Sh

Почему не работает программа Ардуино?

Всем привет. Начал увлекаться ардуинами несколько дней назад. Решил написать код, описывающий работу светофора. Суть - поморгать светодиодами, по нажатию кнопки - отключить весь свет. Изначально задержки написал на delay(), но из-за этого не работала кнопка, понятно почему. Переписал на счётчике millis(), кнопка заработала, а светодиоды вместе гаснут и включаются. Помогите, в чем проблема. Вот код:
//зададим исходные данные для счета millis()
uint32_t tmr1, tmr2, tmr3, tmr4;

uint32_t per1 = 3000;
uint32_t per2 = 500;
uint32_t per3 = 1500;

// инициализируем пины светодиода
const int RLED = 11;
const int YLED = 10;
const int GLED = 9;
// пин кнопки
const int BUT = 2;

boolean lastBUT = LOW; //переменная хранит предыдущее состояние кнопки
boolean currentBUT = LOW; //переменная хранит текущее состояние кнопки

int ledin = 0; //состояние светодиода (вкл, выкл)

//задаем флажки
boolean GLEDflag = false;

void setup() 
{
  pinMode(BUT, INPUT);
  pinMode(RLED, OUTPUT);
  pinMode(YLED, OUTPUT);
  pinMode(GLED, OUTPUT);
}
/*
* Функция сглаживания дребезга
* принимает в качестве аргумента предыдущее состояние конпки
* и выдает фактическое
*/

boolean debounce(boolean last) //задаем функцию, которая принимает только логическую переменную boolean last (последнее состояние кнопки)
{
  boolean current = digitalRead(BUT); //читаем конпку
  if (last != current) //сравниваем состояние, если отличаются, то...
  {
    delay(10); //ждем 10 мс
    current = digitalRead(BUT); //читаем кнопку еще раз
    return current; //возвращаем состояние кнопки
  }
}

void trLight(int mode)
{
  if (mode == 1)
  {
    digitalWrite(GLED, HIGH);
    if (millis() - tmr1 >= per1)
    {
      tmr1 = millis();
      digitalWrite(GLED, LOW);
    }
      for (int i = 0; i < 4; i++)
      {
        if (millis() - tmr2 >= per2)
        {
          tmr2 = millis();
          digitalWrite(GLED, GLEDflag);
          GLEDflag =! GLEDflag;
        }
      }
      digitalWrite(GLED, LOW);
      digitalWrite(RLED, HIGH);
      if (millis() - tmr3 >= per1)
      {
        tmr3 = millis();
        digitalWrite(YLED, HIGH);
      }
      digitalWrite(YLED, HIGH);
      if (millis() - tmr4 >= per3)
      {
        digitalWrite(RLED, LOW);
        digitalWrite(YLED, LOW);
      }
    }
  
  else
  {
    digitalWrite(RLED, LOW);
    digitalWrite(YLED, LOW);
    digitalWrite(GLED, LOW);
  }
}

void loop() 
{
  currentBUT = debounce(lastBUT); //вызываем функцию антидребезга кнопки
  if (lastBUT == LOW && currentBUT == HIGH)
  {
    ledin =! ledin;
  }
  lastBUT = currentBUT;
  trLight(ledin);

}
  • Вопрос задан
  • 91 просмотр
Подписаться 1 Простой Комментировать
Решения вопроса 1
Ocelot
@Ocelot
Похоже, вы в trLight() запихнули всю последовательность переключений, только заменив delay() на опрос таймеров. А должна быть логика немного другая: trLight() вызывается каждую (условно) миллисекунду, она должна один раз считать millis(), понять, какая сейчас фаза светофорного цикла, и в зависимости от этого погасить или зажечь нужные светодиоды. Сделайте функцию, у которой на входе текущее время, а на выходе — три бита состояния светодиодов.

И в debounce() осталась delay(), её тоже хорошо бы на таймерах сделать
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Vlad0ss_Sh Автор вопроса
Ocelot получилось решить, подсказку посмотрел в chat gpt. Решил применить switch() case(). millis() использую один раз, потом уже пробегаюсь по состояниям светодиодов. Вот решение. Однако, теперь хз, как использовать цикл для мигания зеленым светодиодом))) Приходится делать нижеприведенные костыли
// инициализируем пины светодиода
const int RLED = 11;
const int YLED = 10;
const int GLED = 9;

// пин кнопки
const int BUT = 2;

//режим работы светофора
int trmode = 0; //будет использоваться в switch case для переключения режима

uint32_t time0 = 5000; //время горения красного сигнала
uint32_t time1 = 1500; //время горения красного и желтого сигнала
uint32_t time2 = 3000; //время горения зеленого сигнала
uint32_t interval = time0; //присвоим по умолчанию интервал зеленого света
uint32_t prev = 0; //изначальное время, присвоим 0. Нужно для вычисления разницы

boolean lastBUT = LOW; //переменная хранит предыдущее состояние кнопки
boolean currentBUT = LOW; //переменная хранит текущее состояние кнопки

//для мигания зеленым светом
//boolean gFlag = false;
uint32_t timeblk = 500; //период мигания светодиодом
//int counter = 0;

int ledin = 1; //состояние светодиода (вкл, выкл)


void setup() 
{
  pinMode(BUT, INPUT);
  pinMode(RLED, OUTPUT);
  pinMode(YLED, OUTPUT);
  pinMode(GLED, OUTPUT);
  digitalWrite(RLED, HIGH); //красный по умолчанию

}
/*
* Функция сглаживания дребезга
* принимает в качестве аргумента предыдущее состояние конпки
* и выдает фактическое
*/

boolean debounce(boolean last) //задаем функцию, которая принимает только логическую переменную boolean last (последнее состояние кнопки)
{
  boolean current = digitalRead(BUT); //читаем конпку
  if (last != current) //сравниваем состояние, если отличаются, то...
  {
    delay(10); //ждем 10 мс
    current = digitalRead(BUT); //читаем кнопку еще раз
    return current; //возвращаем состояние кнопки
  }
}


void trLight(int mode)
{
  if (ledin == 1)
  {
    if (millis() - prev >= interval) //вычисляем разницу и сравниваем с заданным интервалом
    {
      prev = millis();
      switch(trmode)
      {
        case 0: //выключаем зеленый, включаем красный
          digitalWrite(GLED, LOW);
          digitalWrite(RLED, HIGH);
          interval = time0;
          trmode = 1; //смотрим случай 1
          break;
        case 1: //подключаем желтый
          digitalWrite(YLED, HIGH);
          interval = time1;
          trmode = 2; //смотрим случай 2
          break;
        case 2: //включаем зеленый
          digitalWrite(YLED, LOW);
          digitalWrite(RLED, LOW);
          digitalWrite(GLED, HIGH);
          interval = time2;
          trmode = 3; //смотрим случай 3
          break;
        case 3: //гасим на время переменной timeblk
          digitalWrite(GLED, LOW);
          interval = timeblk;
          trmode = 4;
          break;
        case 4: //включаем на время переменной timeblk
          digitalWrite(GLED, HIGH);
          interval = timeblk;
          trmode = 5;
          break;
        case 5: //гасим на время переменной timeblk
          digitalWrite(GLED, LOW);
          interval = timeblk;
          trmode = 6;
          break;
        case 6: //включаем на время переменной timeblk
          digitalWrite(GLED, HIGH);
          interval = timeblk;
          trmode = 7;
          break;
        case 7: //включаем на время переменной timeblk
          digitalWrite(GLED, LOW);
          interval = timeblk;
          trmode = 0;
          break;
      }
    }
  }

  else
  {
    digitalWrite(RLED, LOW);
    digitalWrite(GLED, LOW);
    digitalWrite(YLED, LOW);
  }
}

void loop() 
{
  currentBUT = debounce(lastBUT); //вызываем функцию антидребезга кнопки
  if (lastBUT == LOW && currentBUT == HIGH)
  {
    ledin =! ledin;
  }
  lastBUT = currentBUT;
  trLight(ledin);

}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы