Skocz do zawartości

Błąd odczytu czujników linefollowera


mateusz797

Pomocna odpowiedź

Witam, 

Skonstruowałem ostatnio linefollowera. 

Zostały przetestowany program z arduino. Część mechaniczna oraz elektryczna, programistyczna została ukończona. Jednak robót nie reaguje poprawnie na czarny i biały kolor. Czy ktoś mógłby mi wyjaśnić co jest tego przyczyną skoro nie ma błędów w programie, część mechaniczna i elektryczna jest poprawnie ukończona. Program ponizej

#include <LiquidCrystal_I2C.h>
#include <Wire.h>        // zalacz biblioteki


LiquidCrystal_I2C lcd(0x27,16,2); // adres I2C oraz liczba kolumnt i wierszy LCD

int sensor1 = A0;
int sensor2 = A1; 
int sensor3 = A2;
int sensor4 = A3;


const int IN1 = 7;
const int IN2 = 6;
const int IN3 = 4;
const int IN4 = 5;

const int ENA = 9;
const int ENB = 3;


void setup()
{
  lcd.init(); 
  lcd.backlight (); //podswietlenie obrazu

  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
  pinMode (IN3, OUTPUT);
  pinMode (IN4, OUTPUT);
  pinMode (ENA, OUTPUT);
  pinMode (ENB, OUTPUT);
  

}

void loop() {


  if ((analogRead(sensor1)<=300)&&(analogRead(sensor2)<=300)&&(analogRead(sensor3)<=300)&&(analogRead(sensor4)<=300)) // 1,2,3, 4 - czarne
    {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);

  analogWrite(ENA, 85);
  analogWrite(ENB, 85);   // prosto

delay(50);
  
   //PWM Speed Control
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);
    
     delay(50);
  }

  else if ((analogRead(sensor1)>=300)&&(analogRead(sensor2)<=300)&&(analogRead(sensor3)<=300)&&(analogRead(sensor4)<=300)) // // 1 białe 2,3,4 - czarne
    {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);

  analogWrite(ENA, 90);
  analogWrite(ENB, 0);    //  lekki skret w prawo
  delay(50);
  
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);


delay(50);
  
    }

     else if ((analogRead(sensor1)>=300)&&(analogRead(sensor2)>=300)&&(analogRead(sensor3)<=300)&&(analogRead(sensor4)<=300)) // // 1,2, białe 3,4 - czarne
    {
      
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);

  analogWrite(ENA, 90);
  analogWrite(ENB, 0);    //  lekki skret w prawo
  delay(50);
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);

delay(50);


    }

    else if ((analogRead(sensor1)>=300)&&(analogRead(sensor2)>=300)&&(analogRead(sensor3)>=300)&&(analogRead(sensor4)<=300)) // // 1,2,3 białe 4 - czarne
    {
      
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);

  analogWrite(ENA, 100);
  analogWrite(ENB, 0);    //  mocny skret w prawo
  delay(50);
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);

delay(50);

  
    }

    else if ((analogRead(sensor1)<=300)&&(analogRead(sensor2)<=300)&&(analogRead(sensor3)<=300)&&(analogRead(sensor4)>=300)) // // 1,2,3, czarne 4 - białe
    {
      
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);

  analogWrite(ENA, 0);
  analogWrite(ENB, 100);    //  lekki skret w lewo
  delay(50);
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);

delay(50);

  
    }

    else if ((analogRead(sensor1)<=300)&&(analogRead(sensor2)<=300)&&(analogRead(sensor3)>=300)&&(analogRead(sensor4)>=300)) // // 1,2, białe 3,4 - czarne
    {
      
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);

  analogWrite(ENA, 0);
  analogWrite(ENB, 90);    //  lekki skret w lewo 

   delay(50);
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);

  delay(50);
    }

    else if ((analogRead(sensor1)<=300)&&(analogRead(sensor2)>=300)&&(analogRead(sensor3)>=300)&&(analogRead(sensor4)>=300)) // // 1 czarne 2,3,4 - czarne
    {
      
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);

  analogWrite(ENA, 0);
  analogWrite(ENB, 90);    //  lekki skret w lewo
  
    lcd.setCursor (0,0);
    lcd.print ("1:");
    sensor1= analogRead(A0);
    lcd.print(sensor1);
    
    lcd.setCursor (6,0);
    lcd.print ("2:");
    sensor2= analogRead(A1);
    lcd.print(sensor2);

    lcd.setCursor (0,1);
    lcd.print ("3:");
    sensor3= analogRead(A2);  
    lcd.print(sensor3);
  

    lcd.setCursor (6,1);
    lcd.print ("4:");
    sensor4= analogRead(A3);  
    lcd.print(sensor4);

delay(50);

  
    }

    }

 

1589445298780234176737950031269.jpg

1589445339486934183333260736020.jpg

15894453690645351025094362203631.jpg

Edytowano przez Gieneq
Link do komentarza
Share on other sites

Skoro "nie ma błędów w programie, część mechaniczna i elektryczna jest poprawnie ukończona", to wszystko działa prawidłowo i zgodnie z założeniami konstruktora 🙂.

A tak na poważnie, na początek trzy kroki:

1. Czy czujniki są we właściwej odległości od linii? Powinno być jakieś 2-3 mm, żeby linie były dobrze wykrywane. Rozwiązanie z kółkiem skrętnym z przodu nie należy do optymalnych...

2. Czy diody podczerwone się świecą? Zrób zdjęcie telefonem komórkowym.

3. Czy sensory zbierają poprawne dane?

U siebie to robiłem takim prostym programem, który przy okazji pokazuje, który czujnik wykrywa linię

int odczytanaWartosc = 0;
int prog = 250;
int czujnik = 0;
int ileczujnik = 0;
int i;

void setup() {
  Serial.begin(9600);//Uruchomienie komunikacji
}
 
void loop() {
  czujnik = 0; 
  ileczujnik = 0;
  for (i = 1; i <= 5; i++) {
    odczytanaWartosc = analogRead(i);
    Serial.print(odczytanaWartosc);//Wysyłamy ją do terminala
    Serial.print("\t"); // Znak tabulatora
    if (odczytanaWartosc > prog) {
      ileczujnik++;
      czujnik = i;
      }
    }    
  Serial.print(ileczujnik);//Wysyłamy ją do terminala
  Serial.print("\t"); // Znak tabulatora
  Serial.println(czujnik);//Wysyłamy ją do terminala
  delay(500);//Czekamy, aby wygodniej odczytywać wyniki  
}

Powodzenia

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

Dziękuję za wysłanie programu.  Przydaje się. Na jego podstawie i nie  tylko  mam następujące wnioski:

 

1.Czujnik znajduje się na wysokości 2cm od linii

 

2.Zdjecie diod podczerwonych 

 

3. Na wyświetlaczu LCD wyraźnie się wyświetla że jak robót widzi Linie : wartości są mniejsze od 200. Jeśli jej nie widzi : większe od 800.

Myślę że inna jest przyczyną. Wyślę jeszcze plik pdf z danymi jak Twój program widzi na monitorze portu szeregowego w zależności od wskazania moje LCD. 

 

 

 

IMG_20200514_190730.jpg

IMG_20200514_190916.jpgIMG_20200514_190903.jpg

Pomiary czujnikow w zalenosci od barwy podloza(1).pdf

Edytowano przez Gieneq
Link do komentarza
Share on other sites

Idziemy zatem dalej:

1. Jednak bym opuścił, 2 cm to trochę sporo...

2. No i pięknie się świeci.

3. Wygląda zatem, że czujniki widzą linię. Chociaż...

- masz 5 czujników, a wykorzystujesz tylko 4. Ten środkowy też jest przydatny.

- załączony przeze mnie kod należało zmodyfikować, przez zmianę linii sterującej pętlą na

for (i = 0; i < 4; i++) {

bo przecież sprawdzasz cztery czujniki podpięte od A0 do A3. Teraz ważniejsze

4. Sprawdź swoje elsify. Zmodyfikuj na przykład program tak, aby zamiast sterować silnikiem, wyświetlał na LCD stosowny komunikat. Czyli na przykład gdy linia jest pośrodku, niech wyświetla się słowo Prosto I tak dalej dla wszystkich warunków.

5. Jeśli to będzie działało tak, jak chcesz, dopiero możesz przejść do instrukcji sterującej silnikami.

Miłej zabawy!

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

(edytowany)

Dobrze napisze po kolei na poszczególne punkty :

 

1. Listwa jest położona  7mm od ziemi 

2. Fotodiody świeca więc punkt spełniony 

3. Wysyłam szkic oraz filmik z tego jak reagują czujniki na podłoże. Widać że jest pewien bałagan. Źle odczytują. 

Na zdjęciach widać że jedynie jak robót widzi czarna Linie to każe skręcać. I wogole dziwi mnie to że napisy się wyświetlają. Wyślę zaraz kod programu. 

 

15895318742765184286225524588605.jpg15895319319981397474302299256657.jpg1589531951714100376973033292372.jpg

15895319756978736876921276316907.jpg15895319936623914410110839466789.jpg15895320116251043528545935802693.jpg

15895320303718467415768682120665.jpgIMG_20200515_084816.jpg

Teraz kod programu, na wyswietlaczu wogole to co sie dzieje nie odpowiada kodowi programu: jakies dodatkowe litery wyskakuja. Dobrze podpisalem to co ma sie wyświetlić. Teraz podstawowe pytania  :

 

1.Co jest przyczyną że wyskakują dodatkowe litery na wyświetlaczu(napisy się łącza ze sobą np.,, Prosto : w prawo,, ?  Przecież w programie jest wyraźnie napisane że prosto ma wyświetlać lub w prawo. 

2. Źle odczyty czujników. Odległość nad ziemią to 7mm.Diody listwy się podświetlają (np. Czarny kolor dioda czerwona się zapala, biały kolor dioda czerwona gasnie). Czyli listwa działa dobrze. Tylko czujniki coś źle przekazują do LCD. 

#include <LiquidCrystal_I2C.h>
#include <Wire.h>        // zalacz biblioteki


LiquidCrystal_I2C lcd(0x27,16,2); // adres I2C oraz liczba kolumnt i wierszy LCD

int sensor1 = A0;
int sensor2 = A1; 
int sensor3 = A2;
int sensor4 = A3;

void setup()
{
  lcd.init(); 
  lcd.backlight (); //podswietlenie obrazu


  

}

void loop() {


  if ((digitalRead(sensor1)==1)&&(digitalRead(sensor2)==1)&&(digitalRead(sensor3)==1)&&(digitalRead(sensor4)==1)) // 1,2,3, 4 - czarne
    {
  
   //PWM Speed Control
    lcd.setCursor (0,0);
    lcd.print ("Prosto:");
    
     delay(50);
  }

  else if ((digitalRead(sensor1)==0)&&(digitalRead(sensor2)==1)&&(digitalRead(sensor3)==1)&&(digitalRead(sensor4)==1)) // // 1 białe 2,3,4 - czarne
    {
 
    lcd.setCursor (0,0);
    lcd.print ("Minim R");
    
    }
else if ((digitalRead(sensor1)==0)&&(digitalRead(sensor2)==0)&&(digitalRead(sensor3)==1)&&(digitalRead(sensor4)==1)) // // 1,2 białę ,3,4 - czarne
    {

  
    lcd.setCursor (0,0);
    lcd.print ("Skret w prawo");
   


 }


    else if ((digitalRead(sensor1)==0)&&(digitalRead(sensor2)==0)&&(digitalRead(sensor3)==0)&&(digitalRead(sensor4)==1)) //  1 białe 2,3,  4 - czarne
    {
    
    lcd.setCursor (0,0);
    lcd.print ("M w prawo");
    }
    else if ((digitalRead(sensor1)==1)&&(digitalRead(sensor2)==1)&&(digitalRead(sensor3)==1)&&(digitalRead(sensor4)==0)) // 1 2,3, czarne 4 - biale
    {
   
    lcd.setCursor (0,0);
    lcd.print ("Lekko w lewo");
   
 }

else if ((digitalRead(sensor1)==1)&&(digitalRead(sensor2)==1)&&(digitalRead(sensor3)==0)&&(digitalRead(sensor4)==0)) //  1,2, czarne 3,4 - biale
    {

    lcd.setCursor (0,0);
    lcd.print ("Skret w lewo");
   
    
   
 }

else if ((digitalRead(sensor1)==1)&&(digitalRead(sensor2)==0)&&(digitalRead(sensor3)==0)&&(digitalRead(sensor4)==0)) // // 1 czarne 2,3,4 - biale
    {
 
    lcd.setCursor (0,0);
    lcd.print ("M w lewo");
   

delay(50);
    }
     }

 

Edytowano przez Gieneq
Zachęcam do używania bloku kodu
Link do komentarza
Share on other sites

1. Odpowiedź na pytanie pierwsze jest prosta: a kto wyczyści poprzedni napis? Przecież to jego resztki widzisz.

Musisz dać najpierw lcd.clear(), a dopiero potem przystąpić do wyświetlania kolejnych napisów. Polecam:

https://forbot.pl/blog/kurs-arduino-wyswietlacz-tekstowy-lcd-id4263

2. Testowanie czujników warunkiem if ((analogRead(sensor1)<=300)

Jest znacznie lepsze niż warunkiem if ((digitalRead(sensor1)==0)

Po to podłączasz je do wejść analogowych, aby odczytać wartość analogową.

3. Czemu taka gruba linia?

4. Bonus na koniec. Przyjrzyj się zdjęciu czwartemu. Robot jest skierowany na lewo od linii. W którą stronę powinien skręcić, aby wrócić na linię?

Miłej zabawy, wracam do pracy.

Rafalini

 

Link do komentarza
Share on other sites

(edytowany)

Dziękuję za podpowiedź. Efekty 

Czyli wiemy że pomogła wysokość czujników oraz poprawność programu. LCD clear. Czy mogę teraz pisać komendy dla silników? Linia jest gruba bo robót się gubi przy niewielkiej. Mało tego. Robót czasami z opóźnieniem zmienia napisy na wyświetlaczu. Płynnie nie zmienia. 

15895392392096095354695569864216.jpg15895392690643765435015478184616.jpg15895392902268446356638691659862.jpg

15895393152099184562302182057403.jpg15895393243985963462419533501876.jpg15895393466037149681250450865353.jpg15895393621286197217268201276513.jpg

Edytowano przez Gieneq
Dodatkowe pytania
Link do komentarza
Share on other sites

(edytowany)

Zanim załączę silniki będę musiał naładować robota. Zamówiłem ładowarkę. Jeżeli nie podziała już i robót będzie zjeżdżał z trasy  po tym to będą możliwe 3 przyczyny :

A. Czujniki źle odczytują pomiar

B. Czujniki źle przekazują do silników 

C. Układ się poprostu zacina jak

komputer. 

 

Test ma trasie zdany. Pomógł Twój program ten co 4 czujniki trzeba było wpisać. Dziękuję! 😊 

 

IMG_20200515_194836.jpgIMG_20200515_194829.jpg

IMG_20200515_194824.jpgIMG_20200515_194808.jpg

IMG_20200515_194754.jpgIMG_20200515_194733.jpg

IMG_20200515_194723.jpgIMG_20200515_194703.jpg

IMG_20200515_194604.jpgIMG_20200515_194553.jpg

Edytowano przez Gieneq
Link do komentarza
Share on other sites

Akurat nie widać filmu, tylko zdjęcie 🙂, ale...

Hej,

musisz pamiętać, że program sterujący oparty na ifach i elsifach to bardzo zgrubne podejście do tematu. Drugim krokiem jest przypisanie wagi do każdego z czujników i na tej podstawie obliczanie odchylenia od ścieżki, by potem sterować silnikami. Wymaga to też odpowiedzi na pytanie: A co, jeśli żaden czujnik nie widzi linii?

Do poczytania, przemyślenia i zastosowania:

https://forbot.pl/forum/topic/3723-algorytmy-pid-w-robotyce-amatorskiej-linefollower-cz1-czlon-p/

Warto też przy okazji wykorzystać ten środkowy czujnik

Dużo więcej wskazówek (to już trzeci, albo czwarty krok) znajdziesz w artykule:

https://forbot.pl/blog/algorytm-linefollowera-c-poczatkujacych-id2722

W ogóle Forbot i to forum to kopalnia wiedzy o linefollowerach.

Powodzenia

Rafalini

 

Link do komentarza
Share on other sites

Przy tak "szerokiej drodze" wydaje mi się, że powinien lepiej jeździć. No ale dobrze, że już się zbytnio nie gubi. Gdy będziesz miał chwilę przeczytaj podany poniżej artykuł. Jest tam pokazana implementacja mechanizmu PID, który to może poprawić jazdę Twojego pojazdu.

https://forbot.pl/blog/algorytm-linefollowera-c-poczatkujacych-id2722

Link do komentarza
Share on other sites

Dziękuję za przesłanie artykuły. Powiem szczerze że niewiele rozumiem z tego kodu bo to typowy język C jest. Ja programuje w Arduino czysto dla funu. Nie rozumiem języka C bo są trudniejsze instrukcje. Z tego artykułu też niewiele wyciągnąłem. Na if i Else jest proste rozwiązanie. W arduino nie wiedziałbym jak taki program z regulatorem PID napisać. 

Link do komentarza
Share on other sites

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!

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

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.