vangalvin
Member
I have been working on a project for my son who has just moved from an acoustic guitar to electric guitar. The teensy 3.2 seems to be a great platform to build an effects pedal that has all sorts of features. One of the issues I have had is when using ADC1 for the pots, I seem to be getting a little bit of jitter that causes the delay to click. So i implemented some smoothing. I did try and use a resistor and cap to smooth the signal but still noticed the occasional click on occasion.
Here is a copy of the code that I am using but was wondering if I could move the smoothing routine in to a class so I do not need to have the code repeated for each pot. My programming skills are not overly advanced and although I have written a few of my own functions and some really basic classes I was unsure if the variables set for the class stay with the object created.
Here is the code that seems to work prety well for me.
And this was the class I was thinking about setting up to handle the smoothing.
do the variables in the class become unique to the object or are they shared between the objects. For instance if an object is created such as
ctrlKnob kv1(A16, 0);
then it was updated using something like..
update(adc->analogRead(knob1, ADC_1));
would the variable lastknobval be set inside the kv1 object until the update is called again?
is the variable unique to kv1 or if another object was created would setting the variable in the kv1 object also change the variable for other objects created?
Here is a copy of the code that I am using but was wondering if I could move the smoothing routine in to a class so I do not need to have the code repeated for each pot. My programming skills are not overly advanced and although I have written a few of my own functions and some really basic classes I was unsure if the variables set for the class stay with the object created.
Here is the code that seems to work prety well for me.
Code:
#include <ADC.h> //ADCZ to read the POT values
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h> //Button Library
ADC *adc = new ADC();; // adc object
Bounce button0 = Bounce(2, 15);
// GUItool: begin automatically generated code
AudioInputUSB usb1; //xy=68,39
AudioMixer4 mixer1; //xy=209,51
AudioEffectDelayExternal dly(AUDIO_MEMORY_23LC1024); //xy=382,215
AudioMixer4 mixer2; //xy=682,49
AudioOutputUSB usb2; //xy=1027,37
AudioOutputAnalog dac1; //xy=1027,85
AudioConnection patchCord1(usb1, 0, mixer1, 0);
AudioConnection patchCord2(usb1, 1, mixer1, 1);
AudioConnection patchCord3(mixer1, dly);
AudioConnection patchCord4(mixer1, 0, mixer2, 0);
AudioConnection patchCord5(dly, 0, mixer2, 1);
AudioConnection patchCord6(dly, 7, mixer1, 3);
AudioConnection patchCord7(dly, 7, mixer2, 2);
AudioConnection patchCord8(mixer2, 0, usb2, 0);
AudioConnection patchCord9(mixer2, 0, usb2, 1);
AudioControlSGTL5000 audioShield; //xy=81,135
// GUItool: end automatically generated code
const int ledPin = 13;
int knob1 = A16; // Effects Knob
int knob2 = A17; // Effects Knob
int knob3 = A18; // Effects Knob
#define SDCARD_CS_PIN 10 // CS for Caltex Card
#define SPIRAM_CS_PIN 6 //CS for SRAM
//#define SDCARD_MOSI_PIN 7 //MOSI on Caltex Card
//#define SDCARD_MISO_PIN 12 //MISO on Caltex Card
//#define SDCARD_SCK_PIN 14 //SCK on caltex card
void set_adc1_to_3v3(){
ADC1_SC3 = 0; // cancel calibration
ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref 3.3v
ADC1_SC3 = ADC_SC3_CAL; // begin calibration
uint16_t sum;
//serial_print("wait_for_cal\n");
while( (ADC1_SC3 & ADC_SC3_CAL))
{
// wait
}
__disable_irq();
sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
sum = (sum / 2) | 0x8000;
ADC1_PG = sum;
sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0;
sum = (sum / 2) | 0x8000;
ADC1_MG = sum;
__enable_irq();
}
void setup() {
pinMode(SDCARD_CS_PIN, OUTPUT); //Enable SD CS pin for output
pinMode(SPIRAM_CS_PIN, OUTPUT); //Enable SRAM CS pin for output
digitalWrite(SDCARD_CS_PIN, HIGH); //Make sure the pin is HIGG on start up
digitalWrite(SPIRAM_CS_PIN, HIGH); //Make sure the pin is HIGG on start up
AudioMemory(50);
//Setup For Delay
//mixer1.gain(0, 1);
//mixer1.gain(1, 1);
//mixer2.gain(0, 0.7);
//mixer2.gain(1, 0.7);
//Setup for Loop
mixer1.gain(0, 0.5);
mixer1.gain(1, 0.5);
mixer1.gain(2, 0);
mixer1.gain(3, 0.7);
mixer2.gain(0, 1);
mixer2.gain(1, 0);
mixer2.gain(2, 1);
mixer2.gain(3, 0);
// All this just to check one POT
adc->setAveraging(16, ADC_1); // set number of averages
adc->setResolution(8, ADC_1); // set bits of resolution
adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_LOW_SPEED, ADC_1);
adc->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED, ADC_1); adc->setReference( ADC_REFERENCE::REF_3V3, ADC_1 );
set_adc1_to_3v3();
delay(200);
dly.delay(0, 0);
}
float mapfloat(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;
}
float NEW_WEIGHT = 0.2;
float SPD_WEIGHT = 0.4;
int k1val = 0;
int k2val = 0;
int k3val = 0;
int k1val_old = 0;
int k2val_old = 0;
int k3val_old = 0;
int k1diff = 0;
int k2diff = 0;
int k3diff = 0;
int k1diff_speed = 2;
int k2diff_speed = 2;
int k3diff_speed = 2;
int k1val_last = 0;
int k2val_last = 0;
int k3val_last = 0;
void loop() {
k1val = adc->analogRead(knob1, ADC_1);
k2val = adc->analogRead(knob2, ADC_1);
k3val = adc->analogRead(knob3, ADC_1);
k1diff = NEW_WEIGHT * k1val + (1-NEW_WEIGHT) * (k1diff + k1diff_speed); //updates diff_value, our smoothed pot outputs. Note that diff_speed is used too!
k1diff_speed = SPD_WEIGHT * (k1diff - k1val_old) + (1-SPD_WEIGHT) * k1diff_speed; //updates diff_speed, or the rate of change of the smoothed output
k1val_old = k1diff; //diff_old_value is to let us calculate the speed
k2diff = NEW_WEIGHT * k2val + (1-NEW_WEIGHT) * (k2diff + k2diff_speed); //updates diff_value, our smoothed pot outputs. Note that diff_speed is used too!
k2diff_speed = SPD_WEIGHT * (k2diff - k2val_old) + (1-SPD_WEIGHT) * k2diff_speed; //updates diff_speed, or the rate of change of the smoothed output
k2val_old = k2diff; //diff_old_value is to let us calculate the speed
k3diff = NEW_WEIGHT * k3val + (1-NEW_WEIGHT) * (k3diff + k3diff_speed); //updates diff_value, our smoothed pot outputs. Note that diff_speed is used too!
k3diff_speed = SPD_WEIGHT * (k3diff - k3val_old) + (1-SPD_WEIGHT) * k3diff_speed; //updates diff_speed, or the rate of change of the smoothed output
k3val_old = k3diff; //diff_old_value is to let us calculate the speed
if((k1diff >= k1val_last + 4) || (k1diff <= k1val_last - 4)){
k1val_last = k1diff;
Serial.print("Change Delay : ");
Serial.println(k1diff);
dly.delay(7, map(k1val, 0, 255, 0, 1400));
}
if((k2diff >= k2val_last + 4) || (k2diff <= k2val_last - 4)){
k2val_last = k2diff;
Serial.print("Change Mixer Port 0 : ");
Serial.println(k2diff);
// mixer2.gain(0, mapfloat(k2diff, 0, 255, 0.001, 1.001));
mixer1.gain(0, mapfloat(k2diff, 0, 255, 0.001, 1.001));
mixer1.gain(1, mapfloat(k2diff, 0, 255, 0.001, 1.001));
mixer1.gain(3, 0.7);
}
if((k3diff >= k3val_last + 4) || (k3diff <= k3val_last - 4)){
k3val_last = k3diff;
Serial.print("Change Mixer Port 1 : ");
Serial.println(k3diff);
// mixer2.gain(1, mapfloat(k3diff, 0, 255, 0.001, 1.001));
mixer1.gain(3, mapfloat(k3diff, 0, 255, 0.001, 1.001));
}
delay(100);
}//end loop
And this was the class I was thinking about setting up to handle the smoothing.
do the variables in the class become unique to the object or are they shared between the objects. For instance if an object is created such as
ctrlKnob kv1(A16, 0);
then it was updated using something like..
update(adc->analogRead(knob1, ADC_1));
would the variable lastknobval be set inside the kv1 object until the update is called again?
is the variable unique to kv1 or if another object was created would setting the variable in the kv1 object also change the variable for other objects created?
Code:
class ctrlKnob {
int knob; // the pin of the knob (A16, A17, A18)
int knobval = 0; // the value of the knob
int lastknobval = 0; // previous knob value
float NEW_WEIGHT = 0.6;
float SPD_WEIGHT = 0.7;
int diff_speed = 1;
public:
ctrlKnob(int knob, int knobval){
lastknobval = knobval;
Serial.println(knobval);
}
int Update(int value){
//diff_value is the smoothed output from the pots
//value is the new reading
//diff_speed is the rate of change of the pot value
Serial.print(" lastknobval: ");
Serial.print(lastknobval);
Serial.print(" ");
//NEW_WEIGHT and SPD_WEIGHT are constants (range: 0 to 1) used to adjust how much the filter filters out: lower is more filtering
knobval = NEW_WEIGHT * value + (1-NEW_WEIGHT) * (knobval + diff_speed); //updates diff_value, our smoothed pot outputs. Note that diff_speed is used too!
knobval = SPD_WEIGHT * (knobval - lastknobval) + (1-SPD_WEIGHT) * diff_speed; //updates diff_speed, or the rate of change of the smoothed output
lastknobval = knobval; //diff_old_value is to let us calculate the speed
//Serial.println("knobval");
return(knobval);
}
};