Внешние прерывание Логическая ошибка.

Обсуждаем Arduino, Raspberry Pi и другие электронные компоненты и проекты DIY
Ответить
Ворон
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

Внешние прерывание Логическая ошибка.

Сообщение Ворон »

Приветствую вас изобретатели.
Проблема в Прерывании. Идея была в том, что в проге использую две функции:
по включению и выключению.
То есть, разный алгоритм включения и выкл.
attachInterrupt(pin, PTTon, FALLING);
attachInterrupt(pin, PTTof, RISING);
RISING прерывание вызывается только при смене значения на порту с LOW на HIGH
FALLING прерывание вызывается только при смене значения на порту с HIGH на LOW
Заметил, написав так, действие не происходит, используя RISING происходит дважды при нажатии и отжатии кнопки.
пришлось пользоваться CHANGE и логикой (внешней переменной) при действии проверяется её значение и выполняется действие с её дальнейшем изменением.
http://www.youtube.com/watch?v=5aCN3r4x9p0
У кого какие идеи есть?

void PTTon()
{
if (PTT == LOW)
{
digitalWrite(led, HIGH);
delay(5000);
digitalWrite(led, LOW);
delay(5000);
digitalWrite(led, HIGH);
PTT = !PTT;

}
else
{
digitalWrite(led, LOW);
PTT = !PTT;
}
}
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1020
Зарегистрирован: 22 окт 2010, 23:57

Re: Внешние прерывание Логическая ошибка.

Сообщение Mr.Kubikus »

Привет!

На прерывания можно забить. Они для решения этой задачи не нужны.

Вариант 1. Используем обычный конечный автомат с двумя состояниями.

Код: Выделить всё

#define BTN_PIN 1

int btnMemState = LOW;

void setup() {
  pinMode(BTN_PIN, INPUT);
}

void func1() {
  return;
}

void func2() {
  return;
}

void loop() {
  int btnValue = LOW;
  
  btnValue = digitalRead(BTN_PIN);
  
  switch (btnMemState) {
  case LOW:
    // Ловим переход 0->1
    if (btnValue == HIGH) {
      btnMemState = HIGH;
      func1();
    }
    break;
  
  case HIGH:
    // Ловим переход 1->0
    if (btnValue == LOW) {
      btnMemState = LOW;
      func2();
    }
    break;
  
  default:
    break;
  }
  
  delay(25); // Не убираем иначе поймаем дребезг контактов, если на входе кнопка.
}
Вариант 2. Для тех кто не проникся конечными автоматами делаем все на IFах.

Код: Выделить всё

#define BTN_PIN 1

int btnMemState = LOW;

void setup() {
  pinMode(BTN_PIN, INPUT);
}

void func1() {
  return;
}

void func2() {
  return;
}

void loop() {
  int btnNewState = LOW;
  
  btnNewState = digitalRead(BTN_PIN);
  
  if (btnNewState != btnMemState) {
    // Ловим переход 0->1
    if (btnNewState == HIGH) {
      func1();
    }

    // Ловим переход 1->0    
    if (btnNewState == LOW) {
      func2();
    }  
  }
  btnMemState = btnNewState;
    
  delay(25); // Не убираем иначе поймаем дребезг контактов, если на входе кнопка.
}
Ну и не забываем подтянуть вход МК к VCC или GND. Иначе будем ловить радиоэфир.
С уважением, Григорий
GitHub FB ВК
Ворон
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

Re: Внешние прерывание Логическая ошибка.

Сообщение Ворон »

Это хорошо, но прерывание выполняется сразу после действия, помимо основной задачи.
вписать в тело программы можно, но там идет задержка. ~1.5 сек.
По библиотеке BTN_PIN ознакомлюсь.
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1020
Зарегистрирован: 22 окт 2010, 23:57

Re: Внешние прерывание Логическая ошибка.

Сообщение Mr.Kubikus »

Рекомендую пересмотреть алгоритм главного цикла. Длительность исполнения ГЦ=1,5 сек - это не гуд.

BTN_PIN - это не библиотека, а макроопределение. После строки "#define BTN_PIN 1" компилятор будет подставлять "1" везде, где встретит BTN_PIN.
С уважением, Григорий
GitHub FB ВК
Ворон
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

Re: Внешние прерывание Логическая ошибка.

Сообщение Ворон »

Проблему вроде решил.
Задача:
Решить проблему с внешним прерыванием, при нажатии с HIGH на LOW выполнение одной последовательности при отпуске с LOW на HIGH другую.
Решить её функцией прерывания не удалось.
Решение:
В Функции прерывания идет проверка на состояние входа того же, что и вход прерывания.

volatile boolean PTT = LOW;
int pin = 0;
attachInterrupt(pin, PTTon, CHANGE);

void PTTon()
{
if (PTT == LOW && digitalRead(2) == LOW)
{
digitalWrite(led, HIGH);
PTT == HIGH;
}
else if (PTT == HIGH)
{
digitalWrite(led, LOW);
PTT = LOW;
}
Ворон
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

Re: Внешние прерывание Логическая ошибка.

Сообщение Ворон »

Как Вставить текст Програмы.
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1020
Зарегистрирован: 22 окт 2010, 23:57

Re: Внешние прерывание Логическая ошибка.

Сообщение Mr.Kubikus »

Используйте тег code.
С уважением, Григорий
GitHub FB ВК
Ворон
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

Re: Внешние прерывание Логическая ошибка.

Сообщение Ворон »

Отладочная програма.
Только для прерывания, бегущая строка, для отслеживания процесов в нутри проги.

Код: Выделить всё


#include <Wire.h> 
#include <LiquidCrystal_I2C.h>


 LiquidCrystal_I2C lcd(0x27, 16, 2);
 
 int led = 13;
 int pin = 0;
 volatile boolean PTT = LOW;

 byte degree[8] = {  // значек Градуса.
  B00110,
  B01001,
  B01001,
  B00110,
  B00000,
  B00000,
  B00000,
 };
 byte p20[8] = {   // биты заполнения LCD
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
  B10000,
 };
   byte p40[8] = {
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
  B11000,
 };
 byte p60[8] = {
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
  B11100,
 };
   byte p80[8] = {
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
  B11110,
 };
 byte p100[8] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
 };
 
 void setup ()
   {
     
      lcd.begin();
      
      pinMode(led, OUTPUT);
      pinMode(pin, INPUT);
      attachInterrupt(pin, PTTon, CHANGE);
      
      
      
         // функция теста экрана
        lcd.setCursor(0, 0);
        lcd.print("    R K 5 D     "); 
    }
    
   
 void loop()
  {
     lcd.setCursor(0, 1);
     lcd.print("                ");    
    for (int i=0; i < 16; i++)
          {
             lcd.createChar(0,p20);
             lcd.createChar(1,p40);
             lcd.createChar(2,p60);
             lcd.createChar(3,p80);
             lcd.createChar(4,p100);
   
               for (int j=0; j < 5; j++)
              {
                 lcd.setCursor(i,1);
                 lcd.write(j);
                 delay(80); // скорость 
              }
      
      if (PTT == HIGH)
        {
        lcd.setCursor(13, 0);   
        lcd.print("PTT");
        }
      else 
         {
         lcd.setCursor(13, 0);   
         lcd.print("   ");
          }
       
       }       

 }
 
    
void PTTon()
      {
      if (PTT == LOW && digitalRead(2) == LOW) 
                      {                                    
                       digitalWrite(led, HIGH);
                       PTT = HIGH;
                       
                       }
            else if (PTT == HIGH)
                       {
                       digitalWrite(led, LOW);
                       PTT = LOW;
                       } 
             else 
                       {
                       digitalWrite(led, LOW);
                       PTT = LOW;
                       } 
                    
      }
 
Ответить