Проблема с простым кодом(((

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Доброго времени суток!!!Друзья, суть вопроса следующая. Пишу для товарища код. Использую два датчика температуры DS18B20 и LCD дисплей. Измеряю температуру в двух разных точках и вывожу их на дисплей, также высчитываю перепад температуры между показаниями этих двух датчиков и вывожу на дисплей, с этим проблем никаких нет,все работает идеально. Далее обьявляю переменную ,она используется в роли уставки перепада, то есть двумя кнопками "+" и "-" увеличиваю ее значение или уменьшаю,при совпадении этой уставки и измеряемого перепада температур должен включиться компрессор(подключенный условно к pin12) и вывожу эту уставку на дисплей.С этим тоже порядок, все шикарно отрабатывает! Проблема в том, что для того чтобы компрессор при частом изменении перепада не включался и не выключался, мне нужно сделать так что при совпадении перепада и уставки он гарантированно работал минуты две, независимо от значения перепада и уставки,и чтоб я кнопками мог менять это значение. Расчитываю на Вашу помощь, так как реально зашел в тупик,но если удастся решить этот вопрос,то все получится!!!Использовал функцию delay и получается фигня конеечно же)))

DeN-iZ
Offline
Зарегистрирован: 04.04.2013
 if (dTReading>=b || dTReading<= -b  )
 { 
     
     digitalWrite(12,HIGH); 
      
 } 

dTReading - высчитываемый перепад двух датчиков

b - уставка,которую я меня кнопками

нужно чтобы при этом условии пин 12 оставался в состоянии HIGH какое то минимальное время,которое я могу менять нажатием кнопок

 

Araris
Offline
Зарегистрирован: 09.11.2012

А нужно ли Вам "какое-то минимальное время" ? Может лучше отталкиваться от разницы температур (я так понимаю, что включение компрессора ее уменьшает) ?

Как-то так :

if ( abs(dTReading) >= b )
{
digitalWrite(12,HIGH);
}

if ( abs(dTReading) < (b - bb) )  // где (b - bb) - желаемая начальная разница температур
{
digitalWrite(12,LOW);
}

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Спасибо за совет, интересный вариант,предложу товарищу!А если все таки по регулируемому времени, то как быть?Есть какие то варианты без прерываний, а то не разберусь!)))

Araris
Offline
Зарегистрирован: 09.11.2012

Ну, может быть таймер, например SimpleTimer Library for Arduino (http://playground.arduino.cc/Code/SimpleTimer)

Примерно так:

#include <SimpleTimer.h> 

SimpleTimer timer;

void setup()
{
timer.setInterval( 1000, TimerFired ); // TimerFired() будет вызываться каждую секунду, или как изволите.

/*

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

*/

}

void loop()
{

.....

timer.run();
}

 

void TimerFired()
{
// проверяем состояние компрессора, истекло ли минимальное время его работы, пишем что-нибудь на дисплей и т.д. 

}

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Вопрос, а что означает abs? Не совсем понял)

-Kostik-
Offline
Зарегистрирован: 20.06.2013

Вот код, попробуй его. Может где ошибся - я не компилировал его, писал "на коленке"... Обработку кнопок для изменения MinWorkTime, я думаю, напишешь сам)))

boolean MotorInWork = false;
int MinWorkTime = 30; // в секундах
unsigned long deltatime, time, starttime;

if (abs(dTReading)>=b) { // это вместо if (dTReading>=b || dTReading<= -b)
  if (!MotorInWork) {
    MotorInWork = true;
    WorkTime = MinWorkTime * 1000; // в миллисекундах
    // делаем пересчет времени здесь, чтобы оно не менялось
    // в процессе работы компрессора
    digitalWrite(12,HIGH); // включаем
    starttime = millis(); //засекаем время
  }
}
if (MotorInWork) {
  time = millis();
  // вычисляем время работы
  if (starttime > time) {
    deltatime = 4294967295ul - starttime + time;
  }
  else {
    deltatime = time-starttime;
  }
  if ((deltatime >= WorkTime) && (abs(dTReading)<b) { 
    // выключаем, если перепад температур близок к уставке
    // и компрессор проработал минимальное время
    MotorInWork = false;
    digitalWrite(12,LOW); // выключаем
  }
}

 

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Ух ты !!!Куча незнакомых слов)Обработку кнопок напишу!)

Кстати int MinWorkTime = 30; значение в секундах? или в миллисекундах?

Завтра на работе попробую код, сразу отпишу как прошло!!!

leshak
Offline
Зарегистрирован: 29.09.2011

Если честно, детально не вчитывался, но если вам нужно "какое то минимальное время,которое я могу менять нажатием кнопок", то сделайте, после включения насоса банальное "delay(2000);". И все. 2секунды, скетч будет стоять и ничего не делать (ни кнопки не опрашивать, ни датчики.... ничего).

-Kostik-
Offline
Зарегистрирован: 20.06.2013

DeN-iZ пишет:
Кстати int MinWorkTime = 30; значение в секундах? или в миллисекундах?

Я предвидел этот вопрос))) После объявления переменной MinWorkTime в комментариях написано "в секуднах"

DeN-iZ пишет:
Завтра на работе попробую код, сразу отпишу как прошло!!!

Удачи!

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Так в том то и дело, что программа ничего не будет делать и компрессор будет включен всегдя и этот "delay(2000);" никогда не закончится, так как не будут опрашиваться датчики и условие на включение компрессора всегда будет выполняться!!!!!!!!!!!

Araris
Offline
Зарегистрирован: 09.11.2012

DeN-iZ пишет:

Так в том то и дело, что программа ничего не будет делать и компрессор будет включен всегдя и этот "delay(2000);" никогда не закончится, так как не будут опрашиваться датчики и условие на включение компрессора всегда будет выполняться!!!!!!!!!!!

Зря Вы это написали, delay(2000) закончится ровно через 2000 миллисекунд.

leshak
Offline
Зарегистрирован: 29.09.2011

DeN-iZ пишет:

"delay(2000);" никогда не закончится,

Это как? С чего вы взяли? Он закончится через две секунды. После чего вернет управление скетчу.

leshak
Offline
Зарегистрирован: 29.09.2011

Я конечно могу заподозрить, что вы просто постоянно включаете двигатель (даже когда он включен), поэтому у вас ПОСТОЯННО вызвается delay(2000) и поэтому "никогда не кончается", но может лучше не в угадайку будем играть, а вы код покажете?

leshak
Offline
Зарегистрирован: 29.09.2011

А вообще, такие вещи, чаще решают через реализацию Гистерезис — Википедияг (та же логика, как цифровые пины логический ноль и едницу)

var t=read_temperature();

if(t>15){
   digitalWrite(MOTOR_PIN,HIGH);
}

if(t<10){
   digitalWrite(MOTOR_PIN,LOW);
}

Вот при таких раскладах, в диапазоне от 10 до 15-ти, мотор не будет переключатся. Образуется как-бы "серая зона". Внутри нее температура может гулять, не вызвая срабатываний.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Обязательно завтра покажу код, просто проект на работе находится! К чему написал про "никогда не закончится delay" (понятно что он закончится через значение указанное в скобках))) Просто при использовании delay получалось следующее : при совпадении перепада и уставки включался компрессор,сразу же вступала в силу команда delay ,а так как во время делея прога ничего не может делать , то и стоит опрос датчиков и поэтому прога их не успевает опросить (на каждый DS18B20  750 мс нужно на опрос) и компрессор всегда в HIGH!!!Дйатчики как бы залипают в последнем положении ,я это имел ввиду и так мне показалось по работе программы)

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

С понятием Гистерезис знаком, сам КИПовец)))

-Kostik-
Offline
Зарегистрирован: 20.06.2013

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

DeN-iZ, я у себя в коде опечатку в объявлении переменной исправил, сохрани себе код заново...

leshak
Offline
Зарегистрирован: 29.09.2011

DeN-iZ пишет:

а так как во время делея прога ничего не может делать , то и стоит опрос датчиков и поэтому прога их не успевает опросить (на каждый DS18B20  750 мс нужно на опрос) и компрессор всегда в HIGH!!!)

А зачем ей их опрашивать, если все равно в этот момент ничего нельзя делать/переключать?

Как delay() может мешать датчикам. Ну нужно им 750 мс. - ну так это же будет "после" того как delay отработает. 

Кстати с  "им нужно", может означать и совершенно другое - нельзя опрашивать их слишком часто. Особенно при схеме паразитного питания (просто не успевают конденсаторы зарядится).

Скорее всего, вы именно делаете что-то типа

loop(){
   ... чтение датчиков...

   if(УСЛОВИЕ_ВКЛЮЧЕНИЯ_МОТОРА){
      digitalWrite(..,HIGH);
      delay(2000)
   } else {
     digitalWrite(..,LOW);
  }
}

И у вас, просто постоянно включается постоянно delay(2000)

P.S. Случайно отправил, "продолжение будет..."

leshak
Offline
Зарегистрирован: 29.09.2011

Если у вас вкоде нечто подобное тому что я описал в прошлом посте, то вам нужно доавить условие - включаеть delay не на "мотор должен быть включен", а на "мотор должен быть включен, а сейчас он выключен". Вообщем нужно ловить событие изменения состояния.

Примерно так:

bool prevMotorState; // состояние мотора при прошлом проходе loop()

loop(){
  ... чтение датчиков...
  bool isMotorOn=УСЛОВИЕ_ВКЛЮЧЕНИЯ_МОТОРА;
  digitalWrite(MOTOR_PIN,isMotorOn); // включаем или выключаем мотор

  if(!prevMotorState && isMotorOn){ // был выключен и включился
     delay(2000);
  }

  prevMotorState=isMotorOn;
}

 

-Kostik-
Offline
Зарегистрирован: 20.06.2013

leshak пишет:
А зачем ей их опрашивать, если все равно в этот момент ничего нельзя делать/переключать?

Может показания датчиков нужны для вывода на экран "в динамике процесса", чтобы видеть, как влияет включение компрессора на температуру.

leshak
Offline
Зарегистрирован: 29.09.2011

-Kostik- пишет:

leshak пишет:
А зачем ей их опрашивать, если все равно в этот момент ничего нельзя делать/переключать?

Может показания датчиков нужны для вывода на экран "в динамике процесса", чтобы видеть, как влияет включение компрессора на температуру.

Может. А тут мы пошлем топикстартера читать пример "мигаем диодом без delay()" :) 

Это же уже и есть "угадалки". Сложность нужно вводить, только если она действительно нужна.

Тем более что это не сложно:)

bool prevMotorState; // состояние мотора при прошлом проходе loop()
unsigned long changeTime;// время когда мотор изменил свое состояние

loop(){
  ... чтение датчиков...
  if(millis()-changeTime>2000){ // работаем с мотором, только если прошло 2сек с последнего переключения
    bool isMotorOn=УСЛОВИЕ_ВКЛЮЧЕНИЯ_МОТОРА;
    digitalWrite(MOTOR_PIN,isMotorOn); // включаем или выключаем мотор
    if(prevMotorState!=isMotorOn)changeTime=millis(); // запомнили когда состояние изменилось

     prevMotorState=isMotorOn;
   }
}

Я тут чуток изменил логику. "Засекаю время" не только в момент включения, но и выключения. Что-бы была пауза и после выключения. "Вырубить" и "сразу врубить" тоже для мотора может быть не очень хорошо.

DeN-iZ
Offline
Зарегистрирован: 04.04.2013
loop(){
   ... чтение датчиков...

   if(УСЛОВИЕ_ВКЛЮЧЕНИЯ_МОТОРА){
      digitalWrite(..,HIGH);
      delay(2000)
   } else {
     digitalWrite(..,LOW);
  }
}

Вы правы, я именно так и пробовал с делеем!

DeN-iZ
Offline
Зарегистрирован: 04.04.2013

Господа,наконец дошел до компьютера!Остановился на варианте с гистерезисом, добавил кнопки,вообщем все хорошо отрабатывает!Благодарю всех Вас за помощь!!!!!!!!!