Skocz do zawartości

Jakie czujniki do linefollowera? Pomoc w wyborze


kamdz

Pomocna odpowiedź

No to tak: kod do adc jest tu

Wieczorkiem pokombinuję z tym czujniczkiem, sprawdze połączenia, czy coś gdzieś nie zwiera i te kilka testów od Marka. Jak coś to mam 1 czujnik w zapasie 🙂

Multimetrem też sprawdzałem, nie pamiętam wartości, ale nie działał tak jak powinien.

Schemat chyba nie ma tu znaczenia, skoro jest taki sam dla wszystkich czujek, a reszta działa dobrze.

Link do komentarza
Share on other sites

Przy pytaniach o (dziwne lub nie-) działanie sprzętu schemat ma zawsze znaczenie, bo przecież nie wiemy co tam ostatecznie zmajstrowałeś. Jeśli możesz zastawić własną rękę za to, że wszystko jest OK a problem leży w sofcie, to napisz: wszystko sprawdziłem pięć razy, wykonałem fafnaście taki a takich testów, pomierzyłem co trzeba i sprzęt jest cacy. Jeśli nie wiesz co się dzieje, nie wiesz co i gdzie zmierzyć a prosisz o pomoc, schemat jest nieodłączną częścią pytania. Tylko na jego podstawie możemy snuć domysły i wymyślać kolejne testy.

To nie zawsze musi być pełny rysunek, bo jeśli wcześniej już coś zapodawałeś, to wystarczy wspomnieć co zrealizowałeś i na czym pracujesz: jest to (np.) wersja z dwoma multiplekserami i wspólnym opornikiem w kolektorze.

Inaczej dobrzy ludzie - wyobrażając sobie błędnie co tam masz na biurku - będą poświęcać swój czas na wymyślanie zupełnie nietrafionych podpowiedzi. Oszczędź im tego.

BTW: Żeby obejrzeć Twój kod trzeba się gdzieś zalogować i skorzystać z innego Forum. Nie mogłeś tego wrzucić tutaj? Rozumiem, że obsługa ADC wciąż nie działa. Jeśli tak, pochyl się nad bitami ADCSRA. Napisz w punktach jak powinien wg Ciebie wyglądać algorytm współpracy z tym ADC, od startu konwersji do odczytu wyniku i przygotowania na następny start. Bez kodu, tylko opis które bity/kasujesz ustawiasz i dlaczego.

Link do komentarza
Share on other sites

Schemat taki jak wcześniej, tak jak piszesz. Ale skoro tylko 1 czujnik nie działa, to chyba układ jest dobry, albo coś zwarłem lutując, albo czujka uszkodzona, jak będę w domu to posprawdzam 🙂 teraz jem kanapkę w szkole 😅

Nie wiedziałem, że się da nie mieć konta na elektrodzie 😉

Proszę kod

#include <stdlib.h>




#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(char data ) ;
unsigned char USART_Receive( void ) ;
int getADC(int number);
void USART_TransmitString (char *str) ;
int adc;
char adc1 [4];
int main(void)
{
ADMUX |= (0<<REFS0)|(0<<REFS1); //porównuje z AREF
       //0 tylko dla zasyganlizowania ze jest tam zero bo to nic nie zmienia
       ADCSRA |= (1<<ADEN)
	 |(1<<ADPS0)  
  |(1<<ADPS1)  
  |(1<<ADPS2);  
 //    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);
itoa(adc,adc1,10);
USART_TransmitString(adc1);
	}
//_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(char data )
{

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

void USART_TransmitString (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;
}

Adc mi działa, kod za radą Trekera daję dla potomnych 🙂

A co do trybu adc free run, będę się dość mocno wzorował na tym więc wykorzystam tryb adc który tam jest użyty, czylichyba pojedyńczą konwersję🙂

[ Dodano: 05-10-2017, 19:34 ]

Po pokazaniu czujnikom tej samej lampki wszystkie schodzą do ok 40, ten zostaje na 300 nie widzęna nim żadnych rysek, spróbuję poprawić luty, a jak nie pomoże to go podmienię na zapsowy.

[ Dodano: 05-10-2017, 21:24 ]

Po przelutowaniu działa. Co prawda nie wiem, czemu jedne czujki schodzą do 40, a inne do 200, no ale 200 to nie 700, od 1000 powinno się ładnie odzielać 🙂

No to cóż, hardware mam, to muszę się brać za softa. Także zapraszam do tematu wszystkich znających C, bo napewno będę miał dużo pytań 🙂

Link do komentarza
Share on other sites

Witam ponownie. Zrobiłem już program testujący te multieksery: na uarta wysyła mi dane z wszystkich 8 czujników po kolei. Jednak coś tu nie działa dobrze. Nie wiem co ja mam z tymi czujkami, ale chyba ciąży na mnie fatum linefollowerów 😉 nie mogę ich jakoś zmusić do poprawnej stabilnej pracy. Jak testowałem każde z osobna to jeszcze jakoś działały, po podłączeniu do muxa to z 5 dostaję wyniki 1023 a z 3 kolejnych coś koło 300(na białej kartce).

Schemat jak wcześniej, rezystor do diody 220 omów a do kolektora 10k. Testowane z kondensatorem do masy i bez. Nie mam już pojęcia co tu się dzieje, tak jakbym dostał jakąś felerną partię czujek. Jest jeszcze jakiś parametr, albo coś o czym mogłem zapomnieć? Proszę o pomoc zwłaszcza tych, którzy mieli doczynienia z tymi czujnikami, ale jak ktoś ma jakiś pomysł to walić śmiało, może coś wymyślimy...

Z góry dziękiza wszelkie propozycje.

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

Pokaż ten program. Jeśli każdy czujnik z osobna działa OK, to w zestawie też tak powinno być. Podczas przełączania kanałów trzeba zachować pewną kolejność i reżim czasowy, bo wyniki będą od czapy. Spróbuj tak:

1. Przełączasz kanał.

2. Czekasz np. 10ms.

3. Mierzysz i wynik zapamiętujesz w tablicy.

4. Powtarzasz powyższe aż zassiesz wszystkie czujniki.

5. Dopiero teraz wypisujesz wyniki.

Pytania:

1. Czy sprawdzałeś (np. aparatem foto) że wszystkie diodki w czujnikach świecą? Zrób test i zapalaj każdą po kolei np. na min. sekundę i tak w kółko.

2. Czy jest szansa, że pomyliłeś numery wyjść multipleksera do diodek lub wejść multipleksera tranzystorów? Bo jeśli zapalasz diodkę w jednym a mierzysz drugi, to pomiar wyjdzie 1023, bo temu mierzonemu jest ciemno.

Jeżeli po przelutowaniu coś się poprawiło, to możesz mieć nadal kłopoty z poprawnym montażem - wcale nie znaczy, że pozbyłeś się wszystkich błędów. Bardzo grzałeś te czujniki? Jak to wygląda? Możesz dać dobre zdjęcie całej listwy?

Nie powinno być aż 4-krotnych różnic w prądzie tranzystorów. Zatrzymaj się przy tym i wniknij w to. To nie fatum tylko pośpiech i/lub złe lutowania, w tym być może już przegrzane elementy.

EDIT: Ech, piszę głupoty po ciemku. Przecież zmiana wyniku ADC z 200 na 50 to zmiana napięcia na oporniku kolektorowym z 4V na 4.9V co jest spowodowane zmianą prądu tranzystora o 20%. To jest zupełnie akceptowalne., Inna sprawa, że wynik 50 jest o wiele za mały. Wyrażając to w napięciu (względem zasilania i referencji ADC = 5V) masz na wejściu tylko 240mV czyli tranzystor właśnie zaczyna się nasycać i czujnik przestaje działać liniowo. Zmniejsz opornik kolektorowy lub zwiększ opornik diodek tak by dostawać na białej kartce wyniki w granicach 200-300, bo obecnie czułość jest za duża. No i prześledź te niedziałające. Aparat lub kamerka, multimetr i do roboty. To nie ma prawa niedziałać.

Acha, pomiary lampki to zły pomysł. Światło ze źródeł sztucznych zasilanych z sieci bardzo mocno kołysze się z częstotliwością 100Hz. Sam pomiar ADC jest krótki, więc w zależności od tego kiedy wypadnie w okresie sieci AC taki wynik możesz dostać. Wygląda to, jakby czujniki były niestabilne a to tylko drgania jasności zbyt szybkie dla naszego oka. Spróbuj z oknem za dnia. Wyniki kolejnych pomiarów tego samego czujnika nie powinny różnić się więcej jak o 10 jednostek ADC.

Link do komentarza
Share on other sites

Będę dodawał wszystko stopniowo.

#include <stdlib.h>




#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(char data ) ;
unsigned char USART_Receive( void ) ;
int getADC(int number);
void USART_TransmitString (char *str) ;
void ustawmux (int liczba) ;
int adc;
char adc1 [4];
int main(void)
{
DDRD = 11100000;

ADMUX |= (0<<REFS0)|(0<<REFS1); //porównuje z AREF
       //0 tylko dla zasyganlizowania ze jest tam zero bo to nic nie zmienia
       ADCSRA |= (1<<ADEN)
	 |(1<<ADPS0)
  |(1<<ADPS1)
  |(1<<ADPS2);
 //    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);
		 itoa(adc,adc1,10);
for(int ster=0; ster<9; ster++){
ustawmux(ster);
adc = getADC(0);
itoa(adc,adc1,10);
USART_TransmitString(adc1);
USART_TransmitString("\n");
_delay_ms(2000);
}}
//_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(char data )
{

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

void USART_TransmitString (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;
}
void ustawmux (int liczba)
{
switch (liczba){
case 0:
PORTD=00000000;
break;
case 1:
PORTD=00100000;
break;
case 2:
PORTD=01000000;
break;
case 3:
PORTD=01100000;
break;
case 4:
PORTD=10000000;
break;
case 5:
PORTD=10100000;
break;
case 6:
PORTD=11000000;
break;
case 7:
PORTD=11100000;
break;

}

}

1.....

2. Raczej nie, sprawdzałem to kilka razy..

Grzałem je króciutko, mam oprową lutownice, rozgrzałem ją, i dosłownie w sekundę lutowałem jedną nóżkę.

A tak czytałem gdzieś, że ma być 220omów i 10k...

20171009_090613.zip

Link do komentarza
Share on other sites

Co się stanie, gdy funkcję ustawmux() wywołasz z argumentem 8? A tak robisz pod koniec pętli.

Skan czujników musi wyglądać tak:

1. Ustawienie kanału mux-a

2. Odczekanie krótkiego czasu, np. wywołanie funkcji delay_us(100). Multiplekser musi podać wybrane napięcie do ADC a ono musi się ustalić na linii ADC0 przed pomiarem

3. Wykonanie konwersji czyli Twoje getADC()

4. Zapamiętanie odczytu

5. Wypisanie wyników dopiero po odczytaniu wszystkich 8 (a nie 9 jak teraz) czujników

To ostatnie jest ważne, bo wypisywaniem zaburzasz wykonywanie skanu. Serial.print() nie jest bezkarne i kosztuje czas a w docelowym programie nie będziesz przecież wypisywał wyników w trakcie każdego skanu czujników. Pisz funkcje tak by były podobne do tych ostatecznych. Ew. printy kontrolne wstawiaj tam, gdzie najmniej zmieniają przebieg programu. Od razu stwórz funkcję np:

void skan(uint16_t* wyniki, uint8_t dlugosc)
{
  for (uint8_t kanal=0; kanal<dlugosc; kanal++)
  {
     ustawmux(kanal);
     delay_us(100);
     wyniki[kanal] = getADC(0);
  }
}

i wołaj ją wskazując tablicę gdzie oczekujesz wyników:

#define CZUJNIKI 8
uint16_t wynikiADC[CZUJNIKI];

skan(wynikiADC, CZUJNIKI);

a teraz możesz już sobie w pętli zawartość tablicy wynikiADC na spokojnie wypisać;

Nie musisz używać znakowego (signed) typu int do liczenia w zakresie 0-255, chodzi mi o zmienną ster. Zamiast męczenia procesora arytmetyką 16-bitową używaj krótszego i szybszego uint8_t. Tu przynajmniej widzisz jakiej długości jest zmienna (a wpisując uint16_t od razu byś zajarzył, że 16 bitów nie jest tu potrzebne).

Jeśli sterowanie muxem masz na 3 najstarszych bitach portu D i nie pozamieniałeś linii adresowych, to ustawmux() możesz napisać w jednej prostej linijce. Po co taki switch, który każdy czytający Twój kod musi przejrzeć żeby upewnić, się, ze nie robisz niczego ciekawego?

PORTD = (PORTD & 0b00011111) | ((liczba & 0b111) << 5);

Szukaj wzorców. Tu wystarczy przesunąć trzy najmłodsze bity liczby o 5 pozycji w lewo i wstawić to do portu D, któremu obecne wartości tych bitów zerujesz. Jeśli masz problemy z takimi operacjami, narysuj to sobie na kartce.

Co to znaczy "....."? Oglądałeś świecenie diodek w podczerwieni, czy nie?

Dobrze, że czytasz, ale masz też swój rozum i to on (plus zasady fizyki) ma Ci dyktować co robisz. Jeśli Twój czujnik jest ewidentnie przesterowany, to jaki sens ma trzymanie się ogólnych zasad z internetu?

Link do komentarza
Share on other sites

Ok kody wypróbuję po szkole, bo zaraz idę (czyli koło 19)

.... znaczyło, że jestem w trakcie testu. Testowałem manualnie, bez muxów i wszystkie diody ładnie świecą.

Też myślałem, nad takim kodem jak ten Twój ostatni, ale jestem jeszcze za mało doświadczony w C żeby zrobić coś takiego. Chyba muszę zainwestować w jakąś książkę o C dla AVR (Mógłbyś jakąś polecić? oczywiście w privie, żeby reklamy nie robić 😉)

Link do komentarza
Share on other sites

No ale masz testować układ który zbudowałeś, a nie same elementy składowe. W przypadku gdy skaszaniłeś montaż (na jakimkolwiek etapie), "manualny" test całej partii czujników wykazał 100% poprawności, a końcowy układ nie działa. Obejrzyj aparatem jak mux, komutowany np. co sekundę przemiata kolejne diodki. testy mają dowodzić poprawności poprzednich etapów projektu lub prowadzić do znajdowania błędów. Nie zakładaj, że coś zrobiłeś dobrze i tego nie trzeba sprawdzać, bo następnych testach zaczynasz mieć za dużo niewiadomych.

A na razie skup się na lekcjach 🙂 To też ważne. Gdzie się uczysz i czego?

Link do komentarza
Share on other sites

Oczywiście, wiem, że muszę o zrobić, ale tak jak mówiłem, wieczorkiem 🙂

[ Dodano: 09-10-2017, 18:56 ]

Coś chyba zepsułem, przy podmianie funkcji na Twoje, bo dostaję 2 pytajniki, 3 apostrofy i 3 pytajniku na terminalu 😃

  #include <stdlib.h>




#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 skan(uint16_t* wyniki, uint8_t dlugosc);
void USART_Init(unsigned int ubrr) ;
void USART_Transmit(char data ) ;
unsigned char USART_Receive( void ) ;
int getADC(int number);
void USART_TransmitString (char *str) ;
void ustawmux (int liczba) ;
int adc;
char adc1 [4];
#define CZUJNIKI 8
uint16_t wynikiADC[CZUJNIKI];
int main(void)
{
DDRD = 11100000;

ADMUX |= (0<<REFS0)|(0<<REFS1); //porównuje z AREF
       //0 tylko dla zasyganlizowania ze jest tam zero bo to nic nie zmienia
       ADCSRA |= (1<<ADEN)
	 |(1<<ADPS0)
  |(1<<ADPS1)
  |(1<<ADPS2);
 //    unsigned char d[] = {"xyz"};
 unsigned char odb;
   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {
   	odb = USART_Receive();
   	        if(odb =='0'){
   	skan(wynikiADC, CZUJNIKI);
   	USART_TransmitString (wynikiADC);


   }
   }
//_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(char data )
{

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

void USART_TransmitString (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;
}

void ustawmux (int liczba)
{
   PORTD = (PORTD & 0b00011111) | ((liczba & 0b111) << 5);
}

void skan(uint16_t* wyniki, uint8_t dlugosc)
{
  for (uint8_t kanal=0; kanal<dlugosc; kanal++)
  {
     ustawmux(kanal);
     _delay_us(100);
     wyniki[kanal] = getADC(0);
  }
}

[ Dodano: 09-10-2017, 19:34 ]

A, teraz zauważyłem pytanie czego się uczę...

Te, no

Jestem w 3 gimbie więc wszystkiego 🙂

W Krakowie jak coś 😉

[ Dodano: 09-10-2017, 19:38 ]

A ok, zapomniałem dać konwersji na chara.

  #include <stdlib.h>




#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 skan(uint16_t* wyniki, uint8_t dlugosc);
void USART_Init(unsigned int ubrr) ;
void USART_Transmit(char data ) ;
unsigned char USART_Receive( void ) ;
int getADC(int number);
void USART_TransmitString (char *str) ;
void ustawmux (int liczba) ;
int adc;
char adc1 [4];
#define CZUJNIKI 8
uint16_t wynikiADC[CZUJNIKI];
int main(void)
{
DDRD = 11100000;

ADMUX |= (0<<REFS0)|(0<<REFS1); //porównuje z AREF
       //0 tylko dla zasyganlizowania ze jest tam zero bo to nic nie zmienia
       ADCSRA |= (1<<ADEN)
	 |(1<<ADPS0)
  |(1<<ADPS1)
  |(1<<ADPS2);
 //    unsigned char d[] = {"xyz"};
 unsigned char odb;
   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {
   	odb = USART_Receive();
   	        if(odb =='0'){
   	skan(wynikiADC, CZUJNIKI);
   	 itoa(wynikiADC,adc1,10);
   	USART_TransmitString (adc1);


   }
   }
//_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(char data )
{

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

void USART_TransmitString (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;
}

void ustawmux (int liczba)
{
   PORTD = (PORTD & 0b00011111) | ((liczba & 0b111) << 5);
}

void skan(uint16_t* wyniki, uint8_t dlugosc)
{
  for (uint8_t kanal=0; kanal<dlugosc; kanal++)
  {
     ustawmux(kanal);
     _delay_us(100);
     wyniki[kanal] = getADC(0);
  }
}

Teraz dostaję ciągle 96

Link do komentarza
Share on other sites

Funkcji skan() świadomie przekazuję wskaźnik na tablicę zmiennych 16-bitowych, czyli adres elementu zerowego. A czego potrzebuje funkcja itoa, doczytałeś? Chyba wartości liczbowej a nie adresu w pamięci, prawda? Oj, chyba podręcznik do C bardzo by się przydał. Bierzesz się za pisanie w sumie nietrywialnego dzieła w języku, którego nie znasz. Sekwencję konwersji elementu tablicy na łańcuch i wypisanie przez UART musisz wykonać tyle razy ile masz czujników, za każdym razem dla kolejnego elementu. Szkoda czasu, nie rozumiejąc co robisz co chwila będziesz popełniał takie gafy. Proponuję: odpuść to na razie i poczytaj o C.

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

  #include <stdlib.h>




#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 skan(uint16_t* wyniki, uint8_t dlugosc);
void USART_Init(unsigned int ubrr) ;
void USART_Transmit(char data ) ;
unsigned char USART_Receive( void ) ;
int getADC(int number);
void USART_TransmitString (char *str) ;
void ustawmux (int liczba) ;
int adc;
char adc1 [4];
#define CZUJNIKI 8
uint16_t wynikiADC[CZUJNIKI];
int main(void)
{
DDRD = 0b11100000;

ADMUX |= (0<<REFS0)|(0<<REFS1); //porównuje z AREF
       //0 tylko dla zasyganlizowania ze jest tam zero bo to nic nie zmienia
       ADCSRA |= (1<<ADEN)
	 |(1<<ADPS0)
  |(1<<ADPS1)
  |(1<<ADPS2);
 //    unsigned char d[] = {"xyz"};
 unsigned char odb;
   USART_Init(USART_UBBR_VALUE);
   //InitServ();
   //int i;
   while(1) {
   	odb = USART_Receive();
   	        if(odb =='0'){
   	skan(wynikiADC, CZUJNIKI);

   	for(int a=0; a<8; a++){
   	 itoa(wynikiADC[a],adc1,10);
   	USART_TransmitString (adc1);
   	USART_TransmitString ("\n");
   	}
   }
   }
//_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(char data )
{

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

void USART_TransmitString (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;
}

void ustawmux (int liczba)
{
   PORTD = (PORTD & 0b00011111) | ((liczba & 0b111) << 5);
}

void skan(uint16_t* wyniki, uint8_t dlugosc)
{
  for (uint8_t kanal=0; kanal<dlugosc; kanal++)
  {
     ustawmux(kanal);
     _delay_us(100);
     wyniki[kanal] = getADC(0);
  }
}

Nowy kod z poprawionym błędami. Chyba 😉 Jestem na etapie wyboru książki.

Odpuściłbym sobie, ale to ma być projekt na 6 z techniki informatyki i jeszcze na dzień otwarty 😉 więc do marca by mi to pasowało ogarnać. A książkę będę czytał i przyswajał pewnie ze dwa lata 😉

Czy w klejony kod powinien działać dobrze?

Acha i jakie rezystory zastosować do tych czujek, bo mówisz, że te złe...

Link do komentarza
Share on other sites

Nie ja mówię, tylko Twoje eksperymenty. Też przecież je rozumiesz. Jeśli nowy kod działa, podaj wyniki to je omówimy. Przecież to tylko jeden z testów, nie pisałeś go dla wyglądu i elegancji tylko by coś sprawdzić. I co wyszło? Co mierzy ADC patrząc robotem w okno? Co na białej kartce? A co na czarnej? Liczby, wyniki, Kolego.

Dobrą książkę wciągniesz w tydzień. Potem jeszcze kilka projektów takich jak ten i zaczniesz czaić bazę 🙂

Link do komentarza
Share on other sites

Czy przetestowałeś samą funkcję wypisywania wyników? Nie? To dlaczego jej wierzysz? Dlaczego wiele wpisów jest podwójnych? Skąd wiesz, że wypisywany string jest zakończony bajtem 0x00? Przecież itoa() tego nie robi a bufor ma tylko miejsce na 4 znaki. Może oznaczaj (np. gwiazdką) print pierwszego wyniku, bo teraz to sieczka.

Zacznij od testów poszczególnych kawałków. Jeśli napiszesz takie spaghetti, to same niepewne funkcje nie mają prawa działać a cóż dopiero całość. Wywal wypisywanie wyników do funkcji i każdą przetestuj osobno z pustego maina. Wymyśl jak to zrobić. Możesz np. samodzielnie wypełnić tablicę wyników znanymi liczbami i kazać je wypisać, prawda? Zaczynaj pisanie od prostych rzeczy, sprawdzaj czy to działa i dopiero bazując na tym pisz następne rzeczy.

Wyobraź sobie, że próbujesz naprawić telewizor przy pomocy zepsutego oscyloskopu pokazującego głupoty...

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.