Обработчик по кнопке и функция которая ему мешает.

ardunoob
Offline
Зарегистрирован: 22.04.2016

Здравствуйте. 

Помогите понять в чем дело. У меня в функции loop работает небольшой обработчик, который в зависимости от количества нажатий аппаратной кнопки запускает разные виды отображаемой информации. И все бы ничего, но на одной из функций он тупо не отрабатывает. Вопрос почему?

Обработчик:

void loop() {

MyDataOutput data = GetSensorsData();   //Получаю данные с датчиков
//ShowResultSerial(data);

buttonState = digitalRead(buttonPin);

  if (buttonState != lastButtonState) {
//Serial.print(buttonState);
//Serial.print( lastButtonState);
//Serial.println( buttonPushCounter);
    if (buttonState == HIGH) {
        display.clearScreen();
//        Serial.print(buttonState);
//        Serial.print( lastButtonState);
//        Serial.println( buttonPushCounter);
        buttonPushCounter++;
       }
delay(50);
}

if (buttonPushCounter > 2) {
    lastButtonState = 0;
    buttonPushCounter = 0;
   }
else {
     lastButtonState = buttonState;
    }

//В зависимости от количества нажатий вывожу разные отображения информации
switch (buttonPushCounter) {
    case 1:
      InfoMode(data);       
      break;
    case 2:
      GraphMode(data);
      break;
    default: 
      ClockMode(data); 
      LittleInfo(data);
    break;
  }

}

Функция, которая запустившись уже не видит нажатий и не позволяет перейти к началу. Если ее заменить другой, все работает отлично:

void GraphMode(MyDataOutput data) 
{
    
  //Выводим иконки  
  display.drawBitmap(0, 0, temp, 64, 49, WHITE);
  display.setTextSize(1);
  display.setCursor(100,10);
  display.print("0");
  display.setTextSize(3);
  display.setCursor(105,15);
  display.println("C");
  display.setTextSize(5);
  display.setCursor(35,65);
  display.print(data.avtemp,0);
  
  if (data.avtemp > 30) 
{
   display.fillRect(0, 125, 128, 5, RED);
  } 
else 
{
   display.fillRect(0, 125, 128, 5, GREEN);  
  }
  
  delay(5000);
  display.clearScreen();
  
  display.drawBitmap(0, 0, hum, 33, 45, WHITE);
  display.setTextSize(3);
  display.setCursor(105,15);
  display.println("%");
  display.setTextSize(5);
  display.setCursor(35,65);
  display.print(data.hum,0); 
   
  if (data.hum > 70 || data.hum < 30 ) 
{
   display.fillRect(0, 125, 128, 5, RED);
  } 
else 
{
   display.fillRect(0, 125, 128, 5, GREEN);  
  }
  
  delay(5000);
  display.clearScreen();
  
  display.drawBitmap(0, 0, CO2, 64, 50, WHITE);
  display.setTextSize(2);
  display.setCursor(85,15);
  display.println("ppm");
  display.setTextSize(5);

  if(data.co2 < 999)
  {
    display.setCursor(23,65);  
    }
  else 
  {
    display.setCursor(5,65);
    }
  display.print(data.co2,0); 

  if (data.co2 > 750) 
{
   display.fillRect(0, 125, 128, 5, RED);
  } 
else 
{
   display.fillRect(0, 125, 128, 5, GREEN);  
  }
  
  delay(5000);
  display.clearScreen();
  
  display.drawBitmap(0, 0, airpress, 40, 49, WHITE);
  display.setTextSize(3);
  display.setCursor(85,15);
  display.print(utf8rus("мм"));
  display.setTextSize(5);
  display.setCursor(23,65);
  display.print(data.ap,0); 

  if (data.ap > 750) 
{
   display.fillRect(0, 125, 128, 5, RED);
  } 
else 
{
   display.fillRect(0, 125, 128, 5, GREEN);  
  }
  
  delay(5000);
  display.clearScreen();
  
}

 

 
Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Проблема стопудово в delay(5000);

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

Ну, про delay(5000) Вам уже написали. Надеюсь, Вы достаточно долго ждёте, чтобы быть уверенным, что все эти задержки прошли?

Если Вы уверены, что дело не в delay, и Вы дожидаетесь, попробуйте в этой функции закомментировать все вызовы drawBitmap. Остальное оставьте на месте и посмотрите. что получится.

ardunoob
Offline
Зарегистрирован: 22.04.2016

Блин, это печаль, как еще организовать послайдовый показ я не знаю. То есть мне надо нажать кнопку в тот безумно маденький промежуток времени пока не запустился delay, во время которого ничего не отрабатывает? 

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

Т.е. Вы выяснили, что проблема именно в delay? Если подождать, пока всё кончится, то всё нормально работает?

ardunoob пишет:

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

Нет, нужно просто избаиться от delay и сделать без него.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ardunoob пишет:

Блин, это печаль, как еще организовать послайдовый показ я не знаю. 

Очень просто: избавляетесь от delay, в глобальной переменной запоминаете номер слайда и время старта его показа, в loop проверяете - не кончилось ли время продолжительности показа текущего слайда, если да - запоминаете время начала показа следующего слайда, и показывате следующий слайд. Две переменных и чутка кода - вот и всё.

ardunoob
Offline
Зарегистрирован: 22.04.2016

Цитата:
Т.е. Вы выяснили, что проблема именно в delay? Если подождать, пока всё кончится, то всё нормально работает?

Не совсем, я закомментировал delay и попробовал, поскольку функция вызывается в loop, то все крутится все равно в цикле, но в отличие от варианта с delay, если часто жать кнопку, то можно все-таки переключиться на первый режим.

ardunoob
Offline
Зарегистрирован: 22.04.2016

DIYMan пишет:

ardunoob пишет:

Блин, это печаль, как еще организовать послайдовый показ я не знаю. 

Очень просто: избавляетесь от delay, в глобальной переменной запоминаете номер слайда и время старта его показа, в loop проверяете - не кончилось ли время продолжительности показа текущего слайда, если да - запоминаете время начала показа следующего слайда, и показывате следующий слайд. Две переменных и чутка кода - вот и всё.

Звучит неплохо. С моим уровнем это будет сложно сделать, но я попоробую. Спасибо!

Две переменные это:

long previousMillis = 0;       
long interval = 5000;  
две глобальных переменных, и считывание времени запуска функции в самой функции и если функция работает больше пяти секунд показываем это, если 10 то это, если 15 это, так?

 

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

В качестве идеи:

if (millis() - previousMillis > interval)
{
  previousMillis = millis();
  switch (slide)
  {
    case 0: /*вывод слайда 0*/ break;
    case 1: /*вывод слайда 1*/ break;
    case 2: /*вывод слайда 2*/ break;
  }
  slide++;
}

 

ardunoob
Offline
Зарегистрирован: 22.04.2016

Andy пишет:

В качестве идеи:

...

Ага, по-моему должно сработать. Немного разгребусь и попробую. Спасибо!

ardunoob
Offline
Зарегистрирован: 22.04.2016

Все работает. 

Спасибо всем. AndyDIYMan, особенно.