A library-k jelentős részének nem nagyon van részletes leírása. Ami akad, az vagy az arduino.cc fórumában van, vagy a GitHub-on.
A LiquidCrystal könyvtárban a print és a write között annyi a differencia, hogy a write a zárójelbe írt éréték (vagy a zárójelbe írt változó tartalmának megfelelő) ascii kódú karaktert jeleníti meg (csak azt), míg a print-tel gyakorlatilag bármit kiírhatsz ('a' egy karaktert, "asdf" több karaktert ír ki, míg a változó kiírható magában is (direktben), vagy különböző módokon kódolva (dec, hex, oct, bin).
Változó konverzióra sok mód van, de egyik sem egyszerű. Programozási szempontból az az elsődleges, hogy a célnak megfelelő minimálisan szükséges (vagyis a lehető legkevesebb szabad memóriát lekötő) változó legyen az adott célra deklarálva.
Még arra sem igazán jöttem rá, hogy mi a különbség az lcd.print() és az lcd.write() között.
Nem igazán tudom feldolgozni azt, hogy van egy library (mondjuk az RTC-hez), és nem találok hozzá megfelelően alacson szintű leírást (mármint az én szintemnek megfelelőt).
Sajnos csak itt tudok kérdezgetni, ha már elvesztettem a türelmemet.
1. Tudod, hogy a változódba mi jön meg az rtc-ből (pontosabban a hőmérőből). Valószínűleg egy analóg érték, amit egy viszonylag egyszerű osztás/szorzás/összeadás/kivonás műveletsorral szépen decimális celsius értékké lehet konvertálni. Az, hogy ez egész (int) vagy tört (float). Namost. Az a szám, amit a végén megkapsz (float) praktikusan (a 2. pont szerint) szorzandó tízzel (egy tizedes) vagy százzal (két tizedes), aztán kell belőle gyártani egy sima int vagy long változót (ha csak szobahőmérsékletet mérsz, az int bőven elég). Figyelni kell még arra is, hogy signed vagy unsigned változót használsz-e, mert az előbbi elmehet negatívba, a másik viszont nem. A float signed, a lenti példában (mivel órához használtam) ezért van unsigned long, mert nem lehet negatív az érték.
2. El kell döntened, hogy milyen pontossággal akarod megjeleníteni az értéket. Két tizedes jegy szerintem még sok is (a hőmérő pontossága aligha van 1 fokon belül, innentől meg maximum a változást tudod tized fok pontosan figyelni, és még ez sem teljesen megbízható). Lásd még 1. pont.
3. Kód
void vagy(unsigned long v) { // ide egyébként attól függően kellhet a sima long, hogy elmész-e negatív tartományba vagy sem, lásd fent
// a v a fő loopban a hőmérséklet tárolására használt változó, típusát tekintve legyen azonos ezzel (itt unsigned long) byte ones; // sima változó-deklarálás, ez lesz az "egész" byte tens; // sima változó-deklarálás, ez lesz a "tizes" byte fractions; // tized
byte fractionss; // század
// feltételezzük, hogy a hőmérsékletet két tizedes jegyig akarod megjeleníteni, és így a korábbi egész celsius-t osztottad 100-zal (in da loop)
// itt volt egy v=v/10, de az nem kell, felesleges.
fractionss = v%10; // a század értékét meghatározzuk.
// a v%10 jelentése: oszd el v-t 10-zel, és nézd meg a maradékát. Technikai értelemben ez annyit jelent, hogy "levágjuk" a változó egyes számtartományba eső része feletti összes elemet (tizes, százas stb.), majd a számot tároljuk egy változóban (ami lehet byte, mert az értéke soha nem több 10-nél).
v = v/10; // elosztjuk tízzel, vagyis kvázi levágjuk az utolsó számjegyet, ami eddig 10-es számmező volt, az 1-es lesz, ami 100-as, az 10-es. fractions = v%10; // mint előbb v = v/10; // és tovább. ones = v%10; v = v/10; tens = v%10; // innentől is lehet feljebb menni a százas, ezres, tízezres stb. számmezők felé, amit a változó bír.
// ez innentől a megjelenítés. Pofon egyszerű, meghatározod a tizes számmezőben lévő szám helyzetét (legyen mondjuk az 1. pozíció, és kiírod a számot): lc.setDigit(0,1,tens,false);
// aztán az egyes számmező értékét eggyel jobbra, a 2. pozícióba, de ide ugye kell egy tizedesjelző is (ez itt a "true" jelzés): lc.setDigit(0,2,ones,true);
// aztán megyünk tovább... lc.setDigit(0,3,fractions,false); lc.setDigit(0,4,fractionss,false);
}
Az LiquidCrystal könyvtárral ez úgy fest, hogy:
lcd.setCursor(0, 0); // kurzorpozíció: 0. sor (felső), 0. pozíció (bal szélső). Innen kezdődően jobbra íródik ki a következő sor által definiált karaktersor
lcd.print(tens); // vagyis a tizes számmező számjegye. Mivel ez 0-9-ig lehet valami, csak egy karaktert tartalmaz.
Ez picit kód- és időigényes megoldás, viszont mindig pontosan ugyanúgy jelenik meg a szám.
if, illetve case vizsgálattal azt is meg lehet csinálni, hogy ha az első számjegy 0, akkor üres karaktert adjon, ne 0-t írjon ki (és fordítva is persze).
Biztos van ennél elegánsabb megoldás is, egyelőre nem sikerült rájönnöm.
v = v/10; fractions = v%10; v = v/10; ones = v%10; v = v/10; tens = v%10; lc.setDigit(0,1,tens,false); lc.setDigit(0,2,ones,true); lc.setDigit(0,3,fractions,false); lc.setDigit(0,4,fractionss,false);
}
Ez max72xx-re fogja kiírni, de az elsó rész gyak. bármi lehet.
A sketchben a vagy([homersekletvaltozo]); formulával tudod hívni. A homerseklatvaltozo leginkább unsigned long kell legyen, bár ezen lehet kísérletezni, hogy mi jön ki az rtc-ből (nekem a DS3231-ből sima int jön ki). Lehet, hogy csak egész értékeket fogsz kapni, ez a hőmérőtől függ (bocs, nem néztem vissza, hogy pontosan milyen).
Mindazonáltal nekem is voltak vele nehézségeim jelentős méretű (PROGMEM-mel paraméterezett) tömböknél. Úgyhogy elmatekoztam 1 dimenzióssá és inkább trükkel hívtam, így működött. (Gyakorlatilag adott egység méretű szekvenciák voltak, ezeket egyesítettem.)
Hogy ne legyen feszültség-eltérés. Ez csak annyi, hogy az Arduino kitolja a kártyának, hogy hány volton működik (az elterjedtek közül a Due kivételével mind 5V-on). Bár az arduino.cc kapcsolási rajza szerint be sincs kötve... :-)
Asszem a 10-11-12-13 láb kell adatforgalomra, ebben az SPI is benne van, plusz az 5V, plusz a test plusz a Viref, a többi az SD kártya. Próbapanelen össze lehetne dugdosni, bár nem egy egyszerű művelet. Az SPI csatlakozóval (oldalt középen "anya") ne foglalkozz, annak az összes lába megfelel az Uno V3 (és így a Nano) egy-egy lábával.
Elvileg helyes a meglátás. Valahogy nekem most nem adja, hogy csináljak egy gyors tesztet, de szerintem működik így. Bár azon túl, hogy tudod, hogy működik, sokat nem érsz vele, mert az SD kártyát nem fogod tudni kezelni.
Jól gondolom, hogy egy Eth./SD Shield-nek, ha csak tápot adok és rádugom az RJ45-öt hálózattal, akkor tökéletesn vissza kellene jeleznie a FULLD, 100M, LINK ledekkel, hogy mi van?
"Az eddig begyűjtött információk alapján gyerekkori izgalom motoszkál bennem, mert végre olyan dolgokat is megvalósíthatok, amiket eddig nem is gondoltam volna."
Tökéletesen megfogalmaztad az Arduino platform (egyik) lényegét, valóban ez volt a célja a kitalálóinak!
A magyar Arduino érában én ezen a blogon és a távírós jóemberen kívül érdemi információforrással nem találkoztam. Angolul ennek kb. az ezerszerese van, gyakorlatilag még nem találkoztam olyan problémával (egy halott kárgyát leszámítva), amit ne tudtak volna orvosolni napokon (sokszor órákon) belül. Kiváló angol irodalma van.
Az ATmega328 kontroller lábanként elvileg 40 mA-t bír, gyakorlatilag 20-25 mA-nél többel nem javasolják terhelni. Ezen felül az egész mikrokontroller összesen 400 mA-rel terhelhető.
A kitek (amiket azért tudatosan választottam) kb. harmadát használom, a maradék tök fölösleges. IR távirányító például. Vagy 8x8-as mátrix LED. 7 szegmenses shift register... Dőlésérzékelő... Sok felesleges kacat.
8-10 ledhez már shift register vagy pwm meghajtó kell. Különben 8-10 lábad oda (vagy multiplexelsz, de akkor ugye a mikrokontroller értékes programhelyét és számítási kapacitását pazarlod). Ez nem különösebben alkatrészigényes.
Nem úgy a vezérlések. A "rákötöm a relét, azt kész" eleve nem működik. Kell egy előtétellenállás, egy NPN tranzisztor és egy dióda. Ha elegánsan akarod megcsinálni, akkor még egy optocsatoló, hogy ha az autóban galiba van (ami alapból pl. egy indítózásnál előfordul jelentős tüskék formájában), ne tudjon SEMMILYEN módon visszamenni a lábakra, üzemzavar esetén sem. És ez ugye relénként. Plusz a próbanyák, amire mindezt felforrasztod, meg az egyebek, sorkapcsok, műszerdoboz, kábelek, nyavalyatudjami. Fényérzékelés nem nagy mutatvány, három alkatrész. Jól működőre megcsinálni már annyira nem magától értetődő.