Skocz do zawartości

esio

Użytkownicy
  • Zawartość

    12
  • Rejestracja

  • Ostatnio

Reputacja

0 Neutralna

O esio

  • Ranga
    2/10
  • Urodziny 02.01.1986

Informacje

  • Płeć
    Mężczyzna
  • Lokalizacja
    Danzig
  • Zainteresowania
    bardzo dużo od automatów po historię XX wieku ;)
  • Zawód
    UNIX Admin
  • www
  1. Wybór języka zależy od preferencji i od tego co chce się osiągnąć. Ja do programowania mikrokontrolerów używam C, ale programując cokolwiek na PC bym tego nie uzył bo są o wiele lepsze, obiektowe języki programowania jak np. Ruby. Bezsensowne jest używanie C++ do zaprogramowania czegoś, co można napisać w jednej linijce w Perlu czy Bashu. Z drugiej strony, gdy mikrokontroler jest używany praktycznie na granicy możliwości to C, ewentualnie ze wstawkami assemblerowymi. Co do programowania to polecam zapoznanie się z jakimś systemem kontroli wersji, bardzo przydatne i ratuje czasami życie.
  2. Witam. Mam następujący problem z niedziałającym TWI. Mam kod na atmegę w C. /* Czujnik ultradzwiekowy sterowany z magistrali i2c C= 2010 Grzegorz Eliszewski grzegorz(małpa)eliszewski.pl esio.eu */ #define F_CPU 12000000UL // czestotliwosc kwarcu 12MHz #include <avr/io.h> #include <util/delay.h> // obsluga opoznien #include <compat/twi.h> // obsluga magistrali i2c #include <avr/wdt.h> // obsluga watchdoga #include <avr/interrupt.h> // przerwania volatile uint8_t time=124; // czas potrzebny na powrot odbitych ultradzwiekow volatile uint8_t value; // dane odebrane na magistrali TWI // deklaracje wystąpienia funcji void pomiar(void); void signal(unsigned int o); unsigned int distance(unsigned int time); void twi_init(char adres); // obsluga magistrali i2c // przerwanie od TWI SIGNAL (SIG_2WIRE_SERIAL) { switch(TWSR) //odczytanie bitu sterujacego { case 0x00: // nieoczekiwany start lub stop TWCR = (1<<TWSTO); // ustawienie 1 na bicie TWSTO = STOP! TWCR = (1<<TWINT); // ustawienie 1 na bicie TWINT = START! // w wypadku, gdy pojawi sie nieoczekiwany start lub stop na TWI to: // 1. transmisja jest zatrzymywana // 2. transmisja startuje ponownie break; // TWI w trybie MASTER - RECIVER case 0x60: // TWSR = 0b11000000 // wlasny SLA+W odebrany ACK nadane break; case 0x68: // utrata kontroli nad magistrala, master odlaczony // wlasny SLA+W odebrany ACK nadane break; case 0x80: // transmisja - odbior! // 1. odebrano SLA+W (adres + W jak write, czyli zapis do slave :)) // 2. odebrano dane // 3. nadano ACK = bit potwierdzenia, oczekuje dalszej transmisji // value = TWDR; // TWDR = rejestr z danymi TWI if (TWDR == 0x01) // jezeli TWDR = 0b00000001 { //pomiar(); // wykonanie pomiaru PORTD = 0xFF; } break; case 0x88: // transmisja - odbior! // 1. odebrano SLA+W // 2. odebrano dane // 3. nie nadano ACK (nadano NACK), potwierdzenie i koniec transmisji value = TWDR; // TWDR = rejestr z danymi TWI if (value == 0x01) // jezeli TWDR = 0b00000001 { PORTD = 0xFF; // pomiar(); // wykonanie pomiaru } break; // TWI w trybie MASTER - TRANSMITER case 0xA8: // transmisja - nadawanie! // 1. odebrano SLA+R (adres + odczyt ze slave) // 2. nadano ACK TWDR = time; // zapisanie zmiennej czasu do TWDR TWCR = (1<<TWINT) | (1<<TWEN); // wyczyszczenie TWINT // wlaczenie TWI poprzez 1 na TWEN // przygotowanie do wyslania danych while(!(TWCR & (1<<TWINT))); // transmisja danych <- patrz dataszit // sprawdzanie statusu TWI if ((TW_STATUS) & (0xF8 != TW_MT_DATA_ACK)) { // blad nadawania } break; } } // funkcja generujaca sygnal, o = ilosc okresow // generowanie sygnalu zblizonego do 40kHz, zmiana stanu co 12us zamiast co 12.5us void signal(unsigned int o) { int i; DDRB = 0xFF; // ustawienie portu B jako wyjscie // sbi(DDRB,6); // sbi(DDRB,2); for(i=0;i<o;i++) { // ustaw 1 na PB2 i 0 na PB1 PORTB = 0x04; _delay_us(12); // czekaj 12us PORTB = 0x02; _delay_us(12); } // ustawienie stanu niskiego na porcie nadajnika // tlumienie nadajnika PORTB = 0x00; _delay_ms(1); // odczekanie 1ms = tlumienie nadajnika } // pomiar odleglosci, o = ilosc okresow // wyslanie sygnalu i odbior odbitego od przeszkody void pomiar(void) { TCNT1 = 0x0000; // zerowanie licznika T1 signal(5); // emitowanie 5 okresow sygnalu sterujacego // _delay_ms(10); // odczekanie 10ms przed pomiarem TCCR1B = 0x05; // start T1 jako licznik z prescalerem /1024 0b00000010 // zliczanie co 12Mhz/1024 // czestotliwosc 11.71875kHz // czas jednego impulsu to okolo 85us while(TCNT1 < 0x0FA0) // dopoki licznik nie doliczy do 0x0FA { while(bit_is_clear(ADCSRA,ADIF)); // koniec pomiaru na ADC { // jezeli wartosc na ADC jest mniejsze niz !czulosc! to przerwij odliczanie czasu if(ADCH > 100) { time = TCNT1; // przepisanie wartosci licznika do zmiennej TCNT1 = 0xFFFF; // przepelnienie licznika == wyjscie z petli } } } TCCR1B = 0x00; // wylaczenie licznika // wdt_reset(); // resetowanie watchdoga /* for(echo=0;echo<666;echo++) // petla obliczajaca odleglosc { if(bit_is_set(ACSR,ACO)) // jezeli odebrano sygnal powracajacy { break; // wyjscie z petli } }*/ // return time; } // obliczanie rzeczywistej odleglosci w zaleznosci od czasu // sprawdzic jak to ma sie do siebie :P unsigned int distance(unsigned int time) { unsigned int czas_s; if (time < 60 ) // 60 przebiegow zegara czyli okolo 5ms // mierzymy tylko w jedna strone // wynika z opoznienia na zwarcie czujnikow { return 0; } else { return 50 + time*1.5; } // V_dzwieku w powietrzu +/- 343 m/s // S = (V*t)/2 || droga [m] = predkosc [m/s] * czas [s] // czas [s] = time * 0.000085 | jeden cykl zegara to 85us // jeden cykl zegara to okolo 1.5cm } // inicjacja i konfiguracja magistrali TWI void twi_init(char adres) { DDRC = 0b00000000; // konfiguracja portu C jako wyjscie PORTC = 0b00110011; // PC5 PC4 jako wyjscie TWAR = adres; // przypisanie adresu TWSR = 0; // zerowanie statusu TWI TWCR = 0xC5; // ustawienie TWCR 0b11000101 // TWINT - oczekiwanie na odpowiedzi, uaktywnienie przerwania // TWEA - wlaczenie generowania ACK // TWEN - aktywacja obslugi TWI, aktywacja interface TWI // TWIE - uaktywnienie obslugi przerwan TWI } // funkcja glowna int main(void) { twi_init(0x02); // inicjacja TWI z adresem 0x02 // konfiguracja ADC ADMUX = 0x61; // konfiguracja działania ADC 0b01100001 ADCSRA = 0xC6; // start ADC prescaler /64, f = 187.5kHz // wdt_enable(WDTO_250MS); // watchdog na 250ms sei(); // wlaczenie obslugi przerwan DDRD = 0xFF; // port D jako wyjscie } Problem polega na tym, że jak wysyłam do czujnika na adres 0x10 wartość 0x01 to nie zapala mi się dioda, tak samo z odczytem. Testuje za pomocą arduino. Nie mam pojęcia co robię źle, to pierwsze moje spotkanie z TWI i nie wiem, może popełniłem jakiś prosty błąd. Wrzuciłem program zmodyfikowany do tego, żeby testować sam interfejs. Kod arduino za pomocą którego testuję magistralę: Kod: #include <Wire.h> int ledPin = 13; void setup() { Serial.begin(9600); Wire.begin(); // join i2c bus (address optional for master) pinMode(ledPin, OUTPUT); } int zz = 0; byte x = 0x01; void loop() { Wire.beginTransmission(0x10); // transmit to device #4 //Wire.send("x is "); // sends five bytes Wire.send(0x01); // sends one byte Wire.endTransmission(); // stop transmitting digitalWrite(ledPin, HIGH); // set the LED on // wait for a second Wire.requestFrom(0x10, 8); if (Wire.available()) { zz = Wire.receive(); } else zz = 15; //x++; Serial.print(zz); digitalWrite(ledPin, LOW); delay(500); } Serial pokazuje, że magistrala nie jest gotowa, czyli wywala liczbe 15... zamiast odczytu z czujnika. Przewaliłem tony dokumentacji i nadal nie wiem co jest...
  3. O! Tego to nie wiedziałem. Rozumieme, że żaden z at91sam7 nie ma hosta usb?
  4. W zupełności starczy Ci AT91sam7x256, na pewno możesz zapisywać na SD, ma rs232, z tego co wiem ma także hosta USB. Do tego kostka jest śmiesznie tania.
  5. Widziałem Twoje schematy. Niestety nie zauważyłem żadnego konwertera poziomów oprócz tego do USB. Jak zamieniasz np. X SDL(rozumiem, że 3.3V) na SDL (5V)? Masz to podłączone bezpośrednio? EDIT: Dobra sorry, jest to opisane w pracy pisemnej.
  6. Mam pytanie. Czy ktoś łączył mikrokontroler ARM (dokładnie to AT91SAM7x256) z Atmegą8 za pomocą interfejsu i2c? Nie wiem do końca jak to zrobić sprzętowo, bo wyjścia arma mają maksymalne napięcie 3,3V, a atmegi 5V. Jak to połączyć? Jakiś konwerter napięć? Może sterowanie przez tranzystory? Tak na dobrą sprawę nie wiem do końca jak to zrobić, jakby ktoś miał jakiś pomysł to byłbym szczęśliwy za podpowiedź.
  7. Witam, mam problem z kompilacją kodu w C za pomocą arm-elf-gcc. Mam problem podczas kompilacji przykładowego programu z książki "Mikrokontrolery AT91SAM7 w praktyce". Dostaje taki błąd: [esio@yggdrasil master]$ make -------- begin (mode: ROM_RUN) -------- arm-elf-gcc (GCC) 4.5.0 Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Linking: main.elf arm-elf-gcc -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -DAT91SAM7X256 -Os -Wall -Wcast-align -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=Cstartup.lst -I./include -MD -MP -MF .dep/main.elf.d Cstartup.o main.o Cstartup_SAM7.o --output main.elf -nostartfiles -Wl,-Map=main.map,--cref -lc -lm -lc -lgcc -Tinclude/AT91SAM7X256-ROM.ld /usr/bin/arm-elf-ld: this linker was not configured to use sysroots collect2: ld returned 1 exit status make: *** [main.elf] Błąd 1 Może ktoś pisał programy na army pod linuksem i wie jak to obejść?
  8. rasta, Ja całkowicie zdaję sobie z tego sprawę, naprawdę nie musisz mi tłumaczyć jak działają enkodery. Już niedługo będę miał nawet odpowiednie wykształcenie, aby to wiedzieć, na razie jestem na 10 semestrze. Ja zrozumiałem pytanie autora tematu na tej podstawie, że zapamiętuje co mikrokontroler wysyła do silników i robi tą samą sekwencję podczas drugiego przejazdu. Nie ma to racji bytu, bo jak masz stosunkowo długą trasę i dużo zakrętów to błąd rzędu 2mm na starcie rośnie ci do kilku centymetrów na mecie. Jeżeli chodzi o enkodery to myślę, że dokładność byłaby większa. Jeszcze najlepszym rozwiązaniem byłoby połączenie czujników i zapamiętywania trasy. Robot mógłby "z grubsza" przewidzieć w jaką stronę jest zakręt, dzięki temu zareagować wcześniej. Szczególnie przydatne byłoby to przy pokonywaniu zakrętów o kącie prostym, na filmach widzimy często, że robot wpada na pełnej i często przejeżdża zakręt. Można byłoby to przewidzieć i kazać mu zwolnić. Ja myslę, że i tak jeżeli chodzi o LF to algorytm jest bardzo ważny.
  9. Funkcja prędkości od napięcia. Nie stosowałem enkoderów. Enkodery to już nie jest "zbieranie informacji z silników", myślę, że jakbym zastosował enkodery to byłoby dokładniej.
  10. Nie stosowałem enkoderów. Po prostu sterowałem silnikami i na podstawie funkcji prędkości od napięcia zliczałem odległość. Będy niby nie były duże ale już na dystansie metra miałem różnicę rzędu 15 cm.
  11. Przerabiałem zliczanie odległości na podstawie danych z silników, niestety nie zdaje to egzaminu. Pomysł z predykcją jest bardzo fajny, wystarczy mieć tylko odpowiednio szybki mikrokontroler, który pozwoli na bardzo szybkie zbieranie informacji z czujnikow, do tego bardzo duża ilość czujników (czyjniki ściśle przylegające do siebie). Niestety jeszcze dużo projektów bazuje na kopiowaniu istniejących rozwiązań.
  12. Czy jest możliwość zmniejszenia zasięgu czujnika? Tak do 30cm?
×
×
  • Utwórz nowe...