Skocz do zawartości

Czujnik HC-SR04 - obsługa przez ICP


kiclaw

Pomocna odpowiedź

Witam, otóż mam taki problem, próbuje ogarnąć ten czujnik przez wejście ICP Atmegi32.

Procek jest taktowany 16MHz co daje przerwanie co 0,5uS, czyli wynik w centymetrach to czas_trwania_impulsu/2/58 .

Na chwile obecną spłodziłem taki kod:

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

#define KEY_DOWN !(PINA & (1<<PA1)) //obsługa switcha

void triger(void);
uint8_t licznik_switch=0;

volatile uint16_t PulseWidth; //globalna zmienna licząca szerokośc impulsu


int main()
{

DDRA |= (1<<PA0);	//wyjscie
PORTA &= ~(1<<PA0); //TRIGER

DDRD &= ~(1<<PD6);	//wejscie ECHO
PORTD &= ~(1<<PD6);	//ICP

DDRA &= ~(1<<PA1); // wejscie
PORTA |= (1<<PA1); // uSWITCH

lcd_init();	//inicjalizacja LCD

   TCCR1B |= (1<<ICES1);  /* Zbocze narastające wywoła przerwanie*/
   TCCR1B |= (1<<CS10);   /* preskaler = 1 */
   TIMSK |= (1<<TICIE1);   /* zezwolenie na przerwanie od ICP */

   sei();                 /* globalne zezwolenie na przerwania */

while(1)
{
	lcd_locate(0,0);
	lcd_int(licznik_switch);
	lcd_locate(1,5);
	lcd_int(PulseWidth);
	if(KEY_DOWN)
			{
				_delay_ms(80);
				if(KEY_DOWN)
				{
					lcd_cls(); //czyść LCD
					triger(); //wyzwolenie 10uS na TRIG
					licznik_switch++;//potwierdzenie wyzwolenia na LCD
				}
			}
}//koniec while(1)
}//koniec main
ISR(TIMER1_CAPT_vect)
{
    static uint16_t LastCapture;

    PulseWidth = ICR1 - LastCapture;
    LastCapture = ICR1;

    TCCR1B &= ~(1<<ICES1); //zbocze malejące wywoła przerwanie
}


void triger(void)
{
	PORTA &= ~(1<<PA0);
	_delay_us(2);
	PORTA |= (1<<PA0); //wystawienie jedynki na TRIG
	_delay_us(10);		//wymagane 10 uS stanu wysokiego
	PORTA &= ~(1<<PA0);	//wystawienie zera na TRIG
}

Problem w tym, że na LCD pokazuje mi cały czas przypadkowe wartości. Nawet gdy podłącze ICP do wyjście PA0 (gdzie podaje 10uS stanu wysokiego dla TRIG) to i tak mam te przypadkowe wartości co dowodzi że problem leży w programie a nie czujniku. Przeglądałem post kolegi Sokolsok w którym opisuje obsługę tych czujników ale nie dla ICP.

Walczę już z tym problemem od 2 dni próbując różnych sposobów, ale zawsze kiszka.

Link do komentarza
Share on other sites

Dziwne, przy 16Mhz na jedną us przypada 16 taktów zegara wiec na 0.5 us jest ich ledwie 8. Natomiast ciężko będzie zmieścić same operacje jakie wykonujesz w przerwaniu w tych 8 taktach nie mówiąc już o wprowadzeniu i wyjściu z funkcji obsługującej przerwania.

Link do komentarza
Share on other sites

No na chwilę obecną czujniczek działa, ale liczy tylko i wyłącznie do 14cm. Wyżej nie chce iść. Czy może być to problem z czujnikiem czy jeszcze jednak z programem?

Poniżej kod:

/*
* main.c
*
*  Created on: 2012-12-03
*      Author: Michał
*/

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

#define KEY_DOWN !(PINA & (1<<PA1))

void triger(void);
uint8_t licznik_switch=0;

volatile uint16_t PulseWidth;


int main()
{

DDRA |= (1<<PA0);	//wyjscie
PORTA &= ~(1<<PA0); //TRIGER

DDRD &= ~(1<<PD6);	//wejscie ECHO
PORTD &= ~(1<<PD6);	//ICP

DDRA &= ~(1<<PA1); // wejscie
PORTA |= (1<<PA1); // uSWITCH

lcd_init();

   TCCR1B |= (1<<ICES1);  /* Zbocze narastające wywoła przerwanie*/
   TCCR1B |= (1<<CS11);   /* preskaler = 8 */
   TCCR1B |= (1<<ICNC1); //NOISE CANCELLER
   TIMSK |=  (1<<TICIE1);   /* zezwolenie na przerwanie od ICP */

   sei();                 /* globalne zezwolenie na przerwania */

while(1)
{
	lcd_locate(0,0);
	lcd_int(licznik_switch);
	lcd_locate(1,5);
	lcd_int(PulseWidth);
	if(KEY_DOWN)
			{
				_delay_ms(80);
				if(KEY_DOWN)
				{
					lcd_cls();
					triger(); //wyzwolenie
					licznik_switch++;//potwierdzenie wyzwolenia na LCD
				}
			}
}//koniec while(1)


}//koniec main
ISR(TIMER1_CAPT_vect)
{
   static uint16_t LastCapture;

   if( !(TCCR1B & (1<<ICES1)) ) PulseWidth = ICR1 - LastCapture;
   LastCapture = ICR1;

   TCCR1B ^= (1<<ICES1); //zmiana zbocza
}

void triger(void)
{
	PORTA &= ~(1<<PA0);
	_delay_us(2);
	PORTA |= (1<<PA0); //wystawienie jedynki na TRIG
	_delay_us(10);		//wymagane 10 uS stanu wysokiego
	PORTA &= ~(1<<PA0);	//wystawienie zera na TRIG
}
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.