Вопрос по ESP8266 и энкодеру

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

Я только постигаю ардуино и esp8266, поэтому не кидайтесь тапками(
В чем суть вопроса:
Имею энкодер https://belchip.by/product/?selected_product=42210 
И плату NodeMCU v3.0.
Подключил к пенам D4,D5,D6 у esp8266
Нашел статью https://habr.com/ru/post/586576/
 

Переделал код, добавив прерывания в соответствии с esp, заменив 

PCICR =  0b00000010; // PCICR |= (1<<PCIE1); Включить прерывание PCINT1
  PCMSK1 = 0b00001110; // Разрешить прерывание для  A1, A2, A3

на 

attachInterrupt(digitalPinToInterrupt(D5), Qqy, CHANGE);
  attachInterrupt(digitalPinToInterrupt(D6), Qqy, CHANGE);
  attachInterrupt(digitalPinToInterrupt(D7), Qqy, CHANGE);

В  "ICACHE_RAM_ATTR void Qqy() {" находится обработчик прерываний из статьи, однако ардуино Иде ругается на 

 uint8_t comb = bitRead(PINC, 3) << 2 | bitRead( PINC, 2)<<1 | bitRead(PINC, 1);


а именно на PINC
Я так понял, что считываются значения регистров для панов gpio
Однако...при замене bitRead на digitalRead с соответствующим пином получаю на выходе пусть и результат, но бессмысленный до крайности

Помогите заставить ЭТО работать, пожаааааалуйста
 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Регистро-ориентированный код для AVR на ESP работать не будет.

Читайте пины через digitalRead, потом складывайте бинарно. 

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

А можно более развернутый ответ?)

vrd
Offline
Зарегистрирован: 20.01.2022

А зачем 3(три) пина? Если сопротивление больше килоОма, то один край на + 3.3 второй на - и со среднего снимаем сигнал.

На хабр меня не пускает. Опишите для чего необходимо устройство.

rkit
Offline
Зарегистрирован: 23.11.2016

vrd пишет:

+ 3.3 второй на - и

ловим КЗ

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

Делаю регулируемый блок питания, энкодер необходим для точной настройки выходного напряжения(один щелчок это + или - 0.1В на выходе) + реализация долгого нажатия и поворота с нажатием

знаю, что кнопки было бы проще использовать, но размер устройства не позволяет)

vrd
Offline
Зарегистрирован: 20.01.2022

Меня всё ещё не пускает на хабр. Если вольтметр НЕ завязан на дуину - всё делается легко.

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

vrd пишет:

Меня всё ещё не пускает на хабр. Если вольтметр НЕ завязан на дуину - всё делается легко.

 

я понимаю, мне всего то и нужно отлавливать, что с энкодером происходит (количество щелчков, направление и прочее)

vrd
Offline
Зарегистрирован: 20.01.2022

Три пина. Это лево право и нажатие?

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

vrd пишет:

Три пина. Это лево право и нажатие?

 

именно

выходы А и Б от энкодера  и кнопка в энкодере

vrd
Offline
Зарегистрирован: 20.01.2022
if (A == 0 && B == 1) {
  I++;
  B = 0;
}
if (A == 1 && B == 0) {
  I--;
  A = 0;
}

Логика простая. Чего по кнопке?

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

vrd пишет:

if (A == 0 && B == 1) {
  I++;
  B = 0;
}
if (A == 1 && B == 0) {
  I--;
  A = 0;
}

Логика простая. Чего по кнопке?

 

Т.е. при повороте на одном из выходов в зависимости от направления возникает прямоугольный импульс? 
в таком случае вопрос про подключение (куда питание пихать, в статье что я кидал он просто подключён к земле и трём пинам) и как считать время для длинного нажатия 

vrd
Offline
Зарегистрирован: 20.01.2022

По прерываниям у Гайвера хорошо и понятно написано. Для начинающих.

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

vrd пишет:

По прерываниям у Гайвера хорошо и понятно написано. Для начинающих.

 

в прерывания лез уже, работает, но криво 

конкретно в статье на хабре что я кидал проблема только в обработке сигнала с энкодера (обработка была по регистрам пинов, с digital read не пашет

сейчас приведу код программы

Ilya3Run
Offline
Зарегистрирован: 23.09.2013
/*
При публичном размещении кода ссылка на первоисточник обязательна.
*/

#define btn_long_push 1000   // Длительность долинного нажатия кнопки
volatile uint8_t lastcomb=7, enc_state, btn_push=0;
volatile int enc_rotation=0, btn_enc_rotate=0;
volatile boolean btn_press=0;
volatile uint32_t timer;

//********************************
void setup() 
{
  pinMode(A1,INPUT_PULLUP); // ENC-A
  pinMode(A2,INPUT_PULLUP); // ENC-B
  pinMode(A3,INPUT_PULLUP); // BUTTON

  PCICR =  0b00000010; // PCICR |= (1<<PCIE1); Включить прерывание PCINT1
  PCMSK1 = 0b00001110; // Разрешить прерывание для  A1, A2, A3
  
  Serial.begin(115200);
}

//****************************************
void loop() 
{
  switch (enc_state)
    {
  case 1:   {
            Serial.print("Вращение без нажатия ");
            Serial.println(enc_rotation);
            }
   break;
   
  case 2:  {
            Serial.print("Вращение с нажатием ");
            Serial.println(btn_enc_rotate);  
           }
    break;
    
  case 3: Serial.println("Нажатие кнопки ");
  break;

  case 4: Serial.println("Длинное нажатие кнопки ");
  break;
    }
  enc_state=0; //обнуляем статус энкодера
}

//****************************************
ISR (PCINT1_vect) //Обработчик прерывания от пинов A1, A2, A3
{
  uint8_t comb = bitRead(PINC, 3) << 2 | bitRead( PINC, 2)<<1 | bitRead(PINC, 1); //считываем состояние пинов энкодера и кнопки

 if (comb == 3 && lastcomb == 7) btn_press=1; //Если было нажатие кнопки, то меняем статус
 
 if (comb == 4)                         //Если было промежуточное положение энкодера, то проверяем его предыдущее состояние 
 {
    if (lastcomb == 5) --enc_rotation; //вращение по часовой стрелке
    if (lastcomb == 6) ++enc_rotation; //вращение против часовой
    enc_state=1;                       // был поворот энкодера    
    btn_enc_rotate=0;                  //обнулить показания вращения с нажатием
  }
  
   if (comb == 0)                      //Если было промежуточное положение энкодера и нажатие, то проверяем его предыдущее состояние 
   {
    if (lastcomb == 1) --btn_enc_rotate; //вращение по часовой стрелке
    if (lastcomb == 2) ++btn_enc_rotate; //вращение против частовой
    enc_state=2;                        // был поворот энкодера с нажатием  
    enc_rotation=0;                     //обнулить показания вращения без нажатия
    btn_press=0;                         //обнулить показания кнопки
   }

   if (comb == 7 && lastcomb == 3 && btn_press) //Если было отпускание кнопки, то проверяем ее предыдущее состояние 
   {
    if (millis() - timer > btn_long_push)         // проверяем сколько прошло миллисекунд
    {
      enc_state=4;                              // было длинное нажатие 
    } else {
             enc_state=3;                    // было нажатие 
            }
      btn_press=0;                           //обнулить статус кнопки
    }
   
  timer = millis();                       //сброс таймера
  lastcomb = comb;                        //сохраняем текущее состояние энкодера
}И 

 

vrd
Offline
Зарегистрирован: 20.01.2022

У этого энкодера есть общая нога на которую замыкются А и Б. Эту ногу на +3,3. Выходы через резистор 1к-10к на корпус. Кнопку аналогично.

Прерывание возвращает A или B единицу.

Переменную I на параметр ШИМ. В дуине это значение не должно превышать 255, и не должно быть ниже нуля.

vrd
Offline
Зарегистрирован: 20.01.2022

В дуине прерывания пишутся по другому. Ищите примеры у гугля.

И ищите именно под ESP.

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

vrd пишет:

В дуине прерывания пишутся по другому. Ищите примеры у гугля.

И ищите именно под ESP.

 

дк переписать прерывания я переписал, вопрос в строчке, где считываются состояния входов 

прерывания работают

но ведут себя архинеадекватно(т.е. результат на выходе в мониторе порта есть, но не отвечает реальности) и мой вопрос вопрос заключался в том, как правильно считывать состояния входов без этого вонючего bitRead(), ибо если заменить его на digitalRead получается неадекват

Ilya3Run
Offline
Зарегистрирован: 23.09.2013

Проблему решил, все решилось корректным подключением энкодера, переписыванием прерываний под esp8266,изменением bitRead на digitalRead и программным устранением дребезга, всем спасибо(если кому надо-выложу код)

notfound
Offline
Зарегистрирован: 09.04.2022

А можно код то глянуть?