Jak zaprogramować ultradźwiękowy czujnik odległości HC-SR04 na mikrokontroler AVR ATTINY84A

Spróbujmy zaprogramować pomiar odległości za pomocą ultradźwiękowego czujnika odległości HC-SR04 oraz mikrokontrolera AVR ATTINY84A. Wykorzystamy także wyświetlacz LCD artykułu Jak zaprogramować wyświetlacz LCD (HD44780) na AVR ATTINY84A do wyświetlania wyników naszych testów. Spróbujmy rozpracować temat krok po kroku.

Czujnik ten jest bardzo tani bo kosztuje tylko kilka złotych, więc dalej bawimy się stosunkowo tanią elektroniką świetnie nadającą się do nauki.

Jak podłączyć ultradźwiękowy czujnik odległości HC-SR04 do mikrokontrolera AVR?

Nie powinno być z tym większych problemów bo mamy pozaznaczane wyjścia jak na zdjęciu powyżej. Pierwsze VCC (plus) ostatnie GND (minus) a dwa środkowe podpinamy od PINów mikrokontrolera. Trig podpinam pod PB0 a Echo pod PB1.

Jak odczytać odległość z czujnika odległości HC-SR04?

Temat jest stosunkowo prosty. Aby odczytać odległość trzeba na wejściu Trig dać sygnał poprzez ustawienie stanu niskiego na 2 mikrosekundy a później stan wysoki na 10 mikrosekund. Wyjście Echo powinno nam odpowiedzieć sygnałem (stan wysoki), którego długość mierzymy i przeliczamy na odległość.

Prędkość dźwięku to 340m/s ale my potrzebujemy wiedzieć ile centymetrów ma odległość oraz będziemy mierzyć długość sygnału w mikrosekundach. Po przeliczeniu prędkość dźwięku wyniesie 0,034cm/us. Wynikałoby z tego że dźwięk na przebycie 1 centymetra potrzebuje 29,41 mikrosekund.

Wiemy także że nasz czujnik wysyła dźwięk, ten dźwięk odbija się od przeszkody i wraca ten sam dystans. Musimy więc policzyć drogę w tę i z powrotem, a więc trzeba pomnożyć razy 2. Z tego wynikałoby że pomiar 1cm trwa ok 58,82 mikrosekund, chyba można zaokrąglić to do 59us.

Zacznijmy od napisania funkcji, która będzie wysyłała sygnał do czujnika. Trig mamy pod PINem PB0 i na ten pin ustawimy sygnał.

void HC_SR04_start(void){
    DDRB |= (1 << PB0); //ustawiam na wyjście
    PORTB &= ~(1 << PB0); //ustawiam stan niski
    _delay_us(2);
    DDRB &= ~(1 << PB0); //ustawiam stan na wysoki
    _delay_us(10);
    PORTB &= ~(1 << PB0); //ustawiam stan niski
}

Następnie można by napisać funkcję, która zmierzy nam dystans i zwróci ilość centymetrów. Czujnik ma zasięc do 4metrów. Ja sobie tutaj zwracam 404 (takiż żart – not found 😛 ). U mnie działa to „jakoś” ale do prostych zastosowań do kilku cm powinno wystarczyć.

uint8_t HC_SR04_getCm(void){
    HC_SR04_start();
    uint8_t cm = 0;
    _delay_us(2290);
    while((PINB & (1 << PB1))){
	cm++;
	_delay_us(59);
	if(cm > 400){
	    return 404;
	}
    }
    return cm;
}

I na koniec prosty programik, który będzie aktualizował co sekundę pomiar i wyświetlał go na ekranie jak na zdjęciu na końcu tego artykułu.

int main(void)
{
    LCD_Setup();
    int timer1 = 0;
    uint8_t cm = 0;
    while(1){
	cm = HC_SR04_getCm();
	timer1++; //Dodaję jeden do timera
	LCD_Clear(); //Czyszcze ekran
	LCD_GotoXY(0, 0); //Ustawiam kursor na początku
	LCD_PrintString("Pomiar:"); //Wypisuję słowo czas na ekranie
	LCD_PrintInteger(timer1); //Dopisuję liczbę w zmiennej timer1
	LCD_GotoXY(0, 1); //przechodzę do pierwszego znaku drugiej linii
	LCD_PrintInteger(cm); //WYświetlam wynik pomiaru
	LCD_PrintString(" cm"); //Wypisuję napis SEPTEM
	_delay_ms(1000); //Czekam sekundę żeby zwiększyć timer
    }
    
    return 0;
}

I na koniec obrazek działającego prototypu na potwierdzenie że u mnie działa.