Тел. (495) 972-27-12

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

Обсуждаем Arduino, Raspberry Pi и другие электронные компоненты и проекты DIY

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

Сообщение Ворон » 21 янв 2015, 21:20

Приветствую вас изобретатели.
Проблема в Прерывании. Идея была в том, что в проге использую две функции:
по включению и выключению.
То есть, разный алгоритм включения и выкл.
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;
}
}
Ворон
 
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

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

Сообщение Mr.Kubikus » 21 янв 2015, 21:43

Привет!

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

Вариант 1. Используем обычный конечный автомат с двумя состояниями.
Code: [Выделить всё] [Expand/Collapse]
#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); // Не убираем иначе поймаем дребезг контактов, если на входе кнопка.
}
GeSHi © Codebox Plus


Вариант 2. Для тех кто не проникся конечными автоматами делаем все на IFах.
Code: [Выделить всё] [Expand/Collapse]
#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); // Не убираем иначе поймаем дребезг контактов, если на входе кнопка.
}
GeSHi © Codebox Plus


Ну и не забываем подтянуть вход МК к VCC или GND. Иначе будем ловить радиоэфир.
С уважением, Григорий
GitHub FB ВК TW
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
 
Сообщения: 880
Изображения: 49
Зарегистрирован: 22 окт 2010, 23:57
Откуда: Москва

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

Сообщение Ворон » 22 янв 2015, 18:23

Это хорошо, но прерывание выполняется сразу после действия, помимо основной задачи.
вписать в тело программы можно, но там идет задержка. ~1.5 сек.
По библиотеке BTN_PIN ознакомлюсь.
Ворон
 
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

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

Сообщение Mr.Kubikus » 23 янв 2015, 00:42

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

BTN_PIN - это не библиотека, а макроопределение. После строки "#define BTN_PIN 1" компилятор будет подставлять "1" везде, где встретит BTN_PIN.
С уважением, Григорий
GitHub FB ВК TW
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
 
Сообщения: 880
Изображения: 49
Зарегистрирован: 22 окт 2010, 23:57
Откуда: Москва

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

Сообщение Ворон » 23 янв 2015, 21:47

Проблему вроде решил.
Задача:
Решить проблему с внешним прерыванием, при нажатии с 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: Внешние прерывание Логическая ошибка.

Сообщение Ворон » 23 янв 2015, 21:53

Как Вставить текст Програмы.
Ворон
 
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50

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

Сообщение Mr.Kubikus » 23 янв 2015, 21:59

Используйте тег code.
С уважением, Григорий
GitHub FB ВК TW
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
 
Сообщения: 880
Изображения: 49
Зарегистрирован: 22 окт 2010, 23:57
Откуда: Москва

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

Сообщение Ворон » 23 янв 2015, 23:17

Отладочная програма.
Только для прерывания, бегущая строка, для отслеживания процесов в нутри проги.
Code: [Выделить всё] [Expand/Collapse]

#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;
                       }
                   
      }
 
GeSHi © Codebox Plus
Ворон
 
Сообщения: 5
Зарегистрирован: 21 янв 2015, 20:50


Вернуться в Arduino и Ко. ♥♥♥



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron