Энкодер + ssd1306 = не работает

Тема в разделе "Arduino & Shields", создана пользователем рокки1945, 16 авг 2020.

  1. Здравствуйте! Подскажите в чём может быть проблема есть желание использовать в паре дисплей с энкодером. Так вот когда в основном цикле идёт постоянный опрос энкодера на дисплее всё гаснет, точнее когда обращаюсь к функции пробега по меню.
    Код (C++):
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    #define pin_CLK 2 // Энкодер пин A
    #define pin_DT  3 // Энкодер пин B

    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

    int Position = 0;
    int oldPosition = 0;


    void EncoderRotate() {
      if (digitalRead(pin_CLK) == digitalRead(pin_DT)) {
        Position++;
      } else {
        Position--;
      }
    }

    void main_menu (int x){
      display.clearDisplay();
      display.setTextColor(WHITE);
      display.setCursor(42, 0);
      display.setTextSize(1);
      display.println(utf8rus("МЕНЮШКА:"));
      if (x > 6){x = 0;}
      if (x < 0){x = 6;}
      if (x == 0){display.setCursor(0, 8);display.println(utf8rus("> Конфиги"));}
      else{display.setCursor(0, 8);display.println(utf8rus("  Конфиги"));}
      if (x == 1){display.setCursor(0, 16);display.println(utf8rus("> Температурка"));}
      else{display.setCursor(0, 16);display.println(utf8rus("  Температурка"));}
      if (x == 2){display.setCursor(0, 24);display.println(utf8rus("> Радиопеленгация"));}
      else{display.setCursor(0, 24);display.println(utf8rus("  Радиопеленгация"));}
      if (x == 3){display.setCursor(0, 32);display.println(utf8rus("> Весточка"));}
      else{display.setCursor(0, 32);display.println(utf8rus("  Весточка"));}
      if (x == 4){display.setCursor(0, 40);display.println(utf8rus("> Напрягометр"));}
      else{display.setCursor(0, 40);display.println(utf8rus("  Напрягометр"));}
      if (x == 5){display.setCursor(0, 48);display.println(utf8rus("> Радиотаймер"));}
      else{display.setCursor(0, 48);display.println(utf8rus("  Радиотаймер"));}
      if (x == 6){display.setCursor(0, 56);display.println(utf8rus("> Входит и выходит"));}
      else{display.setCursor(0, 56);display.println(utf8rus("  Входит и выходит"));}
      display.display();
     
    }

    void setup() {
      //Serial.begin(115200);
      if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {for(;;);}
      display.cp437(true);
      main_menu(0);
      pinMode(pin_CLK, INPUT);
      pinMode(pin_DT, INPUT);
      attachInterrupt(digitalPinToInterrupt(pin_CLK), EncoderRotate, RISING);

     
    }
    void loop() {

    if (oldPosition != Position)
      {
        main_menu (Position);
        oldPosition = Position;
      }
     
     

     
    }
    /* Recode russian fonts from UTF-8 to Windows-1251 */
    String utf8rus(String source)
    {
      int i,k;
      String target;
      unsigned char n;
      char m[2] = { '0', '\0' };
      k = source.length(); i = 0;
      while (i < k) {
        n = source[i]; i++;
        if (n >= 0xC0) {
          switch (n) {
            case 0xD0: {
              n = source[i]; i++;
              if (n == 0x81) { n = 0xA8; break; }
              if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
              break;
            }
            case 0xD1: {
              n = source[i]; i++;
              if (n == 0x91) { n = 0xB8; break; }
              if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
              break;
            }
          }
        }
        m[0] = n; target = target + String(m);
      }
    return target;
    }
     
  2. parovoZZ

    parovoZZ Гуру

    Даже дешёвый оптический инкрементальный энкодер даёт звон, а здесь, как я понимаю, используется электроконтактный, который тем более звенит. Так как звон абсолютно хаотичный, то он запросто попадает в момент, когда дисплей очищается. Поэтому весь код под перезапись.
     
  3. Не понятно как теперече быть? Что делать, что изменить - при том, что все опробаванные мною библиотеки нормально отрабатывают и чётко скидывают в сериал изменённое состояние переменной при повороте вала, так что механика тут ни при чём (брал примеры из библиотек), но вызывать функции из обработчика по изменению состояния энокдера и вызова моей функции !Увы! не возможно. Может где-то не догоняю.... Может на одном и том же таймере сидят.... Библии брал от гайвера и энкодер (что на втором таймере).
     
  4. Nekto_nikto

    Nekto_nikto Гик

    Попробуйте из сериала вместо энкодера выводить данные/управлять экраном, не изменяя структуры программы, если получится, значит действительно что то конфликтует.
     
  5. уже переехал на чистый СИ
     
  6. parovoZZ

    parovoZZ Гуру

    что это?
     
    рокки1945 нравится это.
  7. b707

    b707 Гуру

    опа... а код в заглавном сообщении на чем был? :) на питоне? :)))

    На самом деле, в коде из первого сообщения логика ни к черту, в процедуре main_menu() при любом шевелении энкодера перерисовывается весь экран - неудивительно, что код виснет. Рокки, вместо того чтоб заниматься ерундой (это я про "чистый Си") - лучше займитесь "выпрямлением" вашего кривого кода, глядишь он и без "чистого" Си отлично заработает :)
     
    Feofan и Andrey12 нравится это.
  8. Хорошо - спасибо буду знать.