Help (энкодер)

Goblin_
Offline
Зарегистрирован: 12.03.2019

Приветствую, я совсем недавно приобрел Arduino UNO, и мне необходимо с ее помощью выполнить маленький проект. Но у меня возникла проблема, которую я никак не могу решить. Заключается она вследующем: вращая вал энкодера (ROTARY ENCODER E30S4-200-6-L-5) по часовой, срабатывает прерывание и количество импульсов считается, как только направление вращение вала меняется, мне необходимо, запомнить количество импульсов до смены направления вращения вала, и зная количество ипульсов, посчитать угол, так как этот энкодер на 200 импульсов, следовательно 1 импульс = 1,8 (град), затем зная угол, определить cos() и выдать в порт, и ожидать следующего поворота вала по часовой. И Я УЖЕ 3 ДЕНЬ не могу понять, как мне вытянуть quantity_of_impulses, помогите пожалуйста.

volatile unsigned int last_quantity_of_impulses, quantity_of_impulses = 0; 

//========================================================================   
void setup() {
  Serial.begin (9600);
  
  pinMode(2, INPUT_PULLUP); 
  pinMode(3, INPUT_PULLUP); 
  
  attachInterrupt(0, ai0, RISING);
  
  }
//========================================================================     
  void loop() {

  if( quantity_of_impulses != last_quantity_of_impulses ){

  Serial.println (quantity_of_impulses);

  last_quantity_of_impulses = quantity_of_impulses;
;
  }
  }
//========================================================================     
  void ai0() {
    
  if(digitalRead(3)==LOW) {
  quantity_of_impulses++;
  }else{
  detachInterrupt(ai0);
  quantity_of_impulses=0;
  }
  }
//========================================================================

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так Вы ничего не вытяните. Для начала гуглите работу с энкодером. С ним не так работают.

Goblin_
Offline
Зарегистрирован: 12.03.2019

Хорошо, прошу подскажите, в чем моя ошибка?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

У Вас не ошибка, у Вас в корне неверный подход к работе с энкодером. Например, Вы читаете только rise одного пина, и наличие сигнала на втором, ... в общем ... это Вам надо с нуля рассказывать как устроен энкодер. Найдите какую-нибудь статью и почитайте пр энкодер, по код Грея, а то мне придётся учебник переписывать..

 

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

Может так 

volatile unsigned int quantity_of_impulses = 0; 
volatile bool f_enkod = 0; 

//========================================================================   
void setup() {
  Serial.begin (9600);
  pinMode(2, INPUT_PULLUP); 
  pinMode(3, INPUT_PULLUP); 
  
  attachInterrupt(0, ai0, RISING);
}
//========================================================================     
  void loop() {
  if(!f_enkod){
    Serial.println (quantity_of_impulses);
    quantity_of_impulses = 0;
    f_enkod = 1;
   }
}
//========================================================================     
  void ai0() {
  if(digitalRead(3)==LOW) {
    quantity_of_impulses++;
  }
  else{
    f_enkod = 0;
  }
}
//========================================================================

А про енкодер можно посмотреть здесь хороший пример ( http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder?page=2#comm... )

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

У Вас не ошибка, у Вас в корне неверный подход к работе с энкодером. Например, Вы читаете только rise одного пина, и наличие сигнала на втором, ... в общем ... это Вам надо с нуля рассказывать как устроен энкодер. 

А что не так? Rise на одном пине и уровень на втором дают однозначное направление вращения квадратурного энкодера если отсутствует дебезг (подавлен аппаратно).

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так в том и дело, что нигде не сказано об аппаратном подавлении, а значит надо читать и rising, и falling и анализировать ситуацию. Там получается автомат, часть состояний которого отбрасывается ввиду нереальности.

Goblin_
Offline
Зарегистрирован: 12.03.2019

а так?

volatile unsigned int impulseNumber = 0;
volatile unsigned long startTime, time = 0;

//=====================================================================================================================
void setup() {
  Serial.begin (9600);
 pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), ai0, RISING);
  startTime = millis();
}
//=====================================================================================================================
void loop() {
//если количество импульсов не соответствует старому, выводить новое количсетво импульсов
  if(time == 0) {
    startTime = millis();
  }

  time = millis() - startTime;

  if( time >= 2000 && impulseNumber != 0 && impulseNumber > 7  ) {
    Serial.print ("Wheel diameter = ");
    //float wheelD = wheelDCalculator(impulseNumber);
    Serial.println (impulseNumber);
    impulseNumber = 0;
  }
}
//=====================================================================================================================
void ai0() {
  if (digitalRead(2) == digitalRead(3)) {
    impulseNumber++;
    time=0;
  } 
  }

//=====================================================================================================================

 

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
А чем Вас не устроил код из 4-го поста. Условия задачи вроде как выполняет
(Заключается она вследующем: вращая вал энкодера (ROTARY ENCODER E30S4-200-6-L-5) по часовой, срабатывает прерывание и количество импульсов считается, как только направление вращение вала меняется, мне необходимо, запомнить количество импульсов до смены направления вращения вала)
Првда без подавления ДРЕБЕЗГА но о нем Вы не спрашивали - значит сделали АПАРАТНО. Углы тоже не просчитывал, думаю - сами сделаете.