#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/timer.h"
#include "pico/sync.h" // Required for critical_section
// Define GPIO pins for Trigger and Echo
const uint TRIGGER_PIN = 17;
const uint ECHO_PIN = 16;
const uint LED_PIN = 2;
// Global variables to store timestamps, made atomic/thread-safe with a critical section
volatile uint64_t start_time_us = 0;
volatile uint64_t end_time_us = 0;
volatile bool new_measurement_ready = false;
critical_section_t time_section;
// Interrupt handler function
void echo_pin_irq_handler(uint gpio, uint32_t events) {
critical_section_enter_blocking(&time_section);
if (events & GPIO_IRQ_EDGE_RISE) {
start_time_us = time_us_64();
end_time_us = 0; // Reset end time on rising edge
} else if (events & GPIO_IRQ_EDGE_FALL) {
end_time_us = time_us_64();
new_measurement_ready = true;
}
critical_section_exit(&time_section);
}
int main() {
stdio_init_all();
critical_section_init(&time_section);
printf("HC-SR04 Ultrasonic Sensor on Raspberry Pi Pico (Interrupt Version)\n");
// Initialize LED pin
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
// Initialize HC-SR04 pins
gpio_init(TRIGGER_PIN);
gpio_init(ECHO_PIN);
gpio_set_dir(TRIGGER_PIN, GPIO_OUT);
gpio_set_dir(ECHO_PIN, GPIO_IN);
// Ensure trigger is low initially
gpio_put(TRIGGER_PIN, 0);
sleep_ms(100);
// Configure interrupt on the ECHO pin for both rising and falling edges
gpio_set_irq_enabled_with_callback(ECHO_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &echo_pin_irq_handler);
// Main loop
while (true) {
// --- LED Blinking Logic (Runs without blocking) ---
gpio_put(LED_PIN, 1);
sleep_ms(1000);
gpio_put(LED_PIN, 0);
sleep_ms(1000);
// --- HC-SR04 Trigger (Non-blocking part 1) ---
// Send 10us trigger pulse
gpio_put(TRIGGER_PIN, 1);
sleep_us(10);
gpio_put(TRIGGER_PIN, 0);
// The rest of the measurement happens in the IRQ handler
// --- Distance Calculation (Check if data is ready) ---
if (new_measurement_ready) {
critical_section_enter_blocking(&time_section);
uint64_t pulseLength_us = end_time_us - start_time_us;
new_measurement_ready = false; // Reset flag after reading
critical_section_exit(&time_section);
// Calculate distance: Speed of sound = 0.0343 cm/us
float distance_cm = (float)pulseLength_us * 0.0343 / 2.0;
printf("Distance: %.2f cm\n", distance_cm);
}
// Wait a reasonable time before triggering the *next* measurement
// This sleep replaces the original long blocking wait for the echo pulse to return.
// It allows the LED blinking to dominate the inter-measurement time.
sleep_ms(300);
}
}