Skocz do zawartości

Czujnik odległości HC-04, problem z przerwaniami.


komabra

Pomocna odpowiedź

Cześć. Kupiłem czujnik odległości i od razu chciałem go sprawdzić. Jego obsługa wydaje się banalnie prosta, pewnie większość z was ją zna więc nie będę opisywał.

Sens polega na tym, że program nie działa tak jak powinien.

Sprawdzając oddzielnie timer, przerwania oraz czy na ECHO pojawia się stan wysoki to działa wszystko. Jednak,gdy chcę zmierzyć długość impulsu z pinu ECHO to nie bangla.

Program działa tak, że :

czekaj, aż na ECHO będzie stan wysoki.

impuls co 0,000064 sekundy.

licznik zaczyna od 240 a więc przerwanie pojawia się co 16*0,000064 = 1 ms.

Wraz z przerwaniem inkrementuje się zmienna index.

Wyłącz przerwania globalne, gdy ECHO = 0.

Wyświetl miganiem diody zmienną index.

Niestety program nie działa jak należy, a ja już tracę pomysły.

/*
* main.c
*
*  Created on: 23 sty 2016
*      Author: hhjh
*/


#include<avr/io.h>
#include<util/delay.h>
#include<stdio.h>
#include<avr/interrupt.h>

#define ECHO PD6
#define TRIG PD7

void HC_initialize(void);
void Timer_initialize(void);
void HC_readValue(void);

volatile int index=0; //liczenie przerwań od przepelnienia timera0


int main (void){
DDRD |=(1<<PD0);  // LED jako wyjscie
PORTD&=~(1<<PD0);  // ze stanem 0 V

Timer_initialize();
HC_initialize();
while(!PIND & (1<<ECHO));  //czekaj az stan na ECHO nie bedzie 1
sei();                     // wlacz przerwania globalne
while(PIND & (1<<ECHO));   // rob dopoki stan na ECHO bedzie 1
cli();                     // gdy stan na ECHO bedzie 0 wyłącz przerwania
HC_readValue();            // sczytaj miganiem diody ilośc przerwan
}


void HC_initialize(void){

//ustaw we.wy
DDRD |= (1<<TRIG);  //TRIG jako wyjscie
DDRD &=~(1<<ECHO);  //ECHO jako wejscie
PORTD&=~(1<<ECHO);

// wyslij sygnał 10us na TRIG
PORTD |=(1<<TRIG);
_delay_us(15);
PORTD &=~(1<<TRIG);
}


void Timer_initialize(void){
TCCR0 |=(1<<CS01)|(1<CS00);  // prescaler 64 , impuls co 0.000064 s
TIMSK |=(1<<TOIE0); // interrput enable
TCNT0 = 240;        // wartosc poczatkowa
}

void HC_readValue(void){
int i=0;
for(i=0; i<index; i++){
	PORTD |=(1<<PD0);
	_delay_ms(1000);
	PORTD&=~(1<<PD0);
	_delay_ms(1000);
}
}


ISR(TIMER0_OVF_vect){
index ++;
TCNT0 = 240;
}
Link do komentarza
Share on other sites

Co to znaczy, że program nie działa? Wyniki są złe, nie daje ich wcale, nie generuje impulsów?

Gdzie zerujesz zmienną index przed każdym nowym pomiarem?

Po co używasz programowego licznika index inkrementowanego w przerwaniu, skoro i tak marnujesz czas przez cały pomiar w pętli aktywnego oczekiwania na koniec impulsu echa?

A to nie prościej ustawić timer na zliczanie z prescalerem 1/256 (masz wtedy tick=256us), wyzerować go, poczekać na start impulsu, odpalić zliczanie (albo wtedy wyzerować już pracujący timer), poczekać na koniec impulsu, zatrzymać timer (niekoniecznie) i go odczytać? Przy 8 bitach licznika masz wtedy pojemność ponad 65ms a to spokojnie wystarcza do obsłużenia tego czujnika z rozdzielczością 1/4ms czyli jakieś 4cm.

Poza tym do zgłaszania przerwań okresowych timer ma tryb CTC (tabelka "Waveform Generation Mode Bit Description") w którym wpisujesz do rejestru OCR0A długość okresu -1. Teraz masz tak, że jeśli troszkę spóźnisz się z przeładowaniem wartości 240 w przerwaniu, timer "zgubi" jeden impuls taktujący i kaszana. Korzystaj ze sprzętu który kupiłeś.

Podoba mi się wyjście tego systemu: diodka LED i mozolne zliczanie mrugnięć. Może trzeba było zrobić chociaż dłuższe (x10) i krótsze (x1) mignięcia? Wtedy --- --- --- - - oznaczałoby 32 bez czekania ponad minuty na wynik 🙂

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.