Вопрос по программе управления сенсорным монитором

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

Здравтсвуйте товарищи!

У меня опять возник вопрос по управлению реле с помощью Arduino через сенсорный монитор Nexion.

Суть вопроса:

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

У меня получается следующее: при нажатии кнопки реле срабатывает и "Залипает". НО при нажатии кнопки (кнопка с фиксацией) реле выключается и и цикл можно повторить по новой.

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

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

Скетч ардуино

String incStr;

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);
}

void loop() {
  if (Serial.available()) {
    char inc;
    inc = Serial.read();
    incStr += inc;
    if (inc == 0x0A) {
      AnalyseString(incStr);
      incStr = "";
    }
  }
}

void AnalyseString(String incStr) {
  if (incStr.indexOf("bt0-on") >= 0) {
    digitalWrite(2, LOW);
  } else if (incStr.indexOf("bt0-off") >= 0) {
    digitalWrite(2, HIGH);
  }
  if (incStr.indexOf("b2") >= 0) {
    digitalWrite(3, HIGH);
  } else 
{
    digitalWrite(3, LOW);
  }

}

void SendData(String dev, String data)
{
  Serial.print(dev);
  Serial.print("=");
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

Скетч Nexion Editor

Для кнопки с фиксацией bt0

If(bt.0val==1)
{
print "bt0-on"
printf od oa
}else
{
print "bt0-off"
printh od oa
}

Скетч для кнопки без фиксации

print "b2"
printh od oa

Очень прошу разъяснить в чем проблемма.

 Спасибо!

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

Dсе логично.

У вас при нажатии на кнопку b2 отправляется сигнал "b2", поэтому реле включается. А вот событие "отжатие кнопки" никакого нового сигнала не создает и потому отследить его не так просто. Вам нужно переделать логику работы кнопки в Nextion, чтобы в момент отключения кнопка тоже генерила сигнал.

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

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

b707 пишет:

Dсе логично.

У вас при нажатии на кнопку b2 отправляется сигнал "b2", поэтому реле включается. А вот событие "отжатие кнопки" никакого нового сигнала не создает и потому отследить его не так просто. Вам нужно переделать логику работы кнопки в Nextion, чтобы в момент отключения кнопка тоже генерила сигнал.

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

Спасибо за совет, помогло!

 

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

В продолжении темы.

Решил реализовать функцию Millis вместо delay (работает в скетче и железе нормально) на основе вот этого примера:

http://arduino-diy.com/arduino-Ispolzuyem-funktsii-delay-i-millis-pravilno


unsigned long led1OnTime;

bool led1On;

void setup() {
  
pinMode(3, OUTPUT);

pinMode(2, INPUT);

led1On = false;

}

void loop(){

if (digitalRead(2) == HIGH) {

digitalWrite(3, HIGH);

led1On = true;

led1OnTime = millis();

}

if(led1On)

if(millis() - led1OnTime > 3000) {

digitalWrite(3, LOW);

led1On = false;

}

}

Мой скетч под сенсорный монитор


unsigned long led1OnTime = 0;

bool led1On;

String incStr;

void setup() {
  
  Serial.begin(9600);
  
  pinMode(3, OUTPUT); 
  
  led1On = false;
 }
  
void loop() {
  
  if (Serial.available()) {
    char inc;
    inc = Serial.read();
    incStr += inc;
    if (inc == 0x0A) {
      AnalyseString(incStr);
      incStr = "";
    }
  }
}

void AnalyseString(String incStr) {
  
    if (incStr.indexOf("b1") >= 0) { 
    digitalWrite(3, HIGH);
      } if (incStr.indexOf("b2") >= 0) {
    digitalWrite(3, LOW);
    
    led1On = true;

led1OnTime = millis();

}

if(led1On)

if(millis() - led1OnTime > 5000) {

digitalWrite(3, LOW);

led1On = false;

}
}

void SendData(String dev, String data)
{
  Serial.print(dev);
  Serial.print("=");
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

В моем случае ничего не происходит - при нажатии кнопки на мониторе диод загорается, при отпускании гаснет. задержки не происходит.

По сути строка 

    if (incStr.indexOf("b1") >= 0) { 
    digitalWrite(3, HIGH);
      } if (incStr.indexOf("b2") >= 0) {
    digitalWrite(3, LOW);

симмулирует обычную тактовую кнопку поэтому разницы то и нет в скетчах по логике.

Подскажите в чем может быть причина (адоптация встроенного скетча Blink without delay тоже результата не дала, хотя без монритора получилось отключать светодиод без повторения цикла).

Спасибо!

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Andrushkevich, в Вашем коде трудно разбираться, т.к. он весьма странно отформатирован. Возможно, поэтому же Вы сами плохо представляете, как он работает.

Что такое "b1" и "b2" я не знаю, но предполагаю, что первое - нажатие кнопки, а второе - ее же отпускание. Тогда светодиод гасится в 34 строке, и что происходит в строках 42-50 - уже не важно.

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

Да,  Вы все правильно поняли, я не пояснил, b1 и b2 - это прееменные с Nexion Editidor, отвечающие за передачу сигнала с монитора.

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

У меня закралось подозрение, что не в строках 31-34, которые отвечают за непосредственную связь с монитором (всмысле нажатие), а в самом примере, который я взял за основу.

Буду разбираться, спасибо за ответ.

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

Да,  Вы все правильно поняли, я не пояснил, b1 и b2 - это прееменные с Nexion Editidor, отвечающие за передачу сигнала с монитора.

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

У меня закралось подозрение, что проблемма не в строках 31-34, которые отвечают за непосредственную связь с монитором (всмысле нажатие), а в самом примере, который я взял за основу.

Буду разбираться, спасибо за ответ.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Попробуйте так 

unsigned long led1OnTime = 0;
bool led1On;
String incStr;

void setup() {
  Serial.begin(9600);
  pinMode(3, OUTPUT); 
  led1On = false;
}

void loop() {

  if (Serial.available()) {
    char inc;
    inc = Serial.read();
    incStr += inc;
    if (inc == 0x0A) {
      AnalyseString(incStr);
      incStr = "";
    }
  }
}

void AnalyseString(String incStr) {

  if (incStr.indexOf("b1") >= 0) { 
    digitalWrite(3, HIGH);
    led1On = true;
    led1OnTime = millis();
  } 
  if (incStr.indexOf("b2") >= 0) {
    digitalWrite(3, LOW);
  }

  if(led1On){
    if(millis() - led1OnTime > 5000) {
      digitalWrite(3, LOW);
      led1On = false;
    }
  }
}

void SendData(String dev, String data)
{
  Serial.print(dev);
  Serial.print("=");
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

 

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

Результат тот же, оператор не выполняется, просто при нажатии кнопки диод светиться, а при отпускании гаснет.

Если полностью удалить оператор отжатия кнопки, то естественно диод не гаснет.

Попробовол реализовать программу на основе встроенного примера Blink without delay

Скетч

void setup() {
  pinMode(3, OUTPUT);
    digitalWrite(3, HIGH);  
}
void loop()
{
  if(millis() - 0 >= 3000) {
        if (3 == LOW)
            digitalWrite(3, HIGH);
                else
    digitalWrite(3, LOW);
  }
}

Логика следующая: при включении питания pin 3 имеет статус HIGH, следовательно включается в работу оператор millis, после прошествия интервала времени (3 сек) pin 3 переходит в состояние LOW.  При повторном включении цикл повторяеется.

Значит исходя из этой логики мне в моей программе необходимо, чтобы изначально pin 3 был в состоянии LOW, а после подачи команды с монитора переходил в состоянии HIGH и инициировалось выполнение оператора millis уже на основе вышепреведенноого скетчя.

Вот мой адаптированный скетч:

String incStr;


void setup() {
Serial.begin(9600);
pinMode(3, OUTPUT);  

}

void loop() {
if (Serial.available()) {
char inc;
inc = Serial.read();
incStr += inc;
if (inc == 0x0A) {
AnalyseString(incStr);
incStr = "";
    }
  }
}

void AnalyseString(String incStr) 
{
  if (incStr.indexOf("b1") >= 0) 
  digitalWrite(3, LOW);
  else if (incStr.indexOf("b2") >= 0) 
  digitalWrite(3, HIGH);
  {
  if(millis() - 0 >= 2000) {
        if (3 == HIGH)
            digitalWrite(3, HIGH);
                else
    digitalWrite(3, LOW);
  }
  }
}

void SendData(String dev, String data)
{
  Serial.print(dev);
  Serial.print("=");
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

И вот что у меня получилось: вначале я просто сконфигурировал, что у меня при нажатии кнопки pin 3 имеет состоние HIGH, а потом добавил оператор millis, который долден инициироваться по состоянию   pin 3.

Но по факту у меня получилось следующее, при добавлении оператора при нажатии кнопки светодиод просто тускло зажигается и при отжатии кнопки гаснет (если нет оператора, то естественно при нажатии кнопки диод просто включается).

Явно что проблемма кроится в строках с 24 по 33.

И судя по всему, оператор mills должен инициироваться после сигнала 

  if (incStr.indexOf("b1") >= 0) 
  digitalWrite(3, LOW);
  else if (incStr.indexOf("b2") >= 0) 
  digitalWrite(3, HIGH);

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
Самое сложное понять что Вы хотите, логику.
(andriano - Что такое "b1" и "b2" я не знаю но предполагаю, что первое - нажатие кнопки, а второе - ее же отпускание.)
От сябя добавлю - я понял что при удержании кнопки- ЛЕД погаснет после 5 секунд
Если да тогда так.
unsigned long led1OnTime = 0;
bool led1On;
String incStr;

void setup() {
  Serial.begin(9600);
  pinMode(3, OUTPUT); 
  led1On = false;
}

void loop() {

  if (Serial.available()) {
    char inc;
    inc = Serial.read();
    incStr += inc;
    if (inc == 0x0A) {
      AnalyseString(incStr);
      incStr = "";
    }
  }
}

void AnalyseString(String incStr) {

  if (incStr.indexOf("b1") >= 0 && !led1On) { 
    digitalWrite(3, HIGH);
    led1On = true;
    led1OnTime = millis();
  } 
  if (incStr.indexOf("b2") >= 0) {
    digitalWrite(3, LOW);
    led1On = false;
  }

  if(led1On){
    if(millis() - led1OnTime > 5000) {
      digitalWrite(3, LOW);
      
    }
  }
}

void SendData(String dev, String data)
{
  Serial.print(dev);
  Serial.print("=");
  Serial.print(data);
  Serial.write(0xff);
  Serial.write(0xff);
  Serial.write(0xff);
}

 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Andrushkevich пишет:

Да,  Вы все правильно поняли, я не пояснил, b1 и b2 - это прееменные с Nexion Editidor, отвечающие за передачу сигнала с монитора.

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

У меня закралось подозрение, что не в строках 31-34, которые отвечают за непосредственную связь с монитором (всмысле нажатие), а в самом примере, который я взял за основу.

Буду разбираться, спасибо за ответ.

А Вы неправильно выполнили декомпозицию, и это спровоцировало Вас на неверную логику программы.

Смотрите сами: управление светодиодом Вы поместили в функцию анализа строки, что изначально неправильно - анализ состояния и реакцию на изменение состояния нужно разделять. Далее - с одной стороны предполагается, что по истечении времени каким-то образом должен отработать кусок, выключающий светодиод. Но этот кусок размещен в анализе строки, который в свою очередь вызывается только при условии поступления очередного символа в Serial. Если символа нет - анализ строки не вызывается и за временем никто не следит.

Перенесите анализ времени из анализа строки в конец loop() после закрывающей } опроса Serial..

Andrushkevich
Offline
Зарегистрирован: 10.10.2017

Большое спасибо за помощь, разбираюсь.