Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję
PCB.center

Jakie czujniki do linefollowera? Pomoc w wyborze

Autor Wiadomość
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 13-09-2017, 10:59   

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 :)

Popularny artykuł » Silniki elektryczne: szczotkowe, bezszczotkowe, krokowe


Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 13-09-2017, 12:50   

Dobrze?
Przepraszam za jakość, ale na szybko w szkole na przerwie rysowałem...


20170913_123154.jpg
1
Plik ściągnięto 10 raz(y) 2.47 MB

Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 13-09-2017, 13:32   

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 :)

Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 13-09-2017, 13:41   

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?

Ostatnio popularny » Kurs STM32 - #10 - SPI w praktyce, wyświetlacz graficzny


Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 13-09-2017, 14:11   

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

Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 13-09-2017, 14:16   

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:
Kod programu: Zaznacz cały



#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 :)

Ostatnio zmieniony przez kamdz 14-09-2017, 14:12, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 14-09-2017, 14:34   

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?

Ostatnio zmieniony przez marek1707 14-09-2017, 14:40, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 14-09-2017, 14:57   

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

Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 14-09-2017, 15:20   

Może gdzieś ustawiasz, ale w kodzie na pewno nie. Oczekiwałbym czegoś takiego:
Kod programu: Zaznacz cały
 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:
Kod programu: Zaznacz cały
unsigned char d[] = {'x','y','z','\0'};

lub łatwiej tak:
Kod programu: Zaznacz cały
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:
Kod programu: Zaznacz cały
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.

Ostatnio zmieniony przez marek1707 14-09-2017, 15:27, w całości zmieniany 3 razy  
Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 14-09-2017, 15:29   

Ok. mój kod wygląda teraz tak:
Kod programu: Zaznacz cały


#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

Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 14-09-2017, 17:05   

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:
Kod programu: Zaznacz cały
// 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ć.

Ostatnio zmieniony przez marek1707 14-09-2017, 17:08, w całości zmieniany 1 raz  
Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 14-09-2017, 17:18   

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

Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 14-09-2017, 17:38   

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

Postaw piwo autorowi tego posta
 
 
kamdz 



Posty: 39
Wysłany: 14-09-2017, 17:57   

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...
Kod programu: Zaznacz cały

#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;

}

Postaw piwo autorowi tego posta
 
 
marek1707 



Posty: 4102
Pomógł: 442 razy
Otrzymał 585 piw(a)
Skąd: WAW
Programuję w:
C, asm
Wysłany: 14-09-2017, 18:10   

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.

Postaw piwo autorowi tego posta
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Wersja do druku

Skocz do:  

Nie rozwiązałeś swojego problemu? Zobacz podobne tematy: Czujnik siły - jaki ... "czunik" d... Gdzie kupić te czujn... Styczniki w MiniSumo...
lub przeszukaj forum po wybranych tagach: czujniki, do, jakie, linefollowera, pomoc, wyborze


Powered by phpBB modified by Przemo © 2003 phpBB Group
Popularne kursy: Arduinopodstawy elektroniki