Запуск сторонней функции в loop(), нужна помощь.

gatsby163
Offline
Зарегистрирован: 10.03.2014

Здравствуйте, помогите пожалуйста разобраться с кодом. Коротко о проекте: сбор показаний с датчиков с интервалом в 2с, и плюс решил на борту шим регулятор одной кнопкой замутить. Раздельно эти функции выполняются на ура, а вот вместе из-за delay, обработка кнопки тормозит...пробовал проводить измерения сторонней функцией, а шим оставить в loop, но ничего не вышло...я так и не понял как вызвать функцию которая ничего не возвращает в loop. Может сделать вывод в серийный монитор из результатов измериний в loop, а сторонняя функция будет проводить измерения и передавать результаты в loop?

#include "DHT.h"
#define DHTPIN 2   
#define DHTTYPE DHT11    
int vlagaPin = 3; 
int vlagaVal = 0; 
int switchPin = 8;
int ledPin = 11;
boolean lastButton = LOW;
boolean currentButton = LOW;
int ledLevel = 0;
DHT dht(DHTPIN, DHTTYPE);


void setup() {
    Serial.begin(9600); 
    dht.begin();
    pinMode(switchPin, INPUT);
   pinMode(ledPin, OUTPUT);
}
boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void loop() { 

    currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledLevel = ledLevel + 51;
  }
  lastButton = currentButton;
  
  if (ledLevel > 255) ledLevel = 0;
  analogWrite(ledPin, ledLevel);

//__________________________________
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  vlagaVal = analogRead(vlagaPin);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.println(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.println(" *C ");
  Serial.print("Vlagnost' ");
  Serial.println(vlagaVal);
delay(2000);
}
/*
void measurement() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  vlagaVal = analogRead(vlagaPin);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.println(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.println(" *C ");
  Serial.print("Vlagnost' ");
  Serial.println(vlagaVal);
delay(2000);
  
}*/

 

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

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

vde69
Offline
Зарегистрирован: 10.01.2016

не используй delay !!!

примерно так (пока недописано, но думаю принцеп понятен):

 

//*************************************************************************************************
// главный цикл
//*************************************************************************************************
void loop()
{
  unsigned long time_loop_new;  
  unsigned long time_pause;     
  int button_temp;              
  
  time_loop_new = millis();     // получим время начала цикла
 
  // --------------------------------------------------------------------------------------------
  // обработка управления кнопками, должена идти как можно ближе к началу цикла
  button_temp = getPressedButton();
  if (button_new != button_temp) {
    // изменилось состояние клавиатуры, запомним время и новое состояние
    button_new = button_temp;
    time_button_new = time_loop_new;
  }

  time_pause = getDelayTime(time_button_new, time_loop_new);
  if (time_pause <= BUTTON_TIME) { 
    // ожидание минимальной паузы
  }
  else {
    if (button_new != button) {
      // сотояния клавиатуры изменилось, минимальная пауза выдержана
      if (button_new == BUTTON_NONE) { 
        // кнопка отпущена
        // вызовем обработчик, при этом расчитаем время нажатие от события нажатия а не от нового события отпускания  
        OnKeyUp (button, getDelayTime(time_button, time_button_new));  
      }
      else if (button != BUTTON_NONE) { 
        // кнопка нажата, пока обработчик этого события мне не нужен, 
        // по тому, что кнопка SELECT обрабатывается по таймеру двумя разными способами        
        // здесь ничего не делаем, код оставляю для расширения в других проектах
      }
      else { 
        // смена нажатой кнопки на другую, пока обработчик этого события мне не нужен      
        // по тому, что мы работаем не по событию нажатия, а по событию отжатия
        // здесь ничего не делаем, код оставляю для расширения в других проектах
      }      
      // изменения клавиатуры отработаны, теперь запомним новое состояние
      time_button = time_loop_new; 
      button = button_new;
    }  
    else if ((button_new == button) && (button != BUTTON_NONE)) {
      // есть какая-то зажатая кнопка
      if ((button == BUTTON_SELECT) && (time_pause >= BUTTON_TIME_LONG)) { 
        // кнопка SELECT нажата достаточно долго для перехода в режим SETUP  
        // это пока не реализовано, мы пойдем другим путем и будем передовать время удержания в событие отжатия кнопки
        // здесь ничего не делаем, код оставляю для расширения в других проектах
      }
    }   
  }
  

  // --------------------------------------------------------------------------------------------
  // получение актуальной температуры
  time_pause = getDelayTime(time_temp, time_loop_new);
  if (time_pause > TIME_GET_THERMOMETR) { 
   // ReadThermometer(); 
  }


  // --------------------------------------------------------------------------------------------
  // поиск ошибок/аварий и схожих ситуаций, ищет неподконтрольный разогрев/остывание или отсутствие показаний с термопары


  // --------------------------------------------------------------------------------------------
  // расчет параметров для включения и выключения разогрева

  
  // --------------------------------------------------------------------------------------------
  // обновление экрана, это последнее...
  time_pause = getDelayTime(time_anime, time_loop_new);
  if (time_pause > TIME_ANIME) {
    time_anime = time_loop_new;
    screen_out(true, false, false);
  }
  else {
    screen_out(false, false, false);
  }
}

 

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

delay нужно выкинуть. Просто вход в ту часть кода, где происходит измерение датчиков нужно делать раз в 2 сек., вот так например:

#define INTRVAL1 2000
#define INTRVAL2 50
#define INTRVAL3 200
unsigned int t1=0;, t2=0, t3=0, time;
#define TIMER(t) (time-t)
#define CLRTIMER(t) (t=time)
void loop()
{
  time=milles();
  if (TIMER(t1)>INTERVAL1)
  {
    CLRTIMER(t1);
    //измерение датчиков
  }
  if (TIMER(t2)>INTERVAL2)
  {
    CLRTIMER(t2);
    //опрос кнопок
  }
  if (TIMER(t3)>INTERVAL3)
  {
    CLRTIMER(t3);
    //ШИМ
  }
}

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

gatsby163 пишет:

Со светодиодом еще понятно, у него есть 2 состояния которые можно отследить и посчитать millis()

Вы неправильно поняли пример. Для того, чтобы посчитать millis не нужно отслеживать состояние светодиода. Состояние в том примере отслеживается только для того, чтобы его инвертировать (если горит, то потушить; если не горит, то зажечь). С millis это не связано. Для подсчета millis нужно не состояние, а событие. В Вашем случае событием будет чтение с датчика. 

gatsby163
Offline
Зарегистрирован: 10.03.2014

Как мне отслеживать и каждый раз перезапускать чтение с датчика dht например?

P/s Спасибо, действительно, можно разбить программу на временные отрезки с помощью if...else/ сейчас попробую

gatsby163
Offline
Зарегистрирован: 10.03.2014

Получилось довольно таки просто. Теперь кнопка не тормозит и данные корректно приходят в серийный порт.

void loop() { 

    currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledLevel = ledLevel + 51;
  }
  lastButton = currentButton;
  
  if (ledLevel > 255) ledLevel = 0;
  analogWrite(ledPin, ledLevel);
unsigned long currentMillis = millis();

     if(currentMillis - previousMillis >= interval) {
    
    previousMillis = currentMillis;
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  vlagaVal = analogRead(vlagaPin);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.println(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(t);
  Serial.println(" *C ");
  Serial.print("Vlagnost' ");
  Serial.println(vlagaVal);

     }
}