Відповісти

Введіть повідомлення і натисніть Надіслати
Параметри

Назад

Огляд теми (нові повідомленні вгорі)

goodspeedmen
2016-10-13 15:39:14

Спасибо за помощь сейчас нет времени заняться но наша эпопея не закончена smile

qwone
2016-10-03 19:42:14
//#1 энкодер
 const int reset_pin=6; // кнопка сброса показаний 0 нажата /1 нет
 volatile int place_enc; // количество импульсов
 const int enc_A_pin = 2;// нога на энкодер фазы A прерывание 0
 const int enc_B_pin = 3; // нога на энкоде  фазы B.

void scan_enc1() {   // функция работающая по прерыванию 0 подсчет импульсов
  if(digitalRead(enc_B_pin))place_enc++; 
  else place_enc--;
    }  
  void scan_enc2() {   // функция работающая по прерыванию 0 подсчет импульсов
  if(digitalRead(enc_B_pin))place_enc--; 
  else place_enc++;
    }    
//#2 экран 
  #include <Wire.h>
  #include <LiquidCrystal.h>
  LiquidCrystal lcd(12, 11, 10, 9, 8, 7); 
void setup(){
//#1 энкодер
  pinMode(reset_pin, INPUT_PULLUP); // настройка  кнопки сбоса показаний
  pinMode(enc_A_pin, INPUT);
  pinMode(enc_B_pin, INPUT);
  attachInterrupt(0, scan_enc1, FALLING); //прерывание INT0. 1>0
  attachInterrupt(0, scan_enc2, RISING); //прерывание INT0. 0>1
//#2 экран 
  lcd.begin(16, 2); 
}
void loop(){ 
//#1 энкодер  
  if (!digitalRead(reset_pin)) place_enc = 0; //сброс счетчика импульсов                              
//#2 экран обновление раз в 1 секунда
  static uint32_t future2 = 0 ;
  if (millis() >= future2)   {
     future2 = millis() + 1000 ;
     lcd.setCursor(0,0)       ; //курсор. 
     lcd.print("Place=")      ; //выводит текст.
     lcd.print(place_enc)     ; //выводит значение переменной P.
     lcd.print("         ")   ; //выводит выводит пробел.           
     }        
} 
qwone
2016-10-03 19:32:07

разберем это attachInterrupt(0, scan_enc, FALLING);
Консультируемся по этому. http://arduino.ru/Reference/AttachInterrupt
0 это interrupt: номер прерывания  то есть на ноге 2
scan_enc это обработчик прерываний.
FALLING прерывание вызывается только при смене значения на порту с HIGH на LOW
Итого по перепаду на выводе 2 с 1 в 0 вызывается программа прерывания scan_enc. А так как у энкодера 2 вывода сдвинутые по фазе . То второй вывод и есть вывод направления в + или в -.  И да если идет вибрация может быть ошибки. Программно их не устранить.
Конечно можно написать 2 функцию attachInterrupt(0, scan_enc2, RISING); Но где гарантия что во время одного обработчика прерываний не вызовут другой.

if(digitalRead(enc_B_pin))  аналог этого if(digitalRead(enc_B_pin)==1) . То есть спрашивает состояние на другом выводе от прерывания.

void scan_enc2() {                                           // функция работающая по прерыванию 0 подсчет импульсов
  if(digitalRead(enc_B_pin))place_enc--;
  else place_enc++;
    }
вызывается прерыванием attachInterrupt(0, scan_enc2, RISING);

goodspeedmen
2016-10-03 18:35:26

У меня не было этого кода, хотя по сути он не чем не отличается, только нет защит от дребезжания на энкодоре. Ради интереса залью сейчас посмотрю что получится wink Обновление два раза в секунду маловато neutral
Опробовал:
Да как я и сказал нет защиты от вибрации на валу енкодера? стоя на месте от вибрации счет уменьшается или прибавляется.

Не понятно как работает эта функция?
enc_B_pin от куда он берет аргумент из прерывания на 0. То есть если 0 по ++ если нет то --?
значит если нет {} в операторе if  то он берет аргумент из главной функции?

void scan_enc() {                                           // функция работающая по прерыванию 0 подсчет импульсов
  if(digitalRead(enc_B_pin))place_enc++;
  else place_enc--;
    }

qwone
2016-10-03 18:15:50

goodspeedmen А чем вам это не подошло?

//#1 энкодер
 const int reset_pin=6; // кнопка сброса показаний 0 нажата /1 нет
 volatile int place_enc; // количество импульсов
 const int enc_A_pin = 2;// нога на энкодер фазы A прерывание 0
 const int enc_B_pin = 3; // нога на энкоде  фазы B.

void scan_enc() {   // функция работающая по прерыванию 0 подсчет импульсов
  if(digitalRead(enc_B_pin))place_enc++; 
  else place_enc--;
    }    
//#2 экран 
  #include <Wire.h>
  #include <LiquidCrystal.h>
  LiquidCrystal lcd(12, 11, 10, 9, 8, 7); 
void setup(){
//#1 энкодер
  pinMode(reset_pin, INPUT_PULLUP); // настройка  кнопки сбоса показаний
  pinMode(enc_A_pin, INPUT);
  pinMode(enc_B_pin, INPUT);
  attachInterrupt(0, scan_enc, FALLING); //прерывание INT0. 1>0
//#2 экран 
  lcd.begin(16, 2); 
}
void loop(){ 
//#1 энкодер  
  if (!digitalRead(reset_pin)) place_enc = 0; //сброс счетчика импульсов                              
//#2 экран обновление раз в 0,5 секунды
  static uint32_t future2 = 0 ;
  if (millis() >= future2)   {
     future2 = millis() + 500 ;
     lcd.setCursor(0,0)       ; //курсор. 
     lcd.print("Place=")      ; //выводит текст.
     lcd.print(place_enc)     ; //выводит значение переменной P.
     lcd.print("         ")   ; //выводит выводит пробел.           
     }        
} 
goodspeedmen
2016-10-03 16:47:08

#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
//volatile boolean flag
volatile boolean flag_CW = 0;               // переменные тригерра направления.
volatile boolean flag_CWW = 0;            // переменные тригерра направления.
boolean enc_A = 2;                            //переменные входа фазы A.
boolean enc_B = 3;                            //переменные входа фазы B.
unsigned int update_lcd = 0;                //переменная обновления экрана. своеобразное прерывание.
volatile int place_enc;                        // переменная.

void setup()
{
  pinMode(6, INPUT_PULLUP);              // настройка пина кнопки на вход, включае поддяжку.
  pinMode(enc_A, INPUT);
  pinMode(enc_B, INPUT);
  attachInterrupt(0, scan_enc, FALLING);    //прерывание INT0. 1>0
  attachInterrupt(1, flag_reset, RISING);     //прерывание INT1. 0>1
  lcd.begin(16, 2);                                   //старт lcd.
}

void loop()
{         
  if (digitalRead(6)==0)          //сброс.
   {       
    place_enc = 0;
   }                           
  if (update_lcd==0)
  {
   lcd.setCursor(0,0);          //курсор.
   lcd.print("Place=");          //выводит текст.
   lcd.print(place_enc);       //выводит значение переменной P.
   lcd.print("         ");         //выводит выводит пробел.
   update_lcd = 2048;             
  }
   update_lcd = update_lcd-1;       
}   

void scan_enc()
{
  if(flag_CW == 1){goto exit;}
  if((digitalRead(enc_B)==1))
  {
   place_enc ++;               
   flag_CW = 1;
  flag_CWW = 0;
   }
  if(flag_CWW == 1){goto exit;} 
  if((digitalRead(enc_B)==0))
  {
   place_enc --;
  flag_CWW = 1;
   flag_CW = 0;
   }
  exit:;
}   
           
void flag_reset()
{
if ((digitalRead(enc_A)==1) && (flag_CW = 1))

  flag_CW = 0;
}
if ((digitalRead(enc_A)==0) && (flag_CWW = 1))
{
  flag_CWW = 0;
}
     //flag_CW = 0;
}
=========================================================================================

Ардуино приводит меня в ступор, есть код опроса энкодера у меня он на 1250 импульсов на оборот, он взять из программы написанной на СИ и на Tiny2313 работает без проблем он немного не такой там нет флагов flag_CW  flag_CWW  там просто есть флаг flag который устраняет ложное срабатывание от тряски на одном месте при большом количестве импульсов это актуально. Но ардуино не пропускает этот код:
============================================================
Arduino: 1.6.9 (Windows XP), Плата:"Arduino Nano, ATmega328"
collect2.exe: error: ld returned 5 exit status
exit status 1
Ошибка компиляции для платы Arduino Nano.
============================================================
Gришлась городить вот эти двойные опросы. Но проблема не только в этом, она в том? что энкодер считает только в плюс? я просто в недоумении в чем проблема sad

Підвал форуму