Encoder not working properly inside of class

Hey guys!

I am trying to write a method to call my Encoder values, but for some reason, the only value I get printed is -1. If I twist the knob, it turns to -2 for some seconds but jumps back as soon as I let it go.

Main Code:

#include <Arduino.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Encoder.h>
#include "Display.h"
#include "Sequencer.h"

Display display;
Sequencer sequencer;

void setup()
{
  display.init();
}

void loop()
{
  display.update();
  sequencer.update();
}

Sequencer.h relevant section:

  class Sequencer
{
public:
  long positionEnc1 = -999;
  Encoder Enc1;
  private:
}

Sequencer.cpp relevant section:

Sequencer::Sequencer() :
                         _display(),
                         ADCFilter(60, 0),
                         Enc1(21, 22)

{
}

long Sequencer::encoder()
{
  long newEnc1;
  newEnc1 = Enc1.read();

  if (newEnc1 != positionEnc1)
  {
    positionEnc1 = newEnc1;
  }
  return newEnc1;
}

void Sequencer::update()
{
    Serial.println(encoder());
    stepButtons();
    stepLED();
    muxUpdate();
}

How should other users understand your code if you don't post the full sketch?
If you would be 101% sure where the error is you would correct the error and you are done.
But you are asking for help. This means you are not 101% sure

So the error might be just in a place you don't think of
Conclusion post the complete sketch

best regards Stefan

shouldn't you post the Encoder.cpp code? the read()

Thats right, here, my full code:

Sequencer.cpp:

#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::update()
{
    encoder();
    stepButtons();
    stepLED();
    muxUpdate();
}

Sequencer.h:

#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

main.cpp:

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

programing with the Arduino-IDE is - more or less - programming C++
But based on functions setup() and loop() instead of main()

Of course the codelines are the same.
-- .. -- just a moment --
You are using void setup() and void loop()
but why do you call it "main.cpp" ?

And a "real" Arduino-IDE sketch has only one *.ino-file instead of several *.cpp-files

still the definition of the encoder library i smissing wich encoder.h is this?
there are so many encoder-libraries online available - no idea. which one you are using.

Me personal I see no need to put all this into a class. So I'm out as I don't know much about how to write classes

So a final question: did you develop this code in a style "let's put (almost all ) together and then test
or did you write the code add one thing at a time test throuroughly if it works reliable - even - in exceptional circumstances - then add the next small thing?

best regards Stefan

I did the code by adding one thing a time and testing whether it works. I wanted the separation with classes to make it more readable and easier to maintain.

On top of the other questions, Are you getting warnings when you compile? What platform? Esp32?

What's the difference between..

std::array<float, 4> sustain;

and

float sustain[4];

?

-jim lee

jimLee:
What's the difference between..

std::array<float, 4> sustain;

and

float sustain[4];

?

-jim lee

https://www.learncpp.com/cpp-tutorial/an-introduction-to-stdarray/

Huh! Well ain't that fancy.

Thanks for the link.

-jim lee

@J-M-L
I don't get any warnings.. The only output I get from the encoder is -1 and if I twist it, for a short moment it changes to -2.. I am using a Teensy 4.0.

I don't get any warnings..

and they are enabled in the preferences, right?

and I suppose you are using Teensy's encoder library?

I suspected an issue in the way the Enc1 instance variable gets instantiated and gets its pins.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.