Encoder not working properly

Status
Not open for further replies.

topicbird

Active member
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
[url]https://github.com/PaulStoffregen/Encoder.git[/url]

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();
}
 
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.
 
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.
 
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
 
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?
 
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

sc.jpg

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);[B]
    sgtl5000_1.enable();
    sgtl5000_1.volume(defaultVolume);[/B]
    attack.fill(defaultDecayValue);
    decay.fill(defaultDecayValue);
    sustain.fill(defaultSustainValue);
    release.fill(defaultSustainValue);
 
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!
 
Does the fact produce any problem that the tft display and also the audioshield use pin 8, if I want to use both simultaneously?
 
Status
Not open for further replies.
Back
Top