Skocz do zawartości

Program line follower-a zapamiętywanie lini [c]


Pomocna odpowiedź

Napisano

Witam

Męczę się nad tym kilka godzin i nie mam pojęcia co robię nie tak. Usiłuje napisać program który będzie pamiętał ostatni sygnał z czujników, których jest tylko 2.

Oto program:

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

// *************   definicje dla preprocesora
// dioda LED
#define LED_PIN (1<<PB1)

// mostek H
#define PRAWO (1<<PC4)
#define LEWO (1<<PC5)

// czujniki
#define FOTO1 (1<<PD1)
#define FOTO2 (1<<PD2)

uint8_t foto = 3;
// *************************************************** pętla główna main()
int main(void)
{
// ****** inicjalizacja *********
// mostek H
DDRC |= PRAWO;
DDRC |= LEWO;
PORTC |= PRAWO;
PORTC |= LEWO;

// dioda
DDRB |= LED_PIN;
PORTB &= ~LED_PIN;

// czujniki
DDRD &= ~FOTO1;
DDRD &= ~FOTO2;
PORTD |= FOTO1;
PORTD |= FOTO2;


// ****** pętla główna programu  *********

PORTB |= LED_PIN;

while(1)
{
	_delay_ms(20);
	if(!(PIND & FOTO1)) foto = 1;
	if(!(PIND & FOTO2)) foto = 2;
	if(!(PIND & FOTO2 || PIND & FOTO1)) foto = 3;


	if(foto == 1) PORTC &= ~PRAWO;
	else PORTC |= PRAWO;

	if(foto == 2) PORTC &= ~LEWO;
	else PORTC |= LEWO;

	if(foto == 3) PORTC &= ~PRAWO; PORTC &= ~LEWO;
}
}

Szukałem odpowiedzi na forach, lecz większość programuje w bascom. Nie mogę pojąć czemu ten kod nie działa.

Proszę o pomoc w odnalezieniu błędu. Z góry dzięki.

edit:

Zapomniał bym dodać co nie działa. Otóż po uruchomieniu 2 koła zaczynają się kręcić. Gdy zasłonię ręką jeden dalej kręcą się 2. Gdy zasłonię drugi kręci się jedno koło. Z programem bez pamięci dosłownie na 3 if-ach wszystko działa tak jak powinno.

Jeżeli będziesz miał spełniony pierwszy warunek lub drugi, to automatycznie masz spełniony 3 warunek, więc zmienna foto będzie w takim przypadku zawsze przyjmować wartość 3.

Może zamiast spójnika || daj sumę logiczną &&. Wtedy program będzie mógł przyjmować 3 wartości, w zależności od tego, pod którymi czujnikami jest linia.

Właśnie przeprogramowałem i:

Oba koła się kręcą, a czujniki nie reagują.

Chodziło o to?:

if(!(PIND & FOTO2 && PIND & FOTO1)) foto = 3; 

if(foto == 3) PORTC &= ~PRAWO; PORTC &= ~LEWO;

Warunek w tym przypadku dotyczy chyba 1 instrukcji po nim, czyli: PORTC &= ~LEWO; już się wykona samoczynnie, bez względu na to czy warunek jest prawdziwy czy nie.

edit:

Tak, o to chodziło.

Nie za bardzo rozumiem. Ale wyłączyłem z programu (2 linijki) wszystko co związane z foto = 3. I efekt jest taki: jeśli 1 czujnik zobaczy białą kartkę to odpowiedni silnik się włącza i kręci, jednak jeśli zasłonię 2 czujnik, wtedy 2 koło zakręca się przez ok 1s i stoją oba koła.

[ Dodano: 27-03-2012, 20:57 ]

Nikt nie pomoże? To może jakiś kod?

Może spróbuj bez warunków dla foto = 1 i wyłączaj prawo, jednocześnie włączając lewo i vice versa.

Analogicznie dla if (!(PIND & FOTO2) )

while(1)
   {
       _delay_ms(20);
       if (!(PIND & FOTO1) )
       {
           PORTC &= ~PRAWO;
           PORTC |= LEWO;
       }
       else
       {
           PORTC |= PRAWO;
           PORTC &= ~LEWO;
       }
   }

Dzięki za radę, niezła myśl. Jednak jeśli zrobię tak:

        if (!(PIND & FOTO1) ) 
       { 
           PORTC &= ~PRAWO; 
           PORTC |= LEWO; 
       } 
       else 
       { 
           PORTC |= PRAWO; 
           PORTC &= ~LEWO; 
       } 

wtedy robot nie będzie pamiętał, którym czujnikiem ostanio "widział" linie.

Na podstawie tego warunku wymyśliłem taki kod:

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

// *************   definicje dla preprocesora
// dioda LED
#define LED_PIN (1<<PB1)

// mostek H
#define PRAWO (1<<PC4)
#define LEWO (1<<PC5)

// czujniki
#define FOTO1 (1<<PD1)
#define FOTO2 (1<<PD2)

uint8_t foto;

int main(void)
{
// ****** inicjalizacja *********
// mostek H
DDRC |= PRAWO;
DDRC |= LEWO;
PORTC |= PRAWO;
PORTC |= LEWO;

// dioda
DDRB |= LED_PIN;
PORTB &= ~LED_PIN;

// czujniki
DDRD &= ~FOTO1;
DDRD &= ~FOTO2;
PORTD |= FOTO1;
PORTD |= FOTO2;


PORTB |= LED_PIN;

while(1)
{
	if(!(PIND & FOTO1)) foto = 1;
	if(!(PIND & FOTO2)) foto = 2;


	if(!(PIND & FOTO2 || PIND & FOTO1)) //jeśli oba czujniki = 1
	{
		PORTC &= ~PRAWO;				//włącz oba
		PORTC &= ~LEWO;
	}
	else								// jeśli czujniki = 0
	{
		if(foto = 1)
			{
				PORTC &= ~PRAWO;		//włącz prawy
				PORTC |= LEWO;			//wyłącz lewy
			}
			else						//jeśli foto nie równa się 1
			{
				PORTC |= PRAWO;
				PORTC &= ~LEWO;
			}
	}
}
}

Nie rozumiem tylko, dlaczego po kompilacji jest jeden warning:"suggest parentheses around assignment used as truth value"

Dziś trochę późno, ale jutro wgram program i zobaczymy co z tego wyniknie.

aaa, no tak.

if(foto == 1)

Dzięki.

[ Dodano: 28-03-2012, 14:12 ]

Dziś przetestowałem kod, efekt jest taki:

1.Jeśli zasłonię 1 czujnik na chwilę, zaczyna kręcić się odpowiednie koło i kręci do póki nie zasłonię drugiego. Czyli linie zapamiętuje.

2.Jeśli zaś zasłonię 2 czujnik na chwilę, wtedy drugie koło zaczyna się kręcić i po ok. 2s. przestaje, i zaczyna krecić się pierwsze. (Miało kręcić ciągle)

Co może być nie tak? Wartość zmiennej foto zmienia się sama? Przecierz jej wartość ma zostać zmieniona jeśli któryś czujnik "coś zobaczy". Więc powinno pozostać przy tej wartość, i kręcić kołem aż zmienna zosanie zmieniona.

Bład tkwi chyba w:

if(!(PIND & FOTO2 || PIND & FOTO1)) //jeśli oba czujniki = 1 

Nie wiem jakie ten warunek daje wyniki, ale jeśli ma być prawdziwy dla obu czujników powinna być sprawdzana suma logiczna a nie iloczyn.

Wtedy sprawdzasz, czy !(PIND & 0x3) albo (!(PIND & FOTO1) && !(PIND & FOTO2)).

Sprawdź działania warunku.

To na marginesie, bo jeżeli warunek jest prawidłowy, problem tkwi najpewniej po stronie hardware. Nie napisałeś co to za czujniki, czy oba są zamontoweane na płytce i jaka odległość płytki od podłoża i jak sa testowane. Jeśli czujniki są w złej odległości, mogą "siać" jedynkami będąc nad linią.

Jeśli chodzi o hardware to myślę że jest 100% ok. Sprawdzałem na programie bez zapamiętywania ostatnie lini, i ładnie śmigał. Lecz gdy zakręt był zbyt ostry wypadał z trasy.

Ten warunek maił dawać wynik 1, jeśli oba czujniki widzą białą kartkę. Lecz nie był on chyba do końca przemyślany.

Po przemyśleniu doszedłem do tego że powinno być tak: jeśli oba czujniki widzą kolor biały lub czarny to ma być w if-ie 1 i oba kooła powinny się kręcić. Jeśli jest inaczej to ma spełniać się else. Tylko nie wiem jak to zrealizować w if-ie.

P.S. Czy w pętli programu powinno być jakieś opóźnienie? np.20ms?

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