Read controls while sound is playing

Status
Not open for further replies.

urbanspaceman

Well-known member
Hello! It's time to ask for advice
i have a project that include: teensy3.6, 5 encoders with MCP23017, audio board and other stuff..

Now, i have tested the single parts: audio ok, encoders ok
but if i put all the parts together, i can ear the audio but the encoders stop working.

I need an advice to put the pieces together, with the encoders I want to control the audio parameters while the audio keeps playing.

the encoders are read with this library and the pollAll function inside the loop() function

https://github.com/maxgerhardt/rotary-encoder-over-mcp23017

this is the complete loop()

Code:
void loop() {
    pollAll();

    float w;
    for (uint32_t i =1; i<20; i++) {
      w = i / 20.0;
      waveform1.pulseWidth(w);
      envelope1.noteOn();
      delay(800);
      envelope1.noteOff();
      delay(600);    
    }
  }
 
Hi, i have my code on github now
without hardware is difficult to understand but is an early stage.
can someone help me?

i have added

Code:
elapsedMillis updateUI;

before the setup()

and in loop()

Code:
if (updateUI > 250) {      // poll every 250ms
      updateUI = 0;
      pollAll();
    }

but the encoders are not read
 
yes, I tested the circuit piece by piece and it works everything, leds, encoders, audio ...
the problem arises when I try to put everything together
 
It is these delay()'s that are keeping it from polling:
Code:
    for (uint32_t i =1; i<20; i++) {
      w = i / 20.0;
      waveform1.pulseWidth(w);
      envelope1.noteOn();
      [B]delay(800);[/B]
      envelope1.noteOff();
      [B]delay(600);   [/B] 
    }

Those delays and that it does that 19 times before exiting to poll again.

A first quick hack would be:
Code:
    for (uint32_t i =1; i<20; i++) {
      w = i / 20.0;
      waveform1.pulseWidth(w);
      envelope1.noteOn();
      delay(800);
      [B]pollAll();[/B]
      envelope1.noteOff();
      delay(600);    
      [B]pollAll();[/B]
    }

But that will still not poll for 800 or 600 ms. if 250 ms fast enough to poll? They could be broken up or rewritten with an elapsedMillis variable in some fashion.
 
the goal is to read continuosly or at least as fast as possible the interface (buttons and encoders)
then update the sound parameters, the leds and the oled (at least the sound parameters)
 
tried this

Code:
for (uint32_t i =1; i<20; i++) {
      w = i / 20.0;
      waveform1.pulseWidth(w);
      envelope1.noteOn();
      delay(800);
      pollAll();
      envelope1.noteOff();
      delay(600);    
      pollAll();
    }

but the pollAll() stop working...
 
perhaps:
Code:
#define MS_INC 50 // polling delay step increment
// this will overshoot by the time it takes to complete the pollAll()
void PollingDelay() ( uint16_t msDel ) {
uint16_t track=0
  while ( track<msDel ) {
    track += MS_INC;
    delay( MS_INC );
    pollAll();
  }
}

loop() {
// …

    for (uint32_t i =1; i<20; i++) {
      w = i / 20.0;
      waveform1.pulseWidth(w);
      envelope1.noteOn();
      PollingDelay(800);
      envelope1.noteOff();
      PollingDelay(600);    
    }
 
If pollAll() stops - then it has some issue with being call too fast?

The one in the outer loop will be called immediately before and after that for - so two may be back to back
 
even with this last solution, it does not work.
it's a pity because the prototype itself works, I'm sure it's just a code problem
 
Bummer - did you try with :: #define MS_INC 200

Perhaps that will let it run? You can make it higher but will miss the marks of 600 and 800 ms as wtirren.

Also comment out the one in loop() outside the "for" so it run any back-to-back.
 
nope, also with 200 doesn't work

main.cpp (i'm on atom and platformio)

Code:
#include <Arduino.h>
#include <ht16k33.h> //0x77
#include <U8g2lib.h> //oled display
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <Audio.h>
#include <SerialFlash.h>


#include <Leds.h>
#include <Buttons.h>
#include <Encoders.h>
#include <Display.h>
#include <User_functions.h> //user functions

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform1;      //xy=188,240
AudioEffectEnvelope      envelope1;      //xy=371,237
AudioOutputI2S           i2s1;           //xy=565,241
AudioConnection          patchCord1(waveform1, envelope1);
AudioConnection          patchCord2(envelope1, 0, i2s1, 0);
AudioConnection          patchCord3(envelope1, 0, i2s1, 1);
AudioControlSGTL5000     audioShield;     //xy=586,175
// GUItool: end automatically generated code

//timer
elapsedMillis updateUI;
#define MS_INC 200 // polling delay step increment
// this will overshoot by the time it takes to complete the pollAll()
void PollingDelay ( uint16_t msDel ) {
uint16_t track=0;
  while ( track<msDel ) {
    track += MS_INC;
    delay( MS_INC );
    pollAll();
  }
}
void setup() {
    //led and buttons
    lb.begin(0x77); //ht16k33 i2c address
    lb.setBrightness(0); //0-15

    //SPI and display
    SPI.setMOSI(28);
    SPI.setSCK(27);
    pinMode(29, OUTPUT);
    pinMode(30, OUTPUT);
    SPI.begin();
    display.begin();

    //Encoder
    enc.begin(5);

    //serial monitor
    Serial.begin(57600);
    Serial.println("via");

    //audio
    AudioMemory(8);
    audioShield.enable();
    audioShield.volume(0.45);
    //
    waveform1.pulseWidth(0.5);
    waveform1.begin(0.4, 220, WAVEFORM_PULSE);

    envelope1.attack(50);
    envelope1.decay(50);
    envelope1.release(250);
}

void loop() {
  float w;
  for (uint32_t i =1; i<20; i++) {
      w = i / 20.0;
      waveform1.pulseWidth(w);
      envelope1.noteOn();
      PollingDelay(800);
      envelope1.noteOff();
      PollingDelay(600);
    }
}

encoders.h

Code:
#include <RotaryEncOverMCP.h>
//encoder port expander
Adafruit_MCP23017 enc;

/* function prototypes */
void RotaryEncoderChanged(bool clockwise, int id);
Adafruit_MCP23017* allMCPs[] = { &enc };

/* Array of all rotary encoders and their pins */
RotaryEncOverMCP rotaryEncoders[] = {
  RotaryEncOverMCP(&enc, 9, 8, &RotaryEncoderChanged, 1),
  RotaryEncOverMCP(&enc, 11, 10, &RotaryEncoderChanged, 2),
  RotaryEncOverMCP(&enc, 13, 12, &RotaryEncoderChanged, 3),
  RotaryEncOverMCP(&enc, 15, 14, &RotaryEncoderChanged, 4),
  RotaryEncOverMCP(&enc, 1, 0, &RotaryEncoderChanged, 5)
};

void RotaryEncoderChanged(bool clockwise, int id) {
  Serial.println("Encoder " + String(id) + ": "
    + (clockwise ? String("clockwise") : String("counter-clock-wise")));
}

void pollAll() {
  uint16_t gpioAB = allMCPs[0]->readGPIOAB();
    for (int i=0; i < 5; i++) {
      if(rotaryEncoders[i].getMCP() == allMCPs[0])
        rotaryEncoders[i].feedInput(gpioAB);
    }
}
 
looking at added code nothing jumps out at me.

Make a bare example with just the needed encoder calls perhaps. I don't have any to test … but paring that down might show or the issue to resolve
 
I just looked into the referenced encoder library
I may be wrong, but it seems to me it is using I2C bitbang and no wire library
for bitbang it tries to use GPIOA, GPIOB. is that not conflicting with I2S that uses PTA and PTB?

I would try a library that uses a proper I2C library instead of bitbang
 
Status
Not open for further replies.
Back
Top