Skocz do zawartości

Ultradźwiękowy czujnik odległości do robota


Pomocna odpowiedź

A może zakłócenia? Jak całkowicie zakryjesz odbiornik to jest nadal to samo?

Niestety to samo. Wydaje mi się, że powinienem coś jeszcze zmienić w programie i że sama zmian pinów AIN0 i AIN1 nie wystarczy być może ktoś kto się zna na C coś mi podpowie. Co do nadajnika nie posiadam oscyloskopu aby sprawdzić czy nadaje 40KHz ( na pewno coś nadaje bo w jego miejsce podłączyłem piezo i było słychać brzęczenie).

Skoro byłeś w stanie usłyszeć to brzęczenie, to zapewne nie było to 40kHz. Jakie masz taktowanie uC, a jakie masz zapisane w programie?

Armir, to najwyraźniej masz źle zestrojony nadajnik, u osób bardzo młodych granica słyszalności to 20kHz (u dorosłej osoby 16kHz), więc nie ma opcji, żebyś to słyszał 🙂 Sprawdź jakimś miernikiem częstotliwości/analizatorem stanów log/oscyloskopem częstotliwość na nadajniku, jeśli to ten z Zenona, to może to jest przyczyną jego mikroskopijnego zasięgu (na przetwornikach 10mm uzyskałem 1,5m zasięgu na nadajniku na ne555 (dobrze dostrojonym do 40kHz) i odbiorniku jak tu: http://users.encs.concordia.ca/~dave/project/elec.html#Obstacle%20detection%20sensor lub jak tu: http://letsmakerobots.com/node/7582 , teraz nie pamiętam. Inna opcja, że może po prostu coś wpada w wibracje w tym twoim nadajniku, dlatego brzęczy (ja jak miałem słabo zestrojony nadajnik, to ewentualnie było słychać baaardzo cieniutki pisk, było to koło 16-18kHz).

Skoro byłeś w stanie usłyszeć to brzęczenie, to zapewne nie było to 40kHz. Jakie masz taktowanie uC, a jakie masz zapisane w programie?

Więc tak taktowanie mam albo 1MHz ( bo z tego co zrozumiałem ustawienie fabrycznego fusebitu lfuse na E1 spowoduje wykorzystanie wewnętrznego rezonatora 1MHz atmegi32 ) czyli wydaje mi się że dostosowane do programu:

wycinek z sonar.h:

#define CYCLES_PER_US ((1000000+500000)/1000000)

void delay(unsigned int us)
{
unsigned int delay_loops;
register unsigned int i;
delay_loops=((us+3)/5*CYCLES_PER_US)*10;
for(i=0;i<delay_loops;i++){};
}

próbowałem też na 16MHz ( w kodzie wyżej wszystkie 1000000 zamieniłem na 1600000) ale też nie działało) zresztą nie bardzo rozumiem skąd to 500000?

__________

Komentarz dodany przez: Nawyk

Używaj znaczników [ code] i [ /code] - lepiej się czyta

Ja mam takie pytanie związane z schematem z pierwszego postu. Oba czujniki są podłączone do 2 wyprowadzeń CPU, to jak tym sterujesz? Tzn. w nadajniku co jeden pin zwierasz do masy, a na drugim generujesz częstotliwość ? A w odbiorniku to już w ogóle nie mam pomysłu jak, bo nie wiem jeden pin do plusa na drugim dokonujesz porównania czy co ?

Z tego co zauważyłem to na piny gdzie jest nadajnik jest wysyłany sygnał o częstotliwości 40kHz.

Odbiornik jest zrobiony bardzo prosto - jest podpięty do komparatora analogowego.

Pytam bo w przyszłym tygodniu jak dobrze pójdzie będę miał przetworniki do testów więc jestem ciekaw.

Tzn. nadajnikiem specjalnie się nie przejmuję, bo to akurat nie jest żaden problem, wygenerowanie 40KHz z CPU też, bo to tylko ustawienie odpowiednio Timera i po robocie.

Bardziej chodzi mi o ten odbiornik, bo jak mnie pamięć nie myli to wejścia w trybie analogowym wiszą w powietrzu, więc chyba trzeba jakoś spolaryzować ten odbiornik choćby jedną końcówką do masy.

Ponieważ niektórzy mają problem z uzyskaniem 40KHz to oto wycinek mojego programu z którego widać jak łatwo za pomocą Timera uzyskać dokładnie 40KHz, wstawiając do komparatora odpowiednią wartość. Może się komu przyda. W komentarzach są podane dokładne częstotliwości jakie się uzyska.

PS. wycinek w programu pilota IR.

'Plik definicji stałych systemowych

'Stałe dla generatora częstotliwosci nośnych
'Dla preskalera = 0, FCPU = 2MHz
Const 33k_2m = 30             '33,333Khz
Const 36k_2m = 28             '35,714Khz
Const 36k7_2m = 27            '37,037Khz
Const 38k_2m = 26             '38,461Khz
Const 40k_2m = 25             '40,000Khz
Const 56k_2m = 18             '55,555Khz
'Dla preskaler = 0, FCPU = 4MHz
Const 33k_4m = 60             '33,333Khz
Const 36k_4m = 55             '36,363Khz
Const 36k7_4m = 54            '37,037Khz
Const 38k_4m = 53             '37,735Khz
Const 40k_4m = 50             '40,00Khz
Const 56k_4m = 36             '55,555Khz
'Dla prescaler = 0, FCPU = 8MHz
Const 33k_8m = 121            '33,057Khz
Const 36k_8m = 111            '36,036KHz
Const 36k7_8m = 109           '36,697Khz
Const 38k_8m = 105            '38,095Khz
Const 40k_8m = 100            '40,000Khz
Const 56k_8m = 71             '56,338Khz
  • 1 miesiąc później...

Witam,

dzisiaj zbudowałem na płytce uniwersalnej podobny układ. uC to ATMega16 z taktowaniem 16MHz. Projekt trochę okroiłem do podstawowej funkcji samego sonaru. Przy portowaniu z amtegi8 na atmege16 prawdopodobnie coś zrobiłem źle. Zależy mi na uzyskaniu dodatniej wartości w zmiennej odleglosc. Jakie mogę mieć błędy? Może jakieś wskazówki?

Odbiornik mam podłączony do PB2 i PB3. Nadajnik do PA6 i PA7. Na PC4 mam diodę sygnalizującą wykrycie obiektu.

Tutaj zamieszczam kod sonar.c

#define F_CPU 16000000L
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include "sonar.h"

int odleglosc=0;


int sygnal(void)			// procedura wysyłania paczki ultradźwięków
{
int echo=0;			// zmienna do bliczenia powrotu ultradźwięków
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();
sinus_40_khz();

// teraz trzeba wytłumić drgania przetwornika zwierając go do masy
PORTA &= ~(1<<PA6);
PORTA &= ~(1<<PA7);
_delay_us(1);//	delay(8);

// przetwornik wejściowy też zwieramy do masy w celu wytłumienia
DDRB |= (1<<PB2);
PORTB &= (1<<PB2);
_delay_us(1);//	delay(8);

DDRB &= ~(1<<PB2);					// no i można go włączyć

for(echo=0;echo<300;echo++)	// i czekać na odbite dźwięki
{
	if(bit_is_set(ACSR,ACO))	// jeżeli bit ACO rejestru ACSR ustawiony
	{
		break;					// to przerwij
	}
}
return echo;					// zwróć wartość zmiennej
}

void sinus_40_khz(void)			// procedura sygnału 40kHz
{
DDRA |= (1<<PA6);PORTA |= (1<<PA6);
DDRA |= (1<<PA7);PORTA &= ~(1<<PA7);

asm volatile("WDR"::);		//watchdog reset, czyli nic nie rób.
asm volatile("WDR"::);
asm volatile("WDR"::);
asm volatile("WDR"::);

PORTA &= ~(1<<PA6);
PORTA |= (1<<PA7);

asm volatile("WDR"::);
asm volatile("WDR"::);
}
void Wynik(void)
{
if (odleglosc > 0) {
	PORTC &= ~(1<<PC4); // zapal LED
} else {
	PORTC |= (1<<PC4); // zgas LED
}
}


int main(void)
{

DDRC |= (1<<PC4); // dioda LED

DDRB |= (1<<PB3);   // odbiornik
PORTB &= ~(1<<PB3);  

TIMSK |= (1<<TOIE0);  // ustawienia komparatora analogowego

for(;;) {
	odleglosc=sygnal();
	Wynik();
}
return(0);
}

Jeszcze pytanie: Czy mogę zrezygnować z funkcji delay(), która jest w sonar.h, na rzecz _delay_us()? Jeśli nie to jak ustawić stałą CYCLES_PER_US? Czy tak jest poprawnie?

#define CYCLES_PER_US ((F_CPU+500000)/1000000)

Dziękuję za pomoc 🙂

Możesz zrezygnować z funkcji delay i zastąpić ją jakąś swoją funkcją która zajmuje tyle samo czasu.

Jest ona używana tylko do wytłumienia odbiornika na czas 1us.

Na innej częstotliwości Ci nie działa ponieważ procedura sinus_40khz jest napisana dość "niefachowo".

Musisz wydłużyć czas pomiędzy ustawianiem 1 a 0 na pinach nadajnika. Czyli ten zestaw

asm volatile("WDR"::);

wydłużyć o tyle o ile masz szybszy kwarc. Czyli w tym przypadku bodajże razy 16. Idąc tym tropem możesz zrobić swoją funkcję delay tak samo;)

 asm volatile("WDR"::);

napisz szesnaście razy ciurkiem i będziesz miał opóźnienie 1us;) oczywiście to taki partyzancki sposób.

@PiotrekEl: Niestety dalej nie działa. Zrobiłem dalay tak jak mówiłeś. Problem, myślę, że nadal jest w generowaniu 40kHz. Próbowałem takiego rozwiązania: Czyli razy 16 WDR, przy czym na wyjście i przejście do następnego wysyłania sinusa -2 WDR.

void sinus_40_khz(void)			// procedura sygnału 40kHz
{
DDRA |= (1<<PA6);PORTA |= (1<<PA6);
DDRA |= (1<<PA7);PORTA &= ~(1<<PA7);

asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);

PORTA &= ~(1<<PA6);
PORTA |= (1<<PA7);

asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);asm volatile("WDR"::);
asm volatile("WDR"::);asm volatile("WDR"::);

}

Niestety, nie posiadam dostępu do oscylatora, żeby sprawdzić czy generuję 40kHz. Podłączyłem diodę dwukolorową (2 piny) i stale jest i czerwona i zielona, więc bardzo szybko zmienia kolory.

Jeśli nie tak to jak inaczej można to rozwiązać nie angażując timerów? (wszystkie mam zajęte)

Dzięki za wszelkie wskazówki.

Strasznie to wygląda;)

W pierwszym zestawie powinno być 16 linijek po 4 a masz 15;) w drugim 16 x 2 a masz dwa razy tyle.

I jeszcze jednej rzeczy nie jestem pewien. Czy aby znak średnika ; nie powoduje że reszta linijki jest ignorowana? Szczerze to już dość dawno nie miałem styczności z WinAVR i nawet nie mam zainstalowanego więc niewiele mogę pomóc.

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