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

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.