Светофор для школы

Legionerio
Offline
Зарегистрирован: 04.02.2019

Задача следующая: сделать для начальной школы макет светофора
несколько режимов чтоб работал с пульта

1) обычный дорожный

2) пешеходный

3) желтый мигающий

Т.К я валянок в этом деле сразу же столкнулся с непреодолимой задачей выхода из цикла

Вот как это выглядит в моем понимании, но пока  работает do....while я не могу выключить и перейти к другой задаче.

#include "IRremote.h"

IRrecv irrecv(7);    // указываем вывод, к которому подключен приемник

decode_results results;

int RedLed = 9;             // Порт 9, красный светодиод
int YelLed = 10;             // Порт 10, желтый светодиод
int GrnLed = 3;             // Порт 3, зеленый светодиод

long Previous = 0;  // устанавливаем значение Mills() от которого будем считать
     


long Time_0 = 0;              // момент зажигания красного сетодиода
long Time_1 = 500;          // момент зажигания желтого сетодиода (красный горит)
long Time_2 = 1000;          // момент зажигания зеленого (красный и желтый гасим)
long Time_3 = 1500;          // гасим зеленый
long Time_4 = 1700;          // зажигаем зеленый,
long Time_5 = 1800;          // гасим зеленый
long Time_6 = 1900;          // зажигаем зеленый,
long Time_7 = 2000;          // гасим зеленый
long Time_8 = 2100;          // зажигаем зеленый,
long Time_9 = 2200;          // момент зажигания желтого сетодиода (зеленый гасим)
long Time_10 = 2500;         // гасим желтый

int val=0;



void setup()
{
  pinMode(RedLed, OUTPUT);   
  pinMode(YelLed, OUTPUT);
  pinMode(GrnLed, OUTPUT);
  pinMode(7, INPUT);

  digitalWrite(RedLed, LOW);
  digitalWrite(YelLed, LOW);
  digitalWrite(GrnLed, LOW);
  
  Serial.begin(9600); // выставляем скорость COM порта
  irrecv.enableIRIn(); // запускаем прием
  
   
}  
void loop(){
  Serial.println( results.value, HEX );
     // печатаем данные
    if ( irrecv.decode( &results )) { // если данные пришли
  

  switch ( results.value ) {
  case 0x202B04F: // Код с пульта
  
  if (millis() - Previous > 100)
  Previous = millis();     // устанавливаем новое состояние previous
  {
        int g = 0;
        do {
    for (val=0; val <2500; val++){

        if (val == Time_0)
       {
         digitalWrite(RedLed, HIGH);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW);
       }
 
       if (val == Time_1)
       {
         digitalWrite(RedLed, HIGH);
         digitalWrite(YelLed, HIGH);
         digitalWrite(GrnLed, LOW);
       }

       if (val == Time_2)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, HIGH);
       }       

       if (val == Time_3)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW);
       } 

       if (val == Time_4)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, HIGH);
       } 

       if (val == Time_5)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW);
       } 

       if (val == Time_6)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, HIGH);
       } 

       if (val == Time_7)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW);
       } 

       if (val == Time_8)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, HIGH);
       } 

       if (val == Time_9)
       {
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, HIGH);
         digitalWrite(GrnLed, LOW);
       } 

       if (val == Time_10)
       {
         val=0;
         digitalWrite(RedLed, HIGH);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW);
         
       } 
       }
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW); 
        g++;
        }while (g < 3);
      
       }
       
break;
case 0x20240BF: // Код с пульта
         digitalWrite(RedLed, LOW);
         digitalWrite(YelLed, LOW);
         digitalWrite(GrnLed, LOW); 
break;

}         

irrecv.resume(); // принимаем следующую команду 
}
}

МОЖЕТ кто сталкивался, помогите разобраться, нифига не понимаю. 

sadman41
Offline
Зарегистрирован: 19.10.2016

А Вы у нас в школе кто?

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

не понял, надо прервать do..while в какой-то момент ?

Legionerio
Offline
Зарегистрирован: 04.02.2019

sadman41 пишет:

А Вы у нас в школе кто?

Я, у нас в школе - отец учащегося, и тк я занимаюсь рекламой, я распечатал и сделал рамку для макета "режимов работы светофора", но она же должна работать. Глянул светофоры эти делают школьники, ну собственно с delay и я могу сделать, но тогда тоже не работает. И с дуру купил эту "ардуину" и убил выходные на это дело и собственно ничего не получилось. Очень хочется это все выбросить в мусор, но как то самому интересно стало, но пока не доганяю

Legionerio
Offline
Зарегистрирован: 04.02.2019

xDriver пишет:

не понял, надо прервать do..while в какой-то момент ?

Пока крутится do..while кнопки пульта не реагируют

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

ну правильно, все четко по алгоритму программы...

Legionerio
Offline
Зарегистрирован: 04.02.2019

xDriver пишет:

ну правильно, все четко по алгоритму программы...

В какую сторону копать, что я не так понял???? 

sadman41
Offline
Зарегистрирован: 19.10.2016

Если кратко, то в сторону конечных автоматов. И это будут не первые выходные, убитые на данный прожект.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

да все вы так поняли, пока крутится do..while кнопки пульта вы не опрашиваете

нужна реорганизация алгоритма

Legionerio
Offline
Зарегистрирован: 04.02.2019

sadman41 пишет:

Если кратко, то в сторону конечных автоматов. И это будут не первые выходные, убитые на данный прожект.

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

Legionerio
Offline
Зарегистрирован: 04.02.2019

xDriver пишет:

да все вы так поняли, пока крутится do..while кнопки пульта вы не опрашиваете

нужна реорганизация алгоритма

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

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Legionerio пишет:

sadman41 пишет:

Если кратко, то в сторону конечных автоматов. И это будут не первые выходные, убитые на данный прожект.

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

на форум надо писать когда не  получается что-то сделать самому,нет понимания при приложении усилий, а если не получается искать - писать надо в гуголь.

mixail844
Offline
Зарегистрирован: 30.04.2012

может ненадо сразу " автоматы " ?  достаточно повесить прием на прерывания ?  

алгоритмически не правильно и на реальном устройстве такое делать не рекомендуеться, но и тут не ракетостроение..

в код сильно не вникал.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

mixail844 пишет:

может ненадо сразу " автоматы " ? 

Вот именно через автоматы. Прерывания это когда человек ну совсем далек от всего. #258

sadman41
Offline
Зарегистрирован: 19.10.2016

IRRemote на внешние прерывания не привешивается, она по прерыванию таймера фунциклирует. Не ставьте перед человеком невыполнимую задачу.

sadman41
Offline
Зарегистрирован: 19.10.2016

Legionerio пишет:

sadman41 пишет:

Если кратко, то в сторону конечных автоматов. И это будут не первые выходные, убитые на данный прожект.

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

Для Вас (как начинающего) это полноценный и непростой проект - поверьте мне.

И, прошу, не заходите на форум с надеждой на то, что тут вы найдете что-то, чего не было в другом интернете. Здесь нет потайной комнаты с готовыми скетчами на все случаи жизни и дежурного по казарме, который подпрыгнет и побежит решать Вашу проблему.

Legionerio
Offline
Зарегистрирован: 04.02.2019

qwone пишет:

mixail844 пишет:

может ненадо сразу " автоматы " ? 

Вот именно через автоматы. Прерывания это когда человек ну совсем далек от всего. #258

Это как раз мой случай. Я очень далек от этого и ардуину эту в пятницу вечером на почте забрал. 

Буду курить автоматы ....

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Пух, срочно нужен класс "СВЕТОФОР", тема всплывает каждый месяц !

Legionerio
Offline
Зарегистрирован: 04.02.2019

sadman41 пишет:

Legionerio пишет:

sadman41 пишет:

Если кратко, то в сторону конечных автоматов. И это будут не первые выходные, убитые на данный прожект.

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

Для Вас (как начинающего) это полноценный и непростой проект - поверьте мне.

И, прошу, не заходите на форум с надеждой на то, что тут вы найдете что-то, чего не было в другом интернете. Здесь нет потайной комнаты со скетчами и дежурного по казарме, который подпрыгнет и побежит решать Вашу проблему.

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

 

b707
Offline
Зарегистрирован: 26.05.2017

xDriver пишет:

Пух, срочно нужен класс "СВЕТОФОР", тема всплывает каждый месяц !

не нужен. Эта тема не только "всплывает". она и разжевана уже неоднократно.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Ну не так все страшно - в цикле while() можно опрашивать пульт и по принятию сигнала вываливаться из цикла командой break. Чтобы считанное значение не тарялось надо поставить ключик, что значение уже было считано, проверить в 53 строке и по проходу ее ключик обнулить. Цикл for конечно отработает полностью, но из while свалите.

Legionerio
Offline
Зарегистрирован: 04.02.2019

b707 пишет:

xDriver пишет:

Пух, срочно нужен класс "СВЕТОФОР", тема всплывает каждый месяц !

не нужен. Эта тема не только "всплывает". она и разжевана уже неоднократно.

то что я видел это в основном delay или с использованием библиотек Meander и Timer_P

Но опять же, если его завтавить 3 раза прокрутится это уже счетчик, for или дл. а у меня, во всяком случае когда пробовал из этого цикла не выходит с нажатием кнопки пульта. 

Так что пока варианты мне не подходят

Legionerio
Offline
Зарегистрирован: 04.02.2019

mykaida пишет:

Ну не так все страшно - в цикле while() можно опрашивать пульт и по принятию сигнала вываливаться из цикла командой break. Чтобы считанное значение не тарялось надо поставить ключик, что значение уже было считано, проверить в 53 строке и по проходу ее ключик обнулить. Цикл for конечно отработает полностью, но из while свалите.

Пробовал, внутрь цикла в do..... while ставил:
 

      break;
      case 0x202807F:

Тоже самое нет реакции

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Legionerio пишет:
беда в том что я не могу найти примеры

Беда - это когда на пиво аллергия, а примеры ... 

Вот здесь, начиная со стр. 8, написано как грамотно делать светофор. Там нет готовой программы, но идея описана так подробно, что осталость только её на ЯП перевести. Изучайте. Это реально грамотный подход.

b707
Offline
Зарегистрирован: 26.05.2017

Legionerio пишет:

если его завтавить 3 раза прокрутится это уже счетчик, for или дл. а у меня, во всяком случае когда пробовал из этого цикла не выходит с нажатием кнопки пульта. 

Так что пока варианты мне не подходят

Простите, но написана откроенная дурость. Никаких принципиально иных вариантов вы не найдете  Вам надо свыкнуться с мыслью, что циклы так или иначе вам использовать придется. И поэтому надо учиться задействовать их так, чтобы они не блокировали программу.

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Legionerio пишет:

Тоже самое нет реакции

Забавно, а в какую строчку ставили, что не отреагировало?

Вам-то, вообще-то надо досконально изучить 50 строку и последовать совету Евгения Петровича.

bwn
Offline
Зарегистрирован: 25.08.2014

А я бы, для начала, посоветовал IR кнопочкой заменить. ИМХО.

KindMan
Offline
Зарегистрирован: 19.12.2018

Вот небольшой пример режима дорожный

// Текущий режим работы светофора
enum State : int {OFF, CAR, WALK, YELLOW}; 
enum Light : uint8_t {WAIT, ON_RED, OFF_RED, ON_YELLOW, OFF_YELLOW, ON_GREEN, OFF_GREEN, RETURN};

// Временные интервалы работы в режиме дорожный
const PROGMEM long TIME_TABLE[]  = {             1,         1,      1000,   1000,     1,        1,    5000,  500,      500,      500,      500,      500,       1,    1500,    1,      5000   };
const PROGMEM uint8_t ACTION_TABLE[]  = {OFF_GREEN, OFF_YELLOW, ON_RED,ON_YELLOW,ON_GREEN,OFF_RED,OFF_YELLOW,WAIT,OFF_GREEN,ON_GREEN,OFF_GREEN,ON_GREEN,OFF_GREEN,ON_YELLOW,ON_RED, OFF_YELLOW, RETURN};

State traffic;
Light lights;

const int RedLed = 9;             // Порт 9, красный светодиод
const int YelLed = 10;             // Порт 10, желтый светодиод
const int GrnLed = 3;             // Порт 3, зеленый светодиод

long TimeDelay = 0;  
long CurrentDelay = 0;
uint8_t CurrentStep = 0;

void setup()
{
    pinMode(RedLed, OUTPUT);   
    pinMode(YelLed, OUTPUT);
    pinMode(GrnLed, OUTPUT);
  
    traffic = CAR;
    CurrentStep = 0;
    CurrentDelay = pgm_read_word_near(TIME_TABLE+CurrentStep);
    lights = pgm_read_word_near(ACTION_TABLE+CurrentStep);
    TimeDelay = millis();
   
}  

void ChangeLight(){
 switch (lights) { 
  case WAIT:
    if (WaitTime(CurrentDelay)) {
     CurrentStep++;
     lights = pgm_read_word_near(ACTION_TABLE+CurrentStep);
     Serial.print("LIGHT - ");
     Serial.println(lights);
     return;
    } 
   else {
    return; 
   }
  break;
  case ON_RED:
    digitalWrite(RedLed, HIGH);
  break;
  case OFF_RED:
    digitalWrite(RedLed, LOW);
  break;
  case ON_YELLOW:
    digitalWrite(YelLed, HIGH);
  break;
  case OFF_YELLOW:
    digitalWrite(YelLed, LOW);
  break;
  case ON_GREEN:
     digitalWrite(GrnLed, HIGH);
  break;
  case OFF_GREEN:
     digitalWrite(GrnLed, LOW);
 break;
  case RETURN:
      CurrentStep = 0;
  break;
   }
   lights = WAIT;
   CurrentDelay = pgm_read_word_near(TIME_TABLE+CurrentStep);  
   TimeDelay = millis();
}

int WaitTime(int timeDelay) {
 if((millis() - TimeDelay) < timeDelay) {
    return 0;
 } else { 
    return 1;
 }
}

void loop(){
switch (traffic) {
  case OFF:
  break;

  case CAR:
    ChangeLight();
  break;
 }
}

https://youtu.be/Ou50ASKA5aA

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

xDriver пишет:

Пух, срочно нужен класс "СВЕТОФОР", тема всплывает каждый месяц !

А как бы это продать? У меня лежит пять плат, сделанных как-то с мыслью "вдруг понадобится". Не понадобилось, местные рекламщики обещали-обещали и на вынаобещали. Так и не могут заказы найти, хотя тоже ухо лечили про кучу школ.

4 года прошло.

Питание от 24, плата с местами под установку оптронов/транзистора для синхронизации, и есть скетч под nRF24. Короче синхро по кабелю или радио. Хотя могу и управление ИК написать. Благовещенск, Амурская область.

Legionerio
Offline
Зарегистрирован: 04.02.2019

KindMan пишет:

Вот небольшой пример режима дорожный

// Текущий режим работы светофора
enum State : int {OFF, CAR, WALK, YELLOW}; 
enum Light : uint8_t {WAIT, ON_RED, OFF_RED, ON_YELLOW, OFF_YELLOW, ON_GREEN, OFF_GREEN, RETURN};


https://youtu.be/Ou50ASKA5aA

Спасибо большое за пример, теперь буду разбираться как это работает и как всунуть туда пульт

KindMan
Offline
Зарегистрирован: 19.12.2018

У меня там изначально заложено был пульт, но не хватило времени. Там ещё лишние строки про Serial, забыл убрать… Меняйте traffic пультом, текущий режим, и подставите пешехода и желтый. Желтый это вообще пример стандартный блинк без делэй. Успехов.

Legionerio
Offline
Зарегистрирован: 04.02.2019

KindMan пишет:
У меня там изначально заложено был пульт, но не хватило времени. Там ещё лишние строки про Serial, забыл убрать… Меняйте traffic пультом, текущий режим, и подставите пешехода и желтый. Желтый это вообще пример стандартный блинк без делэй. Успехов.

 

Это мне на пару дней сначала вкурить как это работает, а потом что-то менять ))))) Спасибо, что откликнулись.

KindMan
Offline
Зарегистрирован: 19.12.2018

Если это просто проект на один раз, зачем вкуривать, добавляйте сюда оставшиеся режимы.
Таблицы вверху содержат состояния ламп, которые переключаются в процедуре changelight, через количество миллисекунд, которые указаны выше. Что в setupe ниже настройки выходов включает режим сфетофора, перенесите этот кусок в то место, где обработаете нажатие кнопки пульта.
Выложите, что получилось, как время появится, я вам помогу, просто не за компом, дома к ночи прихожу. А проекты для садов и школ делал, знаю что это.

Legionerio
Offline
Зарегистрирован: 04.02.2019

KindMan пишет:
Если это просто проект на один раз, зачем вкуривать,

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

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Legionerio пишет:

Охото разобраться как это работает.

 еще бы знать где это все обрабатывать кнопкой с пульта ))))

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Я бы еще 56-58 посоветовал проанализировать, чтобы не делать так больше.

Legionerio
Offline
Зарегистрирован: 04.02.2019

KindMan пишет:
Если это просто проект на один раз, зачем вкуривать, добавляйте сюда оставшиеся режимы. Таблицы вверху содержат состояния ламп, которые переключаются в процедуре changelight, через количество миллисекунд, которые указаны выше. Что в setupe ниже настройки выходов включает режим сфетофора, перенесите этот кусок в то место, где обработаете нажатие кнопки пульта. Выложите, что получилось, как время появится, я вам помогу, просто не за компом, дома к ночи прихожу. А проекты для садов и школ делал, знаю что это.

 

Так я и не понял нифига куда там пульт цеплять - видимо не мое это

Legionerio
Offline
Зарегистрирован: 04.02.2019

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

LIGHT - 4
LIGHT - 1
LIGHT - 3 и тд.

если убираю строку опроса irrecv.resume(); включается и работает, но без опроса кнопок я же не смогу выключить его

void loop(){
 
 if ( irrecv.decode( &results )) { // если данные пришли
  switch ( results.value ) {
   case 0x202B04F: // Код с пульта
   traffic = CAR;
switch (traffic) {
  case OFF:
  break;
  case CAR:
    ChangeLight();
  break; 
 }
 }
irrecv.resume(); // принимаем следующую команду 
}         
}
 
Legionerio
Offline
Зарегистрирован: 04.02.2019

KindMan пишет:
У меня там изначально заложено был пульт, но не хватило времени. Там ещё лишние строки про Serial, забыл убрать… Меняйте traffic пультом, текущий режим, и подставите пешехода и желтый. Желтый это вообще пример стандартный блинк без делэй. Успехов.

СПАСИБО, тебе добрый человек, что не прошел мимо. Я по маленьку начал догать, что происходит, 

void loop(){
 
if ( irrecv.decode( &results )) { // если данные пришли
switch ( results.value ) {
  case 0x202B04F: // Код с пульта
   traffic = CAR;
TimeDelay = millis();
CurrentStep =0;
      break;
case 0x20240BF:
traffic = OFF;
TimeDelay = 0;
CurrentStep = 4;
digitalWrite(YelLed, LOW);
digitalWrite(GrnLed, LOW);
digitalWrite(RedLed, LOW);
    break;
}
irrecv.resume(); // принимаем следующую команду
} 

switch (traffic) {
  case OFF:
  break;
  case CAR:
  ChangeLight();
  break;
}
}

Может и не правильно, но все работает и стартует с красного всегда.

Буду дальше разбирать теперь саму функцию  ChangeLight()   - Даже стало интересно!

А светофоры я заказал!