Fórum témák
» Több friss téma |
A klónok CH340 Soros-USB illesztőjének drivere (Letöltés)
Tegnap tudtam meg, hogy a B4R (basic) fordító 4-es verziója az ESP32-es alaplapokat is támogatja. Támogatja a C++ betéteket is. És úgy látom hogy a C++-ban írt library-ket is.
A számolások esetén nem egyértelmű, mivel az időbe és a program memóriába is belefér, a számolások szerintem az egyszerűség kedvéért maradhatnak float-ok.
A pwmout nincs is használva (hanem ahol kellene, oda be van írva kézzel), az analogin mindenképpen jobb lenne egészben tárolva, például uint8_t típusban. De még jobb, ha ez nem is rendes változó, hanem #define. De ezek kozmetikai kérdések némi teljesítmény vonzattal, de nem ez a kritikus itt.
Tehát 1kHz a becélzott visszacsatolási frekvencia, igaz? 1000 mérésnek kellene lenni, és a mérés alapján a PWM-et frissíteni? Az első posztba bevágott példában van egy delay(100), ami 100ms várakozás, tehát eleve 10Hz-ről indul, 10-szer futna le egy másodperc alatt, ha csak ez az egy sor lenne benne, akkor is. És még annál valamivel lassabb, mert van benne más is.
Maga a hardver simán képes ilyen gyors visszacsatolásra, de ahhoz, hogy tényleg így működjön, ahhoz már gondolkodni és tervezni kell. A csip maga adatlap szerint 15 ezer ADC mintát tud olvasni teljes felbontáson, és 76.9 ezret csökkentett felbontáson. Kb. 15kHz viszacsatolású mágnes lebegtetőt csináltam már vele én is. Ha a szabályozó ciklusból logokat akarsz a serialra írni egy 1000Hz-es szabályzó körből, akkor én azzal kezdeném, hogy a baud rate-et megemelném amennyire csak lehetséges, az 57600 azt hiszem ami még stabilan működik, azt állítanám be. De még ezzel is 57600/1000/10=5.7 bájt jut egy szabályozási körre, annál többet nem lehet kiíratni 1ms alatt. Meg lehetne azt is csinálni, hogy mondjuk minden 10-edik szabályozó körben írsz csak logot, akkor arra összegyűlik 57 bájt, abba belefér egy sor adat. De sajnos az Arduino alap Serial könyvtára a kiírást blokkoló módban kezeli, tehát ha kiírsz 7 bájtot, akkor az több mint egy milliszekundumig blokkolja a futást. Pedig meg lehet úgy is valósítani, hogy egy pufferbe bekerül a kimenet, és ezt a puffert a "háttérben" interruptok segítségével kiadagolja az UART csatornára. Ha valósidejű dolgot csinálok, akkor a serial lib lecserélése szokott az első dolgom lenni. (És ekkor már inkább el is hagyom az Arduino környezetet, és Makefile-os megoldást csinálok helyette inkább.) Ha bele akarsz mélyedni ennyire, akkor tudok ebben is segítséget adni. A szabályzó programozásban az a nehéz, hogy ha növekszik a periódusidő, vagy csak minden tizedik visszacsatolás késik a loggolás miatt, akkor már lényegében más lehet a rendszer viselkedése. Ezért nehéz megfigyelhetővé tenni a folyamatot. Megoldás lehet az is, ha "vakon" programozunk, azaz lemondunk a loggolásról teljesen, és csak a szkóppal mérhető dolgok alapján kalapáljuk helyre a programot. Azt is meg lehet csinálni, hogy betűk helyett binárisan írod ki a logot, például a mért érték 10 bit, a visszacsatolt kimeneti PWM kitöltési tényező 8 bit, az integrátor tag kurrens értéke is legyen 16 bit, tehát körönként 5 bájton ki lehet logolni minden lényeges infót. Ezzel meg az a gond, hogy a PC oldalon valami program kell, ami a bináris értékeket megjeleníti. Nem nagy kunszt megcsinálni, de az alap Arduino környezet szerintem nem tudja. Ahogy én csinálnám: aszinkron serial írás libbel írnék minden tizedik körben logot. Ezen kívül csinálnék egy öndiagnosztikát, ami méri, hogy a szabályzás periódusideje valóban 1kHz-e, és ha nem, akkor hibaüzeneteket ír. Akkor biztosan tudnám, hogy a 10. logolós kör sem lett hosszabb mint a többi. Erre az alapra már biztosan lehet építkezni. És még csak a loggolásnál tartunk. A PID szabályzónak két emlékezete van: az előző error (ez magvan a programodban "error_1" néven), ami a differencia kiszámításához kell, ami a D tag együtthatója (ez nálad rosszul van betűzve szerintem kd * (error - error_1) kellene). De a D tagot szokás 0-ra választani, azaz kikapcsolni, mert "idegessé" teszi a szabályozást, ha nincsen nagyon jól kitalálva az értéke, és nem kellően gyors a visszacsatolás. Az I tag-hoz a hibát integrálni kell, azaz körönként hozzáadni egy gyűjtő változóhoz, az integrálhoz. (integral=integral+error) Ez matematikailag tetszőleges naggyá vagy kicsivé nőhet azokban az esetekben, ha a szabályzó nem tudja elérni a célértéket. Ha például egy szervómotor kimenetéről van szó, és kézzel lefogod pár másodpercig, hogy ne tudjon a helyére mutatni, majd elengeded, akkor egy ideig a másik irányba fog túlmenni, ameddig az integrátor tag vissza nem áll. Ennek elkerülésére le szoktam korlátozni úgy, hogy az együtthatóval szorozva az általa adott érték ne legyen túl nagy. (if(integral>INTEGRAL_MAX) {integral=INTEGRAL_MAX;}if(integral<INTEGRAL_MIN) {integral=INTEGRAL_MIN;}) Más emlékezete nincsen a PID szabályzónak. Az out értéknek nincs emlékezete, és te úgy valósítottad meg, hogy az előző értékhez adod azt, aminek az új értéknek kellene lenni. Szerintem a helyes képlet: out=kd * (error - error_1) + kp*error + ki*integral A kimeneti tartomány korlátozása jól van megcsinálva. Szkópod van, tudod valós időben nézni a PWM-et és a visszacsatolt feszültséget? Ez a feladat annak a bonyolultságnak a határán van egyébként, amire már érdemes lehet szimulátort írni. Ha nem sikerül a valódi rendszert működésre bírni, akkor olyat szoktam megcsinálni, hogy ugyanazt a programot egy másik keretbe foglalva PC-n is futtatom, és ott írok hozzá egy mini szimulátort, ami a szabályzott rendszert szimulálja, a kimenet pedig megjeleníthetővé és elemezhetővé teszi. A szimulátoron minden érték megfigyelhető és minden fajta bemenetre lehet tesztelni és ki lehet javítgatni. (Professzionális munka esetén pedig automatikus teszteket lehet csinálni a szimulátoron, amik bizonyítják a helyes működést.) Utána már az igazi is működni szokott. Ha érdekel tudok ehhez is segítséget adni.
Mivel szimulálsz valós rendszereket? Ez a történet a végén erősen megfogott! Tudnál erről bővebben írni?
Tetszik az is ahogy a pid-et elemezted, ezt így még nem láttam sehol
Mindig az adott rendszerhez tervezek szimulátort, nem ismerek egy kaptafára menő megoldást.
Azzal szoktam kezdeni, hogy minden projektnek készítek egy HAL layert, amin keresztül a program eléri a hardvert. Például ebben az esetben: idő lekérés, PWM állítás, ADC beolvasás, logolás. Az Arduino azon működési módja, hogy a loop-ot hívogatja a HAL, az maradhat. A HAL tehát azt jelenti, hogy a hardver közvetlen piszkálása nem maradhat a programban közvetlenül. De olyan lehet, hogy a HAL művelet a célplatform esetén csak egy define egy közvetlen port műveletre, eddig mindig sikerült úgy megvalósítani, hogy futás idejű lassulást nem okoz a HAL réteg. Itt a HAL réteg lehet maga az Arduino lib. A csak PC-n futó forrásba egy main függvény kell, ami meghívja a setupot és aztán hívogatja a loop-ot. HAL megvalósításra van egy online példám, ami böngészőben fut: https://rizsi.com/programs/lathe_gui/emscripten/lathe.html Itt az ATMEGA328p-re írt program van emscripten segítségével böngészőben futtatva, és az enkóder és gomb bemenetek, illetve hétszegmenses kijelzők hozzá vannak illesztve a weboldalhoz. A forrás itt van: https://github.com/rizsi/playing_with_MCUs/tree/master/lathe_gui Tesztek viszont itt nincsenek. A HAL-t megvalósítom C-ben úgy, hogy egy virtuális órához képest működő rendszert csinálok: A logoláshoz olyat is szoktunk csinálni, hogy a szimulátorban sokkal több log van, ami élesben nem "férne át" az UART vonalon, a valódi platformon ezek a hívások üres define-okkal megoldva ott sincsenek. Itt például a szimulátorban minden körben minden változót ki lehet íratni akár. Ezt az esetet szerintem úgy oldanám meg, hogy az áramkörre egy nagyon egyszerű szimulátort megírnék C-ben, a szimulált értékeket pedig olyan formában íratnám ki, amit meg tud jeleníteni valami grafikon megjelenítő. Ha jól értenék valamelyik áramkörszimulátorhoz, akkor ahhoz is lehetne csatolni, de sajnos ilyet még eddig nem csináltam, nem tudom pontosan hogy is kellene. Van egy saját könyvtárunk is, ami több résztvevős valós idejű rendszerek szimulálásához nagyon hasznos, szabad szoftverként meg is osztottuk, de publikus példa sajnos nincsen hozzá: https://github.com/qgears/simple-realtime-simulator
Volt egy olyan tervem, hogy a W1209 termosztátot átírom, csak a kínaiak már nem stm8-al,
hanem saját ic-vel gyártják. Viszont itt egy szösszenet:
A hozzászólás módosítva: Jan 12, 2024
Köszönöm a kimerítő választ. Mint mondtam, tanulom a programozást.
Mint a programozáshoz nem hozzáértő, valahogy így képzelem el ezt az egészet, azon felül, amit leírtál: belül a programban fut a PI szabályozóm. A helyes működéshez mintát kell vennem az analóg jelből, de ezt gyorsabban kell megtennem, amíg kiszámolom a megfelelő dolgokat és beavatkozok a kimeneten. Sehol nem láttam olyan struktúrát Arduinora, ahol a mintavétel állítható, maga PI program fix és a PWM frekvencia is állítható. A járulékos dolgok nem okoznak problémát (PID tagok számítása, szabályozókör), illetve a műszerezettség sem, van labor (tápegység, szkóp, jelgenerátor stb.). Ja igen, és köszönöm az eddigieket és a továbbiakat is!
> Sehol nem láttam olyan struktúrát Arduinora, ahol a mintavétel állítható.
Azt, hogy mi mennyi ideig tart, azt számolni, illetve mérni kell. Számolni úgy lehet, hogy ha az adatlapból indulsz ki, mérni meg úgy, hogy a művelet előtt és után billegtetsz egy PIN-t, és a kimenetet szkóppal meg tudod mérni. (De vigyázni kell, hogy az Arduino digitalOutput hívás rendkívül lassú, vagy 100 órajelet is felemészt, miközben egy PORTB|=0b00010000; hívás 1 vagy két órajel alatt lefut kb! Ezért írtam, hogy a HAL-t jól kell megtervezni, hogy kicsi legyen az overhead, ha számít.) Az analogRead futásideje például azon is múlik, hogy hogy van az ADC bekonfigurálva, ennek utána kell nézni. Az Arduino libben nem szeretem, hogy mindent ki kell várni, hogy megtörténjen. Ha C-ben megírod, akkor meg lehet csinálni, hogy az ADC alatt futhasson a programod, és akkor nem veszítesz időt vele. De ha a 15kSps-ből indulunk ki, akkor az ms 15-öd része fog elmenni az analogRead-del. A számolást is lehetne saccolni, de egyszerűbb mérni. A PWM frissítése megint olyan, hogy C-ben megírva 2 db regiszter írása volna, ami 2-4 órajel körül van. Az Arduino libraryt nem tudom, de valamennyi overhead biztosan van, az is kb 10-100 órajel lehet. A loggolásról már írtam egy litániát fentebb. Ha a cél 1000us-en belül sikerült maradni, akkor azt kell tudni, hogy a loop megállás és késlekedés nélkül újra lesz hívva, tehát amint az egyik körnek vége, indul a következő. A periódusidő tehát a futásidőn múlik csak. Ha pontosra akarod állítani, akkor ilyet lehet csinálni pszeudókóddal, ami talán nagyjából működik is:
Szimulátor szerint stabil!
A hozzászólás módosítva: Jan 13, 2024
Köszönöm a linkeket! Az az igazság, hogy ezt az esztergás oldalt mintha már mutattad volna, de továbbra sem áll össze a fejemben a komplett egész. Írod hogy a bemenetek a scripthez vannak illesztve. Ezt pl hogyan? Amikor megnyitom az oldalt, csak egy sor gombot és kijelzett értékeket látok. Ennek hogyan kellene működni?
A felső két csúszka egy érzékelő, a hétszegmenses kijelzőkön mutatja az elmozdulást. Maga a program nem túl bonyolult, nem is annyira érdekes - ebből a szempontból -, hogy mit csinál. A lényeg az, hogy pontosan ugyanaz a program fut egy böngészőben mint egy beágyazott processzoron. Nyilván a HAL eltér, tehát az, hogy mit csinál a hardverrel. De a program lényege, az, hogy egyáltalán mit kell csinálni az pontosan ugyanaz, tehát meg tudod mutatni a usernek, illetve ki tudsz próbálni funkciókat anélkül, hogy egyáltalán az első prototípusod elkészült volna. Ha már tudod PC-n futtatni a programot, akkor lehet rá automatikus teszteket is csinálni is. Illetve tudod debuggolni, hogy mit csinál a program, ami beágyazott rendszerekben nem triviális, pláne real-time esetben. Például a PID szabályzó nem tud értelmesen működni, ha az időzítés nem jó. Emiatt PID szabályzót nem lehet debuggolni (kivéve a nagyon lassú időállandójú szabályzókat). Viszont egy szimulált órás szimulált környezetben lehet. Mert ott ameddig a debugger áll, addig az idő se megy előre.
Hogy hogy van összekötve? Az Emscripten alkalmas arra, hogy egy C program a böngésző ablakban tud futni. Olyan programot írok, ami a loop-ot hívogatja. A program amikor a bemeneteket kérdezi, akkor a webes kontrollokban végződik a kérdés, és ADC érték helyett például a csúszka értéke jön vissza persze ugyanarra a tartományra leképezve. A kimenetnél pedig a program megmondja, hogy melyik szegmensek világítsanak, és akkor azoknak a színe lesz HTML-ben átírva. Ez csak egy tech demó arra, hogy a mikrovezérlőre írt programot akár böngészőben is lehet szimulálni. A böngésző főleg arra jó, hogy könnyű megmutatni. Például egy Linuxos programot nem mindenki tudna elindítani. De az automatikus teszteket végső soron Linuxos programként valósítanék meg.
Sziasztok. Új nekem ez az arduino, és csak ez a projektem lenne vele, amiben elakadtam.
Hogyan tudok több nyomógombot használni analóg bemeneteken? Van egy alap program, egy leddel és egy nyomógombbal. Ezt kellene bővítenem 2re. Mi a módja? Egy nyomógomb a bemeneten, egy led a kimeneten. És ebből kellene 2... Mindig hibára futok, tudnátok segíteni?
Analóg bemeneten elvileg lehet több gombot kezelni egy pin-nel, például itt van egy rajz és blogbjeegyzés a témáról: http://www.ignorantofthings.com/2018/07/the-perfect-multi-button-in...r.html (első találat volt nekem). De én egyszer próbáltam csak ilyet csinálni és nem működött megbízhatóan: a gomb ellenállása változik és belezavar a mérésbe. (Mennél több gomb van, annál nagyobb lesz a bizonytalanság, kettőre még biztos egész jót lehet csinálni.)
Számtalan módszer van arra, hogy kevés pin-en sok gombot tudjuk kezelni, és a legtöbb az ellenállásos analóg bemenetes megoldással szemben megbízhatóbban működik. Például van a charlieplexing, vagy a személyes kedvencem a shift regiszteres input, amihez kell kb 5 pin, de az 5 pinnel tetszőleges számú bemenetet lehet kezelni, akár több százat is. Ha két bemenet kell, akkor miért nem használsz egy másik digitális pint a másik bemenethez? Elfogytak már a lábak más célra? Ha többet leírnál a problémádról, akkor jobban tudnánk segíteni. A hozzászólás módosítva: Jan 14, 2024
Néhány autóban is használják hogy néhány gombot analóg bemeneten olvasnak be, jellemzően autórádiók kormánytávirányítója.
Köszönöm, most már megértettem! Érdekes megoldás, tetszik!
Lehet fogalmazhattam volna egyértelműbben.
Minden gomb külön bemeneten lenne. Egy gomb egy ledet (relét) vezérelne. Az alap innen jött. Bővebben: Link A kódban egy csatorna van leírva, de nekem 2 kellene. És nem sikerült rájönnöm, hogy kellene átírnom. Ebben kérem a segítséget. Programozásban nem vagyok jártas, így picit nehézkes A hozzászólás módosítva: Jan 14, 2024
A link valamiért nem beszúrható.
https://www.microcontroller.hu/blog/projektek/ket-csatornas-rele-ve...noval/
Hogyne lenne az?
A link szöveges részét rövidíti a fórummotor, azt meg úgyis emberi nyelven szokás írni...
Ha csak ez kell, tessék:
A releváns részeket megdupláztam, és külön kimeneteket defináltam nekik. A LED ami a 13-as kimenet, az a panelon van, de a LED2 már külső alkatrész ha szeretnéd használni. ezt a 10-es pinre kötöttem. Nem próbáltam ki, de elvileg működnie kellene. Enjoy!
Sajnos hibát talál így is, állapotváltozás összevetésnél, valamint az állapotbeolvasásnál.
Nem értem ennek a logikáját...
Nem túl informatív amikor azt mondod hogy hibát talál.
A logikája az amúgy, hogy definiálunk pár bemenetet és pár kimenetet. A kimenetre mennek a relék, meg a ledek, a bemenetekre meg a gombok. A setup() egyszer lefut, és megcsinálja amit benne találsz. Ebben az esetben inicializálja a már említett be és kimeneteket. A loop() a lényeg! Ezt ciklikusan ismételgeti! Amikor véget ért, rögtön újra végrehajtja a végtelenségig. Beolvassa egy változóba a pin értékét, val1-be az első gombot. Ezután megnézi hogy az értéke magas szint-e, valamint old_val1 érteke alacsony (alapból az) szintű-e. Ha ez így van, akkor a gomb eddig nem volt megnyomva, de most már meg van nyomva. Ekkor a jelzőt beállítjuk az ellenkező értékére (nulláról egybe, vagy egyből nullába) és várunk egy picit hogy lecsengjen a prell. Oldval értékét frissítjük. Itt készen is vagyunk, megyünk tovább. Ha a state értéke bármikor 1, akkor bekapcsoljuk a relét, meg a ledet is. Ha nulla akkor meg ki. Készen van minden, elölről az egész! És mindezt kétszer, mert azt kérted hogy ketten legyenek. szerk.: figyelj oda, hogy alapból egy ellenállás lehúzza testre a pint, és amikor megnyomod a gombot akkor direktbe rákapcsolja az 5V-ra! A rajzon szerintem el van rontva, a zöld vezeték a nyomógomb másik lábára való! A hozzászólás módosítva: Jan 14, 2024
Köszönöm a segítséget! Restartoltam a gépet, és így már sikerült!
Még annyi kérdésem lenne, hogy olyant hogy lehet csinálni, hogy: Teszem azt, a 12es bemenetre ameddig feszültséget adok, addig mindkét relé kikapcsolt állapotban legyen, még ha előtte aktív is volt? Feszültség megszűnése után pedig visszaállnak az előtte lévő állapotba. Ez kivitelezhető?
Persze!
Ugyanígy a második relénél is! Lehetne szebben, de szerintem működik így is!
Unalmamban átírtam kicsit a programot. Nem értem, egyesek miért a + ra kötik a
gombokat, nem véletlenül vannak a uc-kben felhúzó ellenállások.
Ha valaki nem ismerné, a kép Simulide-ben Bővebben: Link készült. Utalva egy másik topikra, a korlátai ellenére ilyen egyszerűbb projectekhez tökéletes.
Arra azért figyelj, hogy így direktben relét meghajtani nem illik. A port láb max 20mA-t bír,
tehát csak olyan relét használj, aminek az áramfelvétele 15mA-t nem haladja meg. Tranzisztorral vagy fettel szokták ezt megoldani.
Kuner kérdésére akartam válaszolni, ott úgy látom optos reléboardot használnak.
De teljesen igazad van! A hozzászólás módosítva: Jan 15, 2024
Majdnem
Én speciel ULN2004 vagy ULN2803 tranzisztormezővel fogom hajtani a reléket. Az alapokra rávezettetek, így már tetszőlegesen tudom bövíteni a csatornákat, variálni a pin hozzárendeléseket. Ma kaptam egy tippet is a bővítésre, GPIO extenderrel, I²C buszon. Majd meglátjuk, sikerül-e. A hozzászólás módosítva: Jan 15, 2024
Köszönöm mindenkinek az eddigi segítséget, az elindulást az arduino világában!
Még anny kérdésem lenne, hogy:
Beleraktam a programba a blink példaprogramot egy külön 'működés jelző ledre', a 13as pinre. 100ms high, 2300ms low. Villog is, ahogy kell. De, akár hova illesztem a programban, mindig csak akkor fogadja a nyomógomb jelét, és akkor hajtja végre, mikor a led villan, csak abban a 100ms-ban. Hova kellene beollóznom, melyik részre? A loop parancs után se jó, és a ptogram legvégén sem. Mit baltázok el?
Azt, hogy a blink alapból várakozást használ a villogtatásra. (Olyan mint mikor nyomsz egy PAUSE gombot a CD lejátszón. A delay() függvénnyel a CPU-n nyomsz egy PAUSE -t.) Várakozás közben pedig semmi mást nem tud csinálni a CPU. Ha LED -et akarsz villogtatni, akkor a milis() függvény kell hozzá.
Keress rá google-ban. A hozzászólás módosítva: Jan 15, 2024
|
Bejelentkezés
Hirdetés |