Skocz do zawartości

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


press2313

Pomocna odpowiedź

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.

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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?

Link do komentarza
Share on other sites

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;
       }
   }
Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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

Link do komentarza
Share on other sites

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?

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.