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
Sziasztok!
Van egy érdekes hibám. Arduino Mega 2560-at használok, és van kb. 30 változóm, aminek a beállított értékeit EEPROM-ban tárolok. Ez egy céleszköz, amit az ügyfél telepén üzemelek be, itt állítom be a változók értékeit a környezethez igazítva. Miután mindent beállítottam akkor történik EEPROM írás csak a kódban. Ezután a vezérlőt újraindítva a beállítói menü ahol az írás történik már nem kerül meghívásra, így elméletileg többször nem fog lefutni az írásos funkció, csak induláskor beolvassa az EEPROM-ban tárolt értékeket egy-egy változóba, és azokat a változókat használja futáskor. Ezek a telepített eszközök hónapok óta tökéletesen működnek, viszont a telepített kb. 100 eszközből 3-4 gépnél előfordult az, hogy a napi bekapcsolását követően az eszköz nem jól működött, és mint kiderült az egyik változó értéke valami hatalmas nagy szám lett. (alapesetben ezek az értékek 0-100-ig vannak, és a beolvasott érték ~23.000 környéki volt) Többszöri újraindítás után is mindig ezt az értéket kapta vissza, tehát magában a memóriában már rossz érték szerepelt. Kérdés hogy ez hogy került oda úgy, hogy az EEPROM írásos függvény elvileg már nem is kellett hogy lefusson, illetve ha lefutott is volna, akkor is írás előtt lecsekkolja, hogy a menteni kívánt érték 100 alatti-e, és 0-nál nagyobb-e. Az EEPROM.put függvényt használom, és sima int értéket teszek bele, egymástól 5 címmel eltolva. Tehát ezek nem fedik egymást. EEPROM library-t használok Amit még fontos tudnotok: eddig balga módon a Brown-Out-Detection-t kikapcsoltam a fuse biteknél. Megvan az oka hogy miért, de nagyon gyanús hogy ez okozhat problémát. Stabil tápot kap a mikrovezérlő, és indításkor 2 másodpercig nem csinál semmit az eszköz, csak várja hogy tuti stabil legyen a táp, és csak a 2sec után kezd EEPROM-ot olvasni. Viszont utána a normál futás közben sosem hívódik meg az írás, mégis valamiért rossz adat került az EEPROM-ba. Ez lehet esetleg amiatt, hogy Brown-Out-Detection hiánya miatt alacsony feszültségnél a proci hibázik, és valamiért meghívja az EEPROM írást és oda hülye értéket ír be? Mert ez nekem annyira lehetetlennek tűnik... A kapcsolásban látható, hogy 1 db 100 nF kondi van zavarszűrésre, és 1-1 db 1000µF/10V LOW ESR kondi van a mikrovezérlő előtt és után. Elképzelhető hogy a stabil 5V betáp megszűnése esetén a két kondi szépen beejti a feszültséget mondjuk a kritikus 4V alá, és a Brown-Out-Detection hiánya miatt ekkor a proci elkezd hibázni és meghívja az EEPROM.Put függvényt amivel betesz egy random számot egy random címre? Vagy mi okozhat ilyen random memória írás hibát? Ha újra konfigurálom, újra lementem a változót a memóriába akkor természetesen megjavul, tehát maga a memóriaterület nem ment tönkre és nem is történik sűrű írás a memóriaterületre. Az eset ritkán fordul elő és nem minden gépen, de simán lehet hogy csak idő kérdése.... UI: a képen a bal oldali kondik fordítva vannak, tehát a 100nF van közvetlenül a táp után A hozzászólás módosítva: Jún 5, 2023
Szia.
Nekem is van hasonló probémám, de nálam írás közbeni tápelvétel az ok (áramszünet vagy bármi más miatt). Amit tudsz tenni: 3 különböző helyre mented le ugyanazt, és beolvasáskor megvizsgálod, hogy mindhárom érték azonos-e. Ha nem, akkor a kettő helyessel felülírod a hibásat. Ezzel kiküszöbölted a hibás működést. Arra tudok gondolni, hogy akár ha olvasáskor szűnik meg a táp, akkor is lehet, hogy az EEPROM-ba hibás adat kerül. Pl. olvasás félbemarad, az EEPROM egy bizonyos állapotban van, és újraindítás után úgy kezeled az EEPROM-ot, mintha alapállapotban lenne, miközben ő mondjuk a címet várja. Erre te elküldesz neki ismét egy olvasás parancsot, amit ő adatnak értelmez, majd utána egy adatot, amit meg utasításnak. Valami ilyesmire gondolok. Tehát kellene egy EEPROM resetet is indításkor csinálni. Én így oldanám meg, ezzel a maradék 3-4% hibalehetőség is eltűnne. Üdv. A hozzászólás módosítva: Jún 5, 2023
Idézet: - Ezt hogyan tudom megcsinálni?„"EEPROM reset"” Hibajavítást most már én is alkalmazok, bár én csak 2 helyre mentek adatot. Ha a fő memóriacímen tárolt adat 0-100-ig van (jellemzően amikor rossz érték került bele akkor szint mindig ilyen nagyon magas szám volt benne) akkor a backup memóriacímről beírom az értéket a fő memória címre. Egyébként ha a fő memóriacímből kiolvasott érték tartományon belüli, akkor a Backupot mindig beírja újra. Elméletileg az EEPROM.put() függvény csak akkor írja ténylegesen be ha változott az érték a tárolthoz képest. Egyébként az, hogy az Arudio Mega-nak 4kbyte-os az EEPROM-ja, azt azt jelenti hogy a max cím amit beírhatok az EEPROM.put(4000, változó)?? Tudom, hülye kérdés, de tényleg nem vágom Idézet: - Ezt egyébként a Brown-Out-Detectionnel megelőzhető? „"akár ha olvasáskor szűnik meg a táp, akkor is lehet, hogy az EEPROM-ba hibás adat kerül. "” A hozzászólás módosítva: Jún 5, 2023
Nézz utána, hogyan működik pontosan az EEPROM írása, olvasása, pl., hogy mennyi idő telhet el az adatok között. Lehet, hogy nincs is időkorlát, elküldöd az olvasás parancsot, majd fél óra múlva a címet, és működik... Nem akarok butaságot írni, már nagyon régen nem foglalkoztam vele. Lehet elégséges, ha indításkor kiküldesz 4db 0-t. Gondolom inicializálás nincs, így reset sem.
Ha csak két helyen tárolod az infót, akkor sosem tudod, hogy melyik a jó (ha véletlenül 100 alatt maradna a hiba is). Háromnál már egyszerűen eldönthető. Ha nagyon magas értéket olvasol, akkor ott több hiba is van. 255-nél nagyobb értéket csak 2 byteon tudsz tárolni. Miért olvasol be egynél több bytot, ha csak egy byteon tárolsz? A második byte fixen nulla kellene hogy legyen, miközben az EEPROM gyárilag 0xFF-fel van feltöltve! Ilyenkor lehetséges, hogy nem is az adatod lesz hibás, hanem az utána levő címre kerül valami beírásra, vagy az előtte levőre. Ne integert-t használj, hanem byte-ot olvass be. Esetleg van egy függvényed, ami a RAM-ot túlcímzi, és miután az adat az EEPROM-ból a RAM-ba került, a hibás függvény pont arra a részre ír be, ahol a változókat tárolod. Ilyenkor ha összehasonlítanás az EEPROM és a RAM tartalmát, más értékeket kapnál. 4kbyte az 4096byte, a címek 0-tól indulnak, a legnagyobb cím 4095 lehet! Integert 2byteon tudsz tárolni, így kettessével kellene lépkedned. A Brown-Out detektorban én nem bíznék, főleg, hogy ha több byteot írsz. Ha elmegy a táp, akkor elment, nem tudsz mit csinálni. Az EEPROM írás lassú folyamat. "Egyébként ha a fő memóriacímből kiolvasott érték tartományon belüli, akkor a Backupot mindig beírja újra" - itt viszont van egy írás, ami félre is sikerülhet, és olyankor hogy melyik adat károsodik, azt nem tudni. Lehet az összes.
Közben átnéztem a programot, és találtam egy hibát:
A program elején definiálom az alábbi tömböt:
Tehát ez egy 51 elemből álló tömb. Majd a program futása közben a user le tudja csekkolni, úgymond lapozgatni tudja a beállított értékeket.
Az aktertek mindig az aktuális érték, ha ezt lapozza akkor ez növelődik egyesével. Észrevettem, hogy a megjelenítésnél van egy érték, ami kifut a tömb tartományból, ugyanis az 50 db konfigurálási értéken kívül van egy ellenörző érték, és ez ha meghívódik, akkor az akterteknek 500-as értéket ad:
Ugyebár a tömb nincs definiálva 500-ig csak 50-ig. A fordításkor a program nem veszi észre mert változóval hívom be az 500-as elemet, így szépen gond nélkül lefordul a program. A poén az, hogy nem is fagy le miatta, szépen fut tovább ha egy pillanatra meghívom az 500-at, de ez okozhat ilyen túlcsordulást, hogy a háttérben szépen memóriaterületeket írogat hülyeségekkel? Gondolnám hogy ebbe bele kellene fagyni, de fut tovább a program. Persze a következő ciklusban az aktertek az 0 lesz mert akkor már az elején lecsekkolom hogy 50 feletti-e az aktertek, ha igen akkor legyen 0. De egyszer engedi 50-ről 500-ra állítani A hozzászólás módosítva: Jún 5, 2023
Mitől lenne 51 az az 50?
50 hely az , a cimzés meg [0]...[49]
Teljesen igazad van, rosszul írtam.
Használd a BOR-t. Az AVR nem szereti, ha lassan megy el a tápja, sérülhet az EEPROM tartalma. Ehhez nem szükséges a függvényt tartalmaznia a programnak, a vezérlőregiszterek vesznek fel fals értéket.
Miért fagyna be? Ez nem windows. Csinálja, amire megkéred, még ha értelmetlen, akkor is. Szépen kiolvassa az 500-as helyen levő memória értékét, és utána fel is használja. Honnan tudná az AVR, hogy ezt esetleg nem direkt csináltad? Ha eljutsz a pointer logikáig, rájössz, hogy AVR mindent IS csinálhatsz, lefagyni nem fog. Ha "lefagy", akkor is inkább user error miatt belement egy olyan ciklusba, amiből nem tud kijönni, de ilyenkor sincs lefagyva, csak nem azt csinálja, amit szeretnél. Jók ezek az AVR-ek.
Kedvenc - valahol hallott - szólásom: a számítógép utasításaid, és nem a a kívánságaid szerint működik
Ezért értik meg jobban a férfiak, mint a nők...
Rendben, ezt megértettem...
Egy dolgot kihagytam a leírásból, így már érthető lesz miért gondoltam hogy "kifagy":
Ilyen módon oldom meg az eltolást. Tehát az 50 konfig érték egymástól 10-re van eltolva. A konfig[1] az 1-es címen tárolódok, a konfig[2] a 11-es címen, és így tovább. A konfig[50] pedig az 501-es címen. Viszont ugye írtam hogy véletlenül bekerül az 500-as érték is, és a konfig[500] az az 5001-es memória címre mutat, ami meg ugye Mega esetén már nem létezik. Ez okozhat anomáliát? Elvileg írni nem akarna erre a területre csak olvasni, de egy hibás címzés miatt az olvasásból lehet valamilyen módon eeprom korrupció? A hozzászólás módosítva: Jún 6, 2023
A konf[1] a 11-es címen tárolódik...
Az 1-es címen a konf[0] lesz (a "for (int i = 0;" miatt). Szerintem így összesen 51 db értéked van (az "i <= 50;" miatt): 0 - 50. Viszont az "int konfig[50];" talán valóban csak 50 db. helyet definiál... Ezt az 50 vs. 51 kérdést célszerű lehet rendezni... Másrészt, azt is meg kellene nézni, hogy miért alakulhat ki az 500-as érték? Ne a lekérdezésnél, hanem már a keletkezésénél zárd ki a lehetőségét...
Ezt a sort már megemeltem a biztonság kedvéért 55-re Gondot nem hiszem hogy okozna az, hogy több elemet definiáltam mint amennyit használok. Az 500-as érték az az én hülyeségem miatt van, nem véletlenül került bele. Ahogy fentebb is olvasható sajnos oda nem számot írtam hanem változót. És a változó sajnos néha lehet 500. EZT tegnap már javítottam, ez a változó már nem vehet fel 500-as értéket, és így elvileg két hibát javítottam: - Nem futok ki az előre definiált tömb méretből (50-et definiáltam csak, de az 500-as elemével is meghívtam és dolgozni akartam vele) - Nem akar még véletlenül sem az 5001-es EEPROM címen olvasni/írni. Mindegyik kritikus hiba, és NAGYON remélem hogy ez okozta azt a problémát, hogy néha-néha elmászott egy-egy EEPROMban tárolt érték. Logikus lenne. Kérdés még továbbra is az, hogy egy hibás címzés (tartományon kívül) miatt az olvasásból, vagy egy tömb túlcsordulásból lehet valamilyen módon eeprom korrupció, és emiatt sérül 1-1 eeprom címen tárolt adat? A hozzászólás módosítva: Jún 6, 2023
Ilyet nem használunk. Nagyon könnyű elrontani. Tele lesz számokkal a kód. Egy helyen átírod, többi meg marad ugyanannyi...
Egy forráskódban sehol sem szerepelhet szám, helyette nevesített konstansokat használni. Aztán az is érdekes, hogy miért két bájtos adattípust (int) használsz, ha az adatod elfér egy bájton is. Használj pontosan definiált méretű adattípust, például uint8_t. Rögtön feleslegessé is válik a tizes cím eltolás. Mondjuk int esetében is csak kettővel kellett volna eltolni... Amúgy pedig a sizeof függvénnyel lehet lekérni a hosszát. Olvashatóbb és változtatás állóbb is a kód.
És akkor a ciklus:
Így aztán nyugodtan változtathatod akár az elemek számát, akár a típusát, a kódod mindig jól fog működni. Vagy ott lenne a C++ array, ami mindezt szükségtelenné tenné...
Köszönöm a sok segítséget, biztos vagyok benne hogy vannak hiányosságaim a kódolás terén. És nyilván ezeket az észrevételeket lehet hogy implementálni fogom a kódba.
Viszont a fő kérdésem továbbra is az hogy egy hibás címzés (tartományon kívül) miatt az olvasásból, vagy egy tömb túlcsordulásból lehet valamilyen módon eeprom korrupció, és emiatt sérül 1-1 eeprom címen tárolt adat? Tehát hogy megnyugodhatok-e vajon a fent említett hibák javításával? UI: egy kérdés, itt a "konfig[0]"-val kell hivatkozni a teljes tömbre? Vagy mindegy hogy melyik elemet adom meg, mert csak arra kell hogy tudjam hány bájtot foglal egy adat?
A hozzászólás módosítva: Jún 6, 2023
Nem állítom, hogy SW oldalról nincs értelme megtámogatni a hibakezelést, de 2000µF puffer esetén nem ez lesz a hosszútávú megoldás. Bővebben: Link
A hozzászólás módosítva: Jún 6, 2023
sizeof(konfig[0]) megmondja, hogy hány bájt a tömb első eleme. Mivel a tömb összes eleme egyforma méretű, így ezzel megkapod a méretét.
Amúgy a ciklust sem kell megírni, mert az AVR GCC libben már megírták nekünk mások.
Ezek a függvények azok:
Forrás Így használhatod:
Idézet: „de 2000µF puffer esetén” Ez miért probléma? Túl sok, túl kevés? vagy mi a gond vele? Elektronikához (is) hülye vagyok
"Ez egy céleszköz, amit az ügyfél telepén üzemelek be, itt állítom be a változók értékeit a környezethez igazítva. Miután mindent beállítottam akkor történik EEPROM írás csak a kódban. Ezután a vezérlőt újraindítva a beállítói menü ahol az írás történik már nem kerül meghívásra, így elméletileg többször nem fog lefutni az írásos funkció, csak induláskor beolvassa az EEPROM-ban tárolt értékeket egy-egy változóba, és azokat a változókat használja futáskor."
Nekem is volt gondom az EEPROM-ban tárolt adatokkal. Főleg akkor, ha hosszú áramszünet miatt a szünetmentes akkumulátora merült le és így szép lassan fogyott el a "delej". Ha csak egyszer (vagy ritkán) állítod az értékeket, akkor szerintem sokkal jobb megoldás, ha flash-be tárolod. Kiolvasod a page-et, a változók helyén módosítod, majd vissza írod. Akár az is lehet, hogy dedikált page-en csak ezek a változóid vannak.
BOD bekapcsolni (tápfesztől függően, az egy egységgel alább). Nincs "EEPROM garbage".
EEPROM 0. címe TILOS írni - > lsd adatlap: tápfeszvesztéskor véletlen beírás lehet. Watchdog kezelendő.
Szervusztok !
A napokban feltöltöttem az Atmel Studió 7-t.Úgy gondolom,hogy valamit nem jó csináltam,mert a végén nem jelent meg a parancsikon,de a helyi lemez fájloknál sem jelenik meg a szokásos Atmel.A programok között fenn van az 5.03 Gb. Persze megnyitani sem lehetett,ezért törölni akartam,de nem lehetséges,sem a vezérlő pulttal,sem a Totalcomander-ral.Törlés alkalmával újra a szokásos telepítési eljárás jelenik meg,de csak egy darabig. Hogy tudnék megszabadulni ettől a förmedvénytől. Üdv:Minden fórumtársnak
Addig-addig győzködtem,míg nem sikerült a problémám megoldása.
Sziasztok! Tönkrement az elektromos rollerem egy step-Down ic hibája miatt úgyhogy új elektronikát csinálok hozzá. Az egyik gondolatom az hogy ha elém kanyarodik valaki akkor egy távolságmérő szenzor segítségével ezt észlelné az avr és magától vészfékezne. Ehhez nekem olyan szenzor kellene ami tud legalább vagy 20 méterre látni. A hc-sr04 sajnos csak 5 méteres. Nem muszáj ultrahangos, lézeres is jó lenne de se a kereső nem ad ki megfelelő érzékelőt se az AliExpress. Tudtok ajánlani valamit?
Sok sikert kívánok a fejlesztéshez.
Hozzá sem kezdenék...
A Suzuki kamerás, radaros érzékelője is időnként ütközésre figyelmeztet indokolatlanul, és elkezd fékezni, pedig azt elég sokan fejleszthették, elég régóta. Ha ilyet sikerülne is kifejlesztened, utána el kellene felejteni a járdán gyalogosok közötti cikázást, mert 10 méterenként fejreállnál... Az emberi agy sokkal jobb ennél, három dimenziós, nemlineáris egyenleteket old meg valós időben. Már ha figyel persze...
Ez jó ! Madár, macska, utcai kuka, számtalan oszlop, kikerülendő tárgy, és igen az emberek.
Azokat se kéne elütni
|
Bejelentkezés
Hirdetés |