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

Thread: potentiometer controller for Teensy (D&D)

  1. #1
    Junior Member
    Join Date
    Oct 2019
    Posts
    14

    potentiometer controller for Teensy (D&D)

    Hi
    I've been working on a little controller PCB with some extra pads for experimenting/hacking.

    https://hackaday.io/project/174682-dd-teensy
    https://github.com/bjc01/D-D_Teensy

    I was working with teensy 3.2 + audio shield (Rev B).
    I got it fabricated by ALLpcb.

    When I have it connected, each of the 8 potentiometers work, but it's not quite behaving as expected.
    There should be three oscillator channels and a noise channel.


    The oscillators seem to warble and drift in unpredictable ways.
    In v6_3 the oscillator frequencies don't stay still and the volume can't be adjusted. The noise and filter pots don't respond.
    Code:
    //DRONEs - not chromatic - roaming quite a bit - creates modulations
    //three sine oscillators - some frequency control audible / 
    //three OSC - amplitude/volume control subtle not working - doesn't change volume - seems to change OSC FREQ!
    // PINK NOISE + FILTER - no audible control over filter cutoff nor amplitude
    
    //add Bounce.h - does it help with stability? not yet
    
    #include <Bounce.h>
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    
    // GUItool: begin automatically generated code
    AudioSynthNoisePink      pink1;          //xy=128,277
    AudioSynthWaveform       waveform2;      //xy=170,161
    AudioSynthWaveform       waveform3;      //xy=173,214
    AudioSynthWaveform       waveform1;      //xy=179,87
    AudioFilterStateVariable filter1;        //xy=262,312
    AudioEffectBitcrusher    bitcrusher1;    //xy=425,291
    AudioMixer4              mixer1;         //xy=523,143
    AudioOutputI2S           i2s1;           //xy=674,144
    AudioConnection          patchCord1(pink1, 0, filter1, 0);
    AudioConnection          patchCord2(pink1, 0, filter1, 1);
    AudioConnection          patchCord3(waveform2, 0, mixer1, 1);
    AudioConnection          patchCord4(waveform3, 0, mixer1, 2);
    AudioConnection          patchCord5(waveform1, 0, mixer1, 0);
    AudioConnection          patchCord6(filter1, 0, bitcrusher1, 0);
    AudioConnection          patchCord7(bitcrusher1, 0, mixer1, 3);
    AudioConnection          patchCord8(mixer1, 0, i2s1, 0);
    AudioConnection          patchCord9(mixer1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=501,357
    // GUItool: end automatically generated code
    
    // Bounce objects to read pushbuttons - cutnpaste from part_2_07_Filters
    //not needed for D&D yet
    /*
    Bounce button0 = Bounce(0, 15);
    Bounce button1 = Bounce(1, 15);  // 15 ms debounce time
    Bounce button2 = Bounce(2, 15);
     */
     
    void setup() {
      
      // put your setup code here, to run once:
    Serial.begin(9600);
      AudioMemory(20);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
      waveform1.begin(WAVEFORM_SINE);
      waveform1.amplitude(0.75);
      waveform1.frequency(330);
    
      waveform2.begin(WAVEFORM_SINE);
      waveform2.amplitude(0.75);
      waveform2.frequency(220);
    
      waveform3.begin(WAVEFORM_SINE);
      waveform3.amplitude(0.75);
      waveform3.frequency(100);
    
      pink1.amplitude(0.7);
    
      mixer1.gain(0, 0.7);
      mixer1.gain(1, 0.7);
      mixer1.gain(2, 0.7);
      mixer1.gain(3, 0.7);
      delay(100);
    
      filter1.frequency(6);
      filter1.resonance(9); 
      //Q ranges from 0.7 to 5.0. Resonance greater than 0.707 will amplify the signal near the corner frequency. 
      //You must attenuate the signal before input to this filter, to prevent clipping.
    
      bitcrusher1.bits(6); 
      bitcrusher1.sampleRate(516);
      /*xcrushBits sets the bitdepth, from 1 to 16. 
       * A Value of 16 does not crush the bitdepth, and is effectively a passthru for this part of the function. 
       * xsampleRate sets the frequency, from 1 to 44100Hz, 
       * however it works in integer steps so you will only really get a handful of results from the many samplerates you can pass. 44100 is passthru.
       * set xbitDepth to 16 and xsampleRate to 44100 to pass audio through without any Bitcrush effect.
     */
      }
    
    void loop() { 
      // put your main code here, to run repeatedly:
      // Read the knobs, scale knobs to 0-1.0 - WaveformsModulated
      
      float knob_A0 = (float)analogRead(A0);
      float knob_A1 = (float)analogRead(A1);
      float knob_A2 = (float)analogRead(A2);
      float knob_A3 = (float)analogRead(A3);
      float knob_A4 = (float)analogRead(A4) / 1023;
      float knob_A5 = (float)analogRead(A5) / 1023;
      float knob_A6 = (float)analogRead(A6) / 1023;
      float knob_A7 = (float)analogRead(A7) / 1023;
    
      // use Knobs to adjust the waveform frequency
      waveform1.frequency(knob_A0);
      waveform2.frequency(knob_A1);
      waveform3.frequency(knob_A2);
      filter1.frequency(knob_A3);
      
      // pink1.(knob_A3); - some DRAMA filter cutoff effect parameter
        // use Knobs to adjust the amount of waveform amplitude
      waveform1.amplitude(knob_A4);
      waveform2.amplitude(knob_A5);
      waveform2.amplitude(knob_A6);
      pink1.amplitude(knob_A7);
      
      // read the knob and adjust the filter frequency DRAMA
      int knob = analogRead(A3);
      // quick and dirty equation for exp scale frequency adjust
      float freq =  expf((float)knob / 150.0) * 10.0 + 80.0;
      filter1.frequency(freq);
      Serial.print("frequency = ");
      Serial.println(freq);
      delay(100);
      
     }

    In v6_5 it seems as if all pots influence noise and filter.
    Code:
    //odd behaviour - distort crunch - some pulses of hiss
    //3x SINE waves - none audible
    //filter on pink noise channel 4 - 
    //all knobs adjust some noise / filter element - none act as planned
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSine   sine3;          //xy=53,158
    AudioSynthWaveformSine   sine2;          //xy=54,111
    AudioSynthWaveformSine   sine1;          //xy=66,60
    AudioSynthNoisePink      pink1;          //xy=119,242
    AudioFilterStateVariable filter1;        //xy=390,212
    AudioMixer4              mixer1;         //xy=514,108
    AudioOutputI2S           i2s1;           //xy=769,86
    AudioConnection          patchCord1(sine3, 0, mixer1, 2);
    AudioConnection          patchCord2(sine2, 0, mixer1, 1);
    AudioConnection          patchCord3(sine1, 0, mixer1, 0);
    AudioConnection          patchCord4(pink1, 0, filter1, 0);
    AudioConnection          patchCord5(pink1, 0, filter1, 1);
    AudioConnection          patchCord6(filter1, 0, mixer1, 3);
    AudioConnection          patchCord7(mixer1, 0, i2s1, 0);
    AudioConnection          patchCord8(mixer1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=492,322
    // GUItool: end automatically generated code
    
    void setup() {
      // put your setup code here, to run once:
    Serial.begin(9600);
      AudioMemory(20);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.7);
     
      sine1.amplitude(0.8);
      sine1.frequency(220);
      sine1.phase(90);
      
      sine2.amplitude(0.8);
      sine2.frequency(440);
      sine2.phase(95);
    
      sine3.amplitude(0.8);
      sine3.frequency(880);
      sine3.phase(100);
    
      pink1.amplitude(0.8);
    
      mixer1.gain(0, 0.7);
      mixer1.gain(1, 0.7);
      mixer1.gain(2, 0.7);
      mixer1.gain(3, 0.7);
      delay(100);
    
      filter1.frequency(9);
      filter1.resonance(9); 
      //Q ranges from 0.7 to 5.0. Resonance greater than 0.707 will amplify the signal near the corner frequency. 
      //You must attenuate the signal before input to this filter, to prevent clipping.
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      float knob_A0 = (float)analogRead(A0) / 1023;
      float knob_A1 = (float)analogRead(A1) / 1023;
      float knob_A2 = (float)analogRead(A2) / 1023;
      float knob_A3 = (float)analogRead(A3) / 1023;
      float knob_A4 = (float)analogRead(A4) / 1023;
      float knob_A5 = (float)analogRead(A5) / 1023;
      float knob_A6 = (float)analogRead(A6) / 1023;
      float knob_A7 = (float)analogRead(A7) / 1023;
    
      // use Knobs to adjust the waveform frequency
      sine1.frequency(knob_A0);
      sine2.frequency(knob_A1);
      sine3.frequency(knob_A2);
      filter1.frequency(knob_A3);
        // pink1.(knob_A3); - some DRAMA filter cutoff effect parameter
      
    
        // use Knobs to adjust the amount of waveform amplitude
      sine1.amplitude(knob_A4);
      sine2.amplitude(knob_A5);
      sine3.amplitude(knob_A6);
      pink1.amplitude(knob_A7);
      
      // read the knob and adjust the filter frequency DRAMA
      int knob = analogRead(A3);
      // quick and dirty equation for exp scale frequency adjust
      float freq =  expf((float)knob / 150.0) * 10.0 + 80.0;
      filter1.frequency(freq);
      Serial.print("frequency = ");
      Serial.println(freq);
      delay(100);
    }
    Attachment 22636
    Click image for larger version. 

Name:	D&D_Teensy_v4_2 pot pcb col.png 
Views:	35 
Size:	61.6 KB 
ID:	22637

    Is it likely the hardware is wrong or is it more likely to be a code issue?
    Any advice on getting the oscillators to produce steady tones and the knobs to produce consistent behavior?
    Click image for larger version. 

Name:	D&D Teensy v2.jpg 
Views:	33 
Size:	75.9 KB 
ID:	22639

    Is the audio shield potentiometer causing a bad influence?

    Thanks for your time and support.

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,101
    100k is rather high for a pot, which increases sensitivity to noise pickup and may allow some crosstalk in
    the ADC. 10k linear is the go-to value for control pots, and often less than this for critical controls (most
    motor controllers use 5k for instance).

    However you may simply need to do some averaging of analog reads(*), and add extra supply decoupling to keep
    the voltage going to the pots more stable. The Teensy 3.3V is noisy because of all the digital noise injected into
    it by the processor. Adding 100uF or more across the supply may tame this. Alternatively adding 100nF caps
    to ground on each wiper line would be another approach.

    Its usual (though not important here) for power and ground traces on a PCB to be significantly wider than signal traces,
    in order to keep inductance and IR voltages low.

    (*) For each pin:
    discard one reading.
    sum N more readings and divide by N.
    Try N = 4, 8, 16 or so and see if this helps

  3. #3
    Junior Member
    Join Date
    Oct 2019
    Posts
    14
    Many thanks for your feedback MarkT -
    I'll try changing pot values for a start and then try adding capacitors.
    I think making the traces wider is easy to do on eagle.

    Do you have a link to more information on averaging of analogue reads?

  4. #4
    Junior Member
    Join Date
    Oct 2019
    Posts
    14
    "Adding 100uF or more across the supply may tame this".
    Would this be an electrolytic capacitor between + / - ; the negative leg of the capacitor to ground and positive to 3.3v?
    The device should be powered from USB.
    Does this image seem right? Thanks for suggestions.


    Click image for larger version. 

Name:	D&D_Teensy_v4_3 cap pcb.png 
Views:	20 
Size:	73.8 KB 
ID:	22795

  5. #5
    Junior Member
    Join Date
    Oct 2019
    Posts
    14
    I tried using 5k pots and the tones are a lot more stable - thanks MarkT.

    There is still a little wobble, and some audible clicking - like a clock in the background.
    Is that likely a programme error or is can it be resolved by adding the 100uF capacitor?

    ANyone got any suggestions to try?

  6. #6
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    209
    The ADC inputs on the Teensy 4 or Teensy 4.1 are very noisy when the processor is very active.

    I am using an external 12-bit AD converter MPC3208. This noises much less 1 LSB.

    It is connected to SPI Port 0 and can be scanned with a Samplerate of 100KHz.

    Link: http://ww1.microchip.com/downloads/e...Doc/21298e.pdf

    Greetings from germany. Rolf

  7. #7
    Junior Member
    Join Date
    Oct 2019
    Posts
    14
    Hi rolf, thanks for that.
    I can order a MCP3204 to test
    I was hoping that using the teensy audio shield (4+ rev D / 3.2 + rev c) would be able to deliver usable output.

  8. #8
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,504
    You could try this https://github.com/dxinteractive/ResponsiveAnalogRead it usually works wonders out of the box :-)

  9. #9
    Senior Member Rolfdegen's Avatar
    Join Date
    Sep 2020
    Location
    Germany
    Posts
    209
    @Luni

    I tried ResponsiveAnalogRead, but there is also noise in my synth. The best way is an external ADC. There is only 1 bit of noise.

    My projekt blog here: https://forum.pjrc.com/threads/63255...IY-Synthesizer

    and Youtube channel: https://www.youtube.com/channel/UCXQ...5MXSkyDo6PZ4Cw


    Best regards from Germany. Rolf

  10. #10
    Junior Member
    Join Date
    Oct 2019
    Posts
    14
    Hi luni - thanks for the link - I tried it but I am still experiencing issues.

    I think the best thing for me to do is make my project more simple to try to identify the issues.

    It seems that control knob 7 (connected to pin A6) is acting as a kind of 'master'.
    The other pots can make adjustments, but for some reason 7 (A6) as a gain/volume control can make everything go from silence to noise.

    Could this be because I got cheap pots?

    I wanted to be able to control 3 x sine wave channels (pitch/frequency & volume) and one noise channel (filter frequency & volume).
    I am surprised at how difficult this is for me!

  11. #11
    Junior Member
    Join Date
    Oct 2019
    Posts
    14
    Here is the design:

    Click image for larger version. 

Name:	D_D_teensy_v6_bc 2021-01-12 at 16.24.04.jpg 
Views:	24 
Size:	69.7 KB 
ID:	23219

    Here is the code:

    Code:
    //DRONE 
    //three sine oscillators - very close - creates modulations in amplitude
    // PINK NOISE + FILTER 
    //v6 - remove waveshaper - ADD BITCRUSHER
    //waveshape
    //add Bounce.h
    
    #include <Bounce.h>
    
    // GUItool: begin automatically generated code
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthNoisePink      pink1;          //xy=128,277
    AudioSynthWaveform       waveform2;      //xy=170,161
    AudioSynthWaveform       waveform3;      //xy=173,214
    AudioSynthWaveform       waveform1;      //xy=179,87
    AudioFilterStateVariable filter1;        //xy=262,312
    AudioEffectBitcrusher    bitcrusher1;    //xy=425,291
    AudioMixer4              mixer1;         //xy=523,143
    AudioOutputI2S           i2s1;           //xy=674,144
    AudioConnection          patchCord1(pink1, 0, filter1, 0);
    AudioConnection          patchCord2(pink1, 0, filter1, 1);
    AudioConnection          patchCord3(waveform2, 0, mixer1, 1);
    AudioConnection          patchCord4(waveform3, 0, mixer1, 2);
    AudioConnection          patchCord5(waveform1, 0, mixer1, 0);
    AudioConnection          patchCord6(filter1, 0, bitcrusher1, 0);
    AudioConnection          patchCord7(bitcrusher1, 0, mixer1, 3);
    AudioConnection          patchCord8(mixer1, 0, i2s1, 0);
    AudioConnection          patchCord9(mixer1, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=501,357
    // GUItool: end automatically generated code
    
    // GUItool: end automatically generated code
    
    // Bounce objects to read pushbuttons - cutnpaste from part_2_07_Filters
    //not needed for D&D yet
    /*
    Bounce button0 = Bounce(0, 15);
    Bounce button1 = Bounce(1, 15);  // 15 ms debounce time
    Bounce button2 = Bounce(2, 15);
     */
     
    void setup() {
      // put your setup code here, to run once:
    Serial.begin(9600);
      AudioMemory(20);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
      waveform1.begin(WAVEFORM_SINE);
      waveform1.amplitude(0.75);
      waveform1.frequency(55);
    
      waveform2.begin(WAVEFORM_SINE);
      waveform2.amplitude(0.75);
      waveform2.frequency(110);
    
      waveform3.begin(WAVEFORM_SINE);
      waveform3.amplitude(0.75);
      waveform3.frequency(220);
    
      pink1.amplitude(1.0);
    
      mixer1.gain(0, 0.7);
      mixer1.gain(1, 0.7);
      mixer1.gain(2, 0.7);
      mixer1.gain(3, 0.6);
      delay(1000);
    
      filter1.frequency(65);
      filter1.resonance(4.9); 
      //Q ranges from 0.7 to 5.0. Resonance greater than 0.707 will amplify the signal near the corner frequency. 
      //You must attenuate the signal before input to this filter, to prevent clipping.
    
      bitcrusher1.bits(8); 
      bitcrusher1.sampleRate(22050);
      /*xcrushBits sets the bitdepth, from 1 to 16. 
       * A Value of 16 does not crush the bitdepth, and is effectively a passthru for this part of the function.
       * 
       * xsampleRate sets the frequency, from 1 to 44100Hz, 
       * however it works in integer steps so you will only really get a handful of results from the many samplerates you can pass. 44100 is passthru.
       * 
       * set xbitDepth to 16 and xsampleRate to 44100 to pass audio through without any Bitcrush effect.
    
    /*set xbitDepth to 16 and xsampleRate to 44100 to pass audio through without any Bitcrush effect.
     * 
     */
      }
    
    void loop() {
      // put your main code here, to run repeatedly:
    {
     }
    
      // Read the knobs, scale knobs to 0-1.0 - WaveformsModulated
      
      float knob_A0 = (float)analogRead(A0);
      float knob_A1 = (float)analogRead(A1);
      float knob_A2 = (float)analogRead(A2);
      float knob_A3 = (float)analogRead(A3);
      float knob_A4 = (float)analogRead(A4) / 1023.0;
      float knob_A5 = (float)analogRead(A5) / 1023.0;
      float knob_A6 = (float)analogRead(A6) / 1023.0;
      float knob_A7 = (float)analogRead(A7) / 1023.0;
    
      // use Knobs to adjust the waveform frequency
      waveform1.frequency(knob_A0);
      waveform2.frequency(knob_A1);
      waveform3.frequency(knob_A2);
      filter1.frequency(knob_A3);
      
      // pink1.(knob_A3); - some DRAMA filter cutoff effect parameter
        // use Knobs to adjust the amount of waveform amplitude
      waveform1.amplitude(knob_A4);
      waveform2.amplitude(knob_A5);
      waveform2.amplitude(knob_A6);
      pink1.amplitude(knob_A7);
      
      // read the knob and adjust the filter frequency DRAMA
      int knob = analogRead(A3);
      // quick and dirty equation for exp scale frequency adjust
      float freq =  expf((float)knob / 150.0) * 10.0 + 80.0;
      filter1.frequency(freq);
      Serial.print("frequency = ");
      Serial.println(freq);
      delay(100);
      
     }
    Is there anything in the code that is clearly wrong?
    Are my issues all in hardware?

    Thanks for your time and input!

Posting Permissions

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