Skocz do zawartości

Elvis

Użytkownicy
  • Zawartość

    2613
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    195

Wszystko napisane przez Elvis

  1. Nie chciało mi się wierzyć, że enum nie działa. I słusznie, pobrałem kompilator arduino i sprawdziłem. Działa dokładnie jak w C. Nie lubię wklejać kodów na forum, ale tym razem zrobię wyjątek: #include <LiquidCrystal.h> //biblioteka do obslugi LCD enum { KIERUNEK_STOP, KIERUNEK_PROSTO, KIERUNEK_W_LEWO, KIERUNEK_OW_LEWO, KIERUNEK_W_PRAWO, KIERUNEK_OW_PRAWO }; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //LCD podpięty pod te piny int irLPin = 0; // Analog PIN 0; Left IR int irCPin = 1; // Analog PIN 1; Center IR int irRPin = 2; // Analog PIN 2; Right IR int irLval; // Left IR int irCval; // Center IR int irRval; // Right IR const int lewy1Pin = 32; // lewy silnik 32 const int lewy2Pin = 34; // lewy silnik 34 const int prawy1Pin = 36;// prawy 36 const int prawy2Pin = 38;//prawy 36 const int lewyonPin = 8; // wlacz lewy H-bridge const int prawyonPin = 9; // wlacz prawy H-bridge const int ledPin = 13; // LED int j; int czulosc = 500; //czulosc czujnikow IR const int czujnik = 5; int dystans = 0; int i; int PWM1 = 127; //wypelnienie PMW max 255 tu 1/2 max int PWM2 = 64; //wypelnienie PMW tu 1/4 max int kierunek = KIERUNEK_PROSTO; // kierunek jazdy robota void setup() { lcd.begin(16, 2); // inicjuj lcd 16x2 pinMode(irLPin, INPUT); // ustawienie pinu czujnikow jako wejscia pinMode(irCPin, INPUT); pinMode(irRPin, INPUT); pinMode(ledPin, OUTPUT); // ustawienie pinu LED jako wyjscia // ustawienia wyjsc silnika pinMode(lewy1Pin, OUTPUT); pinMode(lewy2Pin, OUTPUT); pinMode(prawy1Pin, OUTPUT); pinMode(prawy2Pin, OUTPUT); pinMode(lewyonPin, OUTPUT); pinMode(prawyonPin, OUTPUT); pinMode(czujnik, INPUT); // ustawienie wyjscia SHARP // wlaczenie silnikow lewy,prawy analogWrite(lewyonPin, 255); //wlacz prawy z pelnym wypelnieniem PWM analogWrite(prawyonPin, 255);//wlacz lewy z pelnym wypelnieniem PWM } void loop() { Look(); decyzja(); sterowanie(); LCD(); //sprawdzanie(); } void Look() //sprawdz czujniki { for (j =0; j <3; j++) { irLval = analogRead(irLPin); irCval = analogRead(irCPin); irRval = analogRead(irRPin); dystans = analogRead(czujnik); //oczytaj warotsc z SHARP } //delay(50); } void jedz() // jedz do przodu { analogWrite(lewyonPin, PWM1); //wlacz prawy analogWrite(prawyonPin, PWM1);//wlacz lewy digitalWrite(lewy1Pin, LOW); // do przodu sil1 digitalWrite(lewy2Pin, HIGH); // do przodu sil1 digitalWrite(prawy1Pin, LOW); // do przodu sil2 digitalWrite(prawy2Pin, HIGH);// do produ sil2 } void wstecz()//jedz w tyl { analogWrite(lewyonPin, PWM1); //wlacz prawy analogWrite(prawyonPin, PWM1);//wlacz lewy digitalWrite(lewy1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(lewy2Pin, LOW); // set leg 2 of the H-bridge low digitalWrite(prawy1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(prawy2Pin, LOW); } void tyllewo() { analogWrite(lewyonPin, PWM1); //wlacz prawy analogWrite(prawyonPin, PWM2);//wlacz lewy digitalWrite(lewy1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(lewy2Pin, LOW); // set leg 2 of the H-bridge low digitalWrite(prawy1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(prawy2Pin, LOW); } void tylprawo() { analogWrite(lewyonPin, PWM2); //wlacz prawy analogWrite(prawyonPin, PWM1);//wlacz lewy digitalWrite(lewy1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(lewy2Pin, LOW); // set leg 2 of the H-bridge low digitalWrite(prawy1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(prawy2Pin, LOW); } void owlewo() //skrec ostro w prawo { analogWrite(lewyonPin, PWM1); //wlacz prawy analogWrite(prawyonPin, 0);//wlacz lewy digitalWrite(lewy1Pin, LOW); // przod digitalWrite(lewy2Pin, HIGH); // przod digitalWrite(prawy1Pin, LOW); // tyl digitalWrite(prawy2Pin, HIGH); // tyl } void wlewo() //skrec w prawo { analogWrite(lewyonPin, PWM1); //wlacz prawy analogWrite(prawyonPin, PWM2);//wlacz lewy digitalWrite(lewy1Pin, LOW); // przod digitalWrite(lewy2Pin, HIGH); // przod digitalWrite(prawy1Pin, LOW); // tyl digitalWrite(prawy2Pin, HIGH); // tyl } void wprawo() // skrec w lewo { analogWrite(lewyonPin, PWM2); //wlacz prawy analogWrite(prawyonPin, PWM1);//wlacz lewy digitalWrite(lewy1Pin, LOW); // tyl digitalWrite(lewy2Pin, HIGH); // tyl digitalWrite(prawy1Pin, LOW); // przod digitalWrite(prawy2Pin, HIGH); // przod } void owprawo() // skrec ostro w lewo { analogWrite(lewyonPin, 0); //wlacz prawy analogWrite(prawyonPin, PWM1);//wlacz lewy digitalWrite(lewy1Pin, LOW); // tyl digitalWrite(lewy2Pin, HIGH); // tyl digitalWrite(prawy1Pin, LOW); // przod digitalWrite(prawy2Pin, HIGH); // przod } void stoj() { analogWrite(lewyonPin, 0); //wlacz prawy analogWrite(prawyonPin, 0);//wlacz lewy digitalWrite(lewy1Pin, LOW); // tyl stop digitalWrite(lewy2Pin, LOW); // tyl stop digitalWrite(prawy1Pin, LOW); // przod stop digitalWrite(prawy2Pin, LOW); // przod stop } void LCD() { lcd.setCursor(0,0); lcd.print("L"); lcd.print(irLval); //lcd.setCursor(0,5); lcd.print("C"); lcd.print(irCval); //lcd.setCursor(0,13); lcd.print("R"); lcd.print(irRval); //delay(100); //lcd.setCursor(0,0); //lcd.print("L "); //lcd.setCursor(0,5); //lcd.print("C "); //lcd.setCursor(0,13); //lcd.print("R "); //delay(100); lcd.setCursor(1,1); lcd.print("Dystans:"); // wyświetl wartość dla dystansu lcd.print(dystans); delay(100); } void decyzja () { if ((irLval >czulosc) && (irCval <czulosc) && (irRval >czulosc)) { kierunek = KIERUNEK_PROSTO; } else if((irLval <czulosc) && (irCval >czulosc) && (irRval >czulosc)) { kierunek = KIERUNEK_W_PRAWO; } else if((irLval >czulosc) && (irCval >czulosc) && (irRval <czulosc)) { kierunek = KIERUNEK_W_LEWO; } else if((irLval <czulosc) && (irCval <czulosc) && (irRval >czulosc)) { kierunek = KIERUNEK_OW_PRAWO; } else if((irLval >czulosc) && (irCval <czulosc) && (irRval <czulosc)) { kierunek = KIERUNEK_OW_LEWO; } if((irLval >czulosc) && (irCval >czulosc) && (irRval >czulosc)) { kierunek = KIERUNEK_STOP; } } void sterowanie() { static int kierunek_poprzedni = KIERUNEK_STOP; // poprzedni kierunek jazdy if (kierunek_poprzedni==kierunek) return; switch (kierunek) { case KIERUNEK_PROSTO: jedz(); break; case KIERUNEK_W_LEWO: wlewo(); break; case KIERUNEK_OW_LEWO: owlewo(); break; case KIERUNEK_W_PRAWO: wprawo(); break; case KIERUNEK_OW_PRAWO: owprawo(); break; case KIERUNEK_STOP: default: stoj(); break; } kierunek_poprzedni=kierunek; } [ Dodano: 22 Mar 10 10:02 ] Nigdy wcześniej arduino nie używałem, ale jak już pobrałem postanowiłem sprawdzić, co to takiego. Więc jest to najzwyklejsze C, kompilator to najzwyklejszy WinAVR, czyli gcc. W katalogu arduino-0018\hardware\tools\avr jest cały pakiet. Czyli jak ktoś poznał arduino to przy okazji nauczył się C. Poza WinAVR arduino daje jakieś IDE napisane w Javie (ja wolę AVRStudio, ale co kto lubi). Najciekawsze są biblioteki. W katalogu arduino-0018\libraries są gotowe biblioteki do obsługi LCD, eeprom, servo, silnika krokowego i wielu innych. Napisane są w standardowym C++, więc nawet jeśli ktoś nie planuje używać arduino może te biblioteki wykorzystać.
  2. To nieprawda. ASCII jest 7-bitowe, jeśli nie wierzysz sprawdź na wikipedii. Co prawda używa się 8 bitowego kodowania, ale to już nie jest ascii. Kody >127 nie należą do standardu.
  3. W C++ można pominąć enum przed deklaracją zmiennej, więc kod był w C++ poprawny. Niestety w C trzeba powtarzać enum przed typem zmiennej.
  4. Nie podłączaj nigdy bezpośrednio - zawsze przez rezystor 100-470ohm.
  5. Jeśli już to: enum NKierunkek kierunek = KIEUNEK_PROSTO; Ale sprawdzałem pod gcc i keil enum {X1, X2 }; i kompilowało bez problemu.
  6. Jest jak najbardziej poprawna. Ma tylko taką wadę, że za rok ciężko sobie przypomnieć co znaczy "kierunek = 2". Jeśli enum nie działa można wykorzystać instrukcję #define, czyli #define KIERUNEK_PROSTO 1 #define KIERUNEK_STOP 2 #define KIERUNEK_PRAWO 3 #define KIERUNEK_LEWO 4
  7. Ja bym proponował małą zmianę - chyba nieco lepiej byłoby mieć rezystory R1-R5 (podciągające) na płytce z czujnikami (o ile tylko jest miejsce). Po pierwsze można wtedy przetestować płytkę czujników zwykłym multimetrem (będzie sygnał napięciowy). Po drugie płytkę można będzie łatwo wykorzystać np. w kolejnym robocie.
  8. Tak jak woltomierz, czyli równolegle. Ale na wszelki wypadek sprawdź co piszą w instrukcji.
  9. Możesz podzielić funkcję sterowanie() na dwie części. Oddzielnie podejmować decyzję (logika programu) gdzie jechać, oddzielnie wykonywać polecenie (sterowanie silnikiem). Dodatkowo warto przechowywać ostatnią decyzję w zmiennej np. globalnej. Czyli: 1) zdefiniuj zmienną globalną: int kierunek = KIERUNEK_PROSTO; ; 2) zdefiniuj wartości dla zmiennej kierunek: enum { KIERUNEK_PROSTO, KIERUNEK_STOP, KIERUNEK_PRAWO, KIERUNEK_LEWO, ... }; 3) zamiast funkcji sterowanie() utwórz 2 funkcje: ustal_kierunek() i steruj_silnikiem() void ustal_kierunek() { if ((irLval >czulosc) && (irCval <czulosc) && (irRval >czulosc)) { kierunek = KIERUNEK_PROSTO; } else if((irLval <czulosc) && (irCval >czulosc) && (irRval >czulosc)) { kierunek = KIERUNEK_PRAWO; } ... } void steruj_silnikiem() { switch (kierunek) { case KIERUNEK_PROSTO: jedz(); break; case KIERUNEK_STOP: .... } } W takiej wersji, jeśli funkcja ustal_kierunek() nie zmieni kierunku, robot będzie jechał zgodnie z poprzednią decyzją. A przy okazji masz oddzielony kod podejmujący decyzje od wykonawczego.
  10. Chyba wiem dlaczego nie działa. Trzeba zdefiniować stałą STARTUP_FROM_RESET. W oknie "Project Explorer" kliknij prawym klawiszem na projekcie i wybierz Properties. Następnie poszukaj "Preprocessor Options"->"Preprocessor Definitions" i dodaj STARTUP_FROM_RESET. [ Dodano: 18 Mar 10 09:47 ] Dwa słowa wyjaśnienia. Przed uruchomieniem funkcji głównej programu, czyli main() dzieje się całkiem sporo. Warto otworzyć plik "Philips_LPC210X_Startup.s" - jest tworzony przez CrossStudio podczas zakładania projektu. W tym pliku zdefiniowany jest wektor przerwań oraz procedura obsługi reset-u (czyli prawdziwy początek programu). Linia 150 i kolejne definiuje od czego nasz program się rozpoczyna: reset_handler_address: #ifdef STARTUP_FROM_RESET .word reset_handler #else .word reset_wait #endif Czyli jeśli nie ma zdefiniowanej stałej STARTUP_FROM_RESET po resecie procesor przechodzi do fragmentu reset_wait gdzie znajduje się nieskończona pętla. Dopiero jeśli zdefiniujemy STARTUP_FROM_RESET po resecie następuje skok do reset_handler i program rozpoczyna się normalnie (reset_handler m.in. konfiguruje PLL, dostęp do pamięci Flash). Takie działanie może wydawać się nieco dziwne, ale jest bardzo przydatne podczas pracy z JTAG-iem. W procesorach ARM (nie wiem czy wszystkich, LPC na pewno) JTAG nawiązuje połączenie z procesorem gdy ten już pracuje. Czyli przez JTAG wykonywany jest reset, procesor wykonuje kawałek programu i dopiero wtedy JTAG zatrzymuje jego działanie (oraz uruchamia program ponownie, tym razem z debuggerem). Oznacza to, że początek programu wykonywany jest 2 razy, a co gorsze jeśli na początku programu jest coś co wyłączy JTAG nie będzie możliwości pracy z JTAG-iem, nie będzie można nawet wgrać innego programu (pozostaje możliwość przez RS232). Aby temu zapobiec CrossStudio domyślnie tworzy nieskończoną pętlę na początku programu. Gdy nasz program jest już przetestowany i gotowy, można zdefiniować stałą STARTUP_FROM_RESET i pozbyć się pętli przed programem.
  11. Pamiętaj, żeby odłączyć przewód programujący - inaczej procesor będzie w trybie bootloadera. Czyli spróbuj tak: odłącz wszystkie przewody od płytki, następnie podłącz tylko zasilanie. [ Dodano: 17 Mar 10 10:53 ] Szkoda, że nie uruchomiłeś JTAG-a. Łatwiej jest diagnozować błędy. Na początek można uruchomić program w trybie debug i sprawdzić czy w ogóle działa. Przy okazji - na pewno masz LED podpięty tam gdzie był w module olimex-a?
  12. Prawdopodobnie najwięcej zajmuje biblioteka liczb zmiennopozycyjnych. Lepszym rozwiązaniem jest stablicowanie wyników, a następnie interpolowanie. Dokładność jest oczywiście mniejsza, ale powinna wystarczyć. Najprościej jest zrobić tak: 1) wybierasz liczbę punktów (czyli dokładność), np. 32 2) dzielisz przedział wyników na 32 równe (tak jest najłatwiej) części 3) w excelu wyliczasz ile wynosi wynik dla każdego przedziału 4) wyniki wstawiasz do programu jako tablicę liczb unsigned int Następnie odczytujesz dane z czujnika (dana[1]) i na jej podstawie wybierasz gotowy wynik z tablicy. Lepszą dokładność uzyskasz dodając interpolację wyników.
  13. Jakby co to mam program w C. W bascomie nie programuję, ale pewnie jest jeszcze łatwiej - wystarczy w module podłączonym do HM-T868S wysłać dane na uart, a w podłączonym do HM-R868S odczytać. HM_FSK.zip
  14. Dużo zależy od środowiska w którym zamierzasz programować. KT-LINK współpracuje z CrossStudio oraz OpenOCD. CrossStudio to całkiem rozsądny wybór, jeśli chodzi o relację jakość/cena. OpenOCD to jeszcze tańsze wyjście - współpracuje z darmowymi narzędziami (GNU). Natomiast narzędzia Keil-a są, delikatnie mówiąc, dość drogie. Kompilator to koszt rzędu 3000 euro.
  15. Logon, tutaj masz opis liczb binarnych http://pl.wikipedia.org/wiki/Dw%C3%B3jkowy_system_liczbowy Bit to cyfra w zapisie binarnym, może mieć wartość 0 lub 1. Najlepiej poproś nauczyciela matematyki, żeby ci wytłumaczył na czym to wszystko polega.
  16. Decado, do poukładania nazwisk zawodników użyj tabeli. Jeśli nie chcesz jej mieć na stronie to ustaw szerokość ramki na zero (border="0").
  17. Dżony, przeczytaj dokładnie instrukcję modułów mobota. $crystal = 8000000 $baud = 9600 Moduły pracują z prędkością 57600 nie 9600.
  18. 1wire na pewno da radę, ale jest dość skomplikowana. UART jest raczej do komunikacji 2 układów, przy większej liczbie trzeba się trochę nagimnastykować. Polecam I2C (inaczej nazywane TWI). Pozwala na łatwą współpracę do 32 układów i wymaga tylko 2 linii. Poza tym jest sprzętowo wspierana przez układy atmega. SPI jest najłatwiej zrealizować, ale wymaga więcej linii.
  19. Nie używałem tych modułów. O ile widzę zalecane jest użycie dodatkowego enkodera/dekodera. Inaczej działanie może wymagać programowego kodowania i dekodowania danych.
  20. Zobacz tutaj: https://www.forbot.pl/forum/topics20/radiowa-transmisja-danych-czyli-robot-zdalnie-sterowany-vt2207.htm?highlight=radiowa Najprościej podłączyć HM-T868S do nadajnika, HM-R868S do odbiornika. Będzie działać, chociaż lepiej w programie dodać kontrolę błędów - inaczej sporo zakłóceń może przechodzić. [ Dodano: 18 Lut 10 07:47 ] Jeśli koniecznie chcesz 433MHz zamiast 868MHz to musisz poszukać nieco innych modułów.
  21. Spróbuj zamienić kolejność instrukcji: WYSW_PORT&=akt_wysw[0]; LED_PORT=wysw_znak(sekundy%10); Ewentualnie dodaj małe opóźnienie
  22. Już sobie poradziłem. Przy podanych na schemacie elementach nie chciało mi za nic ruszyć. Zmieniłem wg. układu w AVT-2822 i poszło. Na pewno masz filtry dobrze policzone?
  23. regrom, miał rację. Pomogło wygaszanie przed przełączeniem do kolejnej cyfry. Nie jest prawdą, że: W programie najpierw przełączasz na kolejny segment: WYSW_PORT&=akt_wysw[5]; co powoduje, że na bardzo krótko, ale zawsze zapalasz na nim cyfrę z poprzedniego. Dopiero później wykonujesz: LED_PORT=wysw_znak(godziny/10); co ustawia poprawną wartość. Takie przełączanie jest krótkie, ale jak sam zaobserwowałeś widoczne. Pomysł 3) wcale nie jest zły - efekt byłby o wiele mniej widoczny, gdyby tranzystor przełączał się szybciej.
  24. A co program wyświetla? [ Dodano: 14 Lut 10 10:34 ] Próbowałeś w case 2: wyświetlać inne cyfry? [ Dodano: 14 Lut 10 10:34 ] Możesz jeszcze dodać volatile do deklaracji zmiennych, czyli volatile unsigned int godziny, minuty, sekundy,dziesiatki,jednosci;
  25. nes86, mam małą prośbę. Wykonałem układ wg. Twojego schematu, niestety mam problemy z uruchomieniem. Oscylogram mam daleki od tego co podałeś. Użyłem czujnika BPU-1640TOAH12, na pinach sygnał nadawania jest jak powinien. Nie bardzo natomiast mogę zobaczyć odpowiedź. Chyba tylko dzwonienie widzę na oscyloskopie. Mam taką prośbę, mógłbyś podać dokładniejszy opis, gdzie i jaki sygnał powinien się pojawić?
×
×
  • Utwórz nowe...