Skocz do zawartości

Jakie czujniki do linefollowera? Pomoc w wyborze


kamdz

Pomocna odpowiedź

A z innymi prędkościami próbowałeś? W szerokim zakresie? Jak zweryfikowałeś F_CPU? To jeszcze proponuję zmienić fusebity z powrotem na wewnętrzny generator np. 1MHz i jeszcze raz skompilować program pod nowe F_CPU. Tę częstotliwość przynajmniej gwarantuje producent. Nie jest to może jakiś superwzorzec, ale UART zwykle z tym kłopotów nie ma.

Być może problem jest w obliczeniach wartości UBRR?

Spróbuj zrobić tak:

#define USART_BAUD 9600UL
#define USART_UBBR_VALUE ((8000000UL/(USART_BAUD<<4))-1)

i napisz jak poszło.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Działa poprawnie 🙂 Brawo Ty 😉 W stosunku do poprzedniego kodu to tylko dodane zostało to UL przy prędkości uarta i taktowania tak? na czym to polega? no bo chciałbym też zrozumieć co robiłem źle...

[ Dodano: 14-09-2017, 19:11 ]

Aha, tylko gdy próbuję odebrać coś to mi wyskakuje błąd w kompilatorze: ../uart.c:35:5: error: assignment to expression with array type

Nie wiem, czy błąd jest jakiś prosty z niedożywienia 😉 czy kolejna rozprawa na 1,5 strony 😃


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

//void setAngle(int angle);
//void InitServ(void);

#include <inttypes.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdint.h>
   #define USART_BAUD 9600UL
   #define USART_UBBR_VALUE ((8000000UL/(USART_BAUD<<4))-1)

/*UART*/
void USART_Init(unsigned int ubrr) ;
void USART_Transmit( unsigned char data ) ;
unsigned char USART_Receive( void ) ;
void USART_TransmitString (unsigned char *str) ;


int main(void)
{
     unsigned char d[] = {"xyz"};
 unsigned char odb[1];
   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {

       USART_TransmitString(d);
_delay_ms(1000);

odb = USART_Receive();
   }

}




void USART_Init (unsigned int ubrr)
{
UBRRH = (unsigned char)((USART_UBBR_VALUE>>8) | _BV(URSEL));
   // Set baud rate
       UBRRH = (unsigned char)(USART_UBBR_VALUE>>8);
       UBRRL = (unsigned char)USART_UBBR_VALUE;

   // Enable receiver and transmitter
       UCSRB = (1<<RXEN)|(1<<TXEN);

   // Set frame format to 8 data bits, no parity, 1 stop bit
       UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);


}

void USART_Transmit( unsigned char data )
{

   /* Wait for empty transmit buffer */
   while ( !( UCSRA & (1<<UDRE)) ) ;
   /* Put data into buffer, sends the data */
   UDR = data;
}

void USART_TransmitString (unsigned char *str)
{
   int i = 0;
   for (i=0; str[i]!='\0'; i++) {
       USART_Transmit(str[i]);
       //_delay_ms(50);
   }
}


unsigned char USART_Receive(void)
{
// Wait until a byte has been received

   while((UCSRA&(1<<RXC)) == 0);

// Return received data

   return UDR;

}
Link do komentarza
Share on other sites

O, fajnie.

Wyrażenia, które wypisujesz w #define są tylko tekstami. Preprocesor czyli taki wstępny analizator szuka swoich dyrektyw (właśnie tych z # na początku), dokonuje odpowiednich podmian tekstu i wynik przesyła do kompilatora, ale niczego sam nie liczy. Dopiero "właściwy" kompilator to robi. Jego arytmetyka (ta używana w trakcie procesu kompilacji programu) jest w GCC taka, jaką założono domyślnie dla docelowego procesora. Maluchy AVR dostały w prezencie arytmetykę 16-bitową - takie są tutaj domyślnie int-y. No i ani 8000000 się w tym nie mieści, ani (9600<<4) też nie. Wynik obliczeń był jakiś przypadkowy i tyle się wpisywało do UBRR. Jakaś prędkość transmisji była bo przecież program działał, ale tylko oscyloskop mógłby powiedzieć jaka. Dodanie na końcu liczby litery 'L' oznacza wymuszenie zwiększenia długości do long int, (czyli tutaj 32 bitów) i to już wystarcza. 'U' z kolei oznacza unsigned, czyli bez znaku.

Funkcja USART_Receive() jest typu unsigned char i taki wynik zwraca. Oznacza to, że to co odda możesz wpisać tylko do czegoś takiego. Ty zrobiłeś tablicę takich "bezznakowych char-ów" a to już jest inny typ. Musisz albo zmienić deklarację na:

unsigned char odb;

i wtedy

odb = USART_Receive();

zadziała, albo zadeklarować tablicę jakiejś sensowniejszej długości, np:

unsigned char odb[10];

i wpisywać odebrany znak do jej konkretnego elementu:

odb[0] = USART_Receive();

Myślę, że zabrałeś się za dwie niełatwe rzeczy na raz. Walczysz ze sprzętem - a wręcz wnętrzem procesora i jednocześnie z językiem. Chyba nie rozumiesz do końca co robisz a praca "na czuja", metodą prób i błędów to moim zdaniem strata czasu. Wiem, że oba tematy są pilne i fajne i że aby zbudować samodzielnie robota musisz być biegły w obu, ale przyhamuj trochę. Przejdź kurs C lub przeczytaj dobrą książkę. Osobno poczytaj o procesorze - o jego peryferiach i samej architekturze. To zaprocentuje. Na kursie będziesz prowadzony za rączkę - to dobrze, każdy musi kiedyś nauczyć się chodzić, żeby później biegać. Wykonaj ćwiczenia z kursu a czytając książkę analizuj ze zrozumieniem pokazane tam programy tak, byś rozumiał każdą ich linijkę. Zacznij od bardzo prostych rzeczy, od typów danych, od podstawowych instrukcji, od poczytania o stylach kodowania, formatowania, czytelności itp. Z kolei mając przegląd tego co procesor ma w środku zupełnie inaczej spojrzysz na system, który projektujesz. Dużo łatwiej będzie Ci ogarnąć zadania jakie będzie on wykonywał i przydzielić je poszczególnym zasobom sprzętowym. Poświęć na to powiedzmy miesiąc a sam zobaczysz z jakim zażenowaniem będziesz patrzył na te swoje dzisiejsze próby rozbudowywania niezrozumiałego kodu. Jeśli chcesz walczyć z robotami, uzbrój się w wiedzę. Powodzenia 🙂

  • Pomogłeś! 1
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

Tak, to jest to o czym myślałem.

Wstawiając potencjometr zamiast opornika podciągającego do Vcc możesz łatwo zmieniać czułość wszystkich czujników na raz, bo na tym oporniku odkłada się napięcie z prądów kolejnych tranzystorów. Jeśli nie wierzysz potencjometrom (bo drgania, starzeją się, szumią itp) możesz tam dać kilka rezystorów załączanych zworkami. Jeśli dasz np. 5k1, 5k1, 10k i 20k szeregowo i tym trzem ostatnim równolegle zworkę, to będziesz miał możliwość regulacji od 5k do 40k z krokiem ok. 5k.

Regulacja jest po to, byś mógł trafić z zakresem sygnałów wyjściowych dla danego oświetlenia/podłoża w zakres działania ADC. Przy zbyt słabej czułości (w danych warunkach) możesz np. dostawać odczyty od 950 do 1023 i to w sumie będzie działać bardzo marnie. Z drugiej strony, gdy przesadzisz z wartością opornika, będziesz czytał z ADC np. 0 do 120 i to też nie wróży dobrze. Jeśli natomiast ustawisz się czułością na środku (tzn. napięcie kolektora na granicy taśmy i podłogi będzie mniej więcej Vcc/2) to sygnał z kolektora będzie miał "najwięcej miejsca" do pracy, nie będzie obijał się ani o Vcc ani o GND i dostaniesz np. zakres 200-800, który dużo łatwiej odróżnić od przypadkowych zakłóceń, choćby tych z lamp na suficie.

Zjadłeś kanapkę na przerwie? Dobre odżywianie to podstawa 🙂

Heja, zabrałem się za produkcję płytki czujników i mam jescze jedno pytanie... Rozumiem, że potencjometr mam dać na gnd diody tak?

Link do komentarza
Share on other sites

Schemat ten co wczesniej z jednym dopiskiem. Ale robie na uniwersalnej, wiec spoko, nic nie stracę 🙂 daje tez fotki dzisiejszej pracy, wiem że luty nie najlepsze, ale wydawalo mi się, że coś mi sie pomieszalo, zacząłem wylutowywac i zorientowalem sie, że jest ok. Ale ważne, że jest połączenie 😉

20170922_190449.thumb.jpg.d3f7ed91a805d42b4824f4ea7d032fae.jpg

20170922_190543.thumb.jpg.ebe5240bad19eeef5cfb17228395d2ee.jpg

20170922_190527.thumb.jpg.29280ff2fa3db4765a22b7192806fa52.jpg

20170922_190513.thumb.jpg.a4dddf757fe1ad5576ae3ac93fd49efa.jpg

20170922_190509.thumb.jpg.b28d95da507443dc406d9d3ff9747698.jpg

Link do komentarza
Share on other sites

Możesz tam dać potencjometr, ale jest on dużo mniej ważny niż ten w kolektorach tranzystorów. Tu przy diodach możesz wstawić np. 500Ω lub 1k szeregowo z opornikiem 100Ω żeby nie zewrzeć na krótko, ale ten prąd raczej możesz zafiksować na stałe. Koniecznie za to daj pot zamiast tego opornika od wejścia ADC do Vcc.

Zawsze miej aktualny schemat tego co robisz, z numerkami pinów. A najlepiej, gdybyś sobie narysował ideowy, wszystko policzył i ustalił a dopiero potem montażowy, gdzie scalaki wyglądają "jak żywe", mają tak samo wyprowadzone nóżki jak naprawdę i do tego druty je łączące. Wtedy liczba błędów i zmarnowanego czasu spada niesamowicie, bo poprawianie na rysunku kosztuje tylko gumkę do ścierania.

Link do komentarza
Share on other sites

Chciałem nawet narysować jeszcze jeden pełny schemat, ale stwierdziłem, że prędzej się pomylę przy przenoszeniu go na płytkę, niż jak bede robił od razu na płytce. Płytka uniwersalna daje taką możliwość 😉 a jak byś skomentował moją dotychczasową pracę? Luty?

Link do komentarza
Share on other sites

Schemat ideowy to podstawa. Tam są wszystkie połączenia ale narysowane tak, by widać było sens działania urządzenia: co czym steruje, z czego jest zasilane, wartości elementów itp. Dopiero na podstawie tego, gdy już jesteś pewien każdego szczegółu robisz - wciąż na papierze lub w kompie - schemat montażowy. Tutaj masz już narysowane wszystko tak jak wygląda w rzeczywistości: scalak jest prostokątem z nóżkami na dwóch lub czterech krawędziach, tranzystor mocy ma trzy nóżki z jednej strony i czasem dziurkę na śrubę radiatora. To wciąż nie ma wiele wspólnego z płytką, ale przybliża Cię do niej. Dopiero teraz zaczynasz kombinować z ułożeniem elementów na prawdziwej płytce, bo dopiero teraz widzisz co i jak fizycznie jest połączone, gdzie jest dużo kabelków a gdzie mało. Który element warto położyć blisko (i na przeciwko i którą krawędzią obrócony do) jakiegoś innego bo między nimi jest 10 linii a który może być dalej, bo do niego dochodzą tylko dwa przewody itp. Potem możesz stworzyć jeszcze trzecią wersję, już z docelowo rozmieszczonymi elementami. Te wszystkie etapy są ważne a chodzenie na skróty wcale nie przyśpiesza. Trzeba mieć dużo wprawy i doświadczenia by na podstawie samego schematu ideowego od razu dobrze położyć elementy na płytce. Zwykle zaraz wychodzi, że to trzeba było przesunąć, dać bliżej albo obrócić. No cóż, sam zobaczysz.

Luty? Zdjęcia są nieostre a płytka jest jednowarstwowa bez metalizacji. Cyna nie wnika w otwory tylko robi kulki na padach. Mogłoby być jej mniej, ale lutowanie nie wygląda na zimne. Ja bym puszczał kabelki po stronie lutowania - jest dużo prościej, bo łączysz wprost piny ze sobą. Do takiego montażu niezbędny jest odpowiedni kabelek. Koniecznie w izolacji teflonowej, bo ta nie znika i nie pali się pod lutownicą. Jest cienki, mieści się między nóżkami scalaków a na tyle sztywny, że połączenia zostają po montażu tak jak je położyłeś. Kup szpuleczkę tzw. kynaru:

http://www.tme.eu/pl/details/kynar30awg50mwh/przewody-jednozylowe-drut/bq-cable/

50m starczy na wiele płytek, a komfort pracy jest nieporównywalny do przewodzików z PVC.

Link do komentarza
Share on other sites

Taaak. Szkoda, żepiszesz teraz jak mi już doszło zamówienie z tme... Myślę, żeten projekt skończe na tym druciku co mam, nie zależy mi na estetyce, ani niczym takim... Dzisiaj polutowałem kolejną masę kabelków i jeden czujnik. Potem poprawiłem 9999 znalezionych błędów i czujniczek zadziałał 🙂 oczywiście sprawdzałem tylko multimetrem, bez atmegi i.muxów... Ale działa 🙂 przy 30k dostałem od 0,18 do 4,12 volta ( ale mój czarny był taki szarawy;)) oczywiście wiem, że muszę zastosować potencjometr... No ale coś mi w końcu działa 😉

Aahaaa bo tam wyżej pytałem się, czy nie znasz może jakiegoś dobrego darmowego kursu C dla mikrokontrolerów...

20170923_222159.thumb.jpg.4885f4c70277471879b961f36a1a9580.jpg

20170923_222212.thumb.jpg.4124335d2e0d10ad79c62ec1dfa30c20.jpg

Link do komentarza
Share on other sites

Witam ponownie. Niniejszym rozpoczynam kolejny rozdział perypetii programowych po tytułem ADC 🙂

Tak więc bez zbytniego owijania w bawełnę

Kod:



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

//void setAngle(int angle);
//void InitServ(void);

#include <inttypes.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdint.h>
   #define USART_BAUD 9600UL
   #define USART_UBBR_VALUE ((8000000UL/(USART_BAUD<<4))-1)

/*UART*/
void USART_Init(unsigned int ubrr) ;
void USART_Transmit( unsigned char data ) ;
unsigned char USART_Receive( void ) ;
void USART_TransmitString (unsigned char *str) ;
int adc;

int main(void)
{
ADMUX |= (1<<REFS0)|(0<<REFS1); //porównuje z AVCC,  AREF--||--GND
       //0 tylko dla zasyganlizowania ze jest tam zero bo to nic nie zmienia
       ADCSRA |= (1<<ADEN);
 //    unsigned char d[] = {"xyz"};
 unsigned char odb;
   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {

       //USART_TransmitString(d);
	odb = USART_Receive();
	if(odb =='0'){
adc = getADC(0);
USART_Transmit(adc);
	}
//_delay_ms(1000);


   }

}




void USART_Init (unsigned int ubrr)
{
UBRRH = (unsigned char)((USART_UBBR_VALUE>>8) | _BV(URSEL));
   // Set baud rate
       UBRRH = (unsigned char)(USART_UBBR_VALUE>>8);
       UBRRL = (unsigned char)USART_UBBR_VALUE;

   // Enable receiver and transmitter
       UCSRB = (1<<RXEN)|(1<<TXEN);

   // Set frame format to 8 data bits, no parity, 1 stop bit
       UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);


}

void USART_Transmit( unsigned char data )
{

   /* Wait for empty transmit buffer */
   while ( !( UCSRA & (1<<UDRE)) ) ;
   /* Put data into buffer, sends the data */
   UDR = data;
}

void USART_TransmitString (unsigned char *str)
{
   int i = 0;
   for (i=0; str[i]!='\0'; i++) {
       USART_Transmit(str[i]);
       //_delay_ms(50);
   }
}


unsigned char USART_Receive(void)
{
// Wait until a byte has been received

   while((UCSRA&(1<<RXC)) == 0);

// Return received data

   return UDR;

}

int getADC(int number)
//number należy do <0, 7>, kod nie sprawdza szkoda pamięci FLASH
{
       ADMUX &= 0xf0; //zerowanie 4 młodszych bitów
       ADMUX |= number; //ustawianie numeru kanału

       ADCSRA |= 1<<ADSC; //zaczyna konwersję
       while(ADCSRA & (1 << ADIF));    //dopuki bit ADIF nie jest ustawiony nie jest gotowa kowersja
       ADCSRA &= ~((1 << ADSC) | (1 << ADIF)); //zeruj flage konwersji i rozkaz rozpoczecia
       return ADCW;
}

Po jego wgraniu na porcie dostaję krzaka. Konfiguracja uarta dobra, bo po zmianie "adc" na "odb" w funkcji wysyłania odsyła mi "0", gdy dostanie "0"

Jak cóś to port adc zwieram do 5V dla testu. Avcc i aref też do 5V

Prrrroszę o pomoc 🙂

[ Dodano: 04-10-2017, 20:21 ]

Ok. ten problem rozwiązałem... Potestowałem więc gotową płytkę i kolejny problem: Większość czujników ma wartość minimalną od 40-188, natomiast 1 na białej kartce pokazuje minimalnie 713. Czy to oznacza, że jest uszkodzony i trzeba go wymienić?

Link do komentarza
Share on other sites

Ok. ten problem rozwiązałem...

Pochwal się jak, na pewno komuś to pomoże w przyszłości 🙂

Potestowałem więc gotową płytkę i kolejny problem: Większość czujników ma wartość minimalną od 40-188, natomiast 1 na białej kartce pokazuje minimalnie 713. Czy to oznacza, że jest uszkodzony i trzeba go wymienić?

Mierzyłeś napięcia miernikiem (aby wykluczyć błąd w programie)? Może masz gdzieś zwarcie i prąd płynący przez jakiś rezystor podnosi odczyty z jednego czujnika? Jeśli masz zapas czujników pod ręką, to może jeszcze wymienić szybko czujnik - wykluczy to ewentualne uszkodzenie sensora.

Link do komentarza
Share on other sites

Dobrze, że ogarnąłeś ADC. Powinieneś zacząć od uważnego przeczytania opisu rejestru ADCSRA oraz zrozumieć co trzeba zrobić by poprawnie rozpocząć i zakończyć proces konwersji. Bity ADCSRA nie zawsze działają tak jak sobie to wyobrażamy, np. ADIF. No i napisz jak wygląda u Ciebie poprawny odczyt. Skoro już jesteś przy ADC, poeksperymentuj z innymi trybami pracy. Single conversion to tylko najprostsza metoda, z resztą bardzo prymitywna. Do testów się nadaje, ale w docelowym programie może warto użyć pełnej prędkości? Akurat mega8 ma chyba najsłabszy ADC wśród AVRów, brakuje tu np. wyzwalania pomiarów przez timery przez co ciężko zrobić próbkowanie z jakąś zadaną częstotliwością. Możesz jednak skorzystać z trybu free-running i obsługiwać odczyty w przerwaniu. Wejdź w to, nie parzy a daje fajne możliwości. Prędkość próbkowania możesz w pewnym zakresie regulować zmieniając podzielnik zegara ADC (bity ADPS).

Pytając o takie rzeczy jak czujniki, zawsze pokazuj schemat. Przecież błąd może być po każdej stronie. Tak sprzętu jak i oprogramowania. W sumienie wiemy który pomysł zrealizowałeś i jak. Jeśli jest multiplekser i wspólny opornik kolektorowy (emiterowy?) to ten fragment odpada, bo obciążenie każdego czujnika jest takie samo. Z liczb jakie przytaczasz rozumiem, że zrobiłeś czujniki emiterami na masie a w kolektorach (przez multiplekser?) jest opornik. Im więcej światła tym większy prąd tranzystora, większy spadek napięcia na oporniku obciążenia podpiętym do Vcc i mniej napięcia widzi ADC. Obejrzyj dokładnie ten czujnik. Wystarczy niewielkie zabrudzenie lub zmatowienie osłonki albo inna odległość od podłoża.

Jeśli zrealizowałeś też przełączanie diod oświetlających, to może tam coś? Przyjrzyj się lutowaniu, zmierz napięcie dna diodzie IR gdy ten czujnik jest wybrany i porównaj z innym, dobrym. Jeśli diodka danego czujnika nie dostaje prądu, to fototranzystor widzi tylko światło z otoczenia - wynik też będzie się zmieniał między białą kartką a czarną taśma, ale o wiele słabiej.

Prosty eksperyment: pokaż robotowi okno. Nie, nie każę Ci go wyrzucać. Skieruj listwę czujników na coś jasnego i równomiernego, np. okno bez Słońca. Dziś jest dobry czas, chyba leje w całym kraju. Światło diod IR nie będzie się odbijało od niczego i pójdzie w przestrzeń więc tranzystory będą widziały tylko to co przyjdzie z zewnątrz. Jeśli wszystkie pokażą mniej więcej to samo to znaczy, że pracują w tych samych warunkach i pomiary są poprawne.

Znając zasadę działania wymyślaj kolejne testy i je realizuj tak by znaleźć błąd. Zanim cokolwiek wylutujesz i spiszesz na straty bądź pewien, że to właśnie ten element jest uszkodzony.

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.