Go Down

Topic: "Momentum" function (Read 1 time) previous topic - next topic

stuart0

#15
Feb 13, 2017, 05:23 am Last Edit: Feb 13, 2017, 12:52 pm by stuart0
PS:

While this is working well for my purposes, it's still not exactly mimicking bellows.

ie:
In a real pump organ, the action of pumping the bellows fills the bag with air.
In this system, pushing the pedal down (pot wiper connected to 3.3V) is what fills the bag.
I think the problem is that in the current setup the position of the pot is mimicking the flow of air, whereas it probably should be the velocity (rate of change of the pot) that is the real analog for air flow.

So we need to use the difference in input pot position "x" rather than just its present value. One problem with that simple approach however, is that the change will be both positive and negative over a cycle, and you'll get no net air flow. So you'll need to either use the absolute value of the change (which actually models a double acting cylinder) or use just positive changes and ignore negative ones (which is a normal single acting pump). I'll assume the latter in the code below.


Now our change in pressure is of the form

if (x>lastx) Change_in_P = -b*P + a*(x - last_x); else Change_in_P= -b*P;

This leads to the new equation:

Code: [Select]

if (x>xlast) P = (1-b)*P + a*(x - lastx);
else P = (1-b)*P;


You'll probably have to re-tune the constant "a" for the new model.

Jiggy-Ninja

#16
Feb 13, 2017, 12:50 pm Last Edit: Feb 13, 2017, 12:50 pm by Jiggy-Ninja
I modified your code with the same idea as stewart's.
Code: [Select]

const int lengthIntervalFilter = 300;
unsigned beginningFilterInterval, currentMillis;
float currentBellowsPressure = 0;
float lastBellowsPressure = 0;
const float BELLOWS_RELEASE_CONSTANT = .5;
const float BELLOWS_FILL_CONSTANT = .6;
int16_t previous_footpedal;

void setup()
{
previous_footpedal = analogRead(A20);
}

void loop {
  currentMillis = millis();
  if (currentMillis - beginningFilterInterval >= lengthIntervalFilter) {
    beginningFilterInterval += lengthIntervalFilter;
    int16_t current_footpedal = (float)analogRead(A20);

// might need to change the polarity of the following difference.
// Does the analogRead() value go up or down when you press it? This code assumed it increases.
    int16_t foot_pedal_difference = current_footpedal - previous_footpedal; // detect the change in the footpedal level;
    if( foot_pedal_difference<0 )
        foot_pedal_difference = 0; // half-wave rectify to simulate one-way air valves.
previous_footpedal = current_footpedal;

    currentBellowsPressure = (1 - BELLOWS_RELEASE_CONSTANT) * lastBellowsPressure +     BELLOWS_FILL_CONSTANT * (float)foot_pedal_difference;
    if (currentBellowsPressure > 1024) {
      currentBellowsPressure = 1024.00;
    }

    Serial.println( currentBellowsPressure );
    Serial.println( footpedal );
    lastBellowsPressure = currentBellowsPressure;
  }

}

It's not really necessary to detect the velocity of the pot's changes (that would imply some sort of numerical differentiation, which is more complicated), just the changes in the value itself (which only requires subtraction). From there, the change value is half-wave rectified to get rid of the negative value. This implies a single-action pump like stuart mentioned, when only one direction fills the bellows. Then that value is put into the bellows pressure calculation.

I have not tested this code.
Hackaday: https://hackaday.io/MarkRD
Advanced C++ Techniques: https://forum.arduino.cc/index.php?topic=493075.0

Go Up