Help in equation parameters in arduino

Hii mates,

I need your help with a programming issue .

I want to implement an equation on my arduino sketch with 4 parameters, A, B and C and D.

What I want is to be able to change the value of those parameters depending of the chosen selection of a SoundProfile.

Parameters present are: global volume, mixing factor for each wav file, silence for each wav (for eg : if velocity of bike is low, silence is low it means (sample - silence for long time - sample- silence....)) and velocity is high silence is for short time and last parameter is speed of wav file means velocity of bike is low it will read each sample in wave table else if velocity is high it reads every 10th sample.

These are Sound Profile I have created .

Sound Profile 1 : x.wav, volume will increase or decrease corresponding to velocity of bike
Sound Profile 2 : y.wav, speed and silence are modified other parameters are constant
sound Profile 3 : z.wav , Silence is modified and other parameters are constant.

Note: All parameters ranges from (0 to 1) for eg : 0 low vol and 1 high vol except silence ranges from 0 to 10.

Now My issue is I want to create such an equation which should be universal to all sound profiles.
I had created a code which will make you understand more clearly. I am getting the output but problem the coding approach is not good because for every switching between sound profile ,code changes which is not good only change parameter according to speed of bike.

My skill in coding are basics. Thanks in advance.

switch (currentSoundProfile) {

    case 1: {

        // Sound Profile 1 : Only Volume modification other parameter constant

        if (currentSoundProfile != oldProfile) {

          for (int i = 0 ; i < samplernumber ; i++) {

            sampler[i].sstop();
          }

          sampler[0].init();
          sampler[0].load("/SoundP~1/1.wav");
          sampler[0].splay();
          sampler[0].buffill();
          oldProfile = currentSoundProfile;
          Serial.println(F("Sound Profile ? "));
        } else {
          sampler[0].splay();
          sampler[0].buffill();
          oldProfile = currentSoundProfile;

        }

        // Set Silence
        sampler[0].setSil(SIL_MAX);

        // Set Speed
        sampler[0].setSpeed1(SPEED_MAX);

        // MIX factor of 1.wav
        m1 = MIX_1;

        // Modification  Volume
        v0 = log(kph);
        sampler[0].setVol(v0);

        // Can load any sound Profile in sampler0

        while (Serial.available() == 0) {
          loop();

        }

        currentSoundProfile = Serial.parseInt();
        Serial.println(currentSoundProfile);


        break;
      }

    case 2 : {
        //  Speed  and silence  Modification and other parameters constant

        if (currentSoundProfile != oldProfile) {

          for (int i = 0 ; i < samplernumber ; i++) {
            sampler[i].sstop();
          }

          sampler[1].init();
          sampler[1].load("/SoundP~1/2.wav");
          sampler[1].splay();
          sampler[1].buffill();
          oldProfile = currentSoundProfile;
          Serial.println(F("Sound Profile ? "));
        } else {

          sampler[1].splay();
          sampler[1].buffill();
          oldProfile = currentSoundProfile;

        }

        // Modification of Silence

        s1 = sqrt(kph);
        sampler[1].setSil(s1);

        // modification of speed of wav file
        //n1 = log(kph);

        kph = kph / MAX_VEHICLE_SPEED; // Smooth sound

        n1 = exp(kph);
        sampler[1].setSpeed1(n1);

        //Set  Volume
        sampler[1].setVol(VOL_MAX);

        m2 = MIX_2;

        //        Serial.println(F("Sound Profile ? "));
        while (Serial.available() == 0) {
          loop();
        }

        currentSoundProfile = Serial.parseInt();
        //  Serial.print("Sound Profile : ");
        Serial.println(currentSoundProfile);


        break;
      }

You must post all your code if we are to make sense of it. However I suspect that function was called from the loop function. It in turn calls the loop function. This is known as recursion and if you do not know what you are doing with it will cause your program to crash as each recursive call eats a bit of memory that is never reclaimed. Eventually you run out of memory.

If each parameter of your equation is an array then selecting the profile of the array index will solve your problem. But having parameters that go from 0 to 1.0 is not a good idea because floating point arithmetic takes a lot longer to do than integer arithmetic.

Hii Mike,

Thanks for reply, Yes you are right that switch cases are actually sound profiles which are called from loop.
I don't have problem to post the code but the code is too big and I don't think that anyone would be interested to read it. Even though I am getting output, You are right recursuion will cause an problem.

Now another approach is that whenever any event occurs when I press button or key it will select that particular sound profile. So, I am planning to use attach interrupt function for sound profiles or any other option is there please let me know. That means sound profiles will not be in loop.

I will create an universal formula which would be in loop where recalculation of parameters take place.

For better understanding
If press key 1 : select sound profile 1
If press key 2 : select sound profile 2

Thanks in advance.

#include <SD.h>
#include <SPI.h>
#include <stdlib.h>
#include <stdio.h>
#include "sampler1.h"

#define COUNT_MAX 30
#define VOL_MAX 1
#define MASTER_VOL 1
#define SPEED_MAX 1
#define SIL_MAX 10
#define SIL_CONST 0.25
#define MIX_1 1
#define MIX_2 1
#define MIX_3 1
#define SAMPLE_RATE 953 // // sets <> 11.1 Khz interrupt rate
#define WAIT 1000
#define FEET_IN_MILE 5280
#define MILLI_TO_SEC 3600000.0
#define MAX_VEHICLE_SPEED 50
const int samplernumber = 3;

void getFile(float);


// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
File folder;
Sampler1 sampler[samplernumber];


static int oldProfile , currentSoundProfile;
float v, s, number, v0, v1, v2, n0, n1 , n2, s0, s1, s2;
int counter = 0;

// variables used in TI are volatile
volatile int ti;
volatile float m1, m2, m3 = 0;
volatile float  m11, m22, m33 = 0;
float kph;


// Parameters initialization for Speed of vehicle
const int inductivePin = 2;


// the following variables are long's because the time, measured in miliseconds,
unsigned long time0 = 0;
unsigned long time1;
static float diff  = 0;

// variables will change

int lastState  = LOW;   // the previous reading from the input pin only after condition for counter is true
long previousMillis;
int lastPulse = HIGH;  //for every current reading state wait for next pulse


void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);

  // setup SD-card
  Serial.print(F("Initializing SD card..."));
  if (!SD.begin(4)) {
    Serial.println(F(" failed!"));
    while (true);
  }

  Serial.println(F(" done."));

  pinMode(inductivePin, INPUT_PULLUP);


  //turn on the timer clock in the power management controller
  pmc_set_writeprotect(false);
  pmc_enable_periph_clk(ID_TC4);

  //we want wavesel 01 with RC
  TC_Configure(TC1, 1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK2);
  TC_SetRC(TC1, 1, SAMPLE_RATE);
  TC_Start(TC1, 1);

  // enable timer interrupts on the timer
  TC1->TC_CHANNEL[1].TC_IER = TC_IER_CPCS;
  TC1->TC_CHANNEL[1].TC_IDR = ~TC_IER_CPCS;

  //Enable the interrupt in the nested vector interrupt controller
  //TC4_IRQn where 4 is the timer n * timer channels (3) + the channel
  //n (=(1*3)+1) for timer1 channel1
  NVIC_EnableIRQ(TC4_IRQn);

  root.openRoot(volume);
  folder = SD.open("/SoundP~1/"); //1
  Serial.println(F("Sound directory"));

  if (printDirectory(folder, 0) == 0) {
    Serial.println(F("No wav files, nothing to do!"));
    while (1);
  }

  // Enable DAC1 Port
  analogWrite(DAC1, 0);

  // Wave file Selection

  Serial.println(F("Sound Profile ? "));
  while (Serial.available() == 0) {

  }

  currentSoundProfile = Serial.parseInt();
  Serial.println(currentSoundProfile);
  Serial.flush();


void loop() {

  //Reading of Inductive Sensor Switch and currentVal is current reading
  int  currentVal = digitalRead(inductivePin);

  if (currentVal == LOW ) {

    // Wait for Next pulse else stop all wav files

    if (currentVal != lastPulse) {
      previousMillis = millis();

    }
    
// used to overcome debounce of inductive sensor using counter

    if ( millis() - previousMillis >= WAIT) {
      for (int i = 0 ; i < samplernumber ; i++) {

        sampler[i].sstop();
      }
    }

    lastPulse = currentVal; // update the laststate



    // Before increment check counter status

    if (counter < COUNT_MAX ) {

      counter++;

      if (counter == COUNT_MAX) {

        if (lastState != currentVal) {

          lastState = currentVal;       //State change and determine kph when sensor coincide with spoke

          time1 = millis();
          diff = time1 - time0;  //Pulse difference
          time0  = time1;
          if (diff == 0) {

            float mph = 0;
            kph = 0;
            getFile(kph); // function call to sound profiles
            Serial.println(kph);
          }
          else {
            float mph = (MILLI_TO_SEC / ((diff) * FEET_IN_MILE));
            //Serial.println(mph);
            kph = (mph * 1.60934);
            //  Serial.println(kph);
            getFile(kph); // Function call

          }
        }
      }
    }
  } else {

    if (currentVal != lastPulse) {
      previousMillis = millis();
    }

    if ( millis() - previousMillis >= WAIT) {
      for (int i = 0 ; i < samplernumber ; i++) {
        sampler[i].sstop();
      }
    }

    lastPulse = currentVal;   // update the laststate

    //Before Decrementing check counter status

    if (counter > 0 ) {

      counter -- ;

      if (counter == 0) {

        if (lastState != currentVal) {

          lastState = currentVal;       //  only do State change

        }
      }
    }
  }
}
}

void getFile(float a1) {

  // ti variable used in TI
  ti = currentSoundProfile;

  switch (currentSoundProfile) {

    case 1: {

        // Sound Profile 1 : Only Volume modification other parameter constant

        if (currentSoundProfile != oldProfile) {

          for (int i = 0 ; i < samplernumber ; i++) {

            sampler[i].sstop();
          }

          sampler[0].init();
          sampler[0].load("/SoundP~1/1.wav");
          sampler[0].splay();
          sampler[0].buffill();
          oldProfile = currentSoundProfile;
          Serial.println(F("Sound Profile ? "));
        } else {
          sampler[0].splay();
          sampler[0].buffill();
          oldProfile = currentSoundProfile;

        }

        // Set Silence
        sampler[0].setSil(SIL_MAX);

        // Set Speed
        sampler[0].setSpeed1(SPEED_MAX);

        // MIX factor of 1.wav
        m1 = MIX_1;

        // Modification  Volume
        v0 = log(kph);
        sampler[0].setVol(v0);

        // Can load any sound Profile in sampler0

        while (Serial.available() == 0) {
          loop();

        }

        currentSoundProfile = Serial.parseInt();
        Serial.println(currentSoundProfile);


        break;
      }
}

void TC4_Handler() //Interrupt at 11KHz rate
{
  TC_GetStatus(TC1, 1);


  // 2048 is the 0 value of audio out.

  int16_t ulOutput = 2048;
  int16_t ulOutput1 = 0;
  int16_t ulOutput2 = 0;
  int16_t ulOutput3 = 0;



  // only 1.wav
  if (ti == 1) {

    m11 = 0;
    m22 = 0;
    m33 = 0;
    m11 = m1;


    ulOutput1 = sampler[0].output();      // Get the value
    ulOutput1 = (ulOutput1 * m11 );      // mix it with obtained value
    ulOutput  += ulOutput1;             // To the result add the offset

  }

 if (ulOutput > 4095) ulOutput = 4095;

  if (ulOutput < 0) ulOutput = 0;
  dacc_write_conversion_data(DACC_INTERFACE, ulOutput);

}

I don't have problem to post the code but the code is too big and I don't think that anyone would be interested to read it.

The thing is that it lest us see overall structure instead of us having to guess, like your call to the loop function. If you want to go back do not call it but just use return.

So, I am planning to use attach interrupt function for sound profiles

I would not use interrupts here. Simply look at the buttons and when you see activity change the profile. Interrupt routines should be short and as they can be triggered anywhere in the code you have to be cairfull what you change in them.

Hii,

I removed the recursion problem, In loop, I am just reading the button, If it is HIGH then, I am linking to my sound profile. So, I can select any sound profile

But my main question is Equation parameters, I am completely new to this concept.

I want to create an universal formula in loop which can calculate speed,silence,mixing factor and volume. I am using quadratic equation ax ² + bx + c where I will set parameters for a,b,c for eg: a = log kph, b=1, c = 10 and calculate vol,speed respectively.

Is this the right method?

Once again thanks for help.

Like I said, you can set the variables before your calculation or you can make those parameters arrays so you would use for example
a[profile] as one of the variables in your calculation so profile acts as an index into a number of values.

I am not entirely sure what you are using this calculation to do. Are you applying it to individual sound samples or are you passing it on to some hardware?.