Skocz do zawarto艣ci
programek

Line Followe - problem z programem

Pomocna odpowied藕

Witam wszystkich 馃槈

Jest to m贸j pierwszy post na tym forum.

Od jakiego艣 czasu pr贸buje zaprogramowa膰 robota ( line follower )

Tu jest schemat i pcb:

Napisa艂em taki program:

main.c

/*
* main.c
*
*  Created on: 30 sty 2015
*      Author: Dominik
*/


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

#include "LCD/lcd44780.h"
#include "ADC/adc.h"

#define IN1 (1<<PC6)
#define IN2 (1<<PC7)
#define IN3 (1<<PC5)
#define IN4 (1<<PC4)

#define MUX_A (1<<PA1)
#define MUX_B (1<<PA0)

#define SET_A PORTA |= MUX_A
#define CLR_A PORTA &= ~ MUX_A;

#define SET_B PORTA |= MUX_B
#define CLR_B PORTA &= ~ MUX_B;

#define MUX_X (1<<PA3)
#define MUX_Y (1<<PA2)

//#define KEY (1<<PC3)
#define linia 850

void silnik_L ( uint8_t kierunek, uint8_t predkosc );
void silnik_R ( uint8_t kierunek, uint8_t predkosc );

void pomiar_czujnik ( uint8_t czujnik );
void napiecie_lipol ( void );

uint16_t wynik=0;
uint8_t predkosc = 45;

int main(void) {

//	PORTC |= KEY;  // podci膮gamy klawisz do VCC

DDRC |= IN1| IN2 | IN3 | IN4;  // wyjscia do sterowania silnikami
DDRD |= (1<<PD4) | (1<<PD5);  // wyjscia PWM

DDRA |= MUX_A | MUX_B;  // wejscia adresowe ( multiplekser ) - jako wyjscia


lcd_init();  // inicjalizaja lcd
lcd_cls();

lcd_str("start...");
_delay_ms(500);

// inicjalizacja ADC
ADCSRA |= (1<<ADEN); // w艂膮cz ADC
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // preskaler = 128
ADMUX |= REF_VCC;	// ustawiamy wewn. 藕r odn. VCC


   // ustawienia TIMER1 w Fast PWM
   TCCR1A |= (1<<WGM10)|(1<<WGM11);                // Fast PWM 10-bitowy
   TCCR1B |= (1<<WGM12);                   // Fast PWM 10-bitowy
   TCCR1A |= (1<<COM1B1)|(1<<COM1A1);	 		// OC1A,OC1B  are cleared on TOP
   TCCR1B |= (1<<CS10);   				// preskaler = 1


accu1_vol.ref_adc = 780;	// zmierzona warto艣膰 ADC  ( 7,42 V )
accu1_vol.ref_v = 742;		// warto艣膰 mierzonego napi臋cia  ( 7,42 V )

napiecie_lipol();     // sprawdzanie napiecia akumulatora

_delay_ms ( 2000 );
lcd_cls();

uint8_t zmienna;
uint8_t wartosc;
float aktualna_pozycja;
float roznica = 0;

   while(1)
   {

   	zmienna = 0;
   	wartosc = 0;
   	aktualna_pozycja=0;
   	roznica=0;

   	for( uint8_t i = 1; i <10; i++ )
   	{
   		pomiar_czujnik(i);
   		if ( (linia-100) < wynik && wynik < (linia + 100) )
   		{
   			zmienna++;
   			wartosc += i;
   		}
   	}


   	aktualna_pozycja = wartosc / zmienna;
   	if(aktualna_pozycja>20)aktualna_pozycja=0; // gdy wsszystkie czujniki sa nad biala
   	roznica = (4.5 - aktualna_pozycja) * 12;       // powierzchnia to zmienna aktualna poz. 
                                                                            //ma wartosc 255 wiec ja zeruje
   	if(aktualna_pozycja==0) roznica = 0;

       silnik_L(0,predkosc-roznica);
       silnik_R(0,predkosc+roznica);

   }
}


/*
*  przod => kierunek = 0
*  tyl => kierunek = 1
*
*  predkosc w %
*/
void silnik_L ( uint8_t kierunek, uint8_t predkosc )
{
if ( kierunek == 0 )
{
	PORTC |= IN3;
	PORTC &= ~IN4;
}
else if ( kierunek == 1 )
{
	PORTC |= IN4;
	PORTC &= ~IN3;
}

OCR1A = (1023 / 100) * predkosc;
}

void silnik_R ( uint8_t kierunek, uint8_t predkosc )
{
if ( kierunek == 0 )
{
	PORTC |= IN2;
	PORTC &= ~IN1;
}
else if ( kierunek == 1 )
{
	PORTC |= IN1;
	PORTC &= ~IN2;
}

OCR1B = (1023 / 100) * predkosc;
}

void pomiar_czujnik ( uint8_t czujnik )
{
switch ( czujnik )
{
	case 1: CLR_A; SET_B; break;  //
	case 2: CLR_A; CLR_B; break;  //
	case 3: SET_A; SET_B; break;  //  Y
	case 4: SET_A; CLR_B; break;  //

	case 5: CLR_A; SET_B; break;  //
	case 6: SET_A; CLR_B; break;  //  X
	case 7: CLR_A; CLR_B; break;  //
	case 8: SET_A; SET_B; break;  //
}

_delay_ms(1);

wynik=0;

if ( czujnik > 0 && czujnik < 5 ) wynik = pomiar( PA2 ); // dokonujemy pomiaru na PA2
if ( czujnik > 4 && czujnik < 9 ) wynik = pomiar( PA3 ); // dokonujemy pomiaru na PA3

}

void napiecie_lipol ( void )
{
uint16_t wynik=0;

lcd_locate(0,0);
lcd_str("Napiecie");

wynik = pomiar( PA7 );		// dokonujemy pomiaru na kanale PA7
get_vol( wynik, &accu1_vol );	// zamiana ADC na napi臋cie

lcd_locate(1,1);

lcd_str( accu1_vol.v1 );	// jednostki i dziesi膮tki zmierzonego napi臋cia
lcd_str( "." );
lcd_str( accu1_vol.v2 );	// cz臋艣膰 u艂amkowa zmierzonego napi臋cia
lcd_str( " V       ");
}

adc.c

/*
* adc.c
*
*  Created on: 9 lut 2015
*      Author: Dominik
*/


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

#include "adc.h"

uint16_t min=1024, max, diff;

// pomiar napi臋cia
uint16_t pomiar( uint8_t kanal ) {

ADMUX = (ADMUX & 0b11111000) | kanal;

ADCSRA |= (1<<ADSC);  // start konwersji

while( ADCSRA & (1<<ADSC) );

return ADCW;
}


// zamiana ADC na napi臋cie
void get_vol( uint16_t adc, TVOL * voltage ) {


voltage->adc_mid = adc;

uint16_t wynik = ( adc * (uint32_t)voltage->ref_v ) / voltage->ref_adc;

div_t divmod = div(wynik, 100);
itoa( divmod.quot, voltage->v1, 10 );
itoa( divmod.rem, voltage->v2, 10);

if( divmod.rem < 10 ) {
	voltage->v2[0]='0';
	voltage->v2[1]=divmod.rem+'0';
}

voltage->v1[2]=0;
voltage->v2[2]=0;
}

adc.h

/*
* adc.h
*
*  Created on: 9 lut 2015
*      Author: Dominik
*/

#ifndef ADC_ADC_H_
#define ADC_ADC_H_

// definicje bit贸w odpowiedzialnych za wyb贸r 藕r贸d艂a odniesienia
#define REF_256 (1<<REFS1)|(1<<REFS0)
#define REF_VCC (1<<REFS0)

// typ strukturalny na potrzeby przeliczania napi臋膰 z ADC do string贸w
// v1 - cz臋艣膰 przed przecinkiem
// v2 - cz臋艣膰 po przecinku
typedef struct {
uint16_t adc_mid;	// u艣redniona warto艣膰 ADC
uint16_t ref_adc;	// 艣rodkowy zakres warto艣ci ADC odpowiadaj膮cej zmierzonemu ni偶ej napi臋ciu
uint16_t ref_v;		// 艣rodkowy zakres napi臋cia * 100 (czyli np dla 6,5V ---> 650)
char v1[3];
char v2[3];
} TVOL;

TVOL accu1_vol;

uint16_t pomiar( uint8_t kanal );
void get_vol( uint16_t adc, TVOL * voltage );

#endif /* ADC_ADC_H_ */

Wgra艂em kod do robota, ustawi艂em na trasie. Robot przeje偶d偶a 1 lub 3/4 okr膮偶enia :/

Nie wiem czy za wolno dokonje pomiar贸w, czy za s艂abo reaguje na moment gdy robot zaczyna zje偶d偶a膰 z trasy.

Prosz臋 o pomoc....

Tak jak pisa艂em, siedz臋 ju偶 kilka dni nad kodem i nic mi nie wychodzi.

Tu jest filmik jak to dzia艂a:

https://www.youtube.com/watch?v=YD71L31Z6So&feature=youtu.be

Z g贸ry dzi臋ki za pomoc 馃槈

Udost臋pnij ten post


Link to post
Share on other sites

Dwie moje uwagi:

1. Ma艂a...

W pomiar_czujnik masz delay_ms(1), co powoduje, 偶e automatycznie tracisz kilka ms. Postaraj si臋 to zoptyamlizowa膰 chocia偶by u偶ywaj膮c delay_us(500)... dodatkowo w p臋tli g艂贸wnej mierzysz od i=1 do i<10... czyli 1,2,3,4,5,6,7,8,9... a masz 8 czujnik贸w?

Zmniejszaj膮c delay zmniejszysz czas wykonywania ka偶dego cyklu i tym samym zwi臋kszy si臋 pr臋dko艣膰 reakcji robota na zmian臋 kierunku linii.

2. Du偶a

Twoja g艂贸wna p臋tla:

while(1)
   {

       zmienna = 0;
       wartosc = 0;
       aktualna_pozycja=0;
       roznica=0;

       for( uint8_t i = 1; i <10; i++ )
       {
           pomiar_czujnik(i);
           if ( (linia-100) < wynik && wynik < (linia + 100) )
           {
               zmienna++;
               wartosc += i;
           }
       }


       aktualna_pozycja = wartosc / zmienna;
       if(aktualna_pozycja>20)aktualna_pozycja=0; // gdy wsszystkie czujniki sa nad biala
       roznica = (4.5 - aktualna_pozycja) * 12;       // powierzchnia to zmienna aktualna poz.
                                                                            //ma wartosc 255 wiec ja zeruje
       if(aktualna_pozycja==0) roznica = 0;

       silnik_L(0,predkosc-roznica);
       silnik_R(0,predkosc+roznica);

   } 

Powoduje, 偶e jak nie widzisz linii to jedziesz prosto.

Jak nie ma linii (zmienna = 0) powiniene艣 zachowa膰 kierunek jazdy (czyli jak ostatnio skr臋cali艣my w prawo to nadal tam skr臋camy, bo tam uciek艂a linia).

Najpro艣ciej to zrobi膰 zmieniaj膮c jedn膮 lini臋:

aktualna_pozycja = wartosc / zmienna;

na

if (zmienna>0) aktualna_pozycja = wartosc / zmienna;
  • Pomog艂e艣! 1

Udost臋pnij ten post


Link to post
Share on other sites

Czesc, gratulacje konstrukcji, wazne, ze wszystkie peryferia Ci dzialaja. Co do zachowania Twojego robota, moim zdaniem problem lezy w przestrzelaniu zakretow. Chodzi dokladnie to, ze robot zachowuje sie przewidywalnie, pod warunkiem, ze nie wylecial czujnikami poza linie(zaden czujnik nie widzi lini). Dlatego powinines dodac do kodu, zapamietywanie, po ktorej stronie znajdowal sie robot po wyleceniu z lini.

Tutaj tak naprawde jest problem, ktory pojawil sie juz w fazie projektowania. Czujniki masz rozmieszczone w formie linijki. Zatem jedyna droga do poprawnego odczytu ostatnio przestrzelonego zakretu, to zapamietanie skrajnych czujnikow. W swoim MacLinerze2.0 mialem ten sam problem. Pomysly mialem trzy:

*implementujac regulator PD, mamy informacje w postaci zmiennej o nazwie np. "Uchyb"- czyli przechowuje tam wartosc, ktora jest odlegloscia od czujnika srodkowego(Uchyb=0-aktulana_pozycja), czujniki mialy wartosc od -9 do +9. Kiedy czujniki znajdowaly sie poza linia(robot przestrzelil zakret), to sprawdzalem jaka byla wartosc uchybu przed przestrzeleniem. Jesli ujemna skrec w lewo, jesli dodatnia to w prawo, jesli blad rowny byl wartosci zero, to oznaczalo, ze mamy przerwe w trasie(jedna z przeszkod w LF z przeszkodami). W taki sposob robot calkiem dobrze robot sobie radzil. Niestety byly takie ulozenia robota/trasy, ze blad wydzodzil 0, mimo, ze byl zakret i robot wypadajac jechal prosto, zamiast podjac manewr powrotu na linie.

*Kolejny pomysl- zaczne sprawdzac skrajne czujniki. Polegalo na tym, ze w kazdym obiegu petli do zmiennych dawalem odpowiednia informacje o stanie czujnika lewego i prawego. Pomysl fajny i ciekawy, ale powyzej jakiejs predkosci program mi sie nie wyrabial no i klopot, byc moze klopot lezal po stronie oswietlenia.

*Tutaj mamy rozwiazanie eliminujace ten klopot w sposob hardware'owy. Zamiast bawiac sie programem, wystarczy linijke czujnikow ulozyc po okregu. Genialny pomysl! Wszystko nagle zaczyna dzialac, za kazdym razem kiedy robot wypada z trasy, ostatnim rzecza jaka robot "zobaczy" to wlasnie ktorys ze skrajnych czujnikow. Ze wzgledu, ze ja musialem dolutowac na kynar skrajne czujniki, bo plytke mialem juz zrobiona, to czasem w najgorszych momentach (finaly 馃構), skrajne czujniki przestawaly dzialac 馃槂.

Powodzenia z robotem, daj znac co zamierzasz 馃槈

Wybaczcie, ale mam angielskiego linuxa 馃檨, za bledy jesli sie pojawily takze przepraszam.

  • Pomog艂e艣! 1

Udost臋pnij ten post


Link to post
Share on other sites

Ewentualnie ze swojej strony sprawdzi艂bym czy pr贸g wykrywania linii jest wystarczaj膮co 'ostry' czy stabilny. W sensie czy nie masz sytuacji takiej, 偶e kt贸ry艣 z czujnik贸w jest nad lini膮, a robot my艣li, 偶e nie jest ze wzgl臋du na b艂臋dny pr贸g.

I taki pomys艂 na interpolacj臋 i sztuczne zwi臋kszenie rozdzielczo艣ci, stosowane m. in. w 2pi lub ARJ Grabo:

1. Normalizacja odczyt贸w ADC czujnik贸w - nie widzi linii 0, widzi lini臋 1024 (lub inna liczba, wa偶ne, 偶eby by艂 to odczyt z ADC, ze stanami po艣rednimi). Najpro艣ciej po uruchomieniu robota obr贸ci膰 si臋 o 90* (tak, by na pewno wszystkie czujniki by艂y poza lini膮), zrobi膰 odczyty i odj膮膰 t臋 warto艣膰 od normalnego pomiaru (trzeba te偶 zrobi膰 zabezpieczenie, 偶eby nie przejecha膰 na warto艣ci ujemne, ani wi臋ksze od 1024 - 2 ify).

2. Liczenie pozycji - w zasadzie tylko 艣rednia wa偶ona. Otrzymamy wtedy dok艂adn膮 pozycj臋 nad lini膮, z rozdzielczo艣ci膮 du偶o wi臋ksz膮, ni偶 tylko 8 progowanych czujnik贸w - od -512 do +512.

#define SENSORS_NUMBER 8 //ilosc czujnikow

int scale[SENSORS_NUMBER]; //nie odwolujemy sie bezposrednio, HERMETYZACJA
int sensor[SENSORS_NUMBER]; //nie odwolujemy sie bezposrednio, HERMETYZACJA


/*funkcje zewnetrzne - musisz je sam napisac i zainclude'owac - dlatego extern (od external ;) )*/
extern void scaleInit(); //funkcja inicjalizuj膮ca tablic臋 wag konkretnymi wagami
extern int getNormalized(int channel); //funkcja zwracaj膮ca znormalizowan膮 (patrz post) warto艣膰 czujnika

/*funkcje w tym  pliku, tylko deklaracje w tym miejscu, zeby bylo czytelniej*/
void initScale(); //TO WYWOLAC!!!
void getSensorTab() //funkcja wypelniajaca tablice czujnikow wartosciami (nie uzywamy jej, HERMETYZACJA)
int getError();	//funkcja liczaca blad (nie uzywamy jej, HERMETYZACJA)
int getPosition(); //funkcja najpierw pobierajaca odczyty z czujnikow i liczaca pozycje (kat) nad linia (TEJ UZYWAMY)


/*definicje*/
void initScale(){ //skaluje od -512 do 512
int i;
for(i=0;i<SENSORS_NUMBER;i++){
	scale[i]=(i-(SENSORS_NUMBER/2))*1024/SENSORS_NUMBER;	
}
}
void getSensorTab(){
int i;	
for(i=0;i<SENSORS_NUMBER;i++){
	sensor[i]=getNormalized(i);
}
}

int getError(){
int i,error_up, error_down; //up - licznik, down - mianownik
for(i=0;i<SENSORS_NUMBER;i++){
	error_up+=sensor[i]*scale[i];
	error_down+=sensor[i];
}
return error_up/error_down;
}

int getPosition(){
getSensorTab();
return getError();
}

Musisz doda膰 swoje funkcje oznaczone jako extern. Mo偶e nie b臋dzie to na 100% rozwi膮zanie Twojego problemu, ale my艣l臋, 偶e opcja warta zastanowienia - odpada problem progowania.

Udost臋pnij ten post


Link to post
Share on other sites

Jak na razie to w programie zmieni艂em tylko tego delay'a, poprawi艂em p臋tl臋 for i zamieni艂em to:

aktualna_pozycja = wartosc / zmienna;

na to

if (zmienna>0) aktualna_pozycja = wartosc / zmienna;

Nie rozumiem tylko o co chodzi koledze booby, m贸g艂by艣 napisa膰 troch臋 ja艣niej? (jestem pocz膮tkuj膮cy)

Zauwa偶y艂em jeszcze jedno dziwne zachowanie u robota (sorry za obrazek, ale chcia艂em co艣 na szybko namalowa膰):

Za艂贸偶my 偶e czarna linia, to ta艣ma po kt贸rej je藕dzi robot, a zielone kropki to czujniki.

Kilka razy trafi艂 mi si臋 taki przypadek, 偶e robot skr贸ci艂 sb zakr臋t ( czyli pojecha艂 tak jak jest zaznaczona strza艂ka ) i gdy doje偶d偶a do czarnej linii to reaguje czujnik najbardziej wysuni臋ty na prawo, czyli lewy silnik przy艣piesza, a prawy zwalnia co skutkuje tym 偶e robot ca艂kowicie odbija z trasy... :/

Udost臋pnij ten post


Link to post
Share on other sites

Tutaj odpowiedz na Twoje problemy:

zauwaz, ze MacLiner2.0 zareagowal podobnie do Twojego robota.

Polecam raz jeszcze przeczytac to co pisalem wyzej, zapomnialem wspomniec, iz duzo takze daje szybkosc wykonywania sie petli. to wlasnie jej czas determinuje, to co jaki dystans robot bedzie analizowal tor, ale patrzac na caloksztalt, Twoj robot jeszcze nie jest tak szybki aby to przeszkadzalo.

P.S przy okazji zachecam do lajkowania mojego fanpage'a 馃槈

Udost臋pnij ten post


Link to post
Share on other sites
implementujac regulator PD, mamy informacje w postaci zmiennej o nazwie np. "Uchyb"- czyli przechowuje tam wartosc, ktora jest odlegloscia od czujnika srodkowego(Uchyb=0-aktulana_pozycja), czujniki mialy wartosc od -9 do +9. Kiedy czujniki znajdowaly sie poza linia(robot przestrzelil zakret), to sprawdzalem jaka byla wartosc uchybu przed przestrzeleniem. Jesli ujemna skrec w lewo, jesli dodatnia to w prawo, jesli blad rowny byl wartosci zero, to oznaczalo, ze mamy przerwe w trasie(jedna z przeszkod w LF z przeszkodami). W taki sposob robot calkiem dobrze robot sobie radzil. Niestety byly takie ulozenia robota/trasy, ze blad wydzodzil 0, mimo, ze byl zakret i robot wypadajac jechal prosto, zamiast podjac manewr powrotu na linie.

Zrobi艂em tak jak napisa艂e艣:

/*
* main.c
*
*  Created on: 30 sty 2015
*      Author: Dominik
*/


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

#include "LCD/lcd44780.h"
#include "ADC/adc.h"

#define IN1 (1<<PC6)
#define IN2 (1<<PC7)
#define IN3 (1<<PC5)
#define IN4 (1<<PC4)

#define MUX_A (1<<PA1)
#define MUX_B (1<<PA0)

#define SET_A PORTA |= MUX_A
#define CLR_A PORTA &= ~ MUX_A;

#define SET_B PORTA |= MUX_B
#define CLR_B PORTA &= ~ MUX_B;

#define MUX_X (1<<PA3)
#define MUX_Y (1<<PA2)

//#define KEY (1<<PC3)
#define linia 850

void silnik_L ( uint8_t kierunek, uint8_t predkosc );
void silnik_R ( uint8_t kierunek, uint8_t predkosc );

void pomiar_czujnik ( uint8_t czujnik );
void napiecie_lipol ( void );

uint16_t wynik=0;
uint8_t predkosc = 45;

int main(void) {

//	PORTC |= KEY;  // podci膮gamy klawisz do VCC

DDRC |= IN1| IN2 | IN3 | IN4;  // wyjscia do sterowania silnikami
DDRD |= (1<<PD4) | (1<<PD5);  // wyjscia PWM

DDRA |= MUX_A | MUX_B;  // wejscia adresowe ( multiplekser ) - jako wyjscia


lcd_init();  // inicjalizaja lcd
lcd_cls();

lcd_str("start...");
_delay_ms(500);

// inicjalizacja ADC
ADCSRA |= (1<<ADEN); // w艂膮cz ADC
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // preskaler = 128
ADMUX |= REF_VCC;	// ustawiamy wewn. 藕r odn. VCC


   // ustawienia TIMER1 w Fast PWM
   TCCR1A |= (1<<WGM10)|(1<<WGM11);                // Fast PWM 10-bitowy
   TCCR1B |= (1<<WGM12);                   // Fast PWM 10-bitowy
   TCCR1A |= (1<<COM1B1)|(1<<COM1A1);	 		// OC1A,OC1B  are cleared on TOP
   TCCR1B |= (1<<CS10);   				// preskaler = 1


accu1_vol.ref_adc = 780;	// zmierzona warto艣膰 ADC  ( 7,4 V )
accu1_vol.ref_v = 742;		// warto艣膰 mierzonego napi臋cia  ( 7,4 V )

napiecie_lipol();     // sprawdzanie napiecia akumulatora

_delay_ms ( 2000 );
lcd_cls();

uint8_t zmienna;
uint8_t wartosc;

float aktualna_pozycja;
float roznica = 0;

   while(1)
   {

   	zmienna = 0;
   	wartosc = 0;
   	aktualna_pozycja=0;
   	roznica=0;

   	for( uint8_t i = 1; i <9; i++ )
   	{
   		pomiar_czujnik(i);
   		if ( (linia-100) < wynik && wynik < (linia + 100) )
   		{
   			zmienna++;
   			wartosc += i-5;
   		}
   	}


   	if (zmienna>0) // jesli linia jest pod ktoryms z czujnikow
   	{
   		aktualna_pozycja = wartosc / zmienna;
       	roznica = (0 - aktualna_pozycja) * 12;


           silnik_L(0,predkosc-roznica);
           silnik_R(0,predkosc+roznica);
   	}
   	else        // jesli robot wyjechal z trazy
   	{
   		if(aktualna_pozycja < 0)
   		{
   	        silnik_L(0,predkosc - 20);
   	        silnik_R(0,predkosc + 20);
   		}
   		if(aktualna_pozycja > 0)
   		{
   	        silnik_L(0,predkosc + 20);
   	        silnik_R(0,predkosc - 20);
   		}
   	}

   }
}


/*
*  przod => kierunek = 0
*  tyl => kierunek = 1
*
*  predkosc w %
*/
void silnik_L ( uint8_t kierunek, uint8_t predkosc )
{
if ( kierunek == 0 )
{
	PORTC |= IN3;
	PORTC &= ~IN4;
}
else if ( kierunek == 1 )
{
	PORTC |= IN4;
	PORTC &= ~IN3;
}

OCR1A = (1023 / 100) * predkosc;
}

void silnik_R ( uint8_t kierunek, uint8_t predkosc )
{
if ( kierunek == 0 )
{
	PORTC |= IN2;
	PORTC &= ~IN1;
}
else if ( kierunek == 1 )
{
	PORTC |= IN1;
	PORTC &= ~IN2;
}

OCR1B = (1023 / 100) * predkosc;
}

void pomiar_czujnik ( uint8_t czujnik )
{
switch ( czujnik )
{
	case 1: CLR_A; SET_B; break;  //
	case 2: CLR_A; CLR_B; break;  //
	case 3: SET_A; SET_B; break;  //  Y
	case 4: SET_A; CLR_B; break;  //

	case 5: CLR_A; SET_B; break;  //
	case 6: SET_A; CLR_B; break;  //  X
	case 7: CLR_A; CLR_B; break;  //
	case 8: SET_A; SET_B; break;  //
}

_delay_us(500);

wynik = 0;

if ( czujnik > 0 && czujnik < 5 ) wynik = pomiar( PA2 ); // dokonujemy pomiaru na PA2
if ( czujnik > 4 && czujnik < 9 ) wynik = pomiar( PA3 ); // dokonujemy pomiaru na PA3

}

void napiecie_lipol ( void )
{
uint16_t wynik=0;

lcd_locate(0,0);
lcd_str("Napiecie");

wynik = pomiar( PA7 );		// dokonujemy pomiaru na kanale PA7
get_vol( wynik, &accu1_vol );	// zamiana ADC na napi臋cie

lcd_locate(1,1);

lcd_str( accu1_vol.v1 );	// jednostki i dziesi膮tki zmierzonego napi臋cia
lcd_str( "." );
lcd_str( accu1_vol.v2 );	// cz臋艣膰 u艂amkowa zmierzonego napi臋cia
lcd_str( " V       ");
}

Robot je藕dzi troch臋 lepiej 馃槂 ale nadal przy ma艂ej pr臋dko艣ci cz臋sto zje偶d偶a z trasy. Co jeszcze mog臋 zmieni膰?

Filmik: LineFollower

Udost臋pnij ten post


Link to post
Share on other sites

Zerknalem na Twoj kod, dodalbym jeszcze warunek:

if(aktualna_pozycja ==0)
     {
           silnik_L(0,predkosc);
           silnik_R(0,predkosc);
     } 

Jest fajny myk jak sprawdzic czy robot zapamietuje po ktorej stronie sie znajdowal. Poloz na lini robota, wlacz go, ale tak, aby caly czas miec nad nim kontrole(utrzymuj go reka 馃檪). Teraz daj mu swobodnie jechac i w trakcie spychaj z lini po obu stronach, zobacz jaka jest reakacja 馃檪. Jesli robot wraca za kazdym razem jest super, natomiast jezeli po "przepchnieciu go poza linie nie wraca na nia, to bedzie oznaczalo, ze problem lezy prawdopodobnie po stronie czujnikow.

Mialem podobny problem, kiedy po raz pierwszy zbudowalem detekecje lini w oparciu o wykorzystanie wewnetrznego przetwornika ADC. Okazalo sie, ze wewnetrzne rezystory podciagajace kolektory czujnikow podowodwaly problemy. Musialem zrobic nowa plytke z rezystorami zewnetrznymi, problem zaniknal 馃檪.

Warto nadmienic, ze w ATmedze 8(innych takze tez) w obudowach SMD, mamy dodatkowe dwa kanaly ADC. Nalezy pamietac, ze nie sa to wejscia/wejscia cyfrowe, lecz jedynie kanal przetwornika, zatem nalezy tam bez wzgledu na wszystko dolaczyc zewnetrzny pull'up.

Jesli masz multimetr, a zakladam, ze kazdy robotyk powinien go posiadac, przelacz go na pomiar napiecia stalego i sprawdz jakie napiecia masz na wyjsciu kolektora swoich czujnikow. Problemem moze byc fakt, ze posiadasz multiplekser. Sprawdz kazdy czujnik po kolei zarowno dla czarnej, jak i dla bialej barwy. Podziel sie wynikami 馃檪.

Jeszcze jedna sprawa, Widze, ze napiecie progowe lini masz ustawione na 850, odniesieniem jest wewnetrzne zrodlo =VCC, zatem po szybkich obliczeniach, wychodzi ze przy okolo 4.15v czujnik wychwytuje linie, wydaje sie to ciut przesadzone. W jaki sposob dobrales taka, a nie inna wartosc? obserwacja, czy raz "na pale" ustawiles taka wartosc i potem jej juz nie zmieniales 馃槂?

Na przyszlosc polecam wyprowadzic sobie zlacze od komunikacji szeregowej UART, pod ktory bedziesz mogl podlaczyc poprzez np. Bluetooth, RF, czy tez komputer swojego robota i zdalnie sprawdzac co sie dzieje we wewnatrz procesora. To naprawda znacznie ulatwia prace!

Swoja droga, super, ze pracujesz w Eclipsie, tez od ostatniego czasu postanowilem sie przerzucic na to srodowisko, z przestarzalego juz AVR Studio 4 馃檪. Jak Ci sie w nim pracuje ? Korzystales wczesniej z dobrodziejstw innych programow? 馃檪

Udost臋pnij ten post


Link to post
Share on other sites

tego warunku:if(aktualna_pozycja ==0) nie da艂em poniewa偶 nie planowa艂em przerw w trasie.

warto艣膰 adc 850 dobra艂em metod膮 pr贸b i b艂臋d贸w.

Dzisiaj rano chcia艂em zrobi膰 test i wywali艂em wszystko z p臋tli g艂贸wnej i da艂em to:

    	pomiar_czujnik(1);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c1 = 1;
   	else c1 = 0;

   	pomiar_czujnik(2);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c2 = 1;
   	else c2 = 0;

   	pomiar_czujnik(3);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c3 = 1;
   	else c3 = 0;

   	pomiar_czujnik(4);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c4 = 1;
   	else c4 = 0;

   	pomiar_czujnik(5);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c5 = 1;
   	else c5 = 0;

   	pomiar_czujnik(6);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c6 = 1;
   	else c6 = 0;

   	pomiar_czujnik(7);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c7 = 1;
   	else c7 = 0;

   	pomiar_czujnik(8);
   	if ( (linia-100) < wynik && wynik < (linia + 100) ) c8 = 1;
   	else c8 = 0;

   	lcd_cls();
   	lcd_locate(0,0);

   	lcd_int(c1);
   	lcd_int(c2);
   	lcd_int(c3);
   	lcd_int(c4);
   	lcd_int(c5);
   	lcd_int(c6);
   	lcd_int(c7);
   	lcd_int(c8);

Na LCD mia艂em 8 cyfr ( ka偶da od innego czujnika ). Wgra艂em program do avr po艂o偶y艂em roota na pod艂odze i mia艂em osiem zer, nast臋pnie po艂o偶y艂em na lini tak 偶e ta艣ma by艂a ustawiona r贸wnolegle to linijki z czujnikami. Teoretycznie powinno pojawi膰 si臋 osiem jedynek, ale by艂o ich tylko 6 ( dwa 艣rodkowe czujniki tak jakby nie wykrywa艂y linii ). Zmieni艂em warto艣膰 850 na #define linia 750 i ju偶 艂adnie dzia艂a艂o.

Na przyszlosc polecam wyprowadzic sobie zlacze od komunikacji szeregowej UART, pod ktory bedziesz mogl podlaczyc poprzez np. Bluetooth, RF, czy tez komputer swojego robota i zdalnie sprawdzac co sie dzieje we wewnatrz procesora. To naprawda znacznie ulatwia prace!

Na p艂ytce mam z艂膮cze do UARTA ( ko艂o gniazda KANDA ).

Swoja droga, super, ze pracujesz w Eclipsie, tez od ostatniego czasu postanowilem sie przerzucic na to srodowisko, z przestarzalego juz AVR Studio 4 馃檪 . Jak Ci sie w nim pracuje ? Korzystales wczesniej z dobrodziejstw innych programow? 馃檪

Jak pierwszy raz chwyci艂em w r臋ce avr to u偶ywa艂em winavr, ale nie polecam.

Potem dowiedzia艂em si臋 o istnieniu ECLIPSA i bardzo mi si臋 on spodoba艂 馃槂

Jest fajny, 艂atwy w obs艂udze i wygodnie si臋 w nim programuje 馃槈

Poloz na lini robota, wlacz go, ale tak, aby caly czas miec nad nim kontrole(utrzymuj go reka 馃檪 ). Teraz daj mu swobodnie jechac i w trakcie spychaj z lini po obu stronach, zobacz jaka jest reakacja 馃檪 . Jesli robot wraca za kazdym razem jest super, natomiast jezeli po "przepchnieciu go poza linie nie wraca na nia, to bedzie oznaczalo, ze problem lezy prawdopodobnie po stronie czujnikow.

Wieczorem b臋d臋 testowa艂 馃槈

Udost臋pnij ten post


Link to post
Share on other sites

programek je偶eli pomog艂a zmiana warto艣ci "reagowania" na lini臋 i mia艂e艣 z 6 jedynek 8 (przy zmianie na #define linia 750), to mo偶e warto by艂oby zainteresowa膰 si臋 autokalibracj膮 przed przejazdem?

MacGyver jak z czasem chcia艂em uczy膰 si臋 C, to po obejrzeniu paru godzin poradnik贸w w艂a艣nie ze 艣rodowiskiem Eclipse mog臋 go naprawd臋 poleci膰, sam go od d艂u偶szego czasu u偶ywam i powiem szczerze, 偶e by艂 on moim pierwszym 艣rodowiskiem, w kt贸rym pisa艂em programy w C 馃檪 Tak偶e, polecam.

Udost臋pnij ten post


Link to post
Share on other sites
programek je偶eli pomog艂a zmiana warto艣ci "reagowania" na lini臋 i mia艂e艣 z 6 jedynek 8 (przy zmianie na #define linia 750), to mo偶e warto by艂oby zainteresowa膰 si臋 autokalibracj膮 przed przejazdem?
Troche nie wiem jak si臋 za to zabra膰 :/

Udost臋pnij ten post


Link to post
Share on other sites

Tu mo偶esz o tym przeczyta膰, cho膰 ja robi臋 to troch臋 inaczej.

Ewentualnie tutaj.

Edit: Ale z tego co widz臋 na filmikach, to musisz doda膰 takie co艣, 偶e je偶eli ostatnio linia widziana po lewej stornie robota i robot przestrzeli zakr臋t, to musi skr臋ca膰 w lewo (jak nie ma linii pod czujnikami i zakr臋t widziany ostatnio po lewej) i analogicznie dla prawej strony. Jak ostatnio widziana po prawej i przestrzeli, to musi skr臋ca膰 w prawo, dop贸ki dop贸ty nie znajdzie si臋 艣rodkowymi czujnikami na linii. Ten zabieg powinien dosy膰 dobrze pom贸c, poniewa偶 teraz robot jak przestrzeli (nie ma pod sob膮 linii), to jedzie sobie prosto. Spr贸buj wyobrazi膰 sobie to co napisa艂em wy偶ej i przeanalizuj. Powodzenia!

Udost臋pnij ten post


Link to post
Share on other sites
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

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!

Go艣膰
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...