5 years, 8 months ago.

How to count incoming pulses so that it changes LED blink frequency more like logarithmically

Suppose I want to blink LED on a regular basis once per, say 1.5 seconds, but if the frequency of incoming signal is increasing (0-up to 2khz.) I want LED to blink faster and faster with each increase almost like logarithmically. The range would be from 0 up to maybe 2khz. I was working this out by using if statements, but I did it with several frequency stages which results in a huge steps. However, I was thinking if there is any way to do this by increasing the blinking smoothly?

I know this code below is far from good, but it does approximately what I wanted.

#include "mbed.h"
#define ON 1
#define OFF 0

DigitalOut myled(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
PwmOut PWM(p21); // pwm out
InterruptIn pulseInterrupt(p5); // Input pulse signal here

int pulseCount;

void highPulseDetected() { // incoming pulse counter
     pulseCount++;
}

int main() {
    pulseCount = 0;
    pulseInterrupt.rise(&highPulseDetected); //attach counter address to the ISR upon rising edge
    
    while(1) {

        PWM.period(pulseInterrupt); // generate pwm to feed back in for counting
        PWM = 0.5;
        wait_ms(100);
        PWM = 0;

        pc.printf("%d\n\r", pulseCount++);

        if(pulseCount <= 102) {
            myled = ON;
            wait(0.1);
            myled = OFF;
            wait(1);

            pulseCount = 0;
        }
        else if(pulseCount <= 202){
            myled2 = ON;
            wait(0.1);
            myled2 = OFF;
            wait(0.6);

            pulseCount = 0;
        }
        else if(pulseCount <= 302){
            myled3 = ON;
            wait(0.1);
            myled3 = OFF;
            wait(0.4);

            pulseCount = 0;
        }
        else if(pulseCount <= 402){
            myled4 = ON;
            wait(0.1);
            myled4 = OFF;
            wait(0.1);

            pulseCount = 0;
        }
        else if(pulseCount <= 502){
            myled = ON;
            wait(0.1);
            myled = OFF;
            wait(0.07);

            pulseCount = 0;
        }
        else if(pulseCount >= 602){
            myled2 = ON;
            wait(0.1);
            myled2 = OFF;
            wait(0.02);

            pulseCount = 0;
        }
    }
}

1 Answer

5 years, 8 months ago.

Hello Saulius,

Interesting task. Below is another attempt for a solution:

#include "mbed.h"
 
DigitalOut          led(LED1);
InterruptIn         input(p5);                      // input line
Timeout             timeout;
volatile bool       counting = false;
volatile uint32_t   counter;
float               period;
const float         GATE_TIME = 1.0f;               // period of time to count pulses within (in seconds)
const float         K = 1;                          // to be tuned
const float         MIN_COUNT = pow(10.0f, 1.5f);   // 10^1.5
  
//ISR to count pulses
void onPulse(void) {
    if (counting)
        counter++;
}
 
// ISR to stop pulse counting
void stopCounting(void) {
    counting = false;
}
 
// Entry point
int main(void) {
    input.rise(callback(&onPulse)); // assign an ISR to pulse counting
    led = 1;
    while (1) {
        if (!counting) {
            period = 1 / log(MIN_COUNT + K * counter);
            counter = 0;
            timeout.attach(callback(&stopCounting), GATE_TIME);
            counting = true;
        }
        wait(period);
        led = !led;
    }
}