Fórum témák
» Több friss téma |
A klónok CH340 Soros-USB illesztőjének drivere (Letöltés)
Arduino kód lassú. A digitalWrite különösen. A shiftOut pedig digitalWrite-ot hívja ciklusból.
Közvetlen port regiszter írással lehetne rajta gyorsítani.
Köszönöm a gyors választ .
Akkor lenne egy bit es kérdésem Megpróbálom igy lerajzolni. led[y][z]=BIN X; tömb a formációja. Azt szeretném 1. lévő értéket elkezdem balra shiftelni és amikor elérte a 8 bitet akkor át töltse 2. 8 bitjébe aztán azt az értéket 3. 8bitjébe ........ Vagy is vizuális ha z irány is ezzel az elvel megcsinálom akkor körbe futt a pl szám az egész ledkockán.
Erre van valami frappáns megoldás? Hogy lehetne shiftelést áttölteni egy másik tömbbe?
Ilyen alapból nincs, de megoldható:
- shifteled a legutolsó byte-ot - teszteled az előtte lévő byte legfelső bitjét, ha az 1 akkor növeled a legutolsó byte-ot 1-gyel - shifteled az előtte lévő byte-ot - így tovább az összes byte-ra Valami ilyesmi egydimenziós tömbbel:
A hozzászólás módosítva: Okt 19, 2021
A char x,y,z; értéke csak pozitív egész szám lehet 0...255-ig!
A -1 feltétel nem jó! for(z=7;z>-1;z--)...
Majkimester köszönöm.
Kapu48 -1 re nem igy megy az érték.
Sajnos az Ardiuno leirás egyértelműen nem mondja ki, hogy a char előjel nélküli vagy előjeles típus, méretre is csak annyit mond hogy minimum 8 bit. Továbbá létezik az unsigned char, ami meg azt sugallja, hogy a sima char előjeles. Igazából a háttérben lévő gcc forditó a char típust alapból előjelesen kezeli, de megadható neki a -funsigned-char command line paraméter amivel meg előjel nélküli lesz. Nem tudom az Arduino használja-e ezt a paramétert. Ugyan a doksiban nincs benne, de leírhatod a char helyett azt is hogy signed char, és akkor egyértelműen előjeles. De én például mindig typedef-fel használom:
A feltétel z>-1 = z nagyobb mint -1! Mindig igaz marad.
Ezért sosem lesz vége a for ciklusnak! Bővebben: char Link The size of the char datatype is at least 8 bits. It’s recommended to only use char for storing characters. For an unsigned, one-byte (8 bit) data type, use the byte data type.
A char típust karakter kódok tárolására találták ki.
Akkor a 128-nál nagyobb grafikus vagy ékezetes karaktereket mínusz előjelesként, hogyan tudná értelmezni a fordító? A hozzászólás módosítva: Okt 19, 2021
Az, hogy előjeles vagy nem a karakter tárolása szempontjából mindegy. Legyen 8 bit egymás után, és kész. Egy karakter kód esetében semmi értelme az előjelességet vizsgálni.
A előjelesség csak akkor jön képbe, ha műveletet akarsz végezni az adott változóval. Ezt nyilván karakterrel is lehet, pl. char c = 'a' + 15; Ha egyértelműsíteni akarod mi is történik, akkor mindig eléírod hogy unsigned vagy signed, vagy használod a fent említett typedef-et. Ami inkább érdekes, hogy azt írja az arduino leírásban, hogy minimum 8 bit, azaz bizonyos platformokon, lehet, hogy UTF-16 karaktert értenek alatta?
Éppen ezért kifogásoltam a for ciklusokban alkalmazott char z<-1 feltétel használatát!
Bővebben: Link a hsz.-re Akkor ide teszem lefordítva az ajánlást amit szintén idéztem: A char adattípus mérete legalább 8 bit. Javasoljuk, hogy a karaktereket csak karakterek tárolására használja. előjel nélkül, egybájtos (8 bites) adattípus esetén használja a bájtos adattípust. A hozzászólás módosítva: Okt 19, 2021
Rendben.
Akkor kijavítom >=0 re akkor gondolom jó lesz. char azért használom mert amikor 1...8 kell for ciklust csinálni elég rá bőven és ram ot nem pazarlom annyira. Idézet: „char azért használom mert amikor 1...8 kell for ciklust csinálni elég rá bőven és ram ot nem pazarlom annyira.” Akkor használj byte-ot: Bővebben: Link Vagy unsigned char-t (ami ugyanaz, mint a byte).
Sziasztok!
Kérdésem a következő lenne... Mérnem kellene egy rakodógép motorjának a fordulatát, majd a későbbiekben tovább foglalkozni vele, de jelenleg a fordulat mérés a lényeg. PNP-s jeladó van gyárilag benne, amit ISR-el figyelek. Ez részben működik is, viszont 20x4 I2C lcd-re is ki kellene írni közben, hogy látható is legyen. Mivel delay-t nem lehet használni, így a kijelzés konkrétan csak van, de nem látható. Ötletet várnék arra, hogyan kellene a kijelzés frissítési idejét kb 1-2mp-re kitolni, míg maga a megszakítás rész nyugodtan fut? Előre is Köszönöm a segítséget! Mellékletben a példaprogram.
Itt javasoltam tanfolyamot a multitaskingra:
Bővebben: Link 22. oldal Időzítés – késleltetés nélkül 23. multitasking.ino És fontos a time változók legyenek:
A hozzászólás módosítva: Okt 19, 2021
Szia!
Köszönöm szépen! Holnap átnézem a linkelt infót!
Bocsánat léptetőmotorom van, elírtam , de nem ilyen segítséget kértem.
Hogyan vársz segitséget, ha még a feladatot sem tudod megfoglamazni?
Mi fontos számodra az idö vagy a léptetés? Ha az idö, akkor csinálj egy megszakitásos idözitöt, ami adja az idöimpulzusokat ( másodpercenként stb). Ezeket számold a poti állásátol függöen, és amig el nem éred az impulzusszámot a motor forog a ráengedett impulzusok szerint. Ha meg a motorba menö impulzusok fontosak. ( mennyit fordul el a motor), akkor meg azokat az impulzusokat számold valamelyik számolo eljárással.
Elsőként a rev változó mindenképpen Volatile float!!
Azok a változók, amik az ISR-ben kapnak értéket, azok elejére mindenképpen kell a Volatile! Aztán kellene kisebb érték esetleg a float helyett. Kell ekkora szám neked mindenképpen? A Setup-ban: volatile float rev=0; volatile A hozzászólás módosítva: Okt 20, 2021
Unortodox választ fogok adni egy ki nem mondott implicit kérdésre:
> Mivel delay-t nem lehet használni, így a kijelzés konkrétan csak van, de nem látható. Miért ne lehetne delay-t használni? Azt hiszem tényleg van ilyen ajánlás, hogy ne használjunk delayt a main loopban, de valójában semmi akadálya nincsen, simán működik. Én pont így csinálnám, tennék egy
Ezen kívül hiba még, hogy az rpm változód float típusú, az lcd.print viszont nem kezeli a floatot, ezért először egész értékké kell alakítani, például long-gá. Így:
Létezik szebb megoldás - amiket a többiek javasoltak, azokat mind érdemes megfontolni - de ez így szerintem már működőképes volna. (A delay nem csak a kijelzés ideje miatt fontos - hogy ne írjuk folyton felül, hanem azért is, mert enélkül a mérési idő nagyon rövid lesz, és többnyire egyetlen rev sem lesz a mérésben, így hibásan 0-t mérünk. Mennél nagyobb a mérés ideje, annál kisebb lesz ez a fajta "alignment" hiba. De mindenképpen ugrálni fog a mért érték ezzel a módszerrel, ha nincsen szinkronban az Arduino periódusa (pl kb 2 másodperc) és a motor fordulatszáma. Stabil kijelzést úgy lehet csinálni, ha a tickek között eltelt időt mérjük, vagy ha a mért tartományon belül az első tick előtti és az utolsó tick utáni időt levonjuk az osztás előtt. Így nem lesz szisztematikus alignment hiba a mérésben, de ez már egy következő verziónak a témája...)
Ha delay()-t nem akar használni, akkor is van még egy halom megoldás. Timer-interrupt túlcsordulásakor hívja meg a kiírást pl.
Vagy a loop-ban mér még egy másik időt is. Ha az nem telik le, akkor nem ír ki semmit. A loop is fut, az ISR() is megy, és akkor ír az LCD-re amikor akar. Kell ugyan bele egy if, de hát na... Bár már régen használtam Arduino-t, PIC-el kell játszanom.
Az egyik probléma a kódoddal, hogy teljesen felesleges minden egyes loop ciklusban frissíteni a kijelzőt, célszerű bizonyos időközönként kiírni az értékeket. Erre itt van egy példa (a kijelző kezelő függvény neve disp):
A másik probléma, hogy amit te fordulatszámnak mérsz, az nem az, legfeljebb hasonlít hozzá, mert a fordulatszámmal arányosan változik az értéke. A fordulatszám a percenkénti impulzusok száma, amennyiben fordulatonként 1 impulzus érkezik. Kétféleképpen lehet a fordulatszámot mérni. Ha magasabb fordulatszámról van szó, akkor egy konstans idő alatt érkezett impulzusok számából lehet kiszámítani a fordulatszámot. A másik lehetőség, alacsonyabb fordulatszám esetén, amikor az impulzusok közötti időt mérjük. A te megoldásodban elvileg az elsőt alkalmaznád, csakhogy az az időtartam, ami alatt méred a beérkező impulzusokat, nincs benne a számítási képletben, márpedig a nélkül nem lesz jó az érték. Ráadásul ez az időtartam a loop hossza mínusz a 33. sor. Azaz ha módosítod a loop tartalmát, akkor ez az időtartam is módosul. Miután már van egy megszakítás kezelőd, ezért annak a kiegészítésére mutatok egy példát, ahol a fordulatszámjelet egy tacho jeladó szolgáltatja:
Az rpmcorrection Atmel processzornál és 16 MHz-es órajelnél 86 Mind a 2 kódrészlet le van tesztelve (ezt használom a motor fordulatszám szabályozómban).
Ha a micros() értékét nem kétszer olvasnád ki a függvényben, hanem rögtön az elején betennéd egy változóba, és utána mindenhol ezt a változót használnád a függvényben, akkor két kiolvasás között mindig ugyanannyi időeltolódással lehetne számolni, azaz szerintem akkor nem lenne szükség az rpmcorrection-ra.
A hozzászólás módosítva: Okt 20, 2021
Annyit azért hozzátennék, hogy az ISR-ből száműzni kellene az egész számítást, az tárolja csak a tachotime-ot a global volatile unsigned long-ban, majd a főprogram meg kiszámolja belőle az RPM-et sokkal ritkában, mondjuk csak akkor amikor tényleg letelt az első kódrészletben az 500mS és ki akarod jelezni.
És maga a tachotime -> RPM számítás meg a float használatával is ágyúval verébre ha nem akarsz tizedes jegyeket kijelezni a fordulatszámnál. Ez simán fixpontos aritmetikával számítható 1 sorban.
(még akár 1 tizedesjeggyel együtt is, ha nagyon kellene, csak akkor 60 millió helyett 600 milliót kell osztani és az eredmény RPM*10 lesz, megfelelő helyre kirakott tizedesponttal kell megjeleníteni). rpmcorrection meg szerintem nem is kellene, ha az ISR-ben a micros()-t nem 2x hívnád fel. Ez a 86uS gondolom az 5-7 sorok lefutási ideje, ami eltelik a két micros() között.
És ami szintén kimaradt, hogy az ISR-ben beállított unsigned long tachotime-ot a főprogramból ne használd direktben, hanem egy atomic blockban másold le, és a másolattal számolj tovább.
Ez azért kell, mert a unsigned long 4 byte hosszú, és simán előfordulhat, hogy a főprogramban éppen számolsz vele, de bejön egy megszakítás ami meg éppen új értékre állítja. Így a főprogramban a számításod félig a régi félig az új értékkel számol. HA nem így teszel. akkor a fordulatszám kijelzésedbe néha néha bevillan egy hibás érték és nem érted miért. Az atomic block tulajdonképpen a benne lévő kód futtatási idejére letíltja a megszakításokat, ezzel megakadályozva, hogy hibás értéket másolj.
Pont ezért (is) tetszett meg az STM32, mert egy ilyen szorzás vagy osztás egy lépésben megvan (14nsec) , tehát gyakorlatilag a fenti probléma fel sem merülhet. Sőt 2x 14nanosec akár a megszakításban is ottmaradhatna
Amúgy azt, hogy az rpmcerrection nem szükséges, előtted fél órával én is leírtam. Azt csak zárójelben jegyzem meg, hogy ha a ArduinoNano estében 85usec körüli idő eltelik azzal a pár utasítással, akkor irgalmatlanul nagy a sebességkülönbség az STM32/BluePill javára...
A hardveres osztás támogatás az STM32-nél(sem) azt jelenti, hogy 1 ciklus alatt oszt el bármit is, hanem hogy célhardver van rá benne, ami relatíve kevés ciklus szám alatt végzi azt el! Nem tévesztendő össze a szorzással, ami tényleg működhet 1 ciklus alatt is...
A hozzászólás módosítva: Okt 21, 2021
Idézek az STM32F103 adatlapjáról (legelső oldal):
Features • ARM® 32-bit Cortex®-M3 CPU Core – 72 MHz maximum frequency, 1.25 DMIPS/MHz (Dhrystone 2.1) performance at 0 wait state memory access – Single-cycle multiplication and hardware division Nekem ez azt jelenti, hogy 1 órajel (single-cycle) ciklus (tehát kb. 14nanosec) ideig tart a szorzás és az osztás is. De fejtsd ki nyugodtan, hogyha szerinted ez mást jelent. Véleményem szerint ha az osztás több ciklus lenne akkor külön kellett volna írni, valahogy így: – Single-cycle multiplication - Hardware division A hozzászólás módosítva: Okt 21, 2021
Idézet: „Single-cycle multiplication and hardware division” Ezt kellene jobban értelmezni! Ez annyit jelent, hogy 1 ciklus alatt szoroz, de nem 1 ciklus alatt oszt, hanem erre ugyan van benne hardver, de az nem 1 ciklus alatt végez vele....
Ne feledd, hogy másodpercenként 2x-5x akarod megjeleníteni az adatot, azaz 200..500mS-onként kell egy 85usec-es számolás float-tal, de én fixpontos szorzás osztást használnék ami meg még gyorsabb. Ez az egész az AVR-nek is gyerekjáték. Az STM32 egy 32 bites kontroller, egész más kategória, de ez a feladat még az AVR-nek is bőven az egyszerű dolgok közé tartozik.
Az rpmcerrection-ös hozzászólásodat már csak utána láttam, de emiatt már nem módosítottam. Az AVR-ben is van egyébként hardver szorzó, 2 órajel a 8 bitre. Osztás viszont nincs. Ezért is írtam így: 60000000L / (tachotime * TACHOPULSES) ahelyett, hogy: 60000000L / tachotime / TACHOPULSES, hogy csak 1 osztás legyen, ami általában lassabb művelet mint a szorzás. Az STM32-ben Cortex M3 mag van ami elvileg az alábbi órajel alatt oszt és szoroz: Multiply 32 1 or 2 MUL, MLA, and MLS. MUL is one cycle and MLA and MLS are two cycles. Multiply with 64-bit result 32 3-7[] UMULL, SMULL, UMLAL, and SMLAL. Cycle count based on input sizes. That is, ABS(inputs) < 64K terminates early. Divide 32 2-12[] SDIV and UDIV. 32/32 divides both signed and unsigned with 32-bit quotient result (no remainder, it can be derived by subtraction). This earlies out when dividend and divisor are close in size. azaz a Single-cycle multiplication and hardware division azt jelenti, hogy 1 órajel alatt szoroz, és van hardware osztás, ami nem 1 órajel. Ez fix pontos szorzás és osztás, lebegőpontos ott is tovább tart. A hozzászólás módosítva: Okt 21, 2021
Sziasztok, ha jól értelmezem az ARM leírást akkor 2 től 12 órajelet vesz igénybe az osztás, a szorzás 1 től 7 órajelet.
Úgy tünik Majkimester gyorsabb volt A hozzászólás módosítva: Okt 21, 2021
|
Bejelentkezés
Hirdetés |