analoge potmeter als soort schakelaar

Arduino specifieke Software
Berichten: 10
Geregistreerd: 31 Mei 2013, 00:26

analoge potmeter als soort schakelaar

Berichtdoor mattnezz » 31 Mei 2013, 10:00

(nieuw op dit forum, dus hoop dat ik in juiste rubriek post)

Ik ben bezig met een deel van een sketch die een LFO moet moet maken, en stuitte voor de 2e keer op een probleempje met potmeters op analoge ingangen.
Ik krijg het niet simpel opgelost, en hoop dat iemnd me kan helpen.
Een LFO (low frequency oscillator) is een langzaam bewegende golf, in mijn geval een sinus-vormige pwm uitsturing met regelbare snelheid en amplitude.
De golfvorm zet ik op de gate van een bs170 fet en gebruik dit om de delaytijd van een PT2399 te moduleren voor een muzikaal vibrato effect.
De amplitude en snelheid regel ik met 2 potmeters die zijn aangesloten op analoog 0 en 1.
Nu geven de grenswaarden problemen, welke ik met 'smoothing' en 'map' niet weggewerkt krijg.
bijv:
Code: Alles selecteren
int depthReading = analogRead(A0);
int depth = map(depthReading, 0, 1023, 0, 127);
int speedReading =analogRead(A1);
int speed = map (speedReading, 0, 1023, 20, 1);

Dit werkt natuurlijk gewoon, maar als ik bij 'speed' de potmeter net tussen bijvoorbeeld 1 en 2 heb staan, dus op het overgangs punt, dan krijg je natuurlijk haperingen.
Ik denk dat dit simpel weg te werken is, maar ik kom er even niet uit.
Ik heb eerst 'smoothing' geprobeerd, maarja, dit vertraagt de hapering alleen een beetje.
Vervolgens iets met currentReading/lastReading, om de potmeterstand alleen bij verandering te lezen. Geen succes.
Toen ik aan de for-loop/switch...case begon om dit probleem aan te pakken, ben ik maar een forum gaan opzoeken, want ik denk dat dit dus heel simpel op te lossen moet zijn.
Wie kan mij in de goede richting duwen?

Advertisement

Berichten: 10
Geregistreerd: 31 Mei 2013, 00:26

Re: analoge potmeter als soort schakelaar

Berichtdoor mattnezz » 31 Mei 2013, 14:52

Wat nu dus het best lijkt te werken is iets als dit, een soort debounce...
Code: Alles selecteren
int smoothSpeed(int last)                           
  {
  potReadingS = analogRead(speedPot);
  int current = map(potReadingS, 0, 1023, 31, 1);   
  if(last <= (current - 3) || last >= (current + 3))
  {
  delay(10);
  potReadingS = analogRead(speedPot);
  current = map(potReadingS, 0, 1023, 31, 1);
  } 
  return current;                             
  }


en in de loop zoiets:
Code: Alles selecteren
speedReading = smoothSpeed(lastSpeedReading);

if(speedReading != lastSpeedReading )
{
  SPEED = (speedReading*200) ;
  Serial.print(" speed: "); Serial.println(speedReading);
}
lastSpeedReading = speedReading;


Maar nog steeds behoorlijk beetje springerige waarden. Hoe zou ik dit kunnen veranderen zodat een fysieke verandering van de potmeterstand als zodanig wordt geregistreerd?

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: analoge potmeter als soort schakelaar

Berichtdoor nicoverduin » 31 Mei 2013, 16:48

Voortschrijdend gemiddelde nemen:Maak een array van 10 elementen bijvoorbeeld :
Code: Alles selecteren
init() {
unsigned int reeks[10];         // reeks met waarden     
unsigned int reeksIndex = 0; // index naar de reeks
unsigned int Som = 0;           // totaal van de reeks waarden
boolean  eersteSerie = true;  // bij eerste 10 waarden is de reeks nog niet gevuld
}
loop(){
   PotReadingS = analogRead(speedPot);
   if (eersteSerie) {
      reeks[reeksindex] = PotReadingS;   // zet de waarde in de eerste vrije reeks regel
      reeksIndex++;                                // verwijs naar de volgende index                                 
      som += PotReadingS;                      // verhoog de som
      gemiddelde = som / reeksindex;      // deel som door aantal velden
      if (reeksIndex == 10) {                    // hele tabel gevuld?
         reeksindex = 0;                           // index op 0 zetten
         eersteSerie = false;                      // en dit doe je nooit meer 
      }
   } else {
      som = som + PotReadingS - reeks[reeksIndex]; // verhoog de som met de nieuwe waarde en verlaag met die waarde uit de tabel
      reeks[reeksIndex] = PotReadingS;                     // zet de nieuwe waarde in de tabel
      gemiddelde = som / 10;                                    // deel de som door 10 (immers de hele tabel is gevuld
      reeksIndex++;                                                  // verhoog de index voor de volgende waarde   
      if (reeksIndex == 10) {                                      // hele tabel gehad?
         reeksIndex = 0;                                             // gewoon opnieuw beginnen 
      }
   }
}
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 10
Geregistreerd: 31 Mei 2013, 00:26

Re: analoge potmeter als soort schakelaar

Berichtdoor mattnezz » 31 Mei 2013, 17:20

Dank nicoverduin.
Ik begrijp dat mijn voorbeeld-code wat lelijk is, hij is inmiddels ook al 10 veranderd, en vandaar dat de term 'smoothSpeed' wellicht misleidend is... ;)
Het voorbeeld wat jij geeft had ik reeds binnen de code zitten, maar het hielp niet dus heb ik het weggehaald.
Wat jouw code doet is volgens mij vergelijkbaar met een analoog laag-doorlaat filter.
Ik zoek eigenlijk alleen detectie van het verdraaien van de potmeter, zodat op dat moment een nieuwe frequentie/amplitude gegeven kan worden aan een LFO.

Wat het best werkte was dus iets met een threshold, maar ik vrees dat ik iets verkeerd doe, want ik krijg nog steeds verspringingen binnen die threshold.
.
Als een analogRead van een potmeter over een threshold gaat, moet er iets gebeuren, anders niets... Misschien zit ik alweer te lang te staren.

Berichten: 10
Geregistreerd: 31 Mei 2013, 00:26

Re: analoge potmeter als soort schakelaar

Berichtdoor mattnezz » 31 Mei 2013, 18:07

Ach het is gelukt! Ook al behoorlijk chaotisch uitgewerkt ;)
De threshold moest toch echt in de loop:
Code: Alles selecteren
speedReading = smoothSpeed(lastSpeedReading);
depthReading = smoothDepth(lastDepthReading);
if( speedReading <= (lastSpeedReading - 2)  || speedReading >= (lastSpeedReading + 2)  ||
    depthReading <= (lastDepthReading - 2) || depthReading >= (lastDepthReading + 2)  )
{
  int fact = map(delayTime,0,timeOut,127,0);
  DEPTH=depthReading/(127.0 + fact + speedReading);
  SPEED = (speedReading*200) ;
  Serial.print("LFO> depth: "); Serial.print(DEPTH*100); Serial.print(" % ");Serial.print(" speed: ");Serial.println(speedReading);
  lastSpeedReading = speedReading;
  lastDepthReading = depthReading;
}


Toch condensatortje van de potmeter gehaald en nicoverduin's code gebruikt, alhoewel een beetje anders en lelijker :( Maar die had ik nog uit eerdere probeersels.
setup()
Code: Alles selecteren
for (int r = 0; r < 5; r ++){
      potReadingsS[r] = 0;
      potReadingsD[r] = 0;
      } 


de smoothing zelf:
Code: Alles selecteren
//AVERAGING FILTER LFO DEPTH:
int smoothDepth(int last)                     
  {
  sumReadingsD= sumReadingsD - potReadingsD[readingCountD];
  potReadingsD[readingCountD] = analogRead(depthPot);
  sumReadingsD= sumReadingsD + potReadingsD[readingCountD];
  readingCountD ++;
  if (readingCountD >= 5)
  readingCountD=0;
  averageReadingsD = sumReadingsD/5;
  int current = map (averageReadingsD, 0, 1023, 0, 127);
  return current;
  }
 
//AVERAGING FILTER LFO SPEED
int smoothSpeed(int last)                           
  {
  sumReadingsS = sumReadingsS - potReadingsS[readingCountS];
  potReadingsS[readingCountS] = analogRead(speedPot);
  sumReadingsS= sumReadingsS + potReadingsS[readingCountS];
  readingCountS ++;
  if (readingCountS >= 5)
  readingCountS=0;
  averageReadingsS = sumReadingsS/5;
  int current = map(averageReadingsS, 0, 1023, 62, 2);
  return current;
  }


Ow nu het werkt is het nog zaak dat ik de LFO een beetje vorm geef...
Voor nu ben ik blij dat de sketch doet wat ie moet doen, een LFO maken waarvan de amplitude afhankelijk is van frequentie, delaytijd (van de echo) en een potmeterstand.
Dit was maar een extratje op een groter project... En alhoewel alles nieuw voor me is, liep het juist op dit relatief simpele stukje vast...
Dank voor het meedenken iig, en als dingen netter of efficienter kunnen hoor ik de suggesties heel graag.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: analoge potmeter als soort schakelaar

Berichtdoor nicoverduin » 31 Mei 2013, 18:45

Ik zei al in mijn intro dat ik een "zeikerd" ben met programmeren :). Commentaar kost niets meer in de executietijd :).
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Analoge potmeter waarde middelen

Berichtdoor astrofrostbyte » 01 Jun 2013, 14:17

Ik zou ook gaan voor een middeling van de analoge potmeter waarden, het is vrij simpel toe te voegen.
Hou er echter wel rekening mee dat je sample-rate ook zeer belangrijk is, als je 100 samples/sec zou nemen dan is een middelings diepte van 5 elementen onvoldoende. een potmeter verdraaing is erg traag.

qua middeling zie je veel varianten,
Zelf ga ik vaak voor de ( 7 x oudeWaarde + nieuweWaarde ) / 8 type, omdat hij zich gedraagt als een 1e orde (RC) filter.
deze methode is ook zeer efficient te coderen (snel,weinig geheugen)
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 10
Geregistreerd: 31 Mei 2013, 00:26

Re: analoge potmeter als soort schakelaar

Berichtdoor mattnezz » 01 Jun 2013, 18:56

Zelf ga ik vaak voor de ( 7 x oudeWaarde + nieuweWaarde ) / 8 type, omdat hij zich gedraagt als een 1e orde (RC) filter.

Ah dat ga ik onthouden!
De middeling die ik heb gebruikt komt van hier: http://arduino.cc/en/Tutorial/Smoothing
Ik ben dus slecht in het schrijven van functies, want ik probeerde die opsomming in de if-statement te veranderen naar een een functie die de drempel maakt...
De LFO amplitude moet afhankelijk zijn van 3 dingen, de instelleing van de 'speed' potentiometer, instelling van de 'depth' potmeter, en de delaytijd.
Het hele verhaal is nu dus zo:
Code: Alles selecteren
speedReading = smoothSpeed(lastSpeedReading);
depthReading = smoothDepth(lastDepthReading);
if( speedReading < (lastSpeedReading - 1) || speedReading > (lastSpeedReading + 1) ||
    depthReading < (lastDepthReading - 1) || depthReading > (lastDepthReading + 1) ||
    delayTime != lastDelayTime)
{
// ... dan LFO updaten
lastSpeedReading = speedReading;
lastDepthReading = depthReading;
lastDelayTime = delayTime;
}

Ik was er reeds achter dat >=2 eigenlijk hetzelfde is als >1... ;)
Kan ik de threshold niet vangen in de smoothSpeed() of smoothDepth() functies? Of is dat niet gebruikelijk?
Deze functies middelen nu alleen de lezingen van de 2 potmeters...
Wat ik eigenlijk zou willen is dat ik met die extra functie de if-statement kan beperken tot:
Code: Alles selecteren
if (speedReading != lastSpeedReading || depthReading != lastDepthReading || delayTime != lastDelayTime)
{
//...dan LFO updaten
}

De huidige code werkt goed hoor, alleen viel iemand mij lastig met de term 'code smell' en ik denk dat de laatste vorm duidelijker is. ;)
zou zoiets mogelijk zijn, of valt dat juist buiten de programmeer etiquetten?
Code: Alles selecteren
int smoothDepth(int last)
{
//eerst een gemiddelde lezing
if(deze lezing meer dan +1/-1 afwijkt van de vorige lezing)
  {
//middel een nieuwe lezing
//geef de nieuwe lezing
//oude lezing = nieuwe lezing
  }
}

Dat laatste idee krijg ik dus niet aan de gang...
Maarja, ik ontving mijn Arduino Uno precies 1 maand en 1 week geleden, en had daarvoor nog nooit ook maar één code/sketch of digitaal kunstwerk gezien.
Ik ben dus allang blij dat ik de dingen die ik voor ogen heb kan doen.
Nu de sketchjes wat groter worden, zijn tips om overzicht te houden dus zeer welkom...

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: analoge potmeter als soort schakelaar

Berichtdoor astrofrostbyte » 01 Jun 2013, 19:18

ja tis een hele kunst om duidelijke code te maken,
zet anders even de volledig code/sketch hier neer ..
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 10
Geregistreerd: 31 Mei 2013, 00:26

Re: analoge potmeter als soort schakelaar

Berichtdoor mattnezz » 01 Jun 2013, 20:38

zet anders even de volledig code/sketch hier neer ..

Ahum... Ik wil dat wel doen :oops: Het is echter de 2e sketch die ik heb geschreven...
Dus misschien is het beter als ik alleen het stukje voor de LFO eruit haal... Maarja, zal heel de waanzin wel posten, maar denk vrees dat er voor jullie teveel
haken en ogen aan zitten om doorheen te komen.

Even kort wat de sketch nu doet, wat iets meer is dan een golfje maken.
(Hij moet ook nog een state-variable filter aansturen, maar dit is de basis die ik eigenlijk 'net' zou willen krijgen.

Ik gebruik een digitale dual potmeter (MCP4251 of MCP42050) om de delaytijd van een echo-pedaaltje te regelen.
Ik gebruik geen datasheet tabellen voor de delaytijd, maar laat de arduino eerst de delaytijden bij de 255 potmeterstanden meten.
Meten gaat door een kleine puls het circuit in te sturen en te kijken hoeveel tijd er tussen de eerste (dry) en de tweede puls (wet) zit.
De puls gaat vanaf Arduino pin 4 via een condensator en weerstand naar GND het delay-circuit (5V puls ook gedempt met weerstand en dioode/led) in en komt via een koppelcondensator ook weer terug op A5;
A5 is expres van PULLUP voorzien en heeft ook een 10k naar GND, dit zodat ook een negatieve uitslag gemeten kan worden.
Deze waardes worden opgeslagen in een array int potValue[255];
deze array wordt bij een succesvolle test naar de EEPROM geschreven.

Bij het opstarten wordt de EEPROM gelezen.

Vervolgens een stuk wat de tijd meet tussen drukken op een moment-schakelaar. Het is belangrijk dat de gemeten tijd een gemiddelde is van 2 of meer drukken.
Als iets langer dan de langst gemeten delaytijd is verstreken moet een potmeterstand gevonden worden die dus de bijbehorende gemeten delaytijd geeft.

LFO is modulatie die aan die tijd wordt toegevoegd/weggehaald.
Ik maak een varierend PWM-signaal (32kHz, iig hoger dan audio) wat van Arduino's pin 3 op de gate van 2 bs170 fetjes staat. drain verbonden met de potmeter en source aan GND. parallel aan de fet een 3k6 weerstand.
Door de sinus om een pwm van 127 te laten draaien, probeer ik de gemiddelde delaytijd hetzelfde te houden.
Modulatie/vibrato/chorus is leuk, maar teveel is onmuzikaal, vandaar dat de LFO amplitude afhankelijk is van de eerder genoemde 3 zaken...(depth, speed, delay time.)

hier foto van UNO/Breadboard/testpedaaltje: https://dl.dropboxusercontent.com/u/23071527/2013-06-01%2019.57.55.jpg
Afijn hier wat ik nu heb, excuses voor gebrekkig commentaar in nederlands en engels door elkaar....
Code: Alles selecteren
//SPI LIBREARY: ****************************************************************************************
#include <SPI.h>               //spi library
const int SSDelayPotPin = 10;  // deze verbinden met Slave Select vd MCP4251
//byte commandByte = B00010011; //Alleen voor MCP42050;
//WRITE TO EEPROM: **************************************************************************************
#include <EEPROM.h>            //EEPROM library
void EEPROMWriteInt(int p_address, int p_value)
      {
      byte lowByte = ((p_value >> 0) & 0xFF);
      byte highByte = ((p_value >> 8) & 0xFF);
      EEPROM.write(p_address, lowByte);
      EEPROM.write(p_address + 1, highByte);
      }
//READ FROM EEPROM: **************************************************************************************
unsigned int EEPROMReadInt(int p_address)
      {
      byte lowByte = EEPROM.read(p_address);
      byte highByte = EEPROM.read(p_address + 1);
      return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
      }

//LFO GLOBAL VARIABLES: ***********************************************************************************
const int speedPot = A1;                           
const int depthPot = A0;
const int LFOPin = 3;
 int speedReading = 0; int lastSpeedReading = 0;
 int depthReading = 0; int lastDepthReading = 0;
//averaging potreadings
int potReadingsS [5];
int readingCountS= 0;
int sumReadingsS = 0;
int averageReadingsS = 0;
int potReadingsD [5];
int readingCountD= 0;
int sumReadingsD = 0;
int averageReadingsD = 0;
//lfo clock
boolean LFOClock = false;
boolean lastLFOClock = false;

int SPEED = 1;
float DEPTH = 0.00;

//sine wave array:
int n =0;
int sineWave[]={
   0,  4,    8,  13,  17,  22,  26,  30,  35,  39,  43,  47,  51,  55,  59, 
  63,  67,  71,  74,  78,  81,  84,  88,  91,  94,  97, 100, 102, 105, 107, 
 109, 112, 114, 116, 117, 119, 120, 122, 123, 124, 125, 125, 126, 126, 126,
 127, 126, 126, 126, 125, 125, 124, 123, 122, 120, 119, 117, 116, 114, 112, 
 109, 107, 105, 102, 100,  97,  94,  91,  88,  84,  81,  78,  74,  71,  67,
  63,  59,  55,  51,  47,  43,  39,  35,  30,  26,  22,  17,  13,   8,   4, 
   0,  -4,  -8, -13, -17, -22, -26, -30, -35, -39, -43, -47, -51, -55, -59, 
 -63, -67, -71, -74, -78, -81, -84, -88, -91, -94, -97,-100,-102,-105,-107, 
-109,-112,-114,-116,-117,-119,-120,-122,-123,-124,-125,-125,-126,-126,-126, 
-127,-126,-126,-126,-125,-125,-124,-123,-122,-120,-119,-117,-116,-114,-112, 
-109,-107,-105,-102,-100, -97, -94, -91, -88, -84, -81, -78, -74, -71, -67, 
 -63, -59, -55, -51, -47, -43, -39, -35, -30, -26, -22, -17, -13,  -8, -4 };


//DELAY_TIME CHECK GLOBAL VARIABLES****************************************************
boolean runCheck = false;    //
int sendPulsePin = 2;        //Arduino-pin to send pulse to delay circuit / AC coupled 4u7 cap limited to 2Vpeak
int recievePulsePin = A5;    //ardiuno-pin to recieve pulse from delay-circuit. AC coupled, referenced at Vdd/2
int testPin = 8;             //connect switch between pulled up pin and gnd
boolean currentState = LOW;
boolean lastState = LOW;
int pulseRead = 0;
int lastPulseRead = 0;
int pulseCount = 0;
int threshold = 2;           //set threshold low enough to read delayed pulse from delay/echo circuit
int potValue[255];           //array filled with delay time readings for digipot value between 0 & 255
int index = 0;

//time measurement
long t1 = 0;
long t2 = 0;
long tCheck = 0;
int delayRead = 1000;

unsigned int resistance = 0; //Arduino calculates resistance connected to PT2399's pin 6 in ohms

int test = 0;                //keeps track fo no of tests, when unexpected value occurs, test same potsetting max 10 times
int fail = 0;                //after 10 tests, report FAIL,keep track of failed measurements, reset if > 10
boolean FIND = true;
int deviation=1;



//TAP TEMPO GLOBAL VARIABLES : *************************************************
const int tapButton = 7;          //mom Sw between pin 7 & GND for tap-tempo


boolean currentTapState = LOW; //variables for debounce
boolean lastTapState = LOW;    //tap-tempo button/ button change detection

unsigned long tap1 = 0;       //time first tap
unsigned long tap2 = 0;       //time second tap

// variables for average interval calculation for >2 taps
int sum = 0;
int divider = 0;
int tapCount = 0;
unsigned long lastInterval = 0;
unsigned long interval = 0;
unsigned long average =300;                 
unsigned long timeOut = EEPROMReadInt(514);  // read longest available delay time from EEPROM
unsigned long delayTime = 300;             //root delay time
unsigned int lastDelayTime = 300;         // to detct change in delay time

//tempo indicatie led:
const int indLed = 4;                     //led with 330R connected to pin 4
int blinkLed = 150;                       // gives rate for tempo indication Led
boolean ledState = LOW;


// SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP * SETUP *
void setup(){
   Serial.begin(9600);
   SPI.begin();
  for (int a = 0 ; a <= 510 ; a += 2){ //collect timing data from EEPROM
      int v = a / 2; 
      potValue[v] = EEPROMReadInt( a );
 
     
      Serial.print("adress: ");Serial.print(a);
      Serial.print(" pot : "); Serial.print(v);
      Serial.print (" value: "); Serial.print(potValue[v]);Serial.println(" ms.");
      delay(1);
      }
  Serial.print("TimeOut: ");Serial.println(timeOut);
  for (int r = 0; r < 5; r ++){ //reset pot reading smoothing array
      potReadingsS[r] = 0;
      potReadingsD[r] = 0;
      } 
 
  pinMode (SSDelayPotPin, OUTPUT);
  pinMode (sendPulsePin, OUTPUT);
  pinMode (testPin,INPUT);
  digitalWrite(testPin,HIGH);
  pinMode (recievePulsePin,INPUT_PULLUP);
  pinMode(tapButton,INPUT_PULLUP);
  pinMode(indLed,OUTPUT);
  pinMode(LFOPin,OUTPUT);
  int prescalerVal = 0x07; //FAST PWM op pin 3 en 11 32kHz.
  TCCR2B &= ~prescalerVal;
  TCCR2B |= 1;
}

// END SETUP * END SETUP * END SETUP * END SETUP * END SETUP * END SETUP * END SETUP * END SETUP * END SETUP * END SETUP *

//DEBOUNCING & AVERAGING ************************************************************************************************
//DEBOUNCE START SYNC PROG SWITCH
int debounceDelay = 5;
boolean debounce(boolean last)                           
{
  boolean current = digitalRead(testPin);                 
  if(last != current)                         
  {
    delay(debounceDelay);
    current = digitalRead(testPin);                 
  }
  return current;                               
}
//DEBOUNCE TAP_TEMPO SWITCH:
boolean debounceTap(boolean last)                           
  {
  boolean current = digitalRead(tapButton);                 
  if(last != current)                         
  {
  delay(debounceDelay);
  current = digitalRead(tapButton);                 
  }
  return current;
  }
 
//AVERAGING FILTER LFO DEPTH:
int smoothDepth(int last)                     
  {
  sumReadingsD= sumReadingsD - potReadingsD[readingCountD];
  potReadingsD[readingCountD] = analogRead(depthPot);
  sumReadingsD= sumReadingsD + potReadingsD[readingCountD];
  readingCountD ++;
  if (readingCountD >= 5)
  readingCountD=0;
  averageReadingsD = sumReadingsD/5;
  int current = map (averageReadingsD, 0, 1023, 0, 127);
  return current;
  }
 
//AVERAGING FILTER LFO SPEED
int smoothSpeed(int last)                           
  {
  sumReadingsS = sumReadingsS - potReadingsS[readingCountS];
  potReadingsS[readingCountS] = analogRead(speedPot);
  sumReadingsS= sumReadingsS + potReadingsS[readingCountS];
  readingCountS ++;
  if (readingCountS >= 5)
  readingCountS=0;
  averageReadingsS = sumReadingsS/5;
  int current = map(averageReadingsS, 0, 1023, 62, 2);
  return current;
  }

// LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP * LOOP *   
void loop(){
 
  unsigned long time = millis();
  pulseRead = analogRead (recievePulsePin); 
  currentState=debounce(lastState);
  currentTapState=debounceTap(lastTapState);   //debounce functie oproepen
  //resistance= (index*195.3125)+1125; //MCP42050
  resistance= (index*195.3125)+1075; //MCP4251
 
// START DELAY TIME MEASUREMENT***************************************************************************
if(lastState == HIGH && currentState == LOW && FIND == false  ){  //send 1st pulse
    analogWrite (LFOPin,127); 
    index=0;
    digiPotWrite(index);
    tCheck = time;
    runCheck= true;
    digitalWrite(sendPulsePin,HIGH);
    delayMicroseconds(80);
    digitalWrite(sendPulsePin,LOW);
    }

if ( pulseCount == 0 && runCheck==true){ //auto send 80us pulse if pulseCount is reset
    tCheck = time;
    digitalWrite(sendPulsePin,HIGH);
    delayMicroseconds(80);
    digitalWrite(sendPulsePin,LOW);
  }

// DELAY TIME MEASUREMENT LOOP ***************************************************************************
if(runCheck==true)
{
if(pulseRead >(lastPulseRead+threshold)|| pulseRead < (lastPulseRead-threshold)) //if a change is detected at A5
{
    pulseCount ++;                                                         
   
    if (pulseCount == 1){                   //at first pulse
    t1=time;                                //flag millis()/time
     
        if((t1-tCheck)<10)                  //if first pulse is recieved within 10ms from the send pulse, it must be the dry signal             
          lastPulseRead=pulseRead;          //record the change
        else {
          delay((potValue[index-1]+500)) ;
          pulseCount = 0;
          }
    delay(30);                             //wait for 30ms. before next pulse detection
    }
       
    if (pulseCount == 2){                 //this must be the delayed/wet signal
      t2=(time-t1);                       //so measure the inteval between 2 pulses
     
    if(t2 < 2000 && t2 > 35){             //if the reading is between 35 and 2000ms, the reading is acceptable.
        delayRead = t2;
        pulseCount=0;
        lastPulseRead = pulseRead;
        delay(50);
        potValue[index] = delayRead;
      }
     
     
      Serial.print(" digi pot: ");
      Serial.print(index);
      Serial.print(" = delay time : ");
      Serial.print(delayRead);
      Serial.print(" ms. ");
      Serial.print(" Resistance =  ");
      Serial.print(resistance);
      Serial.println(" ohm.");
     
 //more checks
      //check if new measurement is longer than last mesurement
      if(potValue[index] > potValue[(index -1)] && (potValue[index]-potValue[index-1])<30){
        index ++;                         //if yes, move to next digipot setting 
        digiPotWrite(index);
        delay(potValue[index]);           //wait at least last delaytime so the detector(A5) won't detect the potshifts noise as avalid pulse.
        test=0;                           //reset test count
        pulseCount = 0;                   //and pulse count.
        Serial.print("--OK-->");
      }
               
      //if an increase in digipot value gives a shorter or the same delay time, something must be wrong, so test again.
      if(potValue[index] <= potValue[(index-1)]){
        if(test>1)delay((potValue[index-1]+1000));

        test++;                                  //keep track of the number of tests
        Serial.print(" test: ");
        Serial.print(test); 
        pulseCount=0;
        if(test == 10){
         Serial.print(" FAIL "); Serial.println(fail);
        fail ++;
        potValue[index] = (potValue[index - 1] + 4);
        index++;
        test=0;
        if (fail>9){index=0;fail=0;}
        }

      }
      else {
        delay((potValue[index-1]+500));
        pulseCount=0;
      }}



      if(index == 255){
        timeOut=delayRead;
        //WRITE POTVALUES/DELAYTIMES TO EEPROM:
         for (int a = 0 ; a <= 510 ; a += 2){
          int v = a / 2; 
          EEPROMWriteInt( a , potValue[v]);
       
        }
        delay(300);                  //relax ??
        EEPROMWriteInt(514,timeOut); //Write longest possible delay time to EEPROM.
       
        FIND=true;               //FIND A GIVEN VALUE:
        Serial.println("DONE");
        Serial.println(" ");
        Serial.print("searching for "); Serial.print(delayTime); Serial.print(" ms. delay time.");
      }
   
    }
}
  lastState = currentState;

if(runCheck==false){ 
//TAP_ TEMPO LOOP START ************************************************************************************* 
if(lastTapState == HIGH && currentTapState == LOW) { //als de TT-knop wordt ingedrukt
   tapCount++;                                  //wordt het aantal keer drukken geteld
   switch(tapCount){
   case 1: tap1 = time; break;                  //bij de eerste tap wordt de 'stopwatch' op 0 gezet
   case 2: tap2 = (time - tap1);                  //bij de tweede wordt de tussentijd berekend
           interval = tap2;                     //deze tussentijd wordt opgeslagen
           tap1 = time;                          //stopwatch wordt opnieuw op 0 gezet
           tapCount= 1;                        //tapcount gaat 1 stap terug, zodat bovenstaande regel opnieuw wordt
                                               //uitgevoerd bij een volgende tap.
 Serial.print (" time: "); Serial.println(interval);
           break;
   }
  }
lastTapState=currentTapState;

if(lastInterval != interval){                  //als er een verandering is in het interval tussen 2 taps
  if(interval > timeOut)interval=(timeOut);
  sum = (sum + interval);                          //worden de getapte tijden opgeteld
  divider ++;                                  //en gedeeld door het aantal taps
  average = (sum/divider);                     //voor een gemiddelde
  lastInterval=interval;                       //hier krijgt lastInterval de waarde van interval, om een verandering te herkennen
  Serial.print ("average = ");Serial.print (sum);Serial.print("/"); Serial.print (divider);  Serial.print (" = ");Serial.println(average);
}

if( (time-tap1) == (timeOut + 500)){                   //na een tijd van timeOut (langst gemeten delaytijd) na de laatste tap,
 delayTime = average;                          //wordt de delaytijd de waarde van de geiddelde tijd tussen de taps
 tapCount = 0;                                 //de tap teller wordt gereset
 sum = 0;                                      //zo ook de tijd optelling
 divider =0;                                   //en de deler
 blinkLed = (delayTime/2);
 Serial.print ("searching delay time: "); Serial.print(delayTime);  Serial.println(" ms.");
 Serial.println(" ------------------------"); Serial.println("  ");
 delay(2);
 FIND = true;
}
 
 
// START FIND POTVALUE FOR GIVEN DELAYTIME: *****************************************************************
if(FIND==true){
    for(int x=0; x<256; x++){
      if(delayTime == potValue[x] ) {    // find exact tapped delaytime is in data
        Serial.print("potVal: ");
        Serial.print(x);
        Serial.print(", time: ");
        Serial.print(potValue[x] ) ;
        Serial.println(" = spot on!") ;
        digiPotWrite(x);
        FIND=false;
        runCheck = false;
        deviation=1;
        break;
      }
      else if(delayTime == ( potValue[x] + deviation ) ) { //if not, let's try to find the closest value 1 ms longer,
        Serial.print("potVal: ");
        Serial.print(x);
        Serial.print(", time: ");
        Serial.print(potValue[x]);
        Serial.print(" ms,");
        Serial.println(" deviation: -");
        Serial.print(deviation);
        Serial.println(" ms");
        digiPotWrite(x);
        FIND=false;
        runCheck = false; 
        deviation=1;
        break;
      }
      else if(delayTime == (potValue[x] - deviation) ) { //if not let's try to find 1 ms. shorter than the tapped time.
        Serial.print("potVal: ") ;
        Serial.print(x) ;
        Serial.print(", time: ") ;
        Serial.print(potValue[x] ) ;
        Serial.print(" ms,");
        Serial.print(" deviation: +" ) ;
        Serial.print(deviation);
        Serial.println(" ms");
        delay(1);
        digiPotWrite(x);
        FIND=false;
        runCheck = false;
        deviation=1;
        break;
      }
      if( x==255 ) {
        deviation++;
        x=0;
      }
      if( deviation==20 ){
        FIND=false;
        runCheck = false;
        Serial.println ("NOT FOUND!");
        deviation=1;
        break;
      }
    }
  }
 
 
  ledState = (time/blinkLed)%2;               //ledje geeft tempo aan
  digitalWrite (indLed,ledState);
 
 
//LFO SETTINGS*************************************************************************
LFOClock = (micros()/SPEED)%2;
speedReading = smoothSpeed(lastSpeedReading);
depthReading = smoothDepth(lastDepthReading);
if( speedReading < (lastSpeedReading - 1) || speedReading > (lastSpeedReading + 1) ||
    depthReading < (lastDepthReading - 1) || depthReading > (lastDepthReading + 1) ||
    delayTime != lastDelayTime)
{
 
  int fact = map(delayTime,50,timeOut,127,0);
  DEPTH=depthReading/(127.0 + fact + speedReading);
  if(DEPTH < 0.01)DEPTH = 0;
  SPEED = (speedReading*200) ;
  lastSpeedReading = speedReading;
  lastDepthReading = depthReading;
  lastDelayTime = delayTime;
  Serial.print("LFO> depth: "); Serial.print(DEPTH*100); Serial.print(" % ");Serial.print(" speed: ");Serial.println(speedReading);
}

if( LFOClock != lastLFOClock ){
  n++; 
  if (n==180)n=0;
  float z = sineWave[n]*DEPTH;
  analogWrite(LFOPin, z+127);
    lastLFOClock = LFOClock;
    }
}//END RUNCHECK==FALSE
}

//END VOID LOOP************************************************************************


// Write to digipot:*******************************************************************
void digiPotWrite( int value) {
  //MCP4251:
  digitalWrite(SSDelayPotPin,LOW);  //Slave Select delay-pot
  SPI.transfer(B00000000);          //Write P0
  SPI.transfer(value);              //data for P0 (0 ~ 255)
  SPI.transfer(B00010000);          //Write P1
  SPI.transfer(value);              //data for P1  (0 ~ 255)
  digitalWrite(SSDelayPotPin,HIGH); //end write to delay-pot
  // MCP42050:
  // digitalWrite(SSDelayPotPin,LOW);
  // SPI.transfer(commandByte);         //Write P0 en P1
  // SPI.transfer(value);               //data voor P0 en P1 (0 ~ 255)
  // digitalWrite(SSDelayPotPin,HIGH);
}

Volgende

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: wxamecunaxavu en 17 gasten