need a different way to smooth results

hi all,

i have build a small system which takes a clock signal on an interrupt line and counts the number of times the line rises. every 192 times it counts that as a "beat" and displays the beats per minute on an LED 7 segment display.

now this is working almost perfectly, the only thing is it "twitches." for example i have a BPM of 100, but every now and again it drops to 99 and back to 100. it is pretty stable most of the time, its maybe one in 20 beats it does this roughly.

anyway i used the smoothing example that is given with the Arduino IDE and it didn't help,

so what i want is something that basically says: only update the display if the bpm has changed significantly, either more than one up or down, or if it has been at a new number for a reasonable length of time.

but i am not sure how to go about that....

any pointers or help would really be apriciated

Whenever you display a bpm value, save the value in a variable of the same type, lastBpm. When it is time to display a new value, compare the current value with the previous value. If the difference is large enough (you decide what that means) display a new value and save it is as the last displayed value.

To see if the new value has been stable long enough, you also need to keep track of when (using millis()) a new value was displayed.

Then, compare the new value to the old value and now to then. If now is significantly larger than then (again, you get to decide what this means) or if the value is significantly larger (or smaller), change to displaying the new value, update the time and the old value variables.

More specific details, and where to make the changes, could be provided if you showed your code.

ok thanks,

how do i compare the differences? i cant use, not equal to because that doesn't say by how much. i need something like, more than 1 or less than 1 of the original number?

i will clean up my code a bit and submit it in a sec

if(abs(oldVal - newVal) > deltaVal)
{
   // Big difference
}

sorry for the messy code, i am still learning very much! any hints on cleaner code would be great also, but it does work for now.

and thanks for that pointer, i will have to look up the abs thing and see how that works

int pinClock     = 2; 
int pinLED1 = 12;
int pinLED2 = 3;
int pinLED3 = 4;

int one;
int ten;
int hundred;

const byte numbers[10] = { 0b1111110, 
0b0110000, 0b1101101, 0b1111001, 0b0110011, 0b1011011,
0b1011111, 0b1110000, 0b1111111, 0b1110011 };

volatile int finalCount      = 192;
volatile boolean firstCount = false;
volatile int long previousTick = 0;
volatile int long bpm = 0;

void setup() {
  pinMode(pinLED1,OUTPUT);
  pinMode(pinLED2,OUTPUT);
  pinMode(pinLED3,OUTPUT);
  pinMode(pinClock,INPUT);
  pinMode(pinClock,   INPUT);  
  for (int i=5; i<12; i++) { 
    pinMode(i, OUTPUT);
  }   

  for (int x=0; x<6; x++){
    lightLEDs(64>>x);
    delay(100);
  }

  attachInterrupt(0, clockCounter, RISING);
}

void loop () {
  updateDisplay (bpm, numbers); 
}

void clockCounter() {
  finalCount++;
  if (finalCount >= 192) { 
    finalCount = 0;
    if (firstCount) {
      firstCount =false;
      bpm = 60000/(millis() - previousTick);
    }
    else {
      firstCount = true;
      previousTick = millis();
    }
  }
}

void updateDisplay (int value, const byte* arrayName) {
  
  hundred = (value/100);
  ten = ((value-(hundred*100))/10);
  one = ((value-(hundred*100))-(ten*10));
  
  digitalWrite(pinLED1,HIGH);   
  lightLEDs(arrayName[hundred]);
  digitalWrite(pinLED3,LOW);
  delay(1);
  digitalWrite(pinLED3,HIGH);
  lightLEDs(arrayName[ten]);
  digitalWrite(pinLED2,LOW);
  delay(1);
  digitalWrite(pinLED2,HIGH);
  lightLEDs(arrayName[one]);
  digitalWrite(pinLED1,LOW);
  delay(1);
}

void lightLEDs(byte number) {
  for (int i = 0; i < 7; i++) {
    int bit = bitRead(number, i);
    digitalWrite(i+5, bit);
  }
}

why the hell have a put pinClock as an output twice?? ignore that bit

abs is the absolute value function. If oldVal was 12 and newVal was 5, oldVal - newVal = 7, so abs() returns 7. If oldVal was 5 and newVal was 12, oldVal - newVal = -7, and abs() would return 7.

So, it wouldn't matter if the bpm value goes up or down. It is the difference in values that is important.

ah thats great! in fact that is really useful to know for a lot of things,

so abs just returns the difference, which i can choose if its too much or not.

thanks very much for your help with this!

A couple of questions. Why is the initial value of finalCount 192? It is incremented each time the interrupt fires. Reaching a value of 192 (it first becomes 193) causes some action. Doing this on the first interrupt does not seem to make sense.

      bpm = [glow]60000[/glow]/(millis() - previousTick);

"Magic" numbers are generally to be avoided. Create a #define statement to give this value a name, or use const long to create a variable with a meaningful name.

The same really holds true for 192, too. Where did that number come from? Maybe it means something to you, but might not be obvious to others that read your code.

What if that value needed to change to 196, for some reason. How many places it is used in the code? Will you remember to change them all?

As for your original issue, you could modify loop to only call updateDisplay if the display really needed to be updated, or you could put the code to determine if the display really needs to change in updateDisplay.

My preference is to make the call to updateDisplay conditional. This way, every call to updateDisplay actually results in a new value being displayed.

why the hell have a put pinClock as an output twice?? ignore that bit

Isn't it amazing how just showing off the code makes silly mistakes blindingly obvious?

ah, well the reason the finalCount is set to 192 is that equals one beat. it is 8 bits of data sent 24 times. changing it would mean that it is no longer counting on the beat.

but i see what you mean about defining the number and using that ref so that it is easy to see what that number means.

but that is answered by question 2, why does it start at 192 and tip over to 193 on the first count? well this code was cut out of a previous project that followed the same clock signal, only it flashed a light. the first transition of the clock line was also the first beat so i wanted the light to flash on the very first transition as well as the 192nd transition. originally this had a pot that defines when the light flashes, if it is twice a beat, or every half beat etc, and in that code i did have #define for all the values, 192 was defined as normal speed, but i cut that bit out when trimming the code down and never put it back. i was going to put it back in as a comment.

as with choosing to call update display, the problem is with how i have written the code, update display needs to be called all the time or the LEDs wont light. they are switched on and off as each digit is written and need to keep cycling through to display it. but you are right and i was actually thinking about this last night, i could put some code in the loop that says if the number hasn't changed for more than, 10 counts of the clock for example, then don't change the value stored in the variable.

exactly! when you go through your code in a different way, you see it in a different way, i like to explain my code to my girlfriend, even though she doesn't understand, listen or care, just because i have to say it out loud and then suddenly it all makes sense!

again thanks for the pointers and taking the time to reply i really apriciate it, i am learning the arduino code on my own just by looking at other code and the reference page on the site, but i still don't know all the little tricks or standards.