Goal

Write a sketch that does the same as in ex #1, but using PWM to make the LED blink, every quarter of second if distance < 50cm, and every half second if distance >50cm and <100cm, no blink over.

Solution

This time, the goal is to avoid calls to delay() function, in order to avoid the problem of "missing events". Since the execution is not delayed anymore, the state machine must be rewritten to avoid to take some actions if they are not useful. For example, there is no need to change the frequency of the blink if the state is not changing. This is why some tests on the state are added in the loop() function to determine if we need to change the state or not.

#include <HCSR04.h>

#define STATE_BLINK1 0
#define STATE_BLINK2 1
#define STATE_NOBLINK 2

#define PIN_TRIG 22
#define PIN_ECHO 19
#define PIN_LED 5

UltraSonicDistanceSensor distanceSensor(PIN_TRIG, PIN_ECHO);
int state = STATE_BLINK1;

void blink() {
  // freq is 2Hz when <50cm and 1Hz if <100 & >50
  ledcChangeFrequency(PIN_LED, (2-state), 10);
  // restart PWM at 50% in case of it was cut-off before
  ledcWrite(PIN_LED, 512);
}

void setup () {
    Serial.begin(115200);  
    pinMode(PIN_LED, OUTPUT);
    ledcAttach(PIN_LED, 1, 10);
    ledcWrite(PIN_LED, 512);
}

void loop () {
  
  // Every 500 miliseconds, do a measurement using the sensor and print the distance in centimeters.
  float distance = distanceSensor.measureDistanceCm();
  Serial.println(distance);
  if (distance < 50) {
    if (state != STATE_BLINK1) {
      state = STATE_BLINK1;
      blink();
    }
  }
  else if (distance < 100) {
    if (state != STATE_BLINK2) {        
      state = STATE_BLINK2;
      blink();
    }
  }
  else {
    if (state != STATE_NOBLINK) {
      state = STATE_NOBLINK;
      // directly ctu-off pwm by setting duty-cycle to 0%
      ledcWrite(PIN_LED, 0);
    }
  }    
}