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   835 / 840
(#) Sipy válasza kendre256 hozzászólására (») Aug 16, 2023 /
 
Igen, biztos vagyok benne hogy többszöri verzió lesz a végső. Szerencsére az avr programozás már elég jól megy. Valamennyi okosságot bele tudok vinni hogy felismerjen egy valós veszelyhelyzetet vagy tudja hogy csak lassítani kell és követni az előttem haladót.
(#) kalmi.kalmi válasza Sipy hozzászólására (») Aug 16, 2023 /
 
Szerintem egy AI - kell telepítened. Persze egy AVR nem megfelelő erre a célra.
A hozzászólás módosítva: Aug 16, 2023
(#) Tambi hozzászólása Aug 17, 2023 /
 
Kedves Fórumtársak!

STEP/DIR rendszerű AC szervo 0,1-50 ford/sec közötti működtetéséhez szükségem lenne 100 Hz - 50 kHz tartományban működő négyszögjel generátorra, ami a teljes tartományt képes átfogni SÁVVÁLTÁS NÉLKÜL, egy "finom" és egy "durva" potenciométer alkalmazásával.

Az AVR melléklet szerinti megerőszakolásával úgy ahogy sikerült is elérni a célt, viszont a frekvencia (vagy inkább az impulzusszélesség) RIGOL DS1054Z szkópon, illetve az ARDUINO IDE 2.1.1 soros monitorán nézve nézve nem stabil.

Mi lehet a probléma, illetve megoldás?

Köszönettel; Tambi
(#) pont válasza Tambi hozzászólására (») Aug 17, 2023 /
 
Mivel magáról a kapcsolásról nem tudunk semmit, csak egy tipp: Túl le van terhelve a négyszögjel kimenet, esetleg zavar, gerjedés, rossz (zavaros) táp....
(#) Tambi válasza pont hozzászólására (») Aug 17, 2023 /
 
A kapcsolás dugdosós panelen készült; az ARDUINO NANO A0-ra rá van kötve a poti csúszkája, egyik vége a GND, a másik vége pedig a 3,3 voltra van kötve, mert itt csupán 5-6 mV-os 6-7kHz-es zavar látható, míg eme laptop a USB +5V-ján kb. kétszer ekkora.

A D9 kimenetet 1 kOhmmal terhelve ugyanaz a jelenség, mint üresen.

Tr9158 tápról hajtva nincs változás.
(#) kapu48 válasza Tambi hozzászólására (») Aug 17, 2023 /
 
Hali!
Első hiba, hogy ADC-t sosem egyszer mérünk mert nagyon zajos lesz az eredmény.
A tone függvény pedig alkalmatlan az ilyen kiélezett szabályozásra.
Ráadásul az AVR-is elavult és csak 8 bites, lassú!

Vannak már 32 bites gyorsabb eszközök jóval korszerűbbek.

Én STM32F103-ast javaslok. Bővebben: Link
És hozzá indulásnak mondjuk ez a PWM generátort:
Bővebben: Link
De ennek bőséges dokumentációja található a neten
Bővebben: Link

STM32 mikrovezérlők programozása: Bővebben: Link
A hozzászólás módosítva: Aug 17, 2023
(#) asch válasza Tambi hozzászólására (») Aug 18, 2023 / 2
 
Nem mondtad, hogy mi a hardvered, feltételezem, hogy valami AVR alapú Arduino lehet, például UNO. Ennek van PWM kimenete, amivel simán meg lehet valósítani ez a jelgenerátort. Viszont az Arduino könyvtárai alig-alig alkalmasak ilyesmire.
Ez az Arduinonak a nagy csapdája, hogy hiába fut mikrovezérlőn, pontos vezérlést, amire a mikrovezérlőket teremtették, azt Arduinoval nagyon nehéz megvalósítani. A szoftver nehézkesen alkalmas csak rá. A hardver viszont simán, az bőven elegendő erre a célra.
Lényegében PWM kimenetet kell használni, csak nem a kitöltési tényezőt kell állítgatni, hanem a periódusidőt, és erre elfelejtettek API-t adni az Arduino-n belül. (Ismereteim szerint, ha valaki tud rá APIt mégis az csak jó.)

Az Arduino környezeten belül is meg lehet csinálni, hogy a PWM-et nem a liben keresztül, hanem közvetlenül a regisztereket írva programozod fel. Én ezt csinálnám, akár úgy, hogy bekapcsolnám a PWM-et az Arduino libben - analogWrite funckcióval, ekkor már látsz valami működést szkópon. És utána felülírnám azokat a változókat az adatlap szerint, amivel másképpen akarom hajtani a PWM modult (Timer/Counter1). Próbálgatva kis lépésekkel lehet haladni.

Alternatív megközelítés, hogy teljesen kihagyod az analogWrite meghívását, és az adatlap szerint a regisztereket beállítva programozod fel a PWM-et.

Itt van az ATMEGA328p csip adatlapja: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

Ezen belül ez a fejezet lesz érdekes: 15.9.2 Clear Timer on Compare Match (CTC) Mode. Ebben a módban hajtva az OCR1A regiszterbe kell beírni a periódusidőt és ezzel lehet állítani a periódust/frekvenciát. Tehát ezt a módot kell bekonfigurálni az adatlap szerint és után az OCR1A értékét állítgatni.

Ha már valamennyire működik, akkor még azt is meg kell csinálni, hogy mindig az átfordulás után kell beírni az értéket, amikor a számláló kicsi. Különben ha kisebbre állítjuk a határt (OCR1A) mint az előző értéke, és a számláló éppen a kettő között van amikor átírjuk, akkor lesz egy hibás teljes periódus. Ezt elkerülni a legegyszerűbben úgy lehet, hogy az OCIE1A interruptot engedélyezed, és ennek az interruptnak a kezelőjében másolod be a következő értéket. Ez az IRQ mindig 0-ra állítás után fut, tehát amikor a lehető legtöbb időnk van beállítani a határt (OCR1A). 50kHz esetén is van 320 órajelünk erre, ami bőven bőven elegendő ezen a processzoron.

Pszeudó kód a periódusidő bemásolására az OCIE1A regiszterbe:

  1. static volatile uint16_t period=255;
  2. loop()
  3. {
  4.   int poti = analogRead(A0);  //A poti két "vége" az ARDUINO NANO 17. lába (3,3V) és 29. lába (GND) közé, csúszkája a 19. lábára (A0) van kötve.
  5.   int freq = 100 + 76 * poti; // min "freq" = 100 Hz, max "freq" = 100 + ((76*1023*(3,3/5)) = 51 314 Hz.
  6.   uint16_t newPeriod=big_number / freq; // periódusidő kiszámolása a frekvencia alapján osztással. A big_number értékét a PWM beállításai alapján kell kiszámolni
  7.   ATOMIC_BLOCK  ( ATOMIC_RESTORESTATE)
  8.   {
  9.     period = newPeriod;
  10.   }
  11. }
  12.  
  13. ISR(TIMER1_COMPA_vect)
  14. {
  15.   OCIE1A=period;
  16. }


Az ATOMIC_BLOCK azért kell, mert 16 bites érték RAM-ba beírása nem atomi művelet.

Arra, hogy ez a proci ne lenne alkalmas ne hallgass, nagyonis alkalmas, a feladat egyáltalán nem nehéz ennek a procinak, csak korrektül kell felprogramozni. Persze az STM32 is alkalmas nyilván, ha mégis arra váltasz.

Valóban érdemes több ADC mérést csinálni és átlagolni. Az, hogy mennyire lesz zajos a mérés, az az áramkör kialakításán múlik nagymértékben, ha nem vagy profi, akkor várhatóan bizony zajos lesz...

Szerk.: ahhoz, hogy a 16 bites tartomány elegendő legyen a periódusidő kifejezéséhez, az osztót /8-ra kell állítani ( TCCR1B CS bitjei). Így 40-20000 között lesz a periódusidő az igényelt frekvenciákhoz.
A hozzászólás módosítva: Aug 18, 2023
(#) Tambi válasza asch hozzászólására (») Aug 19, 2023 /
 
Köszönöm kedves Kapu48!
Hasonló kóddal megpróbálkoztam ESP32-val, de az instabilabbnak tűnt. Nyilván az ismereteim alapján készíthető "legmagasabb szintű" kóddal, amiben egyszer olvasunk be analógot, és persze használjuk a tone funkciót...

Köszönöm kedves ASCH!
Néhány sort megpirosozott, de némi kiegészítéssel a mellékletig jutottam.

A fordító kifogása: Compilation error: lvalue required as left operand of assignment,
magyarul: Fordítási hiba: lvalue szükséges a hozzárendelés bal oldali operandusaként

Ez mit jelenthet, illetve mit tegyek?

Nem gondolom, hogy számít, de nincs csatlakoztatva a NANO a PC-hez...

Köszönettel; Tambi
A hozzászólás módosítva: Aug 19, 2023
(#) pipi válasza Tambi hozzászólására (») Aug 20, 2023 /
 
The Timer/Counter Interrupt Mask Register - TIMSK
4. Bit - OCIE1A: Timer/Counter1 Output CompareA Match Interrupt Enable
ebbe elég nehéz lenne egy egész bájtot(8bitet) beletölteni, ezért fúj szerintem.
De miért is ebbe a regiszterbe akarsz periódust tölteni?
A hozzászólás módosítva: Aug 20, 2023
(#) Tambi válasza pipi hozzászólására (») Aug 21, 2023 /
 
Köszönöm kedves Pipi!

Felnyitottad a szemem, neked van igazad!
Aki nem ért hozzá, az ne csinálja, vagy érje be minimalista, fércmegoldásokkal...
(#) asch válasza Tambi hozzászólására (») Aug 22, 2023 /
 
Bocs, benéztem, a OCR1A regiszterbe kell beírni az értéket. A "pszeudó kód"-ot úgy értettem, hogy ebben a formában nem egy működő kód, hanem a működés egy aspektusát mutatja csak be. Ehhez még be is kell konfigurálni a 15.9.2 fejezet szerinti módot ahhoz, hogy működjön. Sajnos nincsen most lehetőségem kitesztelt kódot adni, ezért csak az alap ötletekre tudtam rávilágítani. Programozás tudás nélkül vagy megíratod valakivel, vagy valóban ésszerűbb lemondani róla.
Írtad, hogy ESP32-vel is próbáltad: mindenbizonnyal azzal a csippel is meg lehet oldani ezt a problémát, de ott is figyelni kell a részletekre, hogy tökéletesen legyen felprogramozva a PWM kimenet, és a frekvencia változtatása helyesen legyen megoldva. Tulajdonképpen akármilyen mikrovezérlőn is hasonló a feladat, az egyetlen amitől egyszerűbb lehet, hogy ha valamelyikre van eleve kész megoldás.
(#) Jáger László hozzászólása Szept 10, 2023 /
 
Üdv Mindenkinek. Segítségre van szükségem, talán itt valaki. Nincs tapasztalatom mikrokontrollerel.
Adott egy Atmega8 -al épített frekvenciamérő aminek egy külső 4MHz-es kvarc ad órajelet. A kiírt frekvencia kb. a 4X -e a valódinak. Úgy néztem, hogy mindegy milyen kvarcot teszek bele, a kiírt értéket nem változtatja. Arra gondoltam, hogy a belső saját órajelet használja (ami nem tűnik túl pontosnak), nem a külső órajelet. Erről lenne szó: Bővebben: Link
Esetleg én néztem be valamit?
Programozásra (mint idáig mindig) Minipro TL866 -ot használok, 6.71 verzióval.
Eddig nem volt ilyen problémám. Ha valaki tud kérem segítsen. Köszönöm.
(#) Tambi válasza asch hozzászólására (») Szept 10, 2023 /
 
Kedves Fórumtársak!
Köszönöm mindenkinek a segítséget; nagyjából három hétbe telt, mire sikerült innen-onnan összeszedegetnem amire szükségem lenne:

void setup () {
pinMode(9, OUTPUT);
analogReference(DEFAULT); // "DEFAULT" : a Vcc (+5V) a referencia feszültség
TCCR1A = 0x82; // pins 9 fast 16 bit
TCCR1B = 0x1A; } // előosztó 8
void loop () {
int poti = analogRead(A0); // Az ADC az A0 bemenet feszültségét méri, ami a poti csúszkája
poti = poti / 10; // az osztás levágja az utolsó, billegő számjegyet
poti = poti * 10; // a szorzás visszaállítja a számot ("0"-ra végződéssel), stabil a jel
unsigned int freq = 39 + 20 * poti; //nagyjából 100Hz-tól 182kHz-ig változtatható a frekvencia
ICR1 = freq;
OCR1A = freq / 2; } // 50% kitöltéssel

Végülis a stabilitást elértem, csak az eszköz használhatatlan... Az Excelben jól látható, hogy a magasabb frekvenciáról indulva 1% potenciométer értékváltozáshoz 95%(!!!) frekvenciaváltozás tartozik.
A frekvencia nagyjából az f KI = 1820000/OCR1 függvény szerint változik a 100Hz-182kHz tartományban. A f KI függvényt tükrözni kellene az y = -9x + 1820000 egyenesre, vagy találni egy olyan, y = -ax*x + b jellegű függvényt, melyet az f KI függvényhez hozzáadva megkapnánk az egyenest. Így lineáris lenne a szabályzás.

Így meg nemsokat ér...

A tone() jó lenne, mert lineáris, de fix frekvencia beírása esetén is változik az impulzusok szélessége, instabil, ADC-vel pedig még rosszabb.

Mi a linearitás megoldása?

Köszönettel; Tambi
A hozzászólás módosítva: Szept 10, 2023
(#) asch válasza Jáger László hozzászólására (») Szept 10, 2023 /
 
Szerintem a FUSE nincsen beállítva. Ezeknél a csipeknél az úgynevezett FUSE bitek állítják az órajel forrását. Ezek programozóval állítható beállítások, amik már a program indulása előtt érvényre jutnak. Ezen oldalon van egy FUSE bit kalkultáor: http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega8 Ezen oldal szerint (az adatlapot nem néztem meg, higgyünk ennek az oldalnak...) az ATMEGA8 csip alap FUSE beállítása szerint 1MHz belső órajellel indul el. Ez valóban pontatlanabb mint egy kvarc és a leolvasás négyszeresre fog kijönni. Tehát majdnem biztos, hogy tényleg ez a probléma oka.
A megoldás, hogy a FUSE biteket be kell állítani külső órára. Én például ezt a beállítást választanám: http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega8&LOW...BIT=FF a default beállításokhoz képest az órát állítottam külsőre, 3-8 MHz-re és a legnagyobb indítási késleltetésre, ami valószínűleg teljesen mindegy, de valamit választani kell.
(#) asch válasza Tambi hozzászólására (») Szept 10, 2023 /
 
Először is gratulálok! Szerintem a legtöbben azt hittük, hogy fel fogod adni! Szép eredmény, innen már nincs sok hátra!

Az első javaslatom, hogy az ADC zajt ne simán az utolsó számjegyek levágásával tompítsd! Ennek az az eredménye, hogy ha éppen a 0 átfordulás körül van a valódi érték, akkor továbbra is "ugrálhat" a kimenet!

Az egyik megoldás az, hogy ha a kimenet is "analóg", tehát a frekvencia kis változása nem okozza valaminek az ugrálását, akkor nem is baj, ha a bemenet zaját továbbítjuk. Például ha egy fordulatszabályzóról van szó, akkor ha a bemenet két érték között billeg, akkor miért baj, ha a kimenet is egy kicsit billeg? A fordulat kicsit lassul, kicsit gyorsul, de egy bitnyi különbségen belül, ami úgyis az elvárt tolerálható hibán belül kell hogy legyen.

A másik megoldás az, hogy az utolsó beállított értéket tárolod, és csak akkor váltasz, ha legalább X különbség van, pl 10. Ennek a módszernek mindegy, hogy éppen tízesátfordulásnál vagy-e vagy nem:

  1. noiseThreshold=10;
  2. readValue=f(analogRead(...)); // Érték beolvasása
  3. if(abs(setValue-readValue)>noiseThreshold)
  4. {
  5.  setValue=readValue;
  6. }


Hogyan találjuk meg a szükséges függvényt? Először is használjuk a platformfüggetlen típusokat (a sima int 16 bites, és a maximum értéke ezért 65536, 32 bites int kell nekünk ide), és úgy matekoljunk!
Másrészt nincs lineáris megoldása ennek, mert a frekvenciáról periódusidőre kell áttérni, ami reciprokot jelent!
  1. uint32_t u32_poti=setValue; // kibővítés 32 bitre, legyen a szám tartománya 0-1023, ami az ADC input tartománya ATMEGA328-on
  2. uint32_t freq = u32_poti*(182000-100)/1023 +100; // Lineáris leképzés a 100->182000 tartományra úgy, hogy a részeredmények is elférnek u32 számábrázolásban
  3. uint32_t T = (2000000ul) / freq; // periódusidő: T=1/freq. 1 helyett a számláló frekvenciáját kell írni, ami 16MHz/8 = 2000000 (ul utótag: azt jelöljük vele, hogy ez egy 32 bites konstans)
  4. ICR1 = (uint16_t)T;
  5. OCR1A = (uint16_t)T/2;} // 50% kitöltéssel
A hozzászólás módosítva: Szept 10, 2023
(#) Tambi válasza asch hozzászólására (») Szept 19, 2023 /
 
Kedves ASCH! (így; csupa nagybetűvel!)

Köszönöm szépen és gratulálok! Ez a projekt nem lett volna befejezve, ha nincs ASCH fórumtársunk!

Lineáris potival lineárisan, STABIL frekvenciára állva, nem változó impulzusszélességgel működik. Néha nem áll vissza 100Hz-re, 4-500Hz lesz, de ez nyilván a zajcsillapítás miatt van. Ezzel együtt lehet élni...

Utólagos engedelmeddel azért neveztem el rólad, és azért adtam neki hangzatos angol nevet, mert nagyjából egy hónapos keresgéléssel sem találtam egy ilyen viszonylag egyszerű és mégis nagyszerű megoldást. Csupa tone(), meg delay van, vagy ötszázsoros szignálgenerátor kód, amiből a magamfajta egyetlen sort sem ért..., meg feleleges is.

"Betömtél egy lukat", nagy hiányt pótoltál; köszönet érte!
(#) Tambi válasza Tambi hozzászólására (») Szept 28, 2023 /
 
Kedves Fórumtársak!
Hogyan kell(ene) beilleszteni egy kódot?

Köszönettel; Tambi.
(#) kapu48 válasza Tambi hozzászólására (») Szept 28, 2023 /
 
Lent a zöld ikon soron találsz Kód gombot azt meg nyomod, és közé:
  1. ide illeszted be a kódot!
A hozzászólás módosítva: Szept 28, 2023
(#) asch válasza Tambi hozzászólására (») Szept 28, 2023 /
 
Kedves Tambi!
Köszönöm, nagyon hízelgő! Tök jó, hogy maga a program összesen pár sor lett, és egészen világos, hogy mi mit csinál benne! Szép munka! Ha visszanézzük a pár héttel ezelőtti kommentjeidet látszik, hogy meg kellett tanulni hozzá, hogy mi hogyan működik.

Egy dologra még felhívnám a figyelmedet, amit az elején is írtam, csak akkor ez még túl távoli probléma volt! Mikor az ICR1 és OCR1A értékeket átírod, akkor van egy versenyhelyzet a számlálóval, hogy éppen hol tart! Ha éppen rosszkor írod be az új értékeket, akkor előfordulhat egy hibásan végrehajtott ciklus. Ha lassan tekergeted a potit, akkor ennek az esélye egészen kicsi, de sajnos létező esély.

Példa: T értéke csökken T0-ról T1-re T1<T0. A számláló értéke éppen T1<CNT<T0 amikor beírja a program az új értéket! Mi történik ekkor? A számláló az új periódusidő felettről folytatja a számlálást, nem találkozik T1-gyel, és ezért egy "teljes kört" megy, ahelyett, hogy T1-nél fordulna át. Tehát a teljes ciklus 65536 hosszú lesz T1 helyett, és a nagy részében off érték lesz.

Függően attól, hogy a kimenet érzékeny-e erre a fajta hibára, ezt még lehet, hogy javítani kell. Egy lehetséges megoldás, amit annó javasoltam az volt, hogy megvárjuk az átfordulás interruptot és akkor frissítünk. De ennél most eszembe jutott egy sokkal egyszerűbb megoldás, simán busy waitelhetünk is ameddig biztosak vagyunk abban, hogy éppen megtörtént az átfordulás a számlálóban:

  1. while(TCNT1>50); // várakozás addig, hogy a periódus elején legyünk: ekkor biztonságos az értékek átírása
  2. ICR1 = (uint16_t)T;                    
  3. OCR1A = (uint16_t)T/2;}                // 50% kitöltéssel

Az értéket, ahová 50-et írtam úgy kell megválasztani, hogy ne tudja "átugorni" a TCNT1, tehát a lekérdezésekbe mindenképpen férjünk bele, és a legkisebb T/2 értéknél kisebb legyen, hogy biztosak lehessünk benne, hogy mindig még az OCR1A érték előtt megtörténik a regiszterek frissítése.
(#) Tambi válasza asch hozzászólására (») Szept 28, 2023 /
 
Köszönöm, kedves Asch!

Ahogy haladunk be az erdőbe, egyre sűrűbben vannak a fák...

Megtoldottam egy 6 digites TM1637, így látni, hogy mennyit is kell(ene) fordulnia a szervomotornak. Jobb lett volna LCD, mert a LED-ek nagyon rángatják az USB tápot, így a "zaj"-t fel kellett emelni 50-re. Cserében a frekvencia nemigazán csökkenthető 1250 Hz alá az eredetileg kívánatos 100 Hz helyett. Kár, hogy az LCD távolabbról már nehézkesen olvasható...

  1. #include <Arduino.h>
  2. #include <TM1637TinyDisplay6.h>
  3. #define CLK 7
  4. #define DIO 6
  5. TM1637TinyDisplay6 display(CLK, DIO);
  6. int zaj = 50;                     // a poti értékének (zajának) maximális ingadozása
  7. unsigned int Poti = 0;
  8. unsigned int ujPoti = 0;
  9.  
  10. void setup () {
  11. display.begin();
  12. display.setBrightness(7);
  13. pinMode(9, OUTPUT);
  14.   analogReference(DEFAULT);             // "DEFAULT" : a Vcc (+5V) a referencia feszültség
  15.   TCCR1A = 0x82;                         // 9 láb fast 16 bit kimenet
  16.   TCCR1B = 0x1A; }                      // előosztó 8
  17.  
  18. void loop () {
  19.   int ujPoti=analogRead(A0);           // új Érték beolvasása
  20. if(abs(Poti - ujPoti) > zaj)           // a különbség anszolutértéke nagyobb a zajnál, akkor
  21. {
  22.  Poti=ujPoti;                          // a Poti értéke legyen egyenlő az újPoti-val
  23. }
  24. uint32_t u32_Poti=Poti;                // kibővítés 32 bitre, legyen a szám tartománya 0-1023, ami az ADC input tartománya ATMEGA328-on
  25. uint32_t freq = 50 * u32_Poti + 100;   // Lineáris leképzés a 100->50000 tartományra úgy, hogy a részeredmények is elférnek u32 számábrázolásban
  26. uint32_t T = (2000000ul) / freq;       // periódusidő: T=1/freq. 1 helyett a számláló frekvenciáját kell írni, ami 16MHz/8 = 2000000 (ul utótag: azt jelöljük vele, hogy ez egy 32 bites konstans)
  27. while(TCNT1>50);                       // várakozás addig, hogy a periódus elején legyünk: ekkor biztonságos az értékek átírása
  28. ICR1 = (uint16_t)T;                    
  29. OCR1A = (uint16_t)T/2;                 // 50% kitöltéssel
  30. display.showNumberDec(freq, 0, false);} // szám, tizedes,


Köszönöm a "while"-t, a szervomotor hálás lesz érte, meg én is!
Mit lehetne cselekedni, hogy továbbra is stabil legyen LED-el mint most, és lemenjen 100 Hz-re?

Köszönettel; Tambi
A hozzászólás módosítva: Szept 28, 2023
(#) asch válasza Tambi hozzászólására (») Szept 29, 2023 /
 
Először is megteheted, hogy a poti beolvasási tartományát lejjebb állítod egy kicsit úgy, hogy a két vége körüli zajon belüli értékeket mind 0-ra és maximumra állítod. Tehát ha csak az a problémád a poti zajával, hogy nem tudod a szélső értékeket beállítani, akkor azt lehet így "javítani":

  1. int ujPoti=analogRead(A0);           // új Érték beolvasása
  2. if(ujPoti<zaj) ujPoti=0 else ujPoti=ujPoti-zaj;
  3. if(ujPoti>1024-2*zaj) ujPoti=1024-2*zaj;
  4. // a poti beolvasott értéke a [0, 1024-2*zaj] tartományra van normálva.


De persze a zajt is le kellene csökkenteni, ez már legalább valódi elektronikai kérdés. Először is szükséges lesz mérni, hogy mi történik. Oszcilloszkópod van? A tápot mérném, hogy a LED-es kijelző PWM-je rángatja-e a tápot? Ez lehet az egyik oka a növekedett zajnak. Ezt úgy tudod mérni, hogy a szkópot a tápra teszed (érdemes több különböző ponton is mérni, mert ez már analóg dolog, nem feltétlenül fogod ugyanazt látni minden mérőponton), és a trigger levelt addig állítgatod, ameddig valamennyire statikus képet nem kapsz. Ha rángatja a LED PWM-je a tápot, akkor lesz ilyen trigger beállítás, ahol látszani fog a képen.

A következő magának a poti kimenetének a mérése: itt mennél konstansabb jelet kellene mérnünk, de ezen is látszódni fog a LED PWM periódusa várhatóan.

A táp kérdés megoldási lehetőségei:

* "hidegítő" Kondenzátor a tápra külön a LED kijelzőnek, plusz kondenzátor az Arduinonak.
* Megoldani, hogy külön tápja legyen a LED-eknek
* Csökkenteni a LED-ek fényerejét, hogy az átlagos teljes áram kisebb legyen.
* Az Arduinót nem az USB-ről tápolni, mivel itt nagyobb áramok esetén elkerülhetetlenül leesik a feszültség, mivel az USB hoszt oldalán van szabályozva az 5V, és a kábelen eső feszültséget nem lehet kiszabályozni. Ha az Arduino RAW bemenetére (a dugasztáp bemenetre) teszel tápot, akkor stabilabb lehet a helyileg regulált 5V. (Lehet dugasztáp vagy két lítiumos cella, a lényeg, hogy a specifikáció szerinti feszültsége legyen.)

Lehetséges az is, hogy nem a tápon keresztül jön a zaj, hanem a LED kijelző PWM-je kapacitív vagy induktív csatolásban van az Arduino és a poti áramköreivel. Ezt úgy lehet tesztelni, hogy ha mozgatod a kijelzőt, akkor változik-e a jelforma a szkópon? Megoldási lehetőségek:

* Úgy elhelyezni, hogy a lehető legkisebb legyen a zavar
* Árnyékolás
* Az ADC-t szinkronizálni a LED PWM-jével, hogy akkor legyen a mintavétel amikor a PWM éppen off. (Ezt nem tudod megcsinálni ha nem tőled jön a LED-ek órajele, csak a teljesség kedvéért írtom ide.)

Az ATMEGA328p adatlapja szerint az Arduino REF bemenete és a GND közé kell tenni egy kondenzátort amennyiben a VCC-t használjuk referenciaként. Szerintem ez nincs rajta az alap Arduino boardokon, mivel ha más volna a REF, akkor viszont lehet, hogy nem akarsz oda kondenzátort tenni. Én ide tennék egy kondenzátort, ha analóg inputot használnék.

A doksik szerint azzal is lehet növelni az analóg beolvasás pontosságát, ha az ADC idejére leállítjuk a processzort. De ez szerintem már több mint amire neked szükséged van, és nem egyszerű megcsinálni.

Ezek jutottak hirtelen eszembe, de az analóg problémáknak számtalan oka lehet.
A hozzászólás módosítva: Szept 29, 2023
(#) Tambi válasza asch hozzászólására (») Okt 2, 2023 / 1
 
Köszönöm kedves Asch!

Ma tudtam kipróbálni a javaslatokat, nagyszerűen sikerült.
Ki fog nevetni a világ, de mióta a NANO-t egy ideig meghajtottam a FOK-GYEM 9158-ról 5V-al, azóta a laptopon is, meg a PC-n is stabil a kimenet 10-es zajszintnél.

Időközben kibővítettem a szoftverecskét forgásirányváltósra. A poti középállásánál (kis hiszterézissel) nincs kimenőjel, tehát leáll a motor, és tovább forgatva a potit megtörténik az irányváltás és ellenkező irányba kezd forogni (STEP-DIR...melléklet). Így csupán 135 fok elfordulás jut 100Hz-50kHz tartományra, ami eléggé babrás, szerencsés lenne egy helipot, de a 10 fordulatút kicsit sokallom, kevesebbet meg még nem találtam.

Azt hiszem, elkészült a végleges, amit még egyszer köszönök szépen.

Derűs napot; Tambi
  1. #include <Arduino.h>
  2. #include <TM1637TinyDisplay6.h>
  3. #define CLK A2
  4. #define DIO A3
  5. TM1637TinyDisplay6 display(CLK, DIO);
  6. int Poti = 0;
  7. int ujPoti = 0;
  8. int led = 13;
  9. int ablak = 0;
  10. unsigned int freq = 0;
  11. int zaj = 10;
  12. uint32_t Time = 0;
  13.  
  14. void setup () {
  15. pinMode(led, OUTPUT);
  16.   Serial.begin(9600);
  17.     display.begin();
  18.     display.setBrightness(7);
  19.       analogReference(INTERNAL);        // "INTERNAL": belső (+1,1V) referencia feszültség
  20.   TCCR1A = 0x82;                        // pins 9 fast 16 bit
  21.   TCCR1B = 0x1A; }                      // előosztó 8
  22.  
  23. void loop () {
  24.   int ujPoti = analogRead(A0);          // új Érték beolvasása
  25. Serial.print("   DIR = ");  
  26.   if(ujPoti < 512) {                    //forgásirány (DIR) meghatározása
  27.      (digitalWrite(led, LOW));
  28. Serial.print("BALRA");
  29.   } else {
  30.      (digitalWrite(led, HIGH));
  31. Serial.print("JOBBRA");        
  32.   }
  33. if(abs(Poti - ujPoti) > zaj) {          // ha a különbség abszolutértéke nagyobb a zajnál, akkor
  34.  Poti = ujPoti;                         // a Poti értéke legyen egyenlő az újPoti-val
  35. }  
  36. Serial.print("   poti = ");
  37. Serial.print(Poti);
  38. ablak = abs(Poti-512);                  // Poti középállás körül f KI = 0Hz
  39. Serial.print("   ablak = ");
  40. Serial.print(ablak);
  41. if(ablak < 50) { freq = 0;
  42. } else { freq = 110 * (ablak - 50);
  43. }
  44. uint32_t Time = (2000000ul) / freq;       // periódusidő: T=1/freq. 1 helyett a számláló frekvenciáját kell írni, ami 16MHz/8 = 2000000 (ul utótag: azt jelöljük vele, hogy ez egy 32 bites konstans)  
  45. while(TCNT1>50);
  46. ICR1 = (uint16_t)Time;                    
  47. OCR1A = (uint16_t)Time / 2;               // 50% kitöltéssel
  48. Serial.print("   freq = ");
  49. Serial.println(freq);
  50. display.showNumberDec(freq, 0, false);    // szám, tizedes,
  51. }
(#) asch válasza Tambi hozzászólására (») Okt 2, 2023 /
 
Gratulálok! Gondolom van még szabad bemeneted, az irányváltásra használhatsz esetleg egy sima kapcsolót, és akkor visszanyered a poti teljes tartományát a sebességszabályozásra.
(#) fecus hozzászólása Okt 17, 2023 /
 
Kínából vennék Arduino mini pro-t. Ha valaki mostanában rendelt és bevált (sok a kínai atmel chipes), megadná a linket? Régen rendeltem már. Azok a linkek már nem élnek.
(#) fotomen32 hozzászólása Okt 20, 2023 /
 
Üdv
Egy nagyon kezdő AVR-es vagyok és egy nagyon kezdő kérdést szeretnék feltenni.Még sosem foglalkoztam atmelel csak pic-el.Van egy óra amit megépítettem ATtyni84 van benne az lenne a kérdésem hogy hogyan tudnám beletölteni a hex állományt a leg egyszerűbben mien hardver és program kell hozzá?Jelenleg van egy PICKIT2 és egy USBASP V2 hardverem esetleg valameik jó lehet a célra?
(#) asch válasza fotomen32 hozzászólására (») Okt 21, 2023 / 2
 
A pickit2 képes AVR-t is programozni, működni fog. ATmega328-ra ezek működő példák voltak (ismerősöm ezzel tette fel a programot Windowson avrdude.exe-vel):
  1. avrdude.exe -cpickit2 -p m328p -u -U flash:w:lathe_atmega328.hex
  2. avrdude.exe -cpickit2 -p m328p -u -U lfuse:w:0xe2:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m

A -p után áll a processzor típusa, ezt t84-re kell állítani.

A fuse-okat pedig ha kell programozni, akkor érdemes egy kalkulátort használni, és ez egyből kiadja, hogy milyen értékeket kell bemásolni az avrdude parancssorba az adott beállításhoz. Például: https://www.engbedded.com/fusecalc/

Tehát a vége valami ilyen lesz:
  1. avrdude.exe -cpickit2 -p t84 -u -U flash:w:programom.hex


Itt leírja, hogy hogyan kell bekötni (GND, VCC, RESET, MISO, MOSI, SCK): https://www.instructables.com/Arduino-Pickit2-As-Programmer/

Ha Linuxot használsz, akkor is az avrdude programot kell használni, a legtöbb disztróban csomagból lehet telepíteni.
A hozzászólás módosítva: Okt 21, 2023
(#) pont válasza fotomen32 hozzászólására (») Okt 21, 2023 / 1
 
Letöltheted a Bascom-AVR Demo programot, 4K ig teljes értékű, tud HEX-et égetni USBASP-on.
(#) fecus hozzászólása Okt 21, 2023 /
 
Arduino pro mini 5V 16MHz-es kristállyal. 3,3V-ról szeretném működtetni, de elég nekem az 1MHz-es működési órajel. Be fog rezegni a 16MHz-es kristállyal az oszcillátor 3,3V-al? Nem találom az adatlapon ezt a görbét.
A hozzászólás módosítva: Okt 21, 2023
(#) Ivan93 válasza fecus hozzászólására (») Okt 21, 2023 /
 
Szia, atmega328p adatlap 260. oldalán van a grafikon amit keresel. E szerint 16MHz-hez minimum 4.5V szükséges.
(#) alita hozzászólása Jan 13, 2024 /
 
Tisztelt Fórumtársak !

Szeretnék felvilágosítást kérni az Atmega 32 és az Atmega 32A közötti különbségről.Annyit
tudok.hogy árban az előbbi duplája az utóbbinak.Azt tudom még,hogy a lábak kiosztása
ugyanaz,és a fuse bitek 0X99-C1,az utóbbi 0x89-C1.
Kérdésem,ugyan arra célra használható mindkettő?

Üdv:Alita
Következő: »»   835 / 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