Skocz do zawartości

Jakie czujniki do linefollowera? Pomoc w wyborze


kamdz

Pomocna odpowiedź

Po prostu narysuj to co zrozumiałeś, bo moim zdaniem dobrze się domyślasz.

Jak to jakiej masy? A to ile ich tam masz?? To samo z Vcc - masz ich kilka w układzie, czy tylko jedno, zasilające wszystko?

Diody oświetlające w czujnikach to diody, mają anody i katody a nie żadne emitery. Oj, braki poważne widzę u Ciebie.

Po jednej stronie masz diodę:

- anoda do plusa,
- katoda wprost do jednej z 8 linii muxa,
- drugi koniec (ten wspólny) muxa przez opornik do masy.

Powstaje układ załączający tylko jedną diodę, akurat tę potrzebną, na raz..

Po drugiej stronie tak jak napisałem wcześniej:

- emiter tranzystora do masy,
- kolektor tranzystora wprost do jednej z 8 linii muxa,
- drugi koniec (ten wspólny) podciągasz opornikiem do ogólnego Vcc zasilającego procesor i cała resztę, ta sama linia przez 10nF do masy i do wejścia ADC.

No to już prawie jak narysowanie schematu 🙂

Link do komentarza
Share on other sites

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 🙂

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

Nie zdążyłem zjeść kanapki 🙁😉

Ok. Myslę,że dam potencjometr, tylko jaką on ma mieć wartość? Zgodnie z tym co piszesz to chyba 5k ale się wolę upewnić...

Aha no i jak na torze będzie wyglądać kalibracja tych czujków? 😉 to znaczy wiem, że mam kręcić potencjometrem, ale skąd mam wiedzieć, jakie jego ustawienie jest optymalne dla danych warunków? Można zrobić coś takiego, że robot będzie miał 2 tryby: jazdy i kalibracji( zmieniane np. Przez bluetooth) no i w trybie kalibracji będzie np. Co 2 sekundy wysyłał dane z wszystkich czujek przez seriala?

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

Potencjometr musi być taki, jaką planujesz największą wartość rezystora. Moim zdaniem 20k, a lepiej 50k plus obowiązkowo szeregowy opornik (5k1?) żeby zwarcia nie zrobić.

Kalibrację zrób jak będzie Ci najwygodniej. Wyobraź sobie sytuację na nowym torze i wymyśl do tego jakąś procedurę. Jeśli będziesz tam miał jakiś LCD, to możesz na nim pokazywać wyniki nawet ze wszystkich czujników na raz. Bluetooth? Czemu nie. byle zadziałał w krytycznej sytuacji. Jeśli program napiszesz mądrzej, to może być nawet jedna, zielona diodka LED zapalająca się gdy powoli przesuniesz listwę czujników w poprzek taśmy a procesor pomierzy i uzna, że sygnały są OK. Im dasz więcej peryferiów, tym system jest bardziej komunikatywny a to przydaje się szczególnie w (nigdy nie kończącej się) fazie eksperymentów.

Dziś wyświetlacze OLED są malutkie, na ekraniku 128x64 można pokazać naprawdę sporo tekstu (i wykresy!). Do tego kilka przycisków i masz cały interfejs użytkownika 🙂

http://allegro.pl/wyswietlacz-lcd-oled-0-96-i2c-arduino-bialy-i6957704637.html

Link do komentarza
Share on other sites

Hah ale ja dopiero zaczynam przygodę z moim C. Wcześniej pisałem w bascomie i arduino, ale ten projekt chce zrobic w C żeby się go nauczyć. Ale i2c to na pewno nie dla mnie. Narazie zrobie z bt, a kiedyś zawsze będę mógł zrobić nową wersję z ekranikami... Dzięki za pomoc. W takim razie będę zamawial czujki i muxy. Może jakąś relację z budowy też zrobię 😉

[ Dodano: 14-09-2017, 14:13 ]

W sumie nie będę na to zakładał nowego tematu 😉

No to próbuję ogarnąć ten uart w c i coś mi nie wychodzi. tzn odbieram miliard spacji...

mój kod to:



#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 9600
#define USART_UBBR_VALUE ((F_CPU/(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) ;


void main(void)
{
   unsigned char d[] = {'x','y','z'};
   unsigned char z = 'a';
   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {

       USART_TransmitString (d);

       USART_Transmit(z);


   }

}




void USART_Init (unsigned int ubrr)
{
// 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);
   (1<<URSEL);
// Set frame format to 8 data bits, no parity, 1 stop bit
   UCSRC = (0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCSZ2);


}

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;

}

Robiłem go w oparciu o to, ale nie wiem jak ostatecznie powinien on wyglądać. Proszę o pomoc 🙂

Link do komentarza
Share on other sites

Pierwsze co się rzuca w oczy 😉 to to, że akurat mega8 ma udziwniony dostęp do UBRRH. Zajrzyj do jej dokumentacji - masz tam dodatkowy bit URSEL który musisz ustawić.

Pisząc tak jak teraz zrobiłeś, ładujesz dane do UCSRC i rzeczywista prędkość transmisji jest jakaś od czapy. Jeśli to nie pomoże, będziemy dalej analizować.

EDIT: A co w ogóle jest podłączone i do czego? Jakie masz F_CPU? Jak taktujesz swój procesor? Masz kwarc i na niego się przełączyłeś czy korzystasz z wewnętrznego generatora w procesorze? Jak ustawionego? Co to znaczy milion spacji? A coś jeszcze? Jakieś krzaki?

Link do komentarza
Share on other sites

Ja tam ustawiam tego ursela.... nie wiem czy prawidłowo, bo tak jak mówię, w c jestem jeszcze bardzo początkujący... F_CPU mam 8000000 taktuję go zewnętrznym kwarcem. dostaję tylko spacje. nic więcej. To znaczy może to nie są spacje, ale jakieś niewidoczne znaczki, które rozszerzają mi okno portu com...

Link do komentarza
Share on other sites

Może gdzieś ustawiasz, ale w kodzie na pewno nie. Oczekiwałbym czegoś takiego:

 UBRRH = (unsigned char)((USART_UBBR_VALUE>>8) | _BV(URSEL));

Poza tym funkcja USART_TransmitString wysyła string a ten, w rozumieniu języka C, jest ciągiem znaków zakończonych bajtem 0. Kompilator odróżnia pojedyncze znaki 'A', '8' od stringów, które zapisujesz tak: "A kuku!". Wtedy w pamięci dostajesz nie tylko znaki tekstu, ale i dodatkowy bajt 0 na końcu.

Twoja deklaracja powinna wyglądać zatem tak:

unsigned char d[] = {'x','y','z','\0'};

lub łatwiej tak:

unsigned char d[] = {"xyz"};

Bez bajtu zakończenia funkcja USART_TransmitString nie zatrzymuje się po trzeciej literze i wysyła cały RAM aż do napotkania (albo nie) bajtu 0x00.

Edit:

A na pewno przełączyłeś fusebity na kwarc? Bo jeśli nie, to "fabrycznie nowy" procesor działa na wewnętrznym 1MHz i wtedy F_CPU=1000000.

Najprościej sprawdzisz to przez napisanie krótkiej pętelki mrugającej diodką 1Hz. Jeśli użyjesz czegoś takiego:

while (1) {
 // tu zapalasz diodke
 _delay_ms(500);
 // tu gasisz
 _delay_ms(500);
}

to się szybko okaże. Funkcje delay() korzystają z aktualnego F_CPU i na tej podstawie obliczają sobie potrzebną liczbę "zmarnowanych" cykli procesora. Jeśli diodka będzie mrugała raz na sekundę, to Twoje F_CPU zgadza się z tym jak rzeczywiście pracuje procesor.

Link do komentarza
Share on other sites

Ok. mój kod wygląda teraz tak:


#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 9600
#define USART_UBBR_VALUE ((F_CPU/(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"};

   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {

       USART_TransmitString (d);



   }

}




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)|(0<<UCSZ2);


}

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;

}

ale dalej dostaję same spacje.

URSELa ustawiam w funkcji usart init

Link do komentarza
Share on other sites

Nie śpiesz się tak. Pisanie programów to nie praca na akord. Zmieniając jakąkolwiek linię kodu pomyśl dwa razy co robisz, po co wprowadzasz modyfikację i czy ją rozumiesz. Spójrz, wstawiłeś linię zapisującą nową wartość do UBRRH, ale za nią zostawiłeś starą. Po za tym, czy rozumiesz mechanizm selekcji rejestrów poprzez URSEL? Tego bitu nie ustawiasz tam na stałe. To tylko taki selektor, wartość ważna tylko podczas operacji zapisu - od wartości najstarszego bitu zależy gdzie de facto procesor sobie te pozostałe 7 bitów zapisze: do UBRRH czy do UCSRC. Bo pod tym samym adresem, nazywanym "UBRRH" mega8 ma dwa rejestry.

Acha, no i przepraszam: URSEL powinien być ustawiony gdy piszesz do UCSRC 🙁 tak więc Twoja funkcja powinna wyglądać tak:

// 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)|(0<<UCSZ2)|(1<<URSEL);

Pisałem z głowy a teraz zajrzałem dla pewności do katalogu no i.. zonk. Cóż, pamięć już nie ta. Nie kopiuj tego na wariata tylko przemyśl i doczytaj jak czytać te rejestry, bo to już oczywiste nie jest i URSEL nie pomoże.

Nie odpowiedziałeś na pytania o F_CPU - czy potwierdziłeś jakoś rzeczywistą prędkość pracy procesora? Zastanów się też co się działo w Twojej ostatniej wersji kodu (zmienionej wg mojej głupiej porady) i dlaczego to nie mogło działać.

Link do komentarza
Share on other sites

No to tak, prędkość procesora jest dobra, ustawiałem zewnętrzny kwarc fusami i on działa. Po wstawieniu tego kodu jest progres: dostaję milion pytajników zamiast tekstu 🙂 Ja tak za bardzo nie wiem co jeszcze by tu można zrobić. Koledze na stronie, którą podlinkowałem działało po dodaniu tego ursela to ja już nie mam pomysłu...

Link do komentarza
Share on other sites

Jak nie masz pomysłów, to upraszczaj środowisko żeby zmniejszać przestrzeń błędów. Spróbuj np. napisać prostszą pętlę główną. Skorzystaj z funkcji USART_Transmit(), bo ta wysyła tylko jeden znak. Wołaj ją co sekundę zawsze np. z argumentem 'A'. Powinieneś dostawać tylko jeden znak na raz a nie cały ciąg - to łatwiej analizować. Jaki znak widzisz? Jeżeli dostajesz kilka krzaków, to prawdopodobnie szybkość UARTa w kompie jest większa niż w mega8. Pokręć tą prędkością. Teraz już chyba rozumiesz, po co programistom nawet najprostszy oscyloskop...

Link do komentarza
Share on other sites

Gdy wysyłam 'A' to w terminalu dostaję "Ŕ Ŕ" Ale ciągle coś tam patrzę, zmieniam, może do czegoś dojdę. Załączę jeszcze raz mój kod, może w nim jeszcze jest jakiś błąd...

#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 9600
#define USART_UBBR_VALUE ((8000000/(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"};

   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {

       USART_Transmit('A');
_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)|(0<<UCSZ2)|(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

Nie wywaliłeś błędnej linii z USART_Init();

W UCSRC nie ma bitu UCSZ2 - wywal to z wyrażenia, bo jeszcze kiedyś przyjdzie Ci do głowy go tu ustawić.

Czy próbowałeś zmieniać prędkość transmisji w programie odbierającym? Jeżeli mimo wszystko procesor pracuje na 1MHz, to UART nadaje na 9600/8=1200. Testowałeś taką prędkość w kompie? Jeśli mega8 nadaje jeden znak, a komputer w tym czasie odbiera trzy to znaczy, że "jego"znaki są szybsze i albo ona nadaje za wolno albo on odbiera za szybko. Jaki masz ustawiony format znaku w programie/terminalu odbierającym? Być może masz coś pokopane z bitami parzystości lub długością samego znaku. To wszystko musi być zgodne po obu stronach.

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.