Fórum témák

» Több friss téma
Fórum » Arduino
A klónok CH340 Soros-USB illesztőjének drivere (Letöltés)
Lapozás: OK   829 / 850
(#) bbatka válasza KoblogPerGyok hozzászólására (») Jan 11, 2024 /
 
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.
(#) asch válasza vargham hozzászólására (») Jan 12, 2024 /
 
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.
(#) asch válasza diamik hozzászólására (») Jan 12, 2024 / 3
 
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.
(#) sargarigo válasza asch hozzászólására (») Jan 12, 2024 /
 
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
(#) asch válasza sargarigo hozzászólására (») Jan 12, 2024 /
 
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
(#) lalca válasza diamik hozzászólására (») Jan 12, 2024 /
 
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:
  1. int k = 0;
  2. int l = 0;
  3. int m = 0;
  4. void setup() {
  5. pinMode(3, OUTPUT);
  6. TCCR2B = TCCR2B & B11111000 | B00000001;
  7. pinMode(A1, INPUT);
  8. pinMode(A0, INPUT);
  9. Serial.begin(9600);
  10. }
  11. void loop() {
  12. m = analogRead(A1);
  13. l = analogRead(A0);
  14. if(m < l) {
  15.   k += 1;
  16.   analogWrite(3,k);
  17.  }
  18. if(m > l) {
  19.   k -= 1;
  20.   analogWrite(3,k);
  21.  }
  22. Serial.println(m);
  23. }
A hozzászólás módosítva: Jan 12, 2024
(#) diamik válasza asch hozzászólására (») 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!
(#) asch válasza diamik hozzászólására (») Jan 12, 2024 / 1
 
> 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:
  1. static uint32_t nextT;
  2. setup(){
  3.   ...
  4.   // A setup utolsó lépése, hogy kiszámoljuk az első periódus kezdetét, ami lehet egyből, mert a setup után egyből a loop-ba lépünk
  5.   nextT=(uint32_t) nanos();
  6. }
  7. loop(){
  8.   // Várakozás, ami jól kezeli a 32 bites körbefordulást. Addig várunk, ameddig elkezdődik a következő periódusidő
  9.   while((nextT-(uint32_t)nanos())<UINT32_MAX/2);
  10.   // A következő ciklus kezdete - mindig ugyanazt a változót növelgetjük, így az időzítési hibák nem adódnak össze
  11.   nextT+=1000;
  12.  
  13.  
  14.   ...
  15.  
  16.   if((nextT-(uint32_t)nanos())>UINT32_MAX/2)
  17.   {
  18.     // Ha túlfutottunk az időn, akkor kiloggoljuk, hogy tudjuk, hogy nem sikerült tartani a ciklusidőt.
  19.     // Éles buildből ezt ki lehet hagyni, akkor már úgysem látja senki a logot
  20.      LOG_ERROR("cycle too long");
  21.     // Ha a hiba után még vissza akarunk állni a ritmusba, akkor jobb reszetelni az időalapot, mert különben késésből indulnánk.
  22.      nextT=micros();
  23.   }
  24. }
(#) lalca válasza lalca hozzászólására (») Jan 13, 2024 / 1
 
Szimulátor szerint stabil!
  1. int k = 0;
  2. int l = 0;
  3. int m = 0;
  4.  
  5. void setup(){
  6.   TCCR1A =
  7.     1 << COM1A1 |
  8.     1 << WGM11;
  9.   TCCR1B =
  10.     1 << WGM13 |
  11.     1 << WGM12 |
  12.     1 << CS10;
  13.   DDRB =
  14.     1 << DDB1;
  15.   ICR1 = 1000;
  16. }
  17.  
  18. void loop() {
  19. m = analogRead(A1);
  20. l = analogRead(A0);
  21. if(m < l) {
  22.   k += 1;
  23.   OCR1A = k;
  24. if((l-m)<10) delay(5);
  25.  }
  26.  
  27. else if(m > l) {
  28.   k -= 1;
  29.   OCR1A = k;
  30. if((m-l)<10) delay(5);
  31.  }
  32.  
  33. else {delay(5);}
  34. }
A hozzászólás módosítva: Jan 13, 2024

Pwm.png
    
(#) sargarigo válasza asch hozzászólására (») 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?
(#) asch válasza sargarigo hozzászólására (») Jan 13, 2024 /
 
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.
(#) kuner hozzászólása Jan 14, 2024 /
 
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?
(#) asch válasza kuner hozzászólására (») Jan 14, 2024 /
 
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
(#) GPeti1977 válasza asch hozzászólására (») 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.
(#) sargarigo válasza asch hozzászólására (») Jan 14, 2024 /
 
Köszönöm, most már megértettem! Érdekes megoldás, tetszik!
(#) kuner válasza asch hozzászólására (») Jan 14, 2024 /
 
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
(#) kuner válasza kuner hozzászólására (») Jan 14, 2024 /
 
(#) Gafly válasza kuner hozzászólására (») Jan 14, 2024 /
 
Hogyne lenne az?
A link szöveges részét rövidíti a fórummotor, azt meg úgyis emberi nyelven szokás írni...
(#) sargarigo válasza kuner hozzászólására (») Jan 14, 2024 / 2
 
Ha csak ez kell, tessék:
  1. #define LED 13           // led világítás
  2. #define LED2 10           // led világítás (opció)
  3.  
  4. #define BUTTON1 2         // nyomógomb #1
  5. #define BUTTON2 3         // nyomógomb #2
  6.  
  7. #define RELAY1 11         // Relé #1 vezérlés
  8. #define RELAY2 12         // Relé #2 vezérlés
  9.  
  10.  int val1=0;               // val1 a nyomógomb #1 beolvasott érték                                              
  11.  int old_val1=0;           // az old_val az előzőleg beolvasott val érték
  12.  
  13.  int val2=0;               // val2 a nyomógomb #2 beolvasott érték                                              
  14.  int old_val2=0;           // az old_val az előzőleg beolvasott val érték
  15.                                              
  16.  int state1=0;             // 0=kiold a relé 1=meghúz a relé #1
  17.  int state2=0;             // 0=kiold a relé 1=meghúz a relé #2
  18.  
  19. void setup(){
  20.  pinMode(LED, OUTPUT);       // Led deklarálása kimenetként
  21.  pinMode(LED2, OUTPUT);       // Led deklarálása kimenetként (opció)
  22.  
  23.  pinMode(BUTTON1, INPUT);     // nyomógomb deklarálása bemenetként
  24.  pinMode(RELAY1, OUTPUT);     // relé kimenet deklarálása
  25.  
  26.  pinMode(BUTTON2, INPUT);     // nyomógomb deklarálása bemenetként
  27.  pinMode(RELAY2, OUTPUT);     // relé kimenet deklarálása
  28. }
  29.  
  30. void loop(){
  31.  val1=digitalRead(BUTTON1);    // beolvassa a nyomógomb állapotát
  32.  val2=digitalRead(BUTTON2);    // beolvassa a nyomógomb állapotát
  33.                                  
  34. // Nyomógomb állapotának és előző állapotának összevetése
  35. if ((val1==HIGH) && (old_val1==LOW))
  36. // Ha a nyomógomb nyomva van : 1-0 akkor state = 1-0=1 ---->
  37. // következő gombnyomásra amikor a state már 1 akkor state = 1-1=0  
  38.  {
  39.    state1 = 1 - state1;
  40.    delay(10);
  41.  }
  42.  
  43.  old_val1=val1;      // Mivel a nyomógomb felengedett ezért nullázza a old_val változót
  44.  
  45. if ((val2==HIGH) && (old_val2==LOW))
  46. // Ha a nyomógomb nyomva van : 1-0 akkor state = 1-0=1 ---->
  47. // következő gombnyomásra amikor a state már 1 akkor state = 1-1=0  
  48.  {
  49.    state2 = 1 - state2;
  50.    delay(10);
  51.  }
  52.  
  53.  old_val2=val2;      // Mivel a nyomógomb felengedett ezért nullázza a old_val változót
  54.  
  55.  if (state1 == 1){
  56.   digitalWrite(LED,HIGH);        // LED bekapcsolása
  57.   digitalWrite(RELAY1,HIGH);      // Relé bekapcsolása
  58.  }else{
  59.   digitalWrite(LED,LOW);         // LED kikapcsolása
  60.   digitalWrite(RELAY1,LOW);       // Relé kikapcsolása
  61.  }
  62.  
  63.  if (state2 == 1){
  64.   digitalWrite(LED2,HIGH);        // LED bekapcsolása
  65.   digitalWrite(RELAY2,HIGH);      // Relé bekapcsolása
  66.  }else{
  67.   digitalWrite(LED2,LOW);         // LED kikapcsolása
  68.   digitalWrite(RELAY2,LOW);       // Relé kikapcsolása
  69.  }
  70.  
  71. }


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!
(#) kuner válasza sargarigo hozzászólására (») Jan 14, 2024 /
 
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...
(#) sargarigo válasza kuner hozzászólására (») Jan 14, 2024 /
 
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
(#) kuner válasza sargarigo hozzászólására (») 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ő?
(#) sargarigo válasza kuner hozzászólására (») Jan 14, 2024 /
 
Persze!
  1. if ((state1 == 1) && (digitalRead(12)==0){
  2.   digitalWrite(LED,HIGH);        // LED bekapcsolása
  3.   digitalWrite(RELAY1,HIGH);      // Relé bekapcsolása
  4.  }else{
  5.   digitalWrite(LED,LOW);         // LED kikapcsolása
  6.   digitalWrite(RELAY1,LOW);       // Relé kikapcsolása

Ugyanígy a második relénél is! Lehetne szebben, de szerintem működik így is!
(#) lalca válasza kuner hozzászólására (») Jan 15, 2024 /
 
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.

  1. #define LED1 10           // led világítás
  2.     #define LED2 11           // led világítás (opció)
  3.      
  4.     #define BUTTON1 2         // nyomógomb #1
  5.     #define BUTTON2 3         // nyomógomb #2
  6.     #define BUTTON3 4
  7.      
  8.     #define RELAY1 8         // Relé #1 vezérlés
  9.     #define RELAY2 9         // Relé #2 vezérlés
  10.      
  11.      int val1=0;               // val1 a nyomógomb #1 beolvasott érték                                              
  12.      int old_val1=0;           // az old_val az előzőleg beolvasott val érték
  13.      
  14.      int val2=0;               // val2 a nyomógomb #2 beolvasott érték                                              
  15.      int old_val2=0;           // az old_val az előzőleg beolvasott val érték
  16.                                                  
  17.      int state1=0;             // 0=kiold a relé 1=meghúz a relé #1
  18.      int state2=0;             // 0=kiold a relé 1=meghúz a relé #2
  19.      
  20.     void setup(){
  21.      pinMode(LED1, OUTPUT);       // Led deklarálása kimenetként
  22.      pinMode(LED2, OUTPUT);       // Led deklarálása kimenetként (opció)
  23.      
  24.      pinMode(BUTTON1, INPUT_PULLUP);     // nyomógomb deklarálása bemenetként
  25.      pinMode(RELAY1, OUTPUT);     // relé kimenet deklarálása
  26.      
  27.      pinMode(BUTTON2, INPUT_PULLUP);     // nyomógomb deklarálása bemenetként
  28.      pinMode(RELAY2, OUTPUT);     // relé kimenet deklarálása
  29.  
  30.      pinMode(BUTTON3, INPUT_PULLUP);
  31.     }
  32.      
  33.     void loop(){
  34.      val1=digitalRead(BUTTON1);    // beolvassa a nyomógomb állapotát
  35.      val2=digitalRead(BUTTON2);    // beolvassa a nyomógomb állapotát
  36.                                      
  37.     // Nyomógomb állapotának és előző állapotának összevetése
  38.     if ((val1==LOW) && (old_val1==HIGH))
  39.     // Ha a nyomógomb nyomva van : 1-0 akkor state = 1-0=1 ---->
  40.     // következő gombnyomásra amikor a state már 1 akkor state = 1-1=0  
  41.      {
  42.        state1 = 1 - state1;
  43.        delay(10);
  44.      }
  45.        old_val1=val1;      // Mivel a nyomógomb felengedett ezért nullázza a old_val változót       
  46.      
  47.      if (state1 == 1){
  48.       digitalWrite(LED1,HIGH);        // LED bekapcsolása
  49.       digitalWrite(RELAY1,HIGH);      // Relé bekapcsolása
  50.      }else{
  51.       digitalWrite(LED1,LOW);         // LED kikapcsolása
  52.       digitalWrite(RELAY1,LOW);       // Relé kikapcsolása
  53.       }
  54.      
  55.     if ((val2==LOW) && (old_val2==HIGH))
  56.     // Ha a nyomógomb nyomva van : 1-0 akkor state = 1-0=1 ---->
  57.     // következő gombnyomásra amikor a state már 1 akkor state = 1-1=0  
  58.      {
  59.        state2 = 1 - state2;
  60.        delay(10);
  61.          }
  62.        old_val2=val2;      // Mivel a nyomógomb felengedett ezért nullázza a old_val változót       
  63.          
  64.      if (state2 == 1){
  65.       digitalWrite(LED2,HIGH);        // LED bekapcsolása
  66.       digitalWrite(RELAY2,HIGH);      // Relé bekapcsolása
  67.      }else{
  68.       digitalWrite(LED2,LOW);         // LED kikapcsolása
  69.       digitalWrite(RELAY2,LOW);       // Relé kikapcsolása
  70.       }          
  71.      
  72.     while (digitalRead(BUTTON3) == 0)
  73.         {
  74.          digitalWrite(LED1,LOW);
  75.       digitalWrite(RELAY1,LOW);
  76.       digitalWrite(LED2,LOW);
  77.       digitalWrite(RELAY2,LOW);
  78.     }    
  79.      
  80.     }


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.

relay.png
    
(#) Régi motoros válasza lalca hozzászólására (») Jan 15, 2024 / 1
 
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.
(#) lalca válasza Régi motoros hozzászólására (») Jan 15, 2024 /
 
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
(#) kuner válasza lalca hozzászólására (») 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
(#) kuner hozzászólása Jan 15, 2024 /
 
Köszönöm mindenkinek az eddigi segítséget, az elindulást az arduino világában!
(#) kuner hozzászólása Jan 15, 2024 /
 
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?
(#) Régi motoros válasza kuner hozzászólására (») Jan 15, 2024 / 1
 
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
Következő: »»   829 / 850
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem