Регулятор громкости на digispark

Тема в разделе "Микроконтроллеры AVR", создана пользователем Roman1, 20 мар 2020.

  1. Roman1

    Roman1 Нуб

    Добрый день, хочется добавить к регулятору громкости плавное включение и затухание светодиода. Пытался сам объединить два скетча, но работает только плавное затухание. По отдельности оба работают, не подскажите что не так?

    Код (C++):
    // see tutorial at http://learn.adafruit.com/trinket-usb-volume-knob

    #include "TrinketHidCombo.h"

    #define PIN_ENCODER_A 0
    #define PIN_ENCODER_B 2
    #define TRINKET_PINx  PINB
    #define PIN_ENCODER_SWITCH 1
    #define LED_PIN 4 // задаем имя для Pin4

    static uint8_t enc_prev_pos   = 0;
    static uint8_t enc_flags      = 0;
    static char    sw_was_pressed = 0;

    void setup()
    {
      // set pins as input with internal pull-up resistors enabled
      pinMode(PIN_ENCODER_A, INPUT);
      pinMode(PIN_ENCODER_B, INPUT);
      pinMode(LED_PIN, OUTPUT); // инициализируем Pin4 как выход
      digitalWrite(PIN_ENCODER_A, HIGH);
      digitalWrite(PIN_ENCODER_B, HIGH);

      pinMode(PIN_ENCODER_SWITCH, INPUT);
      // the switch is active-high, not active-low
      // since it shares the pin with Trinket's built-in LED
      // the LED acts as a pull-down resistor
      digitalWrite(PIN_ENCODER_SWITCH, LOW);

      TrinketHidCombo.begin(); // start the USB device engine and enumerate

      // get an initial reading on the encoder pins
      if (digitalRead(PIN_ENCODER_A) == LOW) {
        enc_prev_pos |= (1 << 0);
      }
      if (digitalRead(PIN_ENCODER_B) == LOW) {
        enc_prev_pos |= (1 << 1);
      }
    }

    void loop()
    {
       // плавное включение светодиода
       // начальное значение на Pin6 i=0, если i<=255, то прибавляем к i единицу
      for(int i=0;i<=255;i++) {
      analogWrite(LED_PIN, i);
      delay(5); // ставим задержку для эффекта
       }

       //плавное затухание светодиода
       // начальное значение на Pin6 i=255, если i>=255, то вычитаем от i единицу
      for(int i=255;i>=0;i--) {
      analogWrite(LED_PIN, i);
      delay(5); // ставим задержку для эффекта
       }

      int8_t enc_action = 0; // 1 or -1 if moved, sign is direction

      // note: for better performance, the code will now use
      // direct port access techniques
      // http://www.arduino.cc/en/Reference/PortManipulation
      uint8_t enc_cur_pos = 0;
      // read in the encoder state first
      if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_A)) {
        enc_cur_pos |= (1 << 0);
      }
      if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_B)) {
        enc_cur_pos |= (1 << 1);
      }

      // if any rotation at all
      if (enc_cur_pos != enc_prev_pos)
      {
        if (enc_prev_pos == 0x00)
        {
          // this is the first edge
          if (enc_cur_pos == 0x01) {
            enc_flags |= (1 << 0);
          }
          else if (enc_cur_pos == 0x02) {
            enc_flags |= (1 << 1);
          }
        }

        if (enc_cur_pos == 0x03)
        {
          // this is when the encoder is in the middle of a "step"
          enc_flags |= (1 << 4);
        }
        else if (enc_cur_pos == 0x00)
        {
          // this is the final edge
          if (enc_prev_pos == 0x02) {
            enc_flags |= (1 << 2);
          }
          else if (enc_prev_pos == 0x01) {
            enc_flags |= (1 << 3);
          }

          // check the first and last edge
          // or maybe one edge is missing, if missing then require the middle state
          // this will reject bounces and false movements
          if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4))) {
            enc_action = 1;
          }
          else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4))) {
            enc_action = 1;
          }
          else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4))) {
            enc_action = -1;
          }
          else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4))) {
            enc_action = -1;
          }

          enc_flags = 0; // reset for next time
        }
      }

      enc_prev_pos = enc_cur_pos;

      if (enc_action > 0) {
        TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
      }
      else if (enc_action < 0) {
        TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
      }

      // remember that the switch is active-high
      if (bit_is_set(TRINKET_PINx, PIN_ENCODER_SWITCH))
      {
        if (sw_was_pressed == 0) // only on initial press, so the keystroke is not repeated while the button is held down
        {
          TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE);
          delay(5); // debounce delay
        }
        sw_was_pressed = 1;
      }
      else
      {
        if (sw_was_pressed != 0) {
          delay(5); // debounce delay
        }
        sw_was_pressed = 0;
      }

      TrinketHidCombo.poll(); // check if USB needs anything done
    }

    Код (Text):
    // see tutorial at http://learn.adafruit.com/trinket-usb-volume-knob

    #include "TrinketHidCombo.h"

    #define PIN_ENCODER_A 0
    #define PIN_ENCODER_B 2
    #define TRINKET_PINx  PINB
    #define PIN_ENCODER_SWITCH 1

    static uint8_t enc_prev_pos   = 0;
    static uint8_t enc_flags      = 0;
    static char    sw_was_pressed = 0;

    void setup()
    {
      // set pins as input with internal pull-up resistors enabled
      pinMode(PIN_ENCODER_A, INPUT);
      pinMode(PIN_ENCODER_B, INPUT);
      digitalWrite(PIN_ENCODER_A, HIGH);
      digitalWrite(PIN_ENCODER_B, HIGH);

      pinMode(PIN_ENCODER_SWITCH, INPUT);
      // the switch is active-high, not active-low
      // since it shares the pin with Trinket's built-in LED
      // the LED acts as a pull-down resistor
      digitalWrite(PIN_ENCODER_SWITCH, LOW);

      TrinketHidCombo.begin(); // start the USB device engine and enumerate

      // get an initial reading on the encoder pins
      if (digitalRead(PIN_ENCODER_A) == LOW) {
        enc_prev_pos |= (1 << 0);
      }
      if (digitalRead(PIN_ENCODER_B) == LOW) {
        enc_prev_pos |= (1 << 1);
      }
    }

    void loop()
    {
      int8_t enc_action = 0; // 1 or -1 if moved, sign is direction

      // note: for better performance, the code will now use
      // direct port access techniques
      // http://www.arduino.cc/en/Reference/PortManipulation
      uint8_t enc_cur_pos = 0;
      // read in the encoder state first
      if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_A)) {
        enc_cur_pos |= (1 << 0);
      }
      if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_B)) {
        enc_cur_pos |= (1 << 1);
      }

      // if any rotation at all
      if (enc_cur_pos != enc_prev_pos)
      {
        if (enc_prev_pos == 0x00)
        {
          // this is the first edge
          if (enc_cur_pos == 0x01) {
            enc_flags |= (1 << 0);
          }
          else if (enc_cur_pos == 0x02) {
            enc_flags |= (1 << 1);
          }
        }

        if (enc_cur_pos == 0x03)
        {
          // this is when the encoder is in the middle of a "step"
          enc_flags |= (1 << 4);
        }
        else if (enc_cur_pos == 0x00)
        {
          // this is the final edge
          if (enc_prev_pos == 0x02) {
            enc_flags |= (1 << 2);
          }
          else if (enc_prev_pos == 0x01) {
            enc_flags |= (1 << 3);
          }

          // check the first and last edge
          // or maybe one edge is missing, if missing then require the middle state
          // this will reject bounces and false movements
          if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4))) {
            enc_action = 1;
          }
          else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4))) {
            enc_action = 1;
          }
          else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4))) {
            enc_action = -1;
          }
          else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4))) {
            enc_action = -1;
          }

          enc_flags = 0; // reset for next time
        }
      }

      enc_prev_pos = enc_cur_pos;

      if (enc_action > 0) {
        TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP);
      }
      else if (enc_action < 0) {
        TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN);
      }

      // remember that the switch is active-high
      if (bit_is_set(TRINKET_PINx, PIN_ENCODER_SWITCH))
      {
        if (sw_was_pressed == 0) // only on initial press, so the keystroke is not repeated while the button is held down
        {
          TrinketHidCombo.pressMultimediaKey(MMKEY_MUTE);
          delay(5); // debounce delay
        }
        sw_was_pressed = 1;
      }
      else
      {
        if (sw_was_pressed != 0) {
          delay(5); // debounce delay
        }
        sw_was_pressed = 0;
      }

      TrinketHidCombo.poll(); // check if USB needs anything done
    }

    Код (C++):
    #define LED_PIN 6 // задаем имя для Pin6

    void setup() {
        pinMode(LED_PIN, OUTPUT); // инициализируем Pin6 как выход
    }

    void loop() {
       // плавное включение светодиода
       // начальное значение на Pin6 i=0, если i<=255, то прибавляем к i единицу
        for(int i=0;i<=255;i++) {
        analogWrite(LED_PIN, i);
        delay(5); // ставим задержку для эффекта
       }

       //плавное затухание светодиода
       // начальное значение на Pin6 i=255, если i>=255, то вычитаем от i единицу
        for(int i=255;i>=0;i--) {
        analogWrite(LED_PIN, i);
        delay(5); // ставим задержку для эффекта
       }

    }
     
  2. SergeiL

    SergeiL Оракул Модератор

    Ну нужно разбираться как написать плавное изменение яркости без deley() и блокировки. Почитать про millis();
    Это мешает работе энкодера и USB.
     
    Последнее редактирование: 22 мар 2020
  3. b707

    b707 Гуру

    Roman1 - этот код "плавного включения светодиода" может работать только отдельно сам по себе, потому что он написан так, что занимает все время контроллера, не позволяя ему выполниять никакую другую работу.
    Чтобы обьединить эти два кода, скетч для светодиода нужно написать полностью заново. Как уже посоветовали выше, используйте миллис, ищите в инете пример "блинк без делей" - там все подробно описано
     
  4. Roman1

    Roman1 Нуб

    Спасибо!