Most karácsonyi leszerelés van, úgyhogy csak röviden.
A MOS-FET egy nagy teljesítményű kapcsolónak tekinthető, kb. mint egy relé, csak a működési elve teljesen más. Nem „állít elő” feszültséget. Nem tudom, hogy mit és hol mértél, de az biztos, hogy ami jelforma a FET-be bemegy, a karakterisztikájának megfelelően nagyjából az fog kijönni belőle. Most semmi FET-es kapcsolásom nincs összerakva mérhető formában, de ha lesz és nem felejtem el, akkor pár screenshotot küldök.
Köszi a kimerítő választ :) és bocs hogy csak kódrészletet adtam. Védelmemben annyit, hogy még készül és kicsit töredezett még a kód, bár igyekeztem kommentelni. Egyébként akvárium vezérlés lesz rengeteg beavatkozási lehetőséggel auto/manual módban. Igazán már csak ez a pwm-es játék a fényerővel és a tápadagoló pumpák vezérlése van hátra, meg sok teszt... (meg az amire még csak ez után gondolok).
A változókra természetesen figyeltem, így a legrosszabb esetben sem tudnak túlcsordulni. Egyetlen változóm sem vehet fel elméletben negatív értéket, az idő alapú int változóim (eltelt_percek, vil_be, stb) általában percben (x óra*60 + y perc) vannak meghatározva, vagy néha hasonló módon másodpercben. A "napfel" tényleg byte, értéke 1-59 között lehet, valójában percértékek és futás közben bármikor változtatható nextion HMI-ról. A nap_kep is a nextion felé megy, illetve a utolsó if-return-ben lévő lehatároló érték is a nextiontól jön, ami fölé nem mehet a a led fénye.
Még arra is figyeltem, hogy a változók se akadhassanak össze (pld ne előzhesse meg a kikapcsolás a bekapcsolást), küldjön hibajelet ha a user ilyet produkálna a sok állítgatással.
A progi mega-n fut és a globális változók 64%-ban vannak kihasználva, így még néhány elefér.
A javaslataid kipróbálom természetesen. Ezek szerint valamit elbaltáztam, amikor valós elemszám nélküli tömböt nem sikerült deklarálnom a setup-ban.
A próbálgatások alatt egyszer olyanba már belefutottam, hogy mem hiányra panaszkodva nem engedte indítani a serial monitort, csak reset után. Ez akkor ált elő, mikor folyamatos óravisszaállítás köztben a for alatti tömbfeltöltést próbálgattam. Lehet akkor sikerült feszegetnem a 8kB határait.
fenyfel[i] = map (n, 0, n_max, 1, 255);
fenyero = fenyfel[index];
analogWrite(napfeny, fenyero);
Az analogWrite függvény 255-nél ad 100%-ot. A led 0-100 közötti kitöltési tényezőjét ez az eredmény határozza meg, melyet a MOS-FET állít elő, jelen esetben "0"-12V-ot. Ezt jól megmagyaráztam magamnak, remélem jól okoskodom. :) Jól gondolom, hogy a MOS-FET-en az 1. tényezőhöz sem a 12V 1%-a tartozik, tehát az sem lineáris?
Egyébként a led kitöltési tényezőjének kiszámításához a for ciklusban először részarányosan osztást alkalmaztam, de úgy nagyon gyorsan elérte a látható max fényerőt. Ekkor váltottam négyzetre, de úgy tűnik, hogy ez sem a legmegfelelőbb, így gyúrok rajta kicsit...
Köszi a segítséget. Egyébként két éve egyszer már kóstolgattam ezt a világot, de akkor időhiány miatt gyorsan félretettem. Most, kb. két hónapja újra belemerültem, és elég sok időt rááldoztam az olvasásra, tanulásra. Az ötleteim téren hajlamos vagyok a saját fejem után menni, a járt utakat kerülöm, így sok kis kudarcból nagyobb élmény lesz... Volt olyan nap, hogy kb 12 óra "programozás" eredménye kb. 20 soros működő kódrészlet lett...
A kitöltési tényező egy százalékos (vagy tört százalékos) érték, 0-től 100-ig. 0-nál csak 0 van (egyáltalán nincs magas jelrészlet), 100-nál meg csak 1 van (csak magas jelrészlet van). A legtöbb led láthatóan nem lineáris. Az, hogy mennyire nem az, a pwm alap frekvenciája, a led árama és néhány egyéb paramétere határozza meg (mi az a küszöbfeszültség, amin az elektronok áramlása és így a fénygerjesztés létrejön és ehhez milyen hosszú fel- és lefutási idő tartozik). Másrészt, az emberi szem a fényesség-eltérést nem lineárisan, hanem logaritmikusan érzékeli még azonos fényviszonyok között is, ezért van, hogy néhány érték (pl. a csillagok fényességének meghatározásához használt magnitudó) sem lineáris skála, hanem logaritmikus. (A decibel is az egyébként.)
Általában 20 százalékos kitöltési tényezőig nagyon intenzív a fényesség emelkedése, 20 és 60 között mérsékelt, 60 és 80 között alig észlelhető és a legtöbb sima lednél 80 és 100 százalék között csak ritkán lehet érdemi fényességváltozást észrevenni (sokszor a ledek gyártási eltérései nagyobb fényerődifferenciát produkálnak). De ez szinte ledenként különbözik, nem hogy led típusonként.
Mátrixot/tömböt létrehozhatsz szabadon, előre nem meghatározott elemszámmal, ekkor a konkrét memóriafoglalás akkor történik, amikor a program fut. Ha a szoftvered hibás és/vagy nem számoltál utána, egykönnyen belefuthatsz olyan helyzetbe, hogy a rendelkezésedre álló memóriát egy sima for ciklus teleírja, és onnantól rossz esedben a kontrollernek is harangoztak. Márpedig olyan sok memóriával nem tudsz gazdálkodni, mert a SRAM Uno (és folyamodványai) esetén 2, Mega2560 esetén 8 kB.
A kóddal nekem több bajom is van.
-- nem látom a napfel változó deklarálását és a kezdeti értékét sem, emiatt,
-- az int signed, a byte unsigned, vagyis az int lehet negatív is, a byte nem. Ha a napfel jó esetben byte, akkor is gáz van, mert ha az értéke 181-et meghaladja, akkor az int n= i*i; és az int n_max = napfel * napfel; sorokban máris túlcsordultál. Az n változót nyugodtan definiálhatod globálisként, de lehetőleg valami értelmesebb névvel, mert így kb. fingja sincs az embernek, hogy mi az.
-- az int változó deklarálásra való, loopban, nem parancssor szinten (for ciklusban például) kerülendő a használata, mint minden változót deklaráló parancsnak.
-- a fenyfel[] tömböt a void setup()-ban is feltöltheted, feltéve, ha csak egyszer van rá szükség (ezt mondjuk a fals értékek elkerülése végett egyébként is érdemes megtenni). Ha változik az értéke futáson belül, akkor tedd ki külön függvénybe a feltöltést. Deklaráld globálisként a maximális elemszámra, és úgy töltsd fel, hogy lehetőleg a kiolvasást és a maximális érdemi elemszámot ugyanaz a változó (ez esetben a napfel) határozza meg. Nagy lesz a memóriafoglalásod, de kicsi lesz az esélye, hogy valami csúnyaságba belefutsz. Ha egyébként memóriaigényes a program és nincs változóra már memória (pláne ennyire), akkor csinálhatsz egy külön függvényben minden alkalommal egy számítást arra, hogy éppen mennyi a fenyero ideális értéke (ami egyébként a [napfel - (vil_be - eltelt_percek)] négyzetének map paranccsal való megfelelő redukálásának eredménye. (Gyk.: ha nem fut le túl sűrűn a program fényerőállítási része, akkor a tömb teljes egészében kihagyható és egy viszonylag komplikált számítással helyettesíthető).
-- az
n = map(n, 0, n_max, 1, 255);
így egy kissé erős. Tisztább, ha összehozod a következő sorral:
fenyfel[i] = map (n, 0, n_max, 1, 255);
-- az if-ben a return; számomra teljesen értelmezhetetlen.
Ahogy a kódot sikerült kisilabizálnom, nagyjából az történik, hogy egy tömböt feltöltesz egy gradációs görbe egyes értékeihez, ahol a sorszám az eltelt időt, az érték a világosságot szimbolizálja. A több értékeit ezután az eltelt idő föggvényében kiolvasod és ennek megfelelően hajtod meg a kimeneten lévő lámpát (PWM módszerrel).
Tudni kellene, hogy a napfel értéke milyen gyakorisággal változik (ha változik egyáltalán), illetve azt, hogy mi lehet a maximális értéke (ha byte, akkor 255). A tömböt a program elején deklaráljuk a lehető maximális értékre ( byte fenyfel[napfel]; ), de csak egyszer. index változó ugyanez. A vil_be és az eltelt_percek nevű változók típusát nem lenne ártalom tisztázni, mert ha az időt millis() alapon méred, akkor a byte egykönnyen bajos lehet, de adott esetben még az int is. (A millis() unsigned long típusú változó.) A (fenyertek) nem tudom miért van zárójelben. A va_napfel.setValue(1) sor honnan jön? A nap_kep = 61; pedig a legnagyobb gyönyörűség, amit programozó láthat, mert innentől fingja sincs, hogy a nap_kep mi a pörgettyűs kóchenger, és a 61-ről is csak annyit tudni, hogy a 42-nél pont 19-cel több. Hivatalos elnevezése "mágikus szám".
Dimmelhető 12V led izzót használok, mely már 90-es kitöltési tényező, cirka 10,4V körül full fénnyel világít, utána már látható fényerő emelkedés nincs.
A kitöltést csak 0-100 között használjam 1-255 helyett vagy van egyéb mód is a PWM jel és a led összehangolására? Vagy a ledem sz*r (ebay - adatlap ismeretlen)?
Az áttekintő poszt akár lehetne témaindító is .... tök jó!
Ehhez kapcsolódóan lenne egy kérdésem: a programomban egy olyan tömböt hozok létre, melynek elemszáma csak a loop-ban derül ki (változó adja), így előre nem tudom deklarálni (legalább is nekem úgy nem fordult le). A tömb feltöltését csak meghatározott feltételek esetén akarom végrehajtatni (ne fusson le mindig, csak adott eset teljesülésekor egyszer). Sajnos ez így nem megy, én erre nem találtam megoldást. A tömb feltöltésnek és a deklarálásnak azonos ciklusban kell lennie, másként hibát ad. Van erre megoldás?
A progarmrész egy adott időpontban a megadott időtartamban megadott jelszintig led fényerőt szabályoz. Sajnos csak úgy tudtam megoldani, hogy a kezdő és végső időpont között minden ciklusban lefut a tömb feltöltése is (teljesen felesklegesen).
A teljes kód már bőven 2000 sor fölött van, így csak a kérdéses részt szúrtam be. Ebben a formában működik, szépen teszi a dolgát... A kiperezett sorok szerint szeretném futtani, de akkor(ahogy írtam) a tömb elemei nem lesznek kiolvashatóak. Tud valaki segíteni? Prof?
// napkelte funkció (a világitás bekapcsolása előtt X percig) if ((eltelt_percek >= (vil_be-napfel)) && (eltelt_percek < vil_be)) { byte fenyfel[napfel]; byte index = 0; // if (szamolo == true) { // tömb feltöltése csak egyszer fut le for (int i = 0; i < napfel; i++) { // tömb feltöltése a percben meghatározott elemszámmal int n = i*i; // parabolikus legyen a számok felfutása int n_max = napfel*napfel; n = map(n, 0, n_max, 1, 255); fenyfel[i] = n; // szamolo = false; }
index = napfel-(vil_be-eltelt_percek); fenyero = fenyfel[index]; //hol tart a kiolvasás if (fenyero > (fenyertek)) { fenyero = (fenyertek); return; } //nem megy a szabályozott érték fölé analogWrite(napfeny, fenyero); va_napfel.setValue(1); nap_kep = 61; // } }
A program minimum eltelt időt néz. Tehát egyedül az garantált, hogy egy "task" ennél sűrűbben nem fut. Vagyis ennél a beállított időnél ritkábban fut, amikor legközelebb sor kerül rá. Ha egy másik task 10 másodpercig tököl egy ciklusban, vagy simán delay()-t használ, akkor sem veszi el tőle senki a vezérlést.
A millis() egy rendszerszintű változó. Az értéke az MCU (újra)indulása vagy legutóbbi túlcsordulás (amikor eléri a változótípus asta maximális értéket és 0-ról kezdi újra) óta eltelt időt méri milliszekundumokban (a másodperc egy ezred részének megfelelő időközökben). Lényegében egy számláló, ami ha nem is halál pontosan, de egységes időközönként (milliszekundumonként) növeli eggyel az értékét.
Minden projektfejlesztést úgy kezdek, hogy felírom a megrendelő (akár saját magam) fejében kialakult vágyakat a lehető legpontosabban. Aztán elképzelem azt, hogy később erre még milyen hülyeség jöhet rá vagy lehet praktikus, milyen kockázatok vannak (pl. hőmérséklet, tápellátás, kosz, zavarok stb.). Ezt is beleveszem, hogy később modulárisan, ha szükséges, a fejlesztés lezárulta után is rá lehessen aggatni a rendszerre újabbakat. Ha ez megvan, akkor jön az, hogy egyedi gyártás lesz, kis széria vagy sorozatgyártás. Sorozatgyártáshoz nem értek, itt mindig segítséget kérek már a tervezési fázisban is olyanoktól, akiknek ez szakmájuk.
Ha ez megvan, elkezdem a rendszer elvi összerakását: az érzékelőknek milyen igénybevételnek kell megfelelniük, milyen tűréshatáron belül kell mérniük, mennyi a pontosság minden tekintetben stb. Példa: van olyan mérési feladat az egyik projektnél, ahol folyadékhőmérsékletet kell mérni 0,1 mp-es mintavételezési sűrűséggel 0,05 celsius pontossággal 70 és 110 fok közötti tartományban, egyik oldalon légköri nyomáson, a másik oldalon 8-10 bar közötti túlnyomáson. Ez azért nem az alapértelmezett "K-hőelem" vagy a "DHT-11" kategória. Ezen belül kommunikációs protokollok, azok gyengeségei/erősségei/rendszerigénye, későbbi tokozás, kábelezés megoldása, tápellátás átgondolása, nem utolsó sorban pedig van-e működő, tesztelt könyvtár hozzá bárhol (sajnos olyanba már belefutottam, hogy Arduinora van, mbedre nincs) és az vajon ütközik-e másikkal vagy sem. Ezzel összeáll egy rendszer-szintű terv, amihez már lehet alkatrészeket túrni akár itthon a fiókokban, akár kintről (ebay, farnell, rs), akár itthonról (hestore, lomex, kontha). Ez alapján kijön, hogy egyáltalán megvalósítható-e a terv gazdaságosan vagy sem (a fenti hőmérsékletes történet most aktuális, még mindig proto szintű büdzséje már 200 000 forintnál jár, de aktuálisan dolgozom projekten, aminek a nettó alkatrészszükséglete is már százezres nagyságrend). Ha gazdaságos, akkor jöhet a következő.
A lapka kiválasztása nehéz ügy. Az Arduino is elég sokféle, az mbed ennek a többszöröse, minden tekintetben. Külön eszközök vannak IoT-re, beépített modulokkal, van olyan modul, ami mikroamperes nagyságrendű fogyasztást tud, vannak brutál erőművi cuccok, vannak olyanok, amik tényleg "mindent" tudnak, pl. a Disco-k. Alapvetően mindegyikre igaz, hogy fejlesztői platform (az Arduino is az, csak más a megközelítés), a központi lapkán kívül van még egy rakat alkatrész mellette (usb, debugger, töbféle tápellátás, kristályok, csak hogy a legfontosabbakat említsem). Ha a projekt proto vagy nagyon kis szériás, akkor szinte minden esetben olyan kártyát választok, amin tüskesor van, így egy hüvelysorral akár próbapanelre, akár egyedi gyártású nyákra fel lehet rakni, a szoftverfrissítés meg annyi, hogy a kártyát kiveszem a helyéről, rádugom számítógépre, frissítek, aztán vissza a helyére.
A kérdésedre a válasz az, hogy nagyjából bármelyikkel. A kérdés az, hogy a vezérlés mekkora részét akarod az egyedi elemekre leosztani vagy mindent központilag irányítani. Az okos ház kategória (ezt pár napja pont egy fejlesztővel beszélgettem) nem éppen az, amit észszerűen meg lehet oldani házi körümények közöt, már feltéve, hogy nem akarod pernyévé égve látni a házad. Egyetlen példát hozok: pár napja se le, se fel szinten befagyott nálam a rendőny. Egy redőnymozgató mechanikának és annak a vezérlésének ezt a helyzetet kezelnie kell. És nem mindegy, hogy hogyan.
Redőnyök: van-e már motor vagy bármilyen vezérlés hozzá? Ha van, akkor egyszerűbb történet, ha nincs, akkor mechanikailag is jóval bonyolultabb. Öntöző: bemész boltba és veszel egy intelligens rendszert. Egyszerűbben és olcsóbban megúszod. A dolog mechanikai részét (szivatyú, rejtett csövezés, szórófejek, csepegtető stb.) ígyis-úgyis meg kell venned, nagyságrendileg ez meg úgyis jóval több, mint az, amibe az egésznek a "lelke" kerül (ami egyébként úgyszintén egy tök egyszerű mikrokontroller). Hőmérséklet: ha csak az kell, akkor Dallas 18B20 vagy hasonló egyszerűen telepíthető és cserélhető cucc. Akár analóg, akár digitális, csillió megoldás létezik. Páratartalom: csak páratartalom hőmérséklet nélkül szerintem felesleges (nem tudsz harmatpontot számolni, ami pl. öntézésnél egy praktikus információ). Kapásból erre nincs ötletem, kicsi túrnom kellene. Villanykapcsolók: RS486 relé modulok CAT6 kábelre fűzve. Mellé tennék még egy passzív érzékelőt (világos van-e, és ha igen, mennyire), plusz visszajelző ledet. Kérdés, hogy a kapcsolókat kiváltani akarod, vagy az eredeti funkciójukat megtartani (kötés szempontjából nem mindegy). Ilyet még nem csináltam, kapásból nem tudok rá eszközt, de olyan végponti modulokat keresnék, amin 4-6 analóg vagy digitális ki/bemenet van és mindegyik külön címezhető a választott buszon. A korábban említett Canbus hátránya az, hogy azt elsősorban autóipari felhasználásra találták ki, ennek megfelelően kevés hozzá a nem erre alapozott gyári érzékelő, így jobbára magadnak kell építened/kitalálnod. Konnektorok: ugyanez, mint a kapcsolók. Én ide még betennék egy-egy hall szenzort is, hogy lássa, van-e rajta valami, és ha van, az mennyit fogyaszt.
Konkrétum nélkül... Valószínű, hogy az mbed referencia lapkájával, az NXP LCP1768-ra épülő egyszerű modulból indulnék ki, vagy valamelyik hasonló alapkapacitású, nem túl erős processzorú darabból (valamelyik Nucleo például). Ha a központi egységre bíznám a grafikus megjelenítést is, akkor valamelyik Disco vagy az egyik nagyobb Nucleo, ezeken direkt kijelzővezérlő vagy kijelző is van.
Minden feladatot külső, kisebb vezérlőkre bíznék (itt jelentős számban előfordulhatnak akár Attiny szintű egészen egyszerű MCU-k is, amik az adott célra bőven elegendők. Mivel pl. a konnektorok egyedi vezérlése 15-ször, a kapcsolóké 17-szer ismétlődik, a sorozatgyártás határán vagyunk. Itt akár az egyedi nyákot is életképesnek tartom (van 10 dollár 10x10 cm-es két oldalas nyákra ajánlat a neten, ebből bőven kijön a szükséges mennyiség, pláne, ha az alkatrészek egy része nem furatszerelt, hanem smt).
És aztán jön a szofver. Külön a modulok MCU-iba, a központi vezérlőbe, modulonként, lehetőleg saját könyvtárakkal, mert azért az mbed háza táján is van (sajnos) Arduino keretrendszerből copy-paste-módszerrel átvett megoldás, ami ugye -- nyilván -- egyáltalán nem működik.
Azt sem tartanám elvetendő megoldásnak, hogy minden feladatra külön rendszert építesz, aztán ezeket integrálod a végén egyetlen egységbe egy központi vezérlővel. Ha faszányos GUI-t szeretnél, akkor itt pl. az RPI már adja magát, bár teljesen más architektúra, más lehetőségekkel.
Kb. ennyi. Nem sok konkrétum van benne. Ez elsősorban annak a következménye, hogy teljesen más irányvonalon fejlesztettem eddig.
1. Mivel az index fórumban nincs kód formázási funkció, az összes beszúrt kód olvashatatlan. Ezért érdemes lenne mindenkinek külső forrásból linkelni a kódot. Vagy tud erre valaki jobb megoldást?
2. Az időzítési kérdésedhez nem szükséges az egész programot beszúrni, elég a releváns részt.
// Send date Serial.print(rtc.getDateStr()); Serial.print(" -- ");
// Send time Serial.println(rtc.getTimeStr()); // Send current temperature Serial.print("Temperature: "); Serial.print(rtc.getTemp()-3); Serial.println(" C"); myGLCD.InitLCD(); myGLCD.clrScr(); myGLCD.setColor(255,255,0); myGLCD.setFont(ArialNumFontPlus); myGLCD.print (rtc.getTimeStr(FORMAT_SHORT), CENTER, 10); myGLCD.setColor(120,0,255); myGLCD.setFont(Inconsola); myGLCD.print (rtc.getDOWStr(), CENTER, 80); myGLCD.setColor(255,255,0); myGLCD.setFont(SevenSegmentFull); myGLCD.print (rtc.getDateStr(), CENTER, 120); myGLCD.setColor(255,0,0); myGLCD.setFont(SevenSegmentFull); myGLCD.printNumF(rtc.getTemp()-3,2, CENTER, 180); } void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) { // sets time and date data to DS3231 Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set next input to start at the seconds register Wire.write(decToBcd(second)); // set seconds Wire.write(decToBcd(minute)); // set minutes Wire.write(decToBcd(hour)); // set hours Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday) Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31) Wire.write(decToBcd(month)); // set month Wire.write(decToBcd(year)); // set year (0 to 99) Wire.endTransmission(); } void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes of data from DS3231 starting from register 00h *second = bcdToDec(Wire.read() & 0x7f); *minute = bcdToDec(Wire.read()); *hour = bcdToDec(Wire.read() & 0x3f); *dayOfWeek = bcdToDec(Wire.read()); *dayOfMonth = bcdToDec(Wire.read()); *month = bcdToDec(Wire.read()); *year = bcdToDec(Wire.read()); } void sd_write() { SD.begin(53); byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // retrieve data from DS3231 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); String dataString = ""; dataString += String(dayOfMonth, DEC); dataString += ";"; dataString += String(hour, DEC); dataString += ";"; dataString += String(minute, DEC); dataString += ";"; dataString += String(second, DEC); dataString += ";"; dataString += String(rtc.getTemp()-3, DEC); dataString += ";"; dataString.replace('.',','); File dataFile = SD.open("datalog.csv", FILE_WRITE);
// if the file is available, write to it: if (dataFile) { dataFile.println(dataString); dataFile.close(); } // if the file isn't open, pop up an error: else { //Serial.println("error opening datalog.txt"); } } int ledPin = 13; // LED connected to digital pin 13 unsigned long currentTime; unsigned long loopTime; void setup() { pinMode(ledPin, OUTPUT); // sets the digital pin as output currentTime = millis(); loopTime = currentTime; // Setup Serial connection Serial.begin(115200); // Uncomment the next line if you are using an Arduino Leonardo //while (!Serial) {}
// Initialize the rtc object rtc.begin(); // The following lines can be uncommented to set the date and time //rtc.setDOW(WEDNESDAY); // Set Day-of-Week to SUNDAY //rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format) //rtc.setDate(8, 12, 2016); // Set the date to January 1st, 2017 pinMode(53, OUTPUT); SD.begin(53); if (!SD.begin(53)) {
Sploc, mielőtt óriási keveredés lenne a dologból, pár alaptétel.
1. Egy programon belül (Arduino 'sketch', konkrétan az Arduino keretrendszer/IDE szabályai szerint) kizárólag egy loop() ciklus lehet. Ez alap esetben végtelen számú alkalommal ismétlődik. Egy programon belül a miniális és egyben maximális követelmény is az egy darab void setup() és az egy darab void loop() megléte. A fordítást, áttöltést követően a setup() minden indítást (reset vagy táp bekapcsolást követően) egyszer fut le, a loop () néhány speciális esetet kivéve végtelen számú alkalommal. A speciális eseteket hagyjuk egyelőre.
2. Léteznek olyan parancsok, amelyek valamely feladatot egy loop() futási körön belül többször futtatnak le. Jellegüket tekintve vagy magukban számolnak (például for ciklus), vagy vamely állapotot figyelnek (például while ciklus). Amikor a program futása során ezek sorra kerülnek, a szintaktika (az Arduino keretrendszer 'nyelvtana') szerinti módon a cikluson belüli utasítás vagy utasítások a megadott/tervezett számú alkalommal futnak le. Ettől a loop() ciklus futása nem változik, mindössze annyi történik, hogy a program futása az adott feltételek teljesülésének idejére csupán néhány utasításra korlátozódik.
halaloszto példája alapján a setup() az alapanyagok és eszközök előszedését jelenti (csak egyszer kell, az elején), a loop () maga az ételkészítés folyamata, a for ciklus megfelel pl. a "vágj fel 4 hagymát"-nak, egészen konkrétan "addig vagdoss hagymákat, ameddig a felvágott hagymák száma el nem éri a 4-et", a while ciklus pedig nagyjából az "addig dinszteld a hagymákat, amíg azok üvegesek nem lesznek".
3. Ide kívánkozik még egy rész, amit ugyan a legtöbb Arduino példa, különösen az egyszerűbbek nem érintenek, de a változók hatókörének megértéséhez fontos. Ezek a függvények. Az Arduino kód alap esetben két függvényt, a loop()-ot és a setup()-ot tartalmazza. Viszont ezen kívül végtelen számú (legalábbis a rendelkezésre álló memória erejéig) további függvényt tartalmazhat. Ezeket önálló programrészeknek kell tekinteni, amelyek akkor és csak akkor futnak le, amikor egy másik függvényből [setup(), loop() vagy másik önálló föggvény] hívás érkezik rájuk. Erre sajnos a legtöbb általam ismert oktatóanyag nem vagy nem kellő alapossággal tér ki.
4. Változók. Az Arduino keretrendszer alapjául szolgáló C nyelvben ez elég jól definiált dolog, ez nagyjából-egészében az Arduinora is igaz szerencsére, bár néhány dolgot jóval egyszerűbben oldottak meg (mert inkább tanulásra, oktatásra kitalált rendszerről van szó). Egy változónak alapvetően két fontos tulajdonsága van: a típusa (char, bool, int stb.), illetve a hatóköre (lokális, globális stb.). A típust kellő angol ismerettel az Arduino honlap REFERENCE szakaszában kifejtik. A hatókör már egy más kérdés. Alap esetben úgy kell elképzelni, hogy egy változó akkor foglal memóriát, ha él, egyébként nem. Ha él, van benne adat (függetlenül attól, hogy hozzárendeltél-e adatot akkor, amikor életre hívtad vagy sem), ha elpusztul, akkor az adat törlődik (egészen pontosan felszabadul az a memóriacím, amin tárolva van, ha ezt nem írja felül semmi, a memóriacímről elvileg beolvasható a régi adat). A változók életciklusa és hatóköre piszok fontos a jó programstruktúra elkészítéséhez (plusz memória-takarékossághoz stb.). Az alap tétel az, hogy egy lokális változó ott férhető hozzá, ahol létrehoztuk. Egy globális változó a programon belül mindenhol hozzáférhető. A legtöbb példában a változók deklarálása (és jó esetben a kezdeti értékek hozzárendelése) a programok legelején történik. Ezek mind globális változók, a setup() és a loop() függvényeken belül bárhol, illetve minden egyedileg létrehozott függvényen belül hozzáférhetők. A for ciklusban deklarált változó viszont lokális, ez csak ott és csak addig él, amíg a for ciklus fut, utána elpusztul (pontosabban felszabadul a memóriahely és a változó neve is "újrahasznosítható" lesz). Egy változó a hatókörén kívül nem él, nem értelmezhető, nem hozzáférhető, normális körülmények között nem írható át (erre van kivétel, de ebbe most nem megyek bele). Nagyon egyszerű példával:
int globalisValtozo = 0; //változó deklaráció a kód elején, ezek a kódon belül végig, mindenütt élnek és hozzáférhetők.
void setup()
{
int vaneGombnyomas = digitalRead(1); // ez lokális változó, csak a setup() függvényen belül él
}
void loop()
{
int loopValtozo = 42; // ez egy lokális változó, csak a loop()-on belül hozzáférhető
for (int i=0; i<10 ; i++) //az i változó csak a for cikluson belül él, csak ott hozzáférhető
{ } //ez a for ciklus parancsszakasza
int i = 21; // ez meg itt egy vicces helyet, amibe sokan belefutnak, lásd alább.
}
A változók a globálistól lefelé a lokális függvény szintű és a lokális parancs (ciklus) szintű változókig építkeznek hatókör szerint. Ennek megfelelően egy adott elnevezésű globális változóból egy programon belül csak egyetlen egy lehet. Egy függvényen belül egy adott elnevezésű változóból csak egyetlen egy lehet, de ugyanazt a változónevet létrehozhatod és használatod egy másik függvényen belül is (elvileg akkor is, ha mindkét változó egyszerre él), és a két függvényben a két teljesen azonos nevű változó teljesen eltérő értékkel bírhat. Ugyanez igaz a ciklusokra is, annyi differenciával, hogy beágyazott ciklusok ugyan vannak (cikluson belüli ciklus), de a beágyazott ciklus nem érhet véget később, mint az a ciklus, amibe beágyaztad. Plusz mivel a változók, amiket a cikluson belül deklaráltál, a cikluson belül élnek és érvényesek, ezért a ciklusba ágyazott ciklusban ugyanazt a változót még egyszer azonos néven nem hozhatod létre (for (int i....)-n belül nem lehet még egy for (int i...)). Sőt, mint a fenti példa is mutatja, ha egy változónak van egy függvényen belül érvényes változata és egy függvényen belüli cikluson belüli változata, akkor a kód fordítása sem fog már megtörténni (mivel a függvényen belül érvényes változó a függvénybe ágyazott utasításszintű változóként lenne újra létrehozva). Ez szintaktikai hiba.
Aztán van még a változó nevezéktan, a változótípusokkal való hatékony munka és a memóriakezelés hatékonyabbá tétele, a változók és a konstansok közötti differencia és ezek hatékony használata, és akkor még mindig nem hívtunk adatot memóriacímről. :-) Ez jó hosszú külön poszt lehetne.
Innentől csak a távoli jövő...No, ha ezzel így megvagyunk, akkor jön a következő csavar, hogy függvényen belül lokális változót át lehet adni másik függvénynek úgy, hogy a lokális változó tartalmát a meghívott függvényben felhasználjuk, sőt, az ottani lokális változóban meg is változtatjuk, majd ezt visszaadhatjuk egy teljesen másik változóba a hívott függvényből a hívó függvénybe. Sőt, megtehetjük azt is, hogy a függvényt kiszedjük a picsába, csinálunk belőle egy könyvtárat, amibe úgyszintén vannak lokális és (a könyvtáron belüli) globális változók, sőt, olyanok is, amik a könyvtárat használó programból is elérhetőek és megváltoztathatóak.
ezek a programok felülről lefele futnak, mint a kajarecept. ha egymás alatt vannak ciklusok, akkor azoknak semmi köze egymáshoz. először dinszteled a hagymás üvegesedésig, a vége fele meg addig főzöd amíg zsírjára le nem sül. ha két ciklus egymás hasában van, az egy spéci eset. a belső annyiszor fog lefutni, ahányszor a külső kényszeríti. vedd az almákat, és mindet darabold 8ba. a belső ciklusban egy almát vágsz nyolc fele, a külső meg végigmegy az almákon.
Mint már írtam nem rég kezdtem el a programozást, így nem túl nagy a lexikális tudásom belőle. Néhány példaprogramnál láttam, hogy több loop ciklus van egy adott kódban, ezt hogy kell érteni? Egymástól függetlenül futnak a ciklusok különböző sebességel? Át is lehet bennük a változókat olvastatni?
Az mbed platformon milyen vezérlőt használnál, ha nem az Arduino Mega2560-at, mert ahogy néztem itt is elég sokféle alaplap van.
Szóval ezt IoT-re hegyezték ki... Ez szerinted stabilabb mint az arduino, vagy miért választanád ezt?
Viszont találtam egy ilyet: Freescale Freedom-K64F, ez szerinted tudásban elég lehet nekem?
Ehhez milyen kiegészítőket lehet kapcsolni ? Mert azt nem nagyon találtam, vagy csak rosszul kerestem... Annyit találtam, hogy "tower"-be lehet építeni.
Arduinoval én nextionos megjelenítést használok. Elég gyorsan lehet vele dolgozni (mármint a grafikákat beilleszteni, változókat létrehozni, stb). Mbed platformon is van valami hasonló, vagy jobb display, vagy itt is használható a nextion?
Reléket hogyan tudok vele meghajtani (30-40db)? Gondolom nem a legjobb ha direkt a kimenetre kötöm, mert nem tudja kiszolgálni elég árammal a lapka.
sensor_inhouse.setResolution (12); // ezt az utasítás hibának nem veszi de figyelmen kívül hagyja sensor_outhouse.setResolution (12); sensor_inhouse.begin(); sensor_outhouse.begin(); } void loop() {
azért ez nem semmi. több mint 4 éve volt. és a manusznak ugyanaz az accountja az ebayen, és ugyanazon az url-en ott van a listing, ugyanaz az id-je. az ár viszont sokat ment fel, 2012ben 9.22usd volt free shippinggel.
1. Alapvetően protokolltól függ, i2c-vel ne is próbálkozz, azt alapvetően nyákon belüli kommunikációra találták ki. Vannak rendszerek (pl. RS485), ami vígan elmegy több tíz métert is különleges birizgálás nélkül. Arduinóval számos minta van rá. Canbus játszik (bár az eszközök köre szűkös). Elgondolkodtató ez esetben a szobánkénti kontroller és a központi vezérlő master/slave-szerű elrendezésben. Cat6 megfelelő az adatátvitelre és a tápkábelnek is.
2. Kérdés, hogy mennyire akarsz pontos értéket. A One Wire vígan elmegy néhány tucat métert, de a távolsággal arányosan a zavarérzékenység nő. Én nem keverném a rendszereket, egy központi busz, az érzékelők meg a sajátjukon (lásd 1. pont). 3. Én nem feltétlen Arduino alapon csinálnám, de a mega2560, ha nem akarsz csili-vili kijelzést, megbírkózik vele. Én valószínűleg mbed platformon és jó eséllyel Can-Bus-szal vagy RS485-tel csinálnám. 4. Amit a rendszer elbír. Tudok közelségérzékelős rendszerről is, ami megfelelő protokoll alapján tök automatikusan kapcsol mindent a lakásban. 5. A műszaki átvétel után azt csinálsz, amit akarsz, a plusz kábelnek a villanyszerelő nem fog örülni, de azt kérheted, hogy másik csatornába húzza és másik fali elosztódobozba rakja, és akkor nincs gond vele semmilyen szempontból. Az biztos, ha valamit elbaltázol, akkor a tűzvizsgálók erősen kérdezgetni fogják, hogy mi hogy volt, és ha úgy alakul, a biztosító például simán kifarol a helyzetből. Az okosházon nem (csak) az elektronika kerül annyiba, hanem az is, hogy felelősséget vállalnak arra, hogy emiatt nem fog leégni a házad (ha mégis, akkor az ő biztosítójuk az ő felelősségbiztosításuk terhére fizetni fog). Építésügyileg ez úgy néz ki, hogy a házba az és úgy kerülhet bele, ahogy a terveken van. Ez a felelős műszaki vezető felelőssége. Ha a terveken szerepel egy sor második kábelcsatorna, benne egy-két-há CAT-6 UTP kábellel, akkor az lesz. Hogy aztán ezzel mi fog történni, ahhoz nekik már semmi közük. A házat úgy kell átadni, hogy a te tervedből semmi nem látszik sem a terveken, sem a házon (maximum kihagyott lyukak, üres kötődobozok stb.). Aztán amikor az e-építési naplót lezárják, akkor jöhet a mehet, mert onnantól az már a te felelősséged, nem az építésvezetőé.
Jövőre építkeznék (160m2), és elkezdtem nézegetni az okosház rendszereket, viszont elég húzós árakat mondtak... (1.5-2Mft) Amire szükségem lenne (kb): - 14-15 világítási kör vezérlése - 6-7 helység hőmérsékletének mérése, és szabályzása - 10 db redőny vezérlése - kapunyitás - szellőztető berendezés vezérlése
Jelenleg egy 50m2-es kis családi házban lakunk, ahova már összeraktam egy kis eszközt, amivel a a szoba, nappali, külső hőmérsékletét mérem. Páratartalmat mérek, és vezérlem a hővisszanyerős szellőztetőmet. Ugyanezzel az eszközzel mérem a vegyes tüzelésű kazán előremenő és visszatérő víz hőmérsékletét és a puffer hőmérsékletét...
Ez eddig elég stabilan működik, viszont itt kicsik a távolságok (10m max.) a szenzorok és relék, és a mikorkontroller között (Arduino MEGA 2560), és itt működik úgy hogy az arduino jelszintekkel kapcsolok...
Buszos rendszerre gondoltam (hogy építek egyet), ahol a fogyasztókig kihúzatnám (villanyszerelővel) a táp kábeleket egy központi vezérlőszekrényből, és a kapcsolók (lámpa, redőny, stb) és szenzorok (hő- és párataratlom mérő) helyére pedig Cat5e vagy Cat6 -os kábelt húznék, és ezen keresztül adnám az adott jelet vissza a mikrokontrollernek, hogy pl kapcsold fel a lámpát vagy nyisd ki a 2.szoba fűtési szelepét, stb...
Arra gondoltam, hogy megcsinálnám magamnak a vezérlést, de van egy csomó kérdés ami miatt még infót szeretnék gyűjteni, hogy érdemes-e belevágnom... 1., a mikorkontrollertől egy távolabbi helység kapcsolójából nem esik-e túl sokat a jel mire elér a MEGA-ig, ezeket ilyenkór hogyan érdemes csinálni? 24V vagy 48V-al kapcsolni, mert az távolabbra is vihető nagyobb jelszint esés nélkül?
2., DS18B20-al mérem a hőmérsékleteket jelenleg, ha mondjuk a legtávolabbi hőmérő van vagy 30m-re az mennyire fog pontos értéket adni?
3., Egy ilyen "nagyobb" rendszerrel mennyire stabil a MEGA, vagy melyik lapkát érdemes használni?
4., Villanykapcsolónak mit érdemes használni? "Csengő" kapcsoló jó választás lehet? Vagy egy Nextion UNO páros relével. (Erre azért gondoltam, mert a kapcsoló programozható, hogy mit szeretnék kapcsolni vele)
5., Lakhatási engedély kiadásánál mennyire veszik figyelembe, hogy a vezérlést nem villanyszerelő csinálta? Szóval mennyire van erre nekem "jogosultságom" hogy megcsináljam? (Elektroműszerész és OKJ-s programozói vizsgám van)