Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 13 of 13

Thread: Encoder not working properly

  1. #1
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14

    Encoder not working properly

    Hello!

    Currently, I am trying to use Encoders inside my code. I am using VSC. For some reason though, the only output I get is -1 and sometimes it jumps to -2 if I twist the knob fast enough.. I would be happy about any help, thank you!

    my platform.ini:

    Code:
    [env:teensy40]
    platform = teensy
    board = teensy40
    framework = arduino
    lib_deps = megunolink/MegunoLink@^1.30
    https://github.com/PaulStoffregen/Encoder.git
    main.cpp:
    Code:
    #include <Arduino.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <Encoder.h>
    #include "Display.h"
    #include "Sequencer.h"
    
    Display display;
    Sequencer sequencer;
    
    int b1 = 0;
    int b2 = 0;
    int b3 = 0;
    int b4 = 0;
    
    void ADSR(float att, float dec, float sus, float rel)
    {
      // b1 = digitalRead(20);
      b2 = digitalRead(2);
      b3 = digitalRead(3);
      b4 = digitalRead(4);
    }
    
    void setup()
    {
      display.init();
    }
    
    void loop()
    {
      display.update();
      sequencer.update();
    }
    sequencer.h:
    Code:
    #ifndef Sequencer_h
    #define Sequencer_h
    #include <array>
    #include <Audio.h>
    #include <Wire.h>
    #include "Display.h"
    #include <MegunoLink.h>
    #include <Filter.h>
    #include "Encoder.h"
    
    class Sequencer
    {
    public:
      Sequencer();
      void start();
      void stop();
      unsigned int counter(float interval);
      void stepButtons();
      void buttonsAbfragen(int zaehler, int digitalPin);
      void stepLED();
      void update();
      float getBPMInterval();
      void muxUpdate();
      long encoder();
      float mapper(float x, float in_min, float in_max, float out_min, float out_max);
      int _deflectionRate;
      int frequency1 = {160};
      int frequency2 = {200};
      int frequency3 = {140};
      int frequency4 = (110);
      ExponentialFilter<long> ADCFilter;
      std::array<float, 4> attack;
      std::array<float, 4> decay;
      std::array<float, 4> sustain;
      std::array<float, 4> release;
      std::array<float, 4> amplitude;
      std::array<int, 4> frequency{{frequency1, frequency2, frequency3, frequency4}};
      std::array<int, 4> m_stepLEDPin{{3, 4, 5, 6}};
      std::array<int, 4> m_stepButtonPin{{0, 1, 14, 15}};
      std::array<boolean, 4> m_stepState{{true, true, true, true}};
      std::array<boolean, 4> digitalReadValues;
      int16_t *wave1Values;
      float defaultAttackValue = {50};
      float defaultDecayValue = {200};
      float defaultSustainValue = {200};
      float defaultReleaseValue = {200};
      float defaultVolume = {0.3};
      unsigned long m_lastMillis;
      float m_interval = (60.0 / average_bpm) * 1000.0;
      unsigned long m_stepStateInterval = 20;
      unsigned int m_STEPNUM = 4;
      unsigned int m_step = 0;
      const int numReadings = 5; // Anzahl der Readings
      int readings[5];           // the readings from the analog input
      int readIndex = 0;         // the index of the current reading
      int total = 0;             // the running total
      float average = 0;         // the average
      int inputPin = A3;         // Analog input
      int average_bpm = 120;
      int average_bpm_alt = 120;
      unsigned long m_BPMInterval = 400;
      int m_AnalogThreshold = 3;
      int ADCFilterBefore;
      float interval;
      float minBPM = 40.0;
      float maxBPM = 800.0;
      int pin_Out_S0 = 0;
      int pin_Out_S1 = 1;
      int pin_Out_S2 = 2;
      int buttonState[48];
      int bit1 = 0;
      int bit2 = 0;
      int bit3 = 0;
      long positionEnc1 = -999;
      Encoder Enc1;
      AudioSynthWaveform *waveform = new AudioSynthWaveform[4];
      AudioEffectEnvelope *envelope = new AudioEffectEnvelope[4];
      AudioMixer4 mixer1;
      AudioOutputI2S i2s1;
      AudioConnection patchCord1;
      AudioConnection patchCord2;
      AudioConnection patchCord3;
      AudioConnection patchCord4;
      AudioConnection patchCord5;
      AudioConnection patchCord6;
      AudioConnection patchCord7;
      AudioConnection patchCord8;
      AudioConnection patchCord9;
      AudioConnection patchCord10;
      AudioControlSGTL5000 sgtl5000_1;
      Display _display;
    
    private:
    };
    
    #endif
    sequencer.cpp:

    Code:
    #include "Sequencer.h"
    #include "Display.h"
    
    Sequencer::Sequencer() : patchCord1(waveform[1], envelope[1]),
                             patchCord2(waveform[2], envelope[2]),
                             patchCord3(waveform[3], envelope[3]),
                             patchCord4(waveform[0], envelope[0]),
                             patchCord5(envelope[3], 0, mixer1, 3),
                             patchCord6(envelope[2], 0, mixer1, 2),
                             patchCord7(envelope[0], 0, mixer1, 0),
                             patchCord8(envelope[1], 0, mixer1, 1),
                             patchCord9(mixer1, 0, i2s1, 0),
                             patchCord10(mixer1, 0, i2s1, 1),
                             _display(),
                             ADCFilter(60, 0),
                             Enc1(21, 22)
    
    {
    
        for (int i{0}; i < 4; ++i)
        {
            envelope[i].attack(attack[i]);
            envelope[i].decay(decay[i]);
            envelope[i].sustain(sustain[i]);
            envelope[i].release(release[i]);
        }
        AudioMemory(20);
        sgtl5000_1.enable();
        sgtl5000_1.volume(defaultVolume);
        attack.fill(defaultDecayValue);
        decay.fill(defaultDecayValue);
        sustain.fill(defaultSustainValue);
        release.fill(defaultSustainValue);
        amplitude.fill(defaultVolume);
    
        for (unsigned int i{0}; i < 4; ++i)
        {
            mixer1.gain(i, defaultVolume);
            waveform[i].begin(WAVEFORM_SINE); // WAVEFORM_SINE expands to 0 WAVEFORM_ARBITRARY expands to 4
            waveform[i].amplitude(amplitude[i]);
            waveform[i].frequency(frequency[i]);
            pinMode(m_stepLEDPin[i], OUTPUT);
            pinMode(m_stepButtonPin[i], INPUT_PULLUP);
        }
    }
    
    float Sequencer::getBPMInterval()
    {
        int RawValue = analogRead(A2);
        ADCFilter.Filter(RawValue);
        if ((millis() - m_lastMillis) > m_BPMInterval && ADCFilterBefore != ADCFilter.Current() && (ADCFilterBefore - ADCFilter.Current() > m_AnalogThreshold))
        {
            m_lastMillis = millis();
            ADCFilterBefore = ADCFilter.Current();
        }
    
        // subtract the last reading:
        total = total - readings[readIndex]; // Alle analoge Inputwerte zusammenaddiert, wobei der Wert der neuen Loop abgezogen wird (zieht den nullten Wert ab)
        // read from the sensor:
        readings[readIndex] = RawValue;
    
        // add the reading to the total:
        total = total + readings[readIndex];
        // advance to the next position in the array:
        readIndex = readIndex + 1;
    
        if (readIndex >= numReadings)
        {
            // ...wrap around to the beginning:
            readIndex = 0;
    
            // calculate the average:
            average = total / numReadings;
            average_bpm = mapper(average, 1.0, 1023.0, minBPM, maxBPM);
        }
        if (average_bpm != average_bpm_alt)
        {
            average_bpm_alt = average_bpm;
        }
        float m_interval = (60.0 / average_bpm) * 1000.0;
        return m_interval;
    }
    
    unsigned int Sequencer::counter(float interval) // Returns the current position
    {
        if ((millis() - m_lastMillis) > getBPMInterval()) // m_interval = 1000 ---> 60 bpm , m_interval = 500 ---> 120bpm
        {
            m_lastMillis = millis();
            m_step++;
            if (m_step == m_STEPNUM)
            {
                m_step = 0;
            }
        }
        return m_step;
    }
    
    void Sequencer::stepButtons()
    {
        std::array<boolean, 4> digitalReadValues = {digitalRead(0), digitalRead(1), digitalRead(14), digitalRead(15)};
    
        for (unsigned int i{0}; i < digitalReadValues.size(); ++i)
        {
            if ((millis() - m_lastMillis) > m_stepStateInterval)
            {
                if (digitalReadValues[i] == LOW) // LOW = GEDRÜCKT
                {
                    m_stepState[i] = !m_stepState[i];
                }
            }
        }
    }
    
    void Sequencer::stepLED()
    {
        if (_display.isTouched())
        {
            wave1Values = _display.getArray();
        }
        waveform[0].arbitraryWaveform(wave1Values, 20000);
        counter(getBPMInterval()); //No constructor needed because you already wrote Sequencer::stepLED()
        for (unsigned int i{0}; i < m_stepLEDPin.size(); ++i)
        {
            if (counter(getBPMInterval()) == 0)
            {
                digitalWrite(m_stepLEDPin[0], m_stepState[0]);
                digitalWrite(m_stepLEDPin[3], LOW);
    
                envelope[0].noteOn();
                waveform[0].amplitude(m_stepState[0]);
                waveform[0].frequency(frequency[0]);
            }
            else if (counter(getBPMInterval()) == i)
            {
                digitalWrite(m_stepLEDPin[i], m_stepState[i]);
                digitalWrite(m_stepLEDPin[i] - 1, LOW);
                envelope[i].noteOn();
                waveform[i].amplitude(m_stepState[i]);
                waveform[i].frequency(frequency[i]);
            }
        }
    }
    
    float Sequencer::mapper(float x, float in_min, float in_max, float out_min, float out_max)
    {
        return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }
    
    void Sequencer::buttonsAbfragen(int zaehler, int digitalPin)
    {
        buttonState[zaehler] = digitalRead(digitalPin);
        // delayMicroseconds(50);
       // Serial.print(buttonState[zaehler]);
       // Serial.print(",");
    }
    
    long Sequencer::encoder()
    {
      long newEnc1;
      newEnc1 = Enc1.read();
      Serial.println(newEnc1);
    
      if (newEnc1 != positionEnc1)
      {
        positionEnc1 = newEnc1;
      }
      return newEnc1;
    }
    
    void Sequencer::muxUpdate()
    {
        for (int i = 0; i <= 7; i++)
        {
            bit1 = bitRead(i, 0);
            bit2 = bitRead(i, 1);
            bit3 = bitRead(i, 2);
    
            digitalWrite(pin_Out_S0, bit1);
            digitalWrite(pin_Out_S1, bit2);
            digitalWrite(pin_Out_S2, bit3);
    
            buttonsAbfragen(i, 14);      // Mux 1
            buttonsAbfragen(i + 8, 15);  // Mux 2
            buttonsAbfragen(i + 16, 16); // Mux 3
            buttonsAbfragen(i + 24, 17); // Mux 4
            buttonsAbfragen(i + 32, 18); // Mux 5
            buttonsAbfragen(i + 40, 19); // Mux 6
        }
    }
    
    void Sequencer::update()
    {
        encoder();
        stepButtons();
        stepLED();
        muxUpdate();
    }

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,742
    Can you reproduce the problem with a simpler program? This one appears to depend on MegunoLink.h, Display.h, Filter.h - maybe other stuff?

    Maybe try testing with the Arduino IDE and the Encoder library examples? That could at least help determine whether you're looking at a hardware issue or if you hardware is fine with the normal Arduino library & software environment and you should focus your effort on how your software is different.

  3. #3
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14
    Thanks for your answer Paul! I just tried the code

    Code:
    #include <Encoder.h>
    
    Encoder Enc1(21, 22);
    long positionEnc1  = -999;
    
    
    void setup() {
    }
    
    void loop() {
      long newEnc1;
      newEnc1 = Enc1.read();
    
      if (newEnc1 != positionEnc1) {
    
        Serial.print("Enc1 = ");
        Serial.print(newEnc1);
    
        positionEnc1 = newEnc1;
      }
    }
    and it works fine. I can't seem to figure out though, why the code I posted before doesn't reproduce the same output.

  4. #4
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14
    i even tried to write a version with the sequencer class and it works fine too.. I have really no idea what I did wrong in my actual code..

    The stripped down, working code:

    main.cpp:
    Code:
    #include <Arduino.h>
    #include <Encoder.h>
    #include "Sequencer.h"
    
    Sequencer sequencer;
    
    
    void setup() {
    }
    
    void loop() {
      sequencer.encoder();
    
    }
    Sequencer.cpp:
    Code:
    #include "Sequencer.h"
    
    Sequencer::Sequencer() : Enc1(21, 22)
    
    {
    }
    
    long Sequencer::encoder()
    {
        long newEnc1;
        newEnc1 = Enc1.read();
    
        if (newEnc1 != positionEnc1)
        {
            Serial.print("Enc1 = ");
            Serial.print(newEnc1);
            positionEnc1 = newEnc1;
        }
        return newEnc1;
    }
    Sequencer.h:
    Code:
    #ifndef Sequencer_h
    #define Sequencer_h
    #include <Encoder.h>
    
    class Sequencer
    {
    public:
        Sequencer();
        long positionEnc1 = -999;
        Encoder Enc1;
        long encoder();
    
    private:
    };
    
    #endif

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,742
    If this is Teensy 4.0, use of pin 21 conflicts AudioOutputI2S, because I2S uses pin 21 for BCLK.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,742
    If using Teensy 3.x, use of pin 22 would also conflict. AudioOutputI2S uses pin 22 for data output on those boards.

    Just move those encoder signals to unused pins and odds are good everything will start working.

    Details on these pages:

    https://www.pjrc.com/teensy/gui/?info=AudioOutputI2S

    https://www.pjrc.com/store/teensy3_audio.html

  7. #7
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14
    If i change it to 17,18 it produces the same error. I have also the TFT ILI9341 Display connected, could that be also an issue?

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,742
    Maybe you're using the Wire library? (can't tell from only a quick look)

    Wire uses pin 18 & 19.

    Again, details here:

    https://www.pjrc.com/store/teensy3_audio.html

    Click image for larger version. 

Name:	sc.jpg 
Views:	11 
Size:	77.5 KB 
ID:	23350

    You need to avoid using those pins the audio shield uses!

    EDIT: yup, definitely a Wire lib conflict, as SGTL5000 uses Wire for config:

    Code:
        AudioMemory(20);
        sgtl5000_1.enable();
        sgtl5000_1.volume(defaultVolume);
        attack.fill(defaultDecayValue);
        decay.fill(defaultDecayValue);
        sustain.fill(defaultSustainValue);
        release.fill(defaultSustainValue);

  9. #9
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14
    Yes, I do.. That could be the issue. I guess I have to use my multiplexers because I don't have any free pins left. Thank you for your help!

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,742
    Maybe switch to Teensy 4.1 and save that 4.0 for another project not needing as much I/O?

  11. #11
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14
    That's a good idea! Thank you for the advice.

  12. #12
    Junior Member
    Join Date
    Nov 2020
    Location
    Germany
    Posts
    14
    Does the fact produce any problem that the tft display and also the audioshield use pin 8, if I want to use both simultaneously?

  13. #13
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,937
    Quote Originally Posted by topicbird View Post
    Does the fact produce any problem that the tft display and also the audioshield use pin 8, if I want to use both simultaneously?
    Yes of course.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •