Не корректная работа энкодера

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

Есть энкодер на основе датчика Холла. Подключен ко второму входу и обрабатывается прерываниями. Суть проблемы в некорректной передаче переменной из прерывания (я так думаю). Пробовал менять датчик, даже поменял на оптический, не помогает. В момент перехода цикла loop переменная сбивается, при обратном счете происходит тоже самое. Есть идеи.

 

Это зачения с монитора: 

 
2
2
2
Up
14
New
14
14
1
14
14
14
14
14
 

#define RPMpin 2 // датчик Холла

volatile unsigned int  rp = 0; // счетчик оборотов
volatile bool  reverce = true;


void setup() 
{
  Serial.begin(9600);
  pinMode(RPMpin,    INPUT_PULLUP);
  digitalWrite(RPMpin, 1);
  attachInterrupt(0, RPM, FALLING);

  
 pinMode(10, OUTPUT); // Тормоз
 pinMode(12, OUTPUT); // Прямое вращение
 pinMode(11, OUTPUT); // обратное вращение

  digitalWrite(10, HIGH);  
  digitalWrite(12, HIGH);
  digitalWrite(11, HIGH);  
}


void loop() 
{
  Serial.println(rp, DEC);
  Serial.println("New");
  Serial.println(rp, DEC); // об/мин
 
//  rpm = 1;
  digitalWrite(10, LOW);  
  digitalWrite(12, LOW);
  Serial.println(rp, DEC);

 // rpm = 1;

 Serial.println(reverce);
// delay (5000);
  while  (rp < 80) 
  { Serial.println(rp, DEC); 
  //   Serial.println("OK");
  //   delay (5000);
   }
  
  digitalWrite(10, HIGH);  
  digitalWrite(12, HIGH);
  reverce = false;
  delay(5000);  

Serial.println("Down");
Serial.println(rp, DEC);
  digitalWrite(10, LOW);  
  digitalWrite(11, LOW);
  Serial.println(rp, DEC);
//  rpm = 199;
  
  while  (rp > 0) 
  { Serial.println(rp, DEC); }
  
  digitalWrite(10, HIGH);  
  digitalWrite(11, HIGH);
  
  reverce= true;
  delay(5000);  
  Serial.println("Up");

}



void RPM ()  // Это счетчик оборотов
{
  if (reverce) {++rp;} else {--rp;}
}

 

 

 

Megawollt
Offline
Зарегистрирован: 06.12.2015

А зачем делей? Тем более такой аццкий. Как ваша система определяет направление вращения?

if (reverce) {++rp;} else {--rp;}

И вот эта строка не ясна. Может 

if (reverce == 1) {++rp;} else {--rp;}

?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Блин. Ну названия темы дают. Энкодер он работает нормально. А вот программист Andrey_vlz не корректно работает. Хрень пишет и хрень получается. Энкодер это не только датчик Холла, но и много много чего-то. Может у вас счетчик оборотов с реверсом.

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

Здесь проверяется внешнее условие направление вращения. В соответствии с этим счетчик либо прибавляется либо отнимается. Ваше написание тойже строки аналогично.

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

В этом и вопрос - ГДЕ ОШИБКА?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот если у вас счетчик оборотов с реверсом, и если вперед вы считаете по фронту. То при обратном вращении надо считать по спаду.

Andrey_vlz пишет:

В этом и вопрос - ГДЕ ОШИБКА?

Ошибка как не странно в непонимании процессов, а программа и ее работа это следствие. "Лечить

"надо причины, а не следствия.

Megawollt
Offline
Зарегистрирован: 06.12.2015

Датчик Холла по спаду и работает. Нужно убрать слово энкодер из темы вообще

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

Я менял способы считывания прерываний. Ничего не меняется. ВОПРОС - почему происходит скачек в значения переменной, причем он всегда разный. Може парамую с ячейкой памяти работать?

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

У оптического датчика таже проблема.

Megawollt
Offline
Зарегистрирован: 06.12.2015

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

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Megawollt, не буду говорить за все датчики, но тот датчик холла что я однажды тестил не давал дребезга вообще.

Andrey_vlz, схем вы не рисовали, фотографий не давали, так что предположение будет таким же неконкретным -у вас откуда то приползают помехи.

Megawollt
Offline
Зарегистрирован: 06.12.2015

Цифровой да, не даёт, но счёт получается все равно нестабильным. Сам сталкивался, но у меня направление не менялось :)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

вот ваша программа. Просто добавил комментарии для остальных

/*
датчик Холла питание ->2 (RPMpin)
              сигнал ->1
тормоз -> 10 (brake_pin) 1 вкл / 0 нет
прямо -> 11 (direct_pin) 0 вкл / 1 нет
обратно -> 12 (back_pin) 0 вкл / 1 нет
*/
#define RPMpin 2 // датчик Холла
const int brake_pin = 10;
const int direct_pin = 11;
const int back_pin = 12;

volatile unsigned int  rp = 0; // счетчик оборотов
volatile bool  reverce = 1; // направление счета  1 вперед / 0 назад

void RPM () { // Это счетчик оборотов обрабатыв прерыванием
  if (reverce)     ++rp;
  else     --rp;
}


void setup() {
  Serial.begin(9600);
  pinMode(RPMpin,    INPUT_PULLUP);
  digitalWrite(RPMpin, 1); // подключить датчик Холла
  attachInterrupt(0, RPM, FALLING);

  pinMode(brake_pin, OUTPUT); // Тормоз
  digitalWrite(brake_pin, 1);
  pinMode(back_pin, OUTPUT); // Прямое вращение
  digitalWrite(back_pin, 1);
  pinMode(direct_pin, OUTPUT); // обратное вращение
  digitalWrite(direct_pin, 1);
}

void loop() {
  Serial.println(rp, DEC);
  Serial.println("New");
  Serial.println(rp, DEC); // об/мин
  //  rpm = 1;
  digitalWrite(brake_pin, LOW); // отк тормоз
  digitalWrite(back_pin, LOW);  // вкл обр вращение
  Serial.println(rp, DEC);
  // rpm = 1;
  Serial.println(reverce);
  // delay (5000);
  while  (rp < 80)  {
    Serial.println(rp, DEC);
    //   Serial.println("OK");
    //   delay (5000);
  }
  digitalWrite(brake_pin, HIGH);  // вкл тормоз
  digitalWrite(back_pin, HIGH);  // откл обр вращение
  reverce = 0; // счет обратно
  delay(5000);

  Serial.println("Down");
  Serial.println(rp, DEC);
  digitalWrite(brake_pin, LOW); // отк тормоз
  digitalWrite(direct_pin, LOW);  // вкл прям вращение
  Serial.println(rp, DEC);
  //  rpm = 199;

  while  (rp > 0) {
    Serial.println(rp, DEC);
  }
  digitalWrite(brake_pin, HIGH);  // вкл тормоз
  digitalWrite(direct_pin, HIGH);  // откл обр вращение
  reverce = 1; // счет вперед
  delay(5000);
  Serial.println("Up");
}

 

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

dimax пишет:

Megawollt, не буду говорить за все датчики, но тот датчик холла что я однажды тестил не давал дребезга вообще.

Andrey_vlz, схем вы не рисовали, фотографий не давали, так что предположение будет таким же неконкретным -у вас откуда то приползают помехи.

Сейчас она упрощена до предела. Есть плата MEGA 2560, к ней на 2 pin подключен оптический датчик (стандартный щелевой из набора) и все. Он впринципе не дребежит. При медленом тесте обнаруживается, что показания счетчика при каждом прохождении меняются не всегда на 1.

Andrey_vlz
Offline
Зарегистрирован: 06.11.2016

Немного изменил код. Стал отслеживать переменную прямо в прерывании. Стало немного понятнее. Из-за высого приоритета прерывания основной код не получает управление и значения ухлдат далеко за пределы допустимого.

/*
датчик Холла питание ->2 (RPMpin)
              сигнал ->1
тормоз -> 10 (brake_pin) 1 вкл / 0 нет
прямо -> 11 (direct_pin) 0 вкл / 1 нет
обратно -> 12 (back_pin) 0 вкл / 1 нет
*/
#define RPMpin 2 // датчик Холла
const int brake_pin = 10;
const int direct_pin = 11;
const int back_pin = 12;

volatile int  rp = 0; // счетчик оборотов
volatile bool  reverce = 1; // направление счета  1 вперед / 0 назад

void RPM () { // Это счетчик оборотов обрабатыв прерыванием
  if (reverce)     ++rp;
  else     --rp;
  Serial.println(rp, DEC);
}


void setup() {
  Serial.begin(9600);
  pinMode(RPMpin,    INPUT_PULLUP);
  digitalWrite(RPMpin, 1); // подключить датчик Холла
  attachInterrupt(0, RPM, FALLING);

  pinMode(brake_pin, OUTPUT); // Тормоз
  digitalWrite(brake_pin, 1);
  pinMode(back_pin, OUTPUT); // Прямое вращение
  digitalWrite(back_pin, 1);
  pinMode(direct_pin, OUTPUT); // обратное вращение
  digitalWrite(direct_pin, 1);
}

void loop() {
  Serial.println("New");
  digitalWrite(brake_pin, LOW); // отк тормоз
  digitalWrite(back_pin, LOW);  // вкл обр вращение
  
  while  (rp < 80)  {  }
  
  digitalWrite(brake_pin, HIGH);  // вкл тормоз
  digitalWrite(back_pin, HIGH);  // откл обр вращение
  reverce = 0; // счет обратно
  delay(5000);

  Serial.println("Down");
  digitalWrite(brake_pin, LOW); // отк тормоз
  digitalWrite(direct_pin, LOW);  // вкл прям вращение

  while  (rp > 0) {  }
  
  digitalWrite(brake_pin, HIGH);  // вкл тормоз
  digitalWrite(direct_pin, HIGH);  // откл обр вращение
  reverce = 1; // счет вперед
  delay(5000);
  Serial.println("Up");
}