Fórum témák
» Több friss téma |
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
Szia!
Te a TIMER1/COUNTER1 8-as PWM módját választottad, ahol a TOP értéket (ameddig felfelé számol a számláló) az ICR1 regiszter határozza meg, egyszerűbben mondva ez fogja meghatározni a PWM frekvenciát, az OCR1A, és OCR1B pedig a két output compare unit kimenetén a kitöltési tényezőt. Adjál értéket az ICR1 regiszternek.
Ha ICR1 regiszternek értéket adok akkor még a PB1 se kapcsol.
Próbáltam változtatni a WGM de a PB2 akkor se akar változni . :/
A kérdés, mekkora értéket adtál?
Próbáltam több értéket 0-tól 65535-ig.
Sikerült egy attiny85 amit akartam.
Ha egy bement ADC ként szolgál és ezt az értéket beírom a pwm jeléhez ez szépen változik is de csak akkor ha a függvény lefutott. Egy megszakítást szeretnék a main függvénybe meghívtam a sei() parancsot és azon kívül pedig a ISR(ADC_vect),de nem változik a kimenet amíg le nem fut az összes függvény. Vagy esetleg meg lehet oldani másként is?
Ha kódot mutatnál, talán könnyebb lenni megpróbálni segíteni.
Kiszedtem a megszakítást de szeretném hogy csak akkor legyen a kimenet aktiv (PB1-OC0B) ha PB0 -ra rákapcsolom a mínuszt.
Ugyan igy a PB3(Bemenet) és PB4(Kimenet). Ha a PB0 megkapja a jelet akkor fel is kapcsol arra a PWM jelre ami épp be van állítva az ADC bemeneten de úgy marad sajnos :/ .
Köszönöm a segítséget.
Át írtam a kódot egy kicsit .
De ilyenkor a PB4 csak villog ha a PB3 aktiv.
Sikerült megoldani az alábbi módon.
Beraktam egy delay-t és így nem villog a PB4 és csak akkor aktív ha van bemenet .
Tiny13-hoz remek forrásanyag 100+ projekt attiny13-hoz.
UART library tiny13-hoz, viszont egy minimális korrekcióval remekül használható 25/45/85-nél is a klasszikus 1000000/8000000/16000000 órajeleken.
Természetesen putty-ban ennek megfelelően kell beállítani a baud rate-et. A hozzászólás módosítva: Feb 20, 2020
Az általam kicsit módosított UART library (header-ként).
Tiny 13/25/45/85 WinAVR és AvrDude környezet (windows/linux/valamint raspberry pi raspbian környezetben használva)
A hozzászólás módosítva: Feb 20, 2020
Attiny 13/25/45/85 családhoz használható HD44780/KS7066 kompatibilis 4/8bites parallel kijelzőhöz 2x16 LCD készítettem shiftregiszteres meghajtót + saját library-t (2 vezetékes, nem i2c és nem SPI). Ha valakit komolyabban érdekelne megosztom a nyák illetve a library forrásokat.
A hozzászólás módosítva: Feb 20, 2020
Sziasztok!
T0,T1,T2 (időzítő bemenetek) beállíthatók-e közvetlen interrupt generáláshoz fel-VAGY lefutó élre úgy, mint az INT lábak? Időzítő CTC mód, OCRn(A)=1, órajel forrás Tn fel-vagy lefutó élen, megszakítás engedélyezve komparálásra. A többi alternatíva (ICP1, AIN1) már foglalt, hasonló célra. Fontos, hogy csak az egyik élen generálhat megszakítást, így a PCINT ki van zárva.
Sziasztok.
Nem kezdtem az elejétől olvasgatni a topic-ot, lehet nem is ide kéne kérdeznem ez ügyben. Nagyon kezdő vagyok a programozásban, igazából meglévő példákat alakítgatok és módosítok a saját feladatomhoz. Gondolom volt is ilyenről szó, valószínűleg beállítási gondjaim vannak. A lényeg, hogy atmega8, de 328-al is ez van. Modbus kommunikációm csak akkor üzemel, ha belső 1MHZ óra van használva. Ha belső 8 vagy külső 12, 16, akkor eldobálja a kommunikációt. bootloaderben kiválasztom a "megfelelőt" az arduino ide progiban is a megfelelő board-ot. Mégis csak default belső 1MHZ beállítással üzemel a modbus. Előre is köszi minden okosságot
Melyik csipről van szó? Nekem ezek a T0, T1, T2 bemenetek nem rémlenek így fejből, hogy mik, azért kérdezem.
A Modbus UART-ra épül, ha jól tudom. Tippjeim:
* Nem jó az UART-serial órajel. Ennek két alfaja lehetséges: ** Egyáltalán nem jó az órajel. A kód 1MHz-hez állítja be jól, más CPU órajelet használva ezért nem működik. (Pl 8MHz-en használva a CPU-t 8-szor gyorsabb lesz a serial jele) ** Nem elég pontos a serial órajele. Ahhoz, hogy a serial ne hibázzon a kommunikációban részt vevők órája kb 8%-os hibán belül együtt kell hogy járjon. A belső órajelek (az általam ismert AVR-ek esetén) kalibráció nélkül nem alkalmasak serial kommunikációhoz. A belső órajel hőmérséklet függő is: kompenzáció nélkül előfordulhat, hogy extrém melegben vagy hidegben "elromlik" az UART kommunikáció. Megoldási lehetőségek: *** Külső kvarc használata pontos és stabil órajel előállításhoz. *** Kalibráció és hőmérséklet kompenzáció. (A csipek belső órajelét tudtommal 3.3V-ra kalibrálják gyárilag. Ha 5V-on használjuk, akkor egy OSCCAL += 3; parancs korrigálja a kalibrációt az internetes néphagyomány szerint. Lásd: http://becomingmaker.com/tuning-attiny-oscillator/ Játszásból ez is elégséges megoldás, de komoly gépet ne így vezéreljünk!) *** Órajel mérése a slave oldalon, és az UART hozzáigazítása. Ilyenkor a kommunikáció első bájtját méréshez használjuk. Ez csak Slave oldalon működik és eléggé komplex megcsinálni. A Series0 és Series1 csipek adatlap szerint már hardveresen tudni fogják ezt a funkciót (még sajnos nem próbáltam). Modbus esetén mivel nincs mérőbájt a protokoll elején, ezért pláne nehézkes volna megcsinálni. Nem teljesen világos a leírásban egyébként, hogy hogyan váltogatod a CPU órajeleket? Tudtommal: A belső és a külső óra között a FUSE bitekkel lehet váltani programozót használva. Ha már elindult a csip, akkor már nem lehet órajelet váltani, ezért a bootloadernek ehhez már nincs köze. Az Arduino IDE pedig board típusonként 1-1 fix órajellel számol, nincs felkészítve a CPU órajel változtatására. Szóval érdemi segítséghez jobban körül kellene írnod, hogy pontosan mit csinálsz. Ha próbálgatással nem jön össze, akkor mérni kellene a serial órajelét. Ennek mikéntjéhez egy másik topikban csináltam egy leírást: https://www.hobbielektronika.hu/forum/topic_post_2331885.html#2331885 A hozzászólás módosítva: Feb 28, 2020
Üdv!
Hibakeresési kérdések: Hogy állítottad be a külső órajeleket? Milyen Fuse Bit konfigurációval? A Fuse bitekben ki van kapcsolva a DIV8? Ez az oszcillátor 8-as osztója, így kapsz belső oszcillátorral 8Mhz helyett 1Mhz-et, vagy külső 16Mhzes kristállyal 2Mhz-et. Milyen F_CPU definíció van beállítva? Ez két helyen lehet. A Make file-ban, vagy magában a kódban. Ha az F_CPU definíciója nem azonos a valód órajellel, akkor történhet ilyesmi történhet, amit leírtál. Hozzátenném, hogy sem Modbust, sem Arduinot nem használok. Utóbbival is csak felületesen találkoztam.
Tehát, atmega8 külső 16mhz kvarccal. Arduino IDE progiba kivállasztom a csippet, külső kvarc-ot 16mhz-el. Itt beletöltök bootloadert. Ellenőrzöm avrdudess-el, fuse biteket átírta. Beletöltöm a modbus példa progit, nem működik, eldobálja a kommunikációt. Ha annyit változtatok, hogy belső 1mhz-ra állítom, akkor tökéletes. Mivel teljesen kezdő vagyok, ezért magamtól nem tudom min kell változtassak. Majd megmérem szkóppal a leírásod alapján.
Üdv!
Ha nem kritikus az időzítése/sebessége a megszakítónak akkor a PCINT-ba egy if() else() beiktatásával szerintem majdnem ugyan azt kapod, mint egy élen generált megszakítással.
Ez persze akkor nem megy, ha csak egy rövid impulzus kap a megszakító bemenete. Talán ezért keresel egy élgeneráltat?
Szia.
A te elképzelésed lehet a megoldásom, de nem tudok most mindenre válaszolni, mert nem vagyok otthon. A példa kódban nincs F_CPU beállítás. Gondolom ezt az átfordításnál beírja a kódba maga a program(Arduino IDE)amit abban kiválasztottam(16mhz external). És bootloadert is éget bele, ha rányomok. A fuse biteket is így írja át. Én csak ellenőrizni szoktam, hogy változtatta-e. A div8-at majd otthon megnézem.
Nálam ilyen opciók nincsenek az Arduino IDE-ben. (1.8.9-est használok, mert eddig nem láttam értelmét 1.8.12-re frissíteni.)
A boards manager részből elérhetően online forrásokból lehet telepíteni plusz boardokat az Arduino alá, lehetséges, hogy onnan telepítettél valami plusz board supportokat? És nálam ez nincs telepítve, azért nem látszik nálam hasonló beállítás? Sick-Bastard-dal egyetértek, a programban más CPU frekvencia lesz beállítva, mint amin a csip valójában fut.
Az atmega328 viszont a belső 8mhz beállítással is jól működik, míg az atmega8 nem. Csak mint érdekesség. Igazából valószínüleg ezt a mikrokontrollert fogom használni. Csak jó lenne tudni a külső 16mhz-vel miért nem jó nekem egyik se.
Atmega8-nál nincs fuse bitek között DIV8 atmega328-nál van, ott nincs bepipálva(Low:E2)
Már próbáltam. Mechanikus enkóder (PEC11R) megy rá, és kétélű megszakítással a ciklusok kb. 3-5%-át elveszíti. Egyélű megszakítással ennek tizede, vagy még kisebb a hibaarány. Jelenleg ATMega16 van, ami elvisz két enkódert az INT0-2 illetve ICP1 lábakon. Ezen próbáltam ki hogyan viselkedik, ha az INTn bemeneteken kétélű megszakítás van. Jól működik a cucc, de át akarom rakni ATMega48-ra. Azon megvan az INT0-1 és ICP1, a negyediket akarom T0 vagy T1 lábbal kiváltani ha lehet. Analóg komparátor egyelőre kiesik, mivel azon nincs schmitt-triggeres szűrés és nem akarom még egy IC-vel (pl. 74HCT1G00) bonyolítani.
ATMega48 lenne. T2 kiesik (konkrétan:nincs), csak az adatlap tévesen utal rá. Marad T0 és T1.
Jé, ezt már el is felejtettem, hogy van ilyen funkciója is. Pedig az ATMega328 adatlappal fekszek és kelek...
Szerintem ha úgy állítod be a számlálót, hogy 1-nél átforduljon, akkor az overflow interrupt lényegében pin change interruptként fog működni. De nem bogarásztam végig az adatlapot. Egyébként milyen gyakoriak a jelek? Mármint mi a megengedett legynagyobb sebessége a jeladónak, és ebből milyen periódusidő, vagy jelváltás idő jön ki? Mozoghatnak-e egyszerre a jeladók és hányféle interruptot használsz? Ha az ISR kiszolgálási időkre is adsz becslést, akkor ki lehet számolgatni, hogy lesz-e és mennyi lesz a jelvesztés. Pont mostanában csináltam ilyet, és végül úgy valósítottam meg, hogy minden jelet egy külön ATTiny25 számol, és SPI-n küldi a mester ATMega-nak. A program garantálja, hogy 12 órajelenként jöhet 1 jelváltás, azt még fel tudja dolgozni. És 16MHz belső óráról jár. Itt van a kódja: https://github.com/rizsi/Arduino-IR-decoder/blob/quadrature_counter...er.asm és a hozzá tartozó ugrótábla is: https://github.com/rizsi/Arduino-IR-decoder/blob/quadrature_counter...le.inc Ha worst-case-re kell tervezni, akkor az interrupt kezelés overhead-je miatt és a kiszámíthatóság miatt lehet, hogy jobban jársz, ha egyetlen fix periódusú időzítővel mintavételezed az összes bemenetet és ugrótábla segítségével számolsz az ISR-en belül. Ezzel a megoldással lehet szerintem a legtöbb kvadratúra jeladót egyszerre feldolgozni egyetlen csipen. És ha jó a megvalósítás, akkor több jeladó egyszerre adott jele nem zavarja meg egymást. Tehát ha beméred, hogy X frekvenciával jövő jelek még fel vannak dolgozva, akkor azok fel lesznek dolgozva akkor is, ha közben a másik csatornán is jönnek a jelek. Illetve ha semmi mást nem csinál a csip, akkor fix periódusú ASM-et lehet még írni, ahogy a fentebb linkelt megoldásom is működik. Egyetlen ISR futtatása kb 50 órajelet is elvisz feldolgozással együtt (számolgattam, mert eredetileg úgy akartam megoldani a számlálást), fix periódussal pedig sikerült 36 CPU ciklusnyi periódusokkal 3 jelet egyszerre feldolgozni. Nekem úgy tűnik, hogy ez a minimum. Talán 11, vagy esetleg 10 CPU órajelre még le lehetne vinni.
Igen, én is 1-re állítanám a komparátort, csak most nincs időm kipróbálni, működik-e vagy sem.
Az áramkörterv előbb kell, utána jöhet a szoftveres próba, csak nehogy koppanás legyen a vége. A cuccos a két PEC mellett a forgókarok lenyomását is érzékeli, 2 db. 4 digites kijelzőt vezérel, I2C-n keresztül 2-2 ADC és DAC-vel kommunikál, és közben erőteljesen konvertálja az ADC és DAC értékeket is. Profik már kitalálták: labortáp vezérlőmodulja. Ezeknek az enkódereknek nem kell bika proci. A nehézséget egyedül az okozza, hogy a mechanikus kivitel erőteljes pergést okoz, valószínű, ez miatt nem jött be a kétélű megszakítás. A bekötés se mindegy: 10k felhúzó ellenállás kell (nálam 4k7), és 100nF kerámia a földre. Ha ez utóbbi nincs, még zavarosabb lesz a jel, vagyis inkább: kezelhetetlen. A megszakításban beolvasom a másik oldali enkóderkimenet állapotát (feltételezi, hogy váltáskor a másik oldalon stabil), majd összevetve egy állapotváltozóval (lastevent) eldönti hogy léptessen-e vagy sem. Léptetni az "enc" változóval, amit egy 2ms-enként futó időzítő megszakítás figyel. Ugyanez az időzítő figyeli és pergésmentesíti az enkóderkar lenyomását is.
A pergésmentesítést szerintem "természetes úton" megoldaná, ha élvezérelt helyett idő alapon kérdezgetnéd a kvadratúra jelek értékeit. Csak úgy kell belőni a periódusidőt, hogy elbírja a proci, és ne vesszen el hasznos jel. Ha kiszámolod a futásidőt, simán kijöhet, hogy 10kHz-vel simán tudod futtatni ezt az interruptot (800 órajelenként egyszer 8MHz CPU órajel mellett), és az már elég lehet mindennek a dekódolására. Csak egy interruptod van, és ezért sokkal egyszerűbb és kiszámíthatóbb lesz minden.
Gondolom akkor a beállító gombok lesznek ilyen digitális enkoderrel megvalósítva: ezek nem fognak túl gyorsan pörögni sosem. Én így csinálnám a mostani eszemmel - miután hetek óta kvadratúra dekódert optimalizálok magam sem tudom minek:
Igen, valójában egyszerű a számlálás, akár diszkrét logikával is meg lehetne valósítani. De nagy sebességgel hibázás nélkül implementálni 8 bites AVR mikrovezérlőn mégis kihívás.
A linkelt oldalon a javaslatomhoz hasonlóan periódikus timerrel veszik a mintákat: egyetértek, szerintem is ez a legjobb. Pláne ha több jeladót kell egyszerre kezelni, ahogy zombee tervezi. |
Bejelentkezés
Hirdetés |