Fórum témák

» Több friss téma
Fórum » AVR - Miértek hogyanok
 
Témaindító: pakibec, idő: Márc 11, 2006
Témakörök:
WinAVR / GCC alapszabályok:
1. Ha ISR-ben használsz globális változót, az legyen "volatile"
2. Soha ne érjen véget a main() függvény
3. UART/USART hibák 99,9% a rossz órajel miatt van
4. Kerüld el a -O0 optimalizációs beállítást minden áron
5. Ha nem jó a _delay időzítése, akkor túllépted a 65ms-et, vagy rossz az optimalizációs beállítás
6. Ha a PORTC-n nem működik valami, kapcsold ki a JTAG-et
Bővebben: AVR-libc FAQ
Lapozás: OK   568 / 840
(#) kraissadam hozzászólása Okt 12, 2013 /
 
Sziasztok!
Egy kis segítségre lenne szükségem!
Kezdő avr programozó vagyok !
Lenne egy ilyen problémám , hogy az istenért nem tudom lefordítani a programomat!
Nem értem mi a baj kérlek segítsetek!

Előre is köszönöm!

kep.JPG
    
(#) zombee válasza kraissadam hozzászólására (») Okt 12, 2013 /
 
Az elérési útban nem lehet se szóköz, se ékezetes karakter. Nálad mindkettő ott van.
Ez már nagyon régi AVR Studio - valójában WinAVR - hiba, nem is értem miért nem került ki
a "WinAVR / GCC alapszabályok" közé, megérdemelne egy fél sort főleg a kezdőknek!
A hozzászólás módosítva: Okt 12, 2013
(#) kurosaki hozzászólása Okt 12, 2013 /
 
Sziasztok szeretnék egy gombot beiktatni ami egy változót növel mikor meg nyomom a gombot.
Elvileg jó mert érzékeli ha meg nyomom a gombot de semmi sem történik.A program elindul mert belépteti a kapcs=1 be de ha meg nyomom a gombot semmi se történik se a 4-es led nem kapcsol-be de nem is lépteti tovább. Mit ronthattam el?
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3.  
  4. #define PLAY1_BE()    PORTB |=  (1<<PB0)
  5. #define PLAY1_KI()    PORTB &= ~(1<<PB0)
  6.  
  7. #define PLAY2_BE()    PORTB |=  (1<<PB1)
  8. #define PLAY2_KI()    PORTB &= ~(1<<PB1)
  9.  
  10. #define PLAY3_BE()    PORTB |=  (1<<PB2)
  11. #define PLAY3_KI()    PORTB &= ~(1<<PB2)
  12.  
  13. #define PLAY4_BE()    PORTB |=  (1<<PB3)
  14. #define PLAY4_KI()    PORTB &= ~(1<<PB3)
  15.  
  16. //-------------------------------------
  17. void m_delay_10ms(unsigned long val) {
  18.         //-------------------------------------
  19.         while(val--) _delay_ms(10);
  20. }
  21.  
  22. //-------------------------------------
  23. int main(void) {
  24. int kapcs;
  25.         //-------------------------------------
  26.        
  27.        
  28.         DDRB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2)|(1<<PINB3);
  29.         DDRB &= ~(1 << PINB4);    
  30.         PORTB |= (1 << PINB4);    
  31.         kapcs = 0;
  32.        
  33.         while(1) {
  34.         if (PINB4 & (1 << PINB4)) {  
  35.                
  36.                 PLAY4_BE();
  37.         }
  38.         else
  39.         {
  40.                  kapcs++;
  41.         }
  42.        
  43.         if (kapcs == 1)
  44.         {
  45.                 PLAY1_BE();
  46.         }
  47.         else{PLAY1_KI();
  48.         }
  49.                 if (kapcs == 2)
  50.                 {
  51.                         PLAY2_BE();
  52.                 }
  53.                 else{PLAY2_KI();
  54.                 }
  55.                
  56.                                 if (kapcs == 3)
  57.                                 {
  58.                                         PLAY3_BE();
  59.                                 }
  60.                                 else{PLAY3_KI();
  61.                                 }
  62.                                
  63.         return 0;
  64. }
  65.  
  66. }
(#) zombee válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
Nézd meg valamelyik ".inc" definíciós fájlt, mindegy melyik AVR-hez, az eredmény ugyanaz lesz
ha benne megkeresed a "PINB4"-re mit ír. Csak egy szám natúrba, ami mindig "4"-et ad vissza
és semmi köze a portlábakhoz. Szerintem neked valami ilyesmi kell:
  1. PINB & (1<<4)
  2. //vagy:
  3. !(PINB & (1<<4))

De ezt a sort még én se tudom mire vélni:
  1. if (PINB4 & (1 << PINB4))

Ha gombnyomást és elengedést akarsz érzékelni, akkor tárolni kell az előző állapotot!
  1. uint8_t elozo = (PINB & (1<<4));  //inicializálás!
  2. if(elozo && !(PINB & (1<<4))) {elozo = (PINB & (1<<4)); (..) } //gomb lenyomása!
  3. if(!elozo && (PINB & (1<<4))) {elozo = (PINB & (1<<4)); (..) } //gomb felengedése!
(#) kurosaki válasza zombee hozzászólására (») Okt 12, 2013 /
 
Igazából egy angol leírásból csináltam és ott ezt írta bele.

a (..) közé mit kéne tennem?

Akkor még utána olvasgatok ennek csak néhol binárisban adják meg a lábakat stb amit nem tudok értelmezni.
(#) zombee válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
A "(..)" részre azt raksz amit akarsz, a programrész ami kezeli a cuccost.
Más ötletem nincs hogyan írjam le...
(#) kurosaki válasza zombee hozzászólására (») Okt 12, 2013 /
 
Be irtam hogy kapcs++; es semmi :'D nem irodott hozzá mert a led ugyan ugy maradt.
(#) brugo hozzászólása Okt 12, 2013 /
 
Szervusztok,
milyen fejlesztő környezetet ajálnátok ha AVR mikrokontrolerekkel szeretnék foglalkozni ?
melyik operácios rendszerrel Windows7/64 vagy esetleg Linux/64bit és melyik IDE ?
(#) kurosaki válasza brugo hozzászólására (») Okt 12, 2013 /
 
Én Windows 7/8 használok AVR Studio 6 és Eddig USBASP programozo most egy USBTinyISP 3.0 használok. remélem segiettem
(#) brugo válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
windows7 / 64 bit ?
(#) kurosaki válasza brugo hozzászólására (») Okt 12, 2013 /
 
Windows 7 / 8 64Bit
(#) zombee válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
Csak keresgélj, hátha nem kötöttél be valamit, felhúzó ellenállás, stb.
Vagy tudod mit? Csináljon annyit a programod hogy vár a gombnyomásra, ha megtörténik
akkor kigyújtasz egy LED-et és kész, nem megy tovább (végtelen ciklus).
Ha még ez sem megy akkor kezdd a LED kigyújtással, feltétel nélkül. Így kezdi mindenki...
(#) brugo válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
Köszönöm szépen .
(#) kurosaki válasza zombee hozzászólására (») Okt 12, 2013 /
 
Nem találok egy épkézláb leírást mindenhol az összes portot állítják be stb. Nekem kifejezetten Egy inputom kell, hogy legyen és azt figyelje.De mindenhol túl van cifrázva. Sajna nekem ez tul magas nincs a kezdő szintemhez mérten leirva mármint ahogy én Nyitom a portot a DDRB stb.
(#) blackdog válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
Bővebben: Link

Ennél egyszerűbben és érthetőbben nem lehet megfogalmazni.
Idézet:
„Nem találok egy épkézláb leírást mindenhol az összes portot állítják be”

Ezt mire alapozod?
A hozzászólás módosítva: Okt 12, 2013
(#) Massawa válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
Elöször a port irányát kell a DDRx- el meghatároznod pl. cbi DDRy,PBx. Ez a PYx lábat ( bitet) fogja az Y porton bemenetre kapcsolni.
Ezután már csak olvasnod kell az adott bemenetet, ha 1 akkor kapcsolhat valamit ( mehetsz tovább), ha 0, akkor ujra olvasod stb. ( azaz egy hurkot csinálsz)
A hozzászólás módosítva: Okt 12, 2013
(#) kurosaki válasza blackdog hozzászólására (») Okt 12, 2013 /
 
Bocsánat javítom az én szintemnek nem megfelelő.
(#) blackdog válasza kurosaki hozzászólására (») Okt 12, 2013 /
 
[off] Az, hogy a te szinteden azt nem tudom értelmezni.
Azt neked kell tudnod, hogy melyik leírás felel meg a te szintednek.
(#) kurosaki válasza blackdog hozzászólására (») Okt 12, 2013 /
 
Amit adtál leírást az segített köszönöm szépen (Bár a végére a return; nem kellet volna) az miatt nem ment eddig már majdnem írtam, hogy mi lehet a hiba.Köszönöm a segítséget.
(#) attti hozzászólása Okt 13, 2013 /
 
Sziasztok!
Neki álltam kíváncsiságból avr-t programozni, "kicsit" haladtam is, de elakadtam és nem tudok rájönni hol.
  1. void InitADC()
  2. {
  3.         ADMUX=(1<<REFS0);                         // For Aref=AVcc;
  4.         ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Rrescalar div factor =128
  5. }
  6.  
  7. uint16_t ReadADC(uint8_t ch)
  8. {
  9.         //Select ADC Channel ch must be 0-7
  10.         ch=ch&0b00000111;
  11.         ADMUX|=ch;
  12.  
  13.         //Start Single conversion
  14.         ADCSRA|=(1<<ADSC);
  15.  
  16.         //Wait for conversion to complete
  17.         while(!(ADCSRA & (1<<ADIF)));
  18.  
  19.         //Clear ADIF by writing one to it
  20.         //Note you may be wondering why we have write one to clear it
  21.         //This is standard way of clearing bits in io as said in datasheets.
  22.         //The code writes '1' but it result in setting bit to '0' !!!
  23.  
  24.         ADCSRA|=(1<<ADIF);
  25.  
  26.         return(ADC);
  27. }


Van ez a kódom hiba nincs benne legalább is a compilártor szerint, de nem úgy működik ahogy neki kellene. Amikor letesztelem akkor az a hibajelenség, hogy amikor lenyomom az egyik gombot akkor nem csinál semmit és ha lenyomom a másik gombot is akkor a kijelzőn meg jelenik az egy. Pedig úgy kéne, hogy működjön, ha egyik gombot nyomom le akkor egyik mutat 1-et, ha a másik gombot nyomom le akkor a másik.
  1. int main(void)
  2. {
  3.     while(1)
  4.     {
  5.                 InitADC();
  6.                 kiirasbal(motor1());
  7.                 _delay_ms(2);
  8.                 InitADC();
  9.                 kiirasjobb(motor2());
  10.                 _delay_ms(2);
  11.         }
  12.                
  13.    
  14. }


A motor1 és motor2-be ez van:
  1. unsigned char motor1(void){
  2.         uint16_t motor1all;
  3.         motor1all = ReadADC(0);
  4.         if ((motor1all > 900) & (motor1all < 1025))
  5.         {
  6.                 return 1;              
  7.         }
  8.         else
  9.         {
  10.                 return 0;
  11.         }
  12. }
  13.  
  14. unsigned char motor2(void){
  15.         uint16_t motor2all;
  16.         motor2all = ReadADC(1);
  17.         if ((motor2all > 900) & (motor2all < 1025))
  18.         {
  19.                 return 1;
  20.         }
  21.         else
  22.         {
  23.                 return 0;
  24.         }
  25. }
A hozzászólás módosítva: Okt 13, 2013
(#) vzoole válasza attti hozzászólására (») Okt 13, 2013 /
 
Habár nem értem hogy jön a gombnyomáshoz az ADC... de a kód szerintem több helyen is hibás.
Nézd át ezt a kódot: Bővebben: Link
(#) attti válasza vzoole hozzászólására (») Okt 13, 2013 /
 
A legegyszerűbb helyzetben szeretném kipróbálni, hogy kell használni az ADC-t. Rendbe, átnézem a kódot.
(#) vzoole válasza attti hozzászólására (») Okt 13, 2013 /
 
Milyen kijelződ van?

Amúgy a readADC visszatérési értéke nem tudom honnan jön.
És az init-et se kéne lefuttatni minden olvasás előtt, csak jól kell megírni az olvasás részt.
De ebben remélem segít a linkelt kód, ott részletesen leírtam mindent.
(#) attti válasza vzoole hozzászólására (») Okt 13, 2013 /
 
A kijelző egy 11 digites 7 szegmenses kijelző multiplexelve és szétosztva úgy, hogy 4 digit, 3 digit és 4 digit. A multiplexelés se megy jól valami ott is el van rontva. A readADC az innen jő
  1. uint16_t ReadADC(uint8_t ch)
  2. {
  3.         //Select ADC Channel ch must be 0-7
  4.         ch=ch&0b00000111;
  5.         ADMUX|=ch;
  6.  
  7.         //Start Single conversion
  8.         ADCSRA|=(1<<ADSC);
  9.  
  10.         //Wait for conversion to complete
  11.         while(!(ADCSRA & (1<<ADIF)));
  12.  
  13.         //Clear ADIF by writing one to it
  14.         //Note you may be wondering why we have write one to clear it
  15.         //This is standard way of clearing bits in io as said in datasheets.
  16.         //The code writes '1' but it result in setting bit to '0' !!!
  17.  
  18.         ADCSRA|=(1<<ADIF);
  19.  
  20.         return(ADC);
  21. }
(#) csabeszq válasza attti hozzászólására (») Okt 13, 2013 /
 
  1. ch=ch&0b00000111;
  2. ADMUX|=ch;


Ez a kód 7-hez konvergál (Az OR művelet miatt az előző állapot megjegyződik).

  1. ch=ch&0b00000111;
  2. ADMUX = (ADMUX & 0xF0) | ch;



Az AVCC be van kötve (VCC-re)? Az AREF és a föld között van 100nF kapacitás?
A hozzászólás módosítva: Okt 13, 2013
(#) gacserus hozzászólása Okt 14, 2013 /
 
Sziasztok,

3 db szervót szeretnék vezérelni egy ATmega328-cal. Szoft PWM-mel próbálkozok, azaz a program törzsben elvégzek egy ellenőrzést, hogy áll a számláló (TCNT1) és ha egy VÁLTOZÓ értéket meghalad akkor a servo vezérlő láb jelszintjét alacsonyba állítom. egyébként meg egy belső megszakítás minden TCNT1 ciklus végén magasba állítja ezen a lábon a jelszintet.

Azt kellene megoldani, hogy egy külső interupt hatására ezen VÁLTOZÓ értéke 1 mp-ig megváltozzon, majd utána megint 1mp-ig egy másik értékre változzon majd utána álljon vissza az eredeti értékre.
Azzal gondoltam, hogy a fenti ellenőrző ciklusba beleteszek egy számlálót amivel az időt tudom kontrollálni, de nem vagyok benne biztos, hogy ez a jó megoldás.

Hogy tudom a leghatékonyabban megoldani?


Gacserus
(#) zombee válasza gacserus hozzászólására (») Okt 14, 2013 /
 
Én azért végiggondolnám mégegyszer. Egyrészt, miért kell PWM, miért kell az az 1mp-es várakozás, stb. Utóbbival az a probléma hogy egy szervó válaszideje ennek töredéke kell hogy legyen és ha beiktatsz egy ilyen várakozást, problémák adódhatnak.

Én így vezérelnék szervót, DC motort és H-hidat feltételezve:
A szervó elektronika(AVR) valahonnan jelet kap hogy egy adott pozícióba kell fordulni.
A megfelelő irányba elindulva a sima indulást PWM-el oldom meg(+H híd), úgy hogy minden
PWM ciklus végén(ahol interruptol!) növelem a komparátor(OCRxA) értékét. Közben azt is
lesem hogy a jeladó (és a rá épülő számláló) milyen közel van a célhoz. Ha már közelít, akkor
a PWM-en keresztül csökkenteni kell(OCRxA). Ha már közel van akkor a H-hidat át kell fordítani,
mert fékezni kell a cuccost. Nem árt a sebességet is figyelni a jeladón, mert ha ezt és a mozgatott
cucc dinamikáját is figyelembe veszed, korábban el kell kezdeni fékezni, és még az is lehet hogy
az ellentétes irányú áramot is csutkára fel kell tolni hogy pont ott álljon meg ahol kell.
Ha jól csinálod, akkor ezután nem lengedezik a cucc a célpont körül.
A hozzászólás módosítva: Okt 14, 2013
(#) zolek hozzászólása Okt 14, 2013 /
 
Sziasztok! Ezt szeretném megípteni de a at89c51-et nem sikerül felprogramozni, mert amit építettem programozót az csak az s szériát támogatja.

TRAI TIM.DSN
    
(#) gacserus válasza zombee hozzászólására (») Okt 14, 2013 /
 
Valójában ez egy módosított servo, hogy folyamatos tudjon forogni és egy robot két kerekét hajtja.
Azt szeretném, hogy ha akadállyal találkozik akkor előbb tolasson 1mpig majd forduljon meg és menjen megint előre.

gacserus
(#) Fizikus válasza gacserus hozzászólására (») Okt 15, 2013 /
 
Szia!

Mellekelem az altalam irt kodot. ATMega8-assal leteszteltem, mukodik. A port D-re kotott max. 8 db szervo vezerlesere jo. A szervok vezerlojele 500-2500 ms kozott valtoztathato, de En csak 1000-2000 ms kozotti jelekkel vezerelnem a szervokat, mert hatha a szelesebb jelet nem birjak. A program fixen 20ms-onkent frissiti a szervo vezerlojelet.

Megprobalom roviden osszefoglalni:
Az ATMega8-nak 3 Timere van, ebbol 2db 8 bites es 1db 16 bites. Ezekhez osszesen 3db hardveres PWM lab tartozik (2db a 16 bites timerhez es 1db a 8 biteshez). Szoftveres szervo PWM-hez a 16 bites Timer1-et erdemes hasznalni.
A 16 bites Timer1 0-tol 65535-ig tud szamolni, de beallithato olyan szamlamasi mod is, ahol meg lehet adni ennel kisebb maximalis erteket is (ez a TOP ertek).
A peldaban egy 8MHz-es AVR-nel 8-as Timer1 eloosztast hasznalva, masodpercenkent pont 1000000-szor fog a timer lepni, ez pont 1us. Ha a timert ugy allitom be, hogy 2500-ig szamoljon, akkor pont 2.5ms-kent csordul tul. (Az ICR1 regiszter erteke adja meg, hogy meddig szamoljon a timer es ezutan kezdi elolrol). Beallithato az is hogy a timer mikor adjon megszakitast. A peldaban 2 megszakitast hasznalok. Az elso amikor a timer eleri a 2500-as erteket es tulcsordul (Timer overflow), a masik amikor a timer elszamol egy megadott ertekig (Output Compare megszakitas- ezt hasznalom a szervojel hosszanak beallitasahoz).
A peldaban annyi az elteres a hagyomanyos Fast PWM beallatasoktol, hogy a PWM jelet nem adja ki az AVR az OCR1A es OCR1B labakra, csak a megszakitasokat hasznalom a szoftveres PWM idozitesere.
A Timer tulcsordulasa utan bekapcsolom az elso szervo vezerlojelet. Ha a Timer1 elszamolt az elso szervo megadott poziciojahoz tartozo jelhosszig, akkor az Output Compare megszakitas lekapcsolja az elso szervot es beallitja a masodik szervohoz tartozo jelhosszt az Output Compare megszakitasban es beallitja a masodik szervot a Timer tulcsordulasahoz tartozo megszakitasban. Ha a Timer 2.5ms utan tulcsordul, akkor az egesz fenti folyamat kezdodik elolrol a masodik szervoval es igy tovabb a nyolcadik szervoig, ami utan ujra az elso szervoval kezdodik az egesz elolrol...

A program a 8 szervot felvaltva allitja be a ket szelso allasba es a kozepallasba...
Következő: »»   568 / 840
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem