Portál AbcLinuxu, 30. dubna 2025 23:50
Relativně nedávno jsem narazil na to, že je nějaká koncepce výuky programování na středních školách založená na Arduinu. Do té doby jsem tuto hračku neznal, ale velice mne to zaujalo. Kdysi před nějakými 35 lety jsem bastlil podle Amatérského Rádia, co se dalo, a pokud by tehdy existovalo něco takového jako dnes, byl bych nadšen, i když by tomu asi padnul za oběť můj volný čas. Takže možná dobře, že nic takového tehdy nebylo
Nyní jsem si z Číny naobjednával spoustu harampádí a ve volných chvílích si s tím hraji a zkouším. Některé věci šlapou hned pěkně, s jinými to samo od sebe nejde, takže zkouším a hledám informace. A sem si chci vkládat poznámky, které se mi mohou hodit, až budu stejnou součástku potřebovat znovu použít. Výsledky některých návodů na internetu dávají bídné nebo žádné výsledky, někde vynechají pro výsledek zcela zásadní informace... Snad se budou hodit i jinému svátečnímu bastlíři. V žádném případě nehodlám vytvářet komplexní ucelené návody.
Začnu tím, čím jsem v reálu aktuálně skončil, a to jsou IR diody. Zatím jsem si hrál s několika součástkami:
Tento senzor se hodí například k dekódování signálu z dálkových ovladačů. Výstupní pin zapojíte do kteréhokoliv digitálního pinu na Arduinu. A potom stačí použít některý z příkladů, které s sebou nese knihovna IRremote
.
IRrecvDemo
vypíše pouze kódy bez bližší identifikace, ty se mohou hodit, pokud hodláte daný ovladač využít pro ovládání nějakého svého výrobku. Podrobnější informace vám dá příklad IRrecvDumpV2
, jehož výstup vypadá například takto:
Encoding : NEC Code : 20D3728D (32 bits) Timing[67]: +8750, -4450 + 550, - 550 + 550, - 550 + 550, -1650 + 550, - 600 + 500, - 600 + 500, - 600 + 500, - 600 + 500, - 600 + 500, -1700 + 500, -1700 + 550, - 550 + 500, -1700 + 550, - 550 + 500, - 600 + 550, -1650 + 550, -1650 + 550, - 600 + 500, -1700 + 500, -1700 + 500, -1700 + 500, - 600 + 500, - 600 + 550, -1650 + 550, - 550 + 550, -1650 + 550, - 550 + 550, - 550 + 550, - 600 + 500, -1700 + 500, -1650 + 550, - 600 + 500, -1700 + 500 unsigned int rawData[67] = {8750,4450, 550,550, 550,550, 550,1650, 550,600, 500,600, 500,600, 500,600, 500,600, 500,1700, 500,1700, 550,550, 500,1700, 550,550, 500,600, 550,1650, 550,1650, 550,600, 500,1700, 500,1700, 500,1700, 500,600, 500,600, 550,1650, 550,550, 550,1650, 550,550, 550,550, 550,600, 500,1700, 500,1650, 550,600, 500,1700, 500}; // NEC 20D3728D unsigned int data = 0x20D3728D;
Nakonec jsem používal výsledky právě z něj, když jsem chtěl vytvořit náhradu ovladače s neznámým kódováním, protože mi dával z nějakého důvodu konzistentnější výsledky, než následující jednodušší kód:
#define sprint Serial.print #define sprintln Serial.println #include <IRremote.h> #define IR_RCVR_PIN 8 IRrecv ir_receiver(IR_RCVR_PIN); decode_results results; void setup() { Serial.begin(9600); ir_receiver.enableIRIn(); // Start the receiver } void loop() { if (ir_receiver.decode(&results)) { dump(&results); ir_receiver.resume(); // Receive the next value } } int c = 1; void dump(decode_results *results) { int count = results->rawlen; sprintln(c); c++; sprintln(""); sprintln("For Arduino sketch: "); sprint("unsigned int raw["); sprint(count, DEC); sprint("] = {"); for (int i = 1; i < count; i++) { sprint("0x"); sprint((unsigned int)results->rawbuf[i], HEX); sprint(","); } sprint("};"); sprintln(""); sprint("irsend.sendRaw(raw,"); sprint(count, DEC); sprint(",38);"); sprintln(""); sprintln(""); }
S velmi špatnou konzistencí výsledků je zde celkově velký problém, nevím, jestli je to dáno tou technologií, nebo třeba ne úplně nejlepším kusem konkrétního senzoru. Každopádně pokud budeme chtít zkusit dekódovaný signál vysílat a zjišťovat, zda jsme zaznamenali špatně či správně zachycený kód, budeme potřebovat vysílací diodu.
Když jsem začal tím ovladačem, tak budu ovladačem i pokračovat. Pokud budete chtít použít vysílací diodu pro vlastní dálkový ovladač, zjistíte, že má velmi malý dosah. Buď si tedy koupíte modul se zesilovačem, nebo zesílíte signál tranzistorem. Já jsem použil socialistický KC238C ze svých starých zásob a fungoval také dobře. Pokud znáte kódování signálu, je vysílání velmi snadné. Vezmete knihovnu IRLibAll
(nebo lépe - vyberete jen potřebné knihovny) z balíku IRLib2
a odešlete krátký kód v daném kódování (mrkněte na příklad send
z balíku IRLib2
).
Pokud kódování neznáte, musíte odesílat raw signál, který jste získali v předešlém bodu, a zkoušet, který z nich je správně zaznamenaný. Kód složitý není. V šestnáctkové soustavě takto:
#include <IRremote.h> IRsend irsend; unsigned int raw[68] = {0xB1,0x58,0xB,0xB,0xA,0xC,0xB,0x21,0xB,0xC,0xA,0xB,0xB,0xC,0xA,0xC,0xA,0xB,0xB,0x22,0xA,0x22,0xA,0xC,0xA,0x22,0xA,0xC,0xB,0xB,0xB,0x21,0xB,0x21,0xB,0xC,0xA,0x22,0xA,0x21,0xB,0x22,0xA,0xC,0xA,0xC,0xA,0x22,0xB,0xB,0xA,0x22,0xB,0xB,0xA,0xC,0xB,0xB,0xB,0x22,0xA,0x22,0xA,0xC,0xA,0x22,0xA,}; void setup() {} void loop() {irsend.sendRaw(raw,68,38);} //samozřejmě s nějakou podmínkou, ať se nevysílá pořád dokola...
Pro odeslání kódu v desítkové soustavě si stačí otevřít IRSendRawDemo
z příkladů knihovny IRremote
.
Ještě důležitá poznámka na závěr. Výstupní pin pro vysílací diodu není v případě knihovny IRremote
uživatelsky konfigurovatelný. U Arduina Uno či Nano je to pin 3, u Mega 2560 je to myslím pin 9, v případě jiných desek je potřeba si informaci najít.
A ještě jedna poznámka na základě připomínky v diskuzi: ten poslední parametr u sendRaw (i potom níže u send z knihovny IRLib2) je nosná frekvence, na které je přenášený kód modulován.
Tuto diodu využijeme v kombinaci s vysílací diodou. Typicky můžeme například hlídat přerušení paprsku nebo měřit odražené světlo formou senzoru přiblížení. Nejlépe se mi osvědčilo následující zapojení, při němž v případě, že na fotodiodu nedopadá světlo, pohybují se hodnoty na analogovém vstupu kolem 900, při osvětlení klesají.
int fotodioda=2; //napájení pro fotodiodu int prijimaciPin=0; //měření na analogovém pinu 0 void setup() { pinMode(fotodioda,OUTPUT); digitalWrite(fotodioda,HIGH); //pošli 5 voltů do fotodiody Serial.begin(9600); // použij serial monitor } void loop() { int hodnotaPrijmu=analogRead(prijimaciPin); // příjem z fotodiody Serial.println(hodnotaPrijmu); // zobraz v serial monitoru }
Na stejném principu funguje i následující modul.
Jeho použití je velmi snadné. Nepotřebujete žádné další součástky, pouze připojíte napájení, GND, a datový pin šoupnete do kteréhokoliv digitálního pinu. Z modulu totiž nelezou průběžné hodnoty, ale při přiblížení předmětu se překlápí true/false, takže je možno ho využít i na interrupt. Trimrem se nastaví citlivost.
Ale pozor, vzhledem k tomu, jakým způsobem funguje (nepoužívá žádné kódování), je strašně zákeřný ve dvou věcech. Jednak nesmí být více modulů příliš blízko u sebe, protože se mohou navzájem ovlivňovat, a jednak ve chvíli, kdy na to zasvítí sluníčko, jste úplně v háji, protože nějaká úroveň vyzařování z IR diody je mu v tu chvíli úplně ukradená. To jsem si uvědomil ve chvíli, kdy jsem dětem udělal ze srandy náhradní ovladač k PopcornHour, na němž byly 2 tyto moduly – jeden (na pinu 6) na ztišení zvuku, druhý (na pinu 5) na zesílení zvuku, a pokud se přiblíží k oběma zaráz, pauzne a poté opět spustí přehrávání. Děti byly nadšeny, ale sluníčko vysvitlo a byl konec…
#include <IRLibAll.h> IRsend mySender; bool paused=false; void setup() { Serial.begin(9600); pinMode(5,INPUT); pinMode(6,INPUT); } void loop() { if (!digitalRead(5) || !digitalRead(6)){ delay(150); if (!digitalRead(5) && digitalRead(6)) {Serial.println("Vol up");mySender.send(NEC,0x20D3728D, 38);delay(100);} // vol up else if (!digitalRead(6) && digitalRead(5)) {Serial.println("Vol down");mySender.send(NEC,0x20D34AB5, 38);delay(100);} //vol down else if (!digitalRead(6) && !digitalRead(5)) { if (!paused) { Serial.println("Pause");mySender.send(NEC,0x20D32AD5, 38);paused=true;delay(1200);} // pause else {Serial.println("Play");mySender.send(NEC,0x20D30AF5, 38);paused=false;delay(1200);} // play } } }
Na fotce je vidět spousta zbytečných káblíků, protože jsem vytáhnul 2 další moduly, které tam původně byly, jenže se ty potvory všechny navzájem ovlivňovaly…
To je zatím asi tak vše. Pokud byste tedy potřebovali kontrolovat IR paprsek tak, aby vám výsledek neovlivňovalo okolní světlo, budete muset použít IR senzor (ten 3vývodový) a nějaké kódování. Jak budu mít čas, tak chci vyzkoušet návod na této stránce. Manipuluje tam v kódu přímo s registry procesoru, takže je zcela mimo pásmo mých znalostí, ale vypadá, že je to funkční.
EDIT: Našel jsem k tomu vysvětlující článek.
Tiskni
Sdílej:
Znamená to, že pokud je skutečná teplota 20 stupňů, může senzor naměřit mezi 19,5 a 20,5 stupně, takže rozdíl mezi nimi dvěma součástkami i při splnění tolerance může být 1 stupeň.Pokud si dobře vzpomínám, tak je tam ještě něco, že ta tolerance platí pro nějaké procento - třeba 99.9% nebo tak - ze všech kusů, tj. pokud trefíte "správný" kus, tak ta odchylka může být i vyšší.
Bylo by občas dobré aspoň jedním očkem nahlédnout do specifikací dané součástky. Pro 100 st. chyba narůstá na +-1 st. u DS18B20A jak to vysvětluje, že při 40 stupních je rozptyl přes 5 stupňů?
A jinak nevím, jestli správně rozumíte pojmu tolerance +-0,5 stupně.Rozumím tomu velmi přesně. Znamená to, že pokud by skutečná teplota byla přesně ve středu mezi naměřenými krajními hodnotami, tak 80 % mnou zakoupených originálních senzorů tuto toleranci nesplňuje.
A myslím, že ve vaší metodice máte někde chybu ( nestejnoměrné rozložení teploty, osvícení sensoru, různá výška v mrazáku atd ).Nějak si nedokážu představit, jak by se mi povedlo docílit toho, že když mám třeba 3 senzory napíchnuté v desce 2 centimetry od sebe, uzavřené v krabici bez proudění vzduchu a ničeho se nedotýkají, tak v okolí jednoho je o 5 stupňů jiná teplota než v okolí druhého.
Jinak pro nejpřesnější výskledky, se napájení DS18B20 zapíná jen po dobu měření, jinak se senzor zahřívá vlastním klidovým proudem. Taky po přívodních vodičích se dokáže k čidlu dostat nějaké teplo.Zajímavé, že ani po 16 hodinách měření se rozdíly neměnily, když by podle této teorie měla narůstat chyba.
Omyl. Podle této teorie, pokud obvod ohříváte napájením nebo pokud se ohřívá od přívodních vodičů (chladí přívodními vodiči), se jeho teplota změní, ale nakonec se dospěje k nějakémnu rovnovážnému stavu, kdy se teplota - přestože se liší od teploty okolního prostředí - dál měnit nebude.Jinak pro nejpřesnější výskledky, se napájení DS18B20 zapíná jen po dobu měření, jinak se senzor zahřívá vlastním klidovým proudem. Taky po přívodních vodičích se dokáže k čidlu dostat nějaké teplo.Zajímavé, že ani po 16 hodinách měření se rozdíly neměnily, když by podle této teorie měla narůstat chyba.
Pěkně dát MCU do nepájivého kontaktního pole a naprogramovat to celý od a do z, ať se učej pořádně, dětičky...MCU? Děláš si srandu? A ještě k tomu máš nejspíš na mysli nějakou komerčně vyrobenou sračku od Atmelu nebo Microchipu. To je naprosto nevhodné. Jakýpak MCU. Pěkně logické obvody - pár švábů z řady 74, jinak budeš jen lepit hotové řešení a vůbec se nenaučíš, jak věci fungují. No když nad tim tak přemejšlim, možná i ty 74ky jsou moc velkej luxus. Nejlépe by se asi mělo začít pěkně od začátku - těžbou křemenného písku. Cokoliv jiného bych považoval za komerční sračku a hrubou urážku intelektu všech zúčastněných obecně a p. Tomáška zvláště.
No když nad tim tak přemejšlim, možná i ty 74ky jsou moc velkej luxus. Nejlépe by se asi mělo začít pěkně od začátku - těžbou křemenného písku. Cokoliv jiného bych považoval za komerční sračku a hrubou urážku intelektu všech zúčastněných obecně a p. Tomáška zvláště.Počkat, jaký křemík? Když chceš jít od začátku, tak musíš jít od koleček přes relátka, načež teprve můžeš přejít na core memory (ehm) a elektronky, které si samozřejmě doma sám vyrobíš. Nějaký křemík, to se pozná, že ta mladá generace už není co bývala a může za to putin a uprchlíci.
komerční sračkaWUT. Já teda nevím v jaké realitě žiješ ty, ale v té mé je ten hardware licencovaný pod CC BY-SA, software pod LGPL a existuje spousta forků a klonů. Nedokážu si představit definici komerční sračky, která by toto splňovala.
a naprogramovat to celý od a do zNevím jestli chceš na ně hned od začátku vytáhnout programování typu komunikaci po I2C zápisem do registrů a nastavováním interrupt handlerů.
Komunikace po I2C pro ovládání IR čidla / IR vysílače? Ses zbláznil? Jinak, je to tak pochopitelně nejlepší, protože jen tak budou mít představu, jak ta věc funguje zevnitř. Jenže začal bych s blikáním a tlačítkama, pak třeba časovače, atd. a I2C by přišlo na přetřes, až by uměly základy...a naprogramovat to celý od a do zNevím jestli chceš na ně hned od začátku vytáhnout programování typu komunikaci po I2C zápisem do registrů a nastavováním interrupt handlerů.
až by uměly základy...A v tomto pořadí je to potřeba dělat z jakého důvodu? Abys co nejvíce lidí odradil už na začátku?
printf("Hello World\n");
. V Pythonu za tři, protože k tomu všemu ještě musíš vysvětlit jak funguje interpret.
Podle mě nějaké zatajování prostě dělat musíš, protože jinak bude kurz základů programování (na běžných počítačích, ne MCU)...Což s tím souhlasím, ale i tak je otázka, jestli nelze zvolit takový výukový prostředek, který toho zbytečného balastu, který v danou chvíli odvádí pozornost, má méně nebo žádný. Což by pro základy programování byl i ten Python*. A když se vrátím k té výuce práce s MCU, tak ekvivalent hello world - rozsvícení světýlka - by se měl v jedné laboratorní hodině (počítám 90 minut) zvládnout i s výkladem. Zejména za předpokladu, že studenti už něco ví o hradlech a logických obvodech, což by - aspoň při rozumně sestaveném studijním plánu - vědět měli. Následuje rozblikání toho světla, vysvětlení, proč akorát slabě svítí, výklad o hodinových signálech atd. - já vim, je to dost konzervativní a tím pádem špatné, ale pokud je cílem studenta naučit něco o práci s MCU a ne lepit dohromady Arduino destičky, tak to má větší šanci na úspěch. * nicméně stále platí, že jakýkoliv programovací jazyk, který dává význam bílým znakům, je sračka
Následuje rozblikání toho světla, vysvětlení, proč akorát slabě svítí, výklad o hodinových signálech atd. - já vim, je to dost konzervativní a tím pádem špatné, ale pokud je cílem studenta naučit něco o práci s MCU a ne lepit dohromady Arduino destičky, tak to má větší šanci na úspěch.A jak definuješ úspěch? A čím to máš podložené? Tyhle věci ohledně učení někoho většinou fungují dost jinak, než člověk čeká. Definuješ úspěch v počtech? V nadšení a chuti pokračovat? V počtu hardcore programátorů co se tím pak budou živit? Ve schopnosti lidí si pak dělat vlastní věci?
* nicméně stále platí, že jakýkoliv programovací jazyk, který dává význam bílým znakům, je sračkaTo je stejně dementní tvrzení jako že každý jazyk co používá chlupaté závorky je sračka. Pokud je tohle fakt to co ti vadí, tak se sám odsuzuješ od irelevance a ztrácíš nárok aby tvůj názor byl vyslyšen.
A když se vrátím k té výuce práce s MCU, tak ekvivalent hello world - rozsvícení světýlka - by se měl v jedné laboratorní hodině (počítám 90 minut) zvládnout i s výkladem. Zejména za předpokladu, že studenti už něco ví o hradlech a logických obvodech, což by - aspoň při rozumně sestaveném studijním plánu - vědět měli.Zeptám se znova: Proč by to tak mělo být? Jsi schopen uvést nějaký důvod jiný než "Mám pocit, že by to tak mělo být"? Odkud se bere to přesvědčení, že ten přístup "od teoretických základů" funguje a je správný? Já na sobě vidím, že spíše nefunguje, že naopak jsem skoro vždycky začal někde uprostřed a teprve časem jsem řešil, jak věci fungují uvnitř. A že motivaci zjišťovat, jak věci fungují uvnitř, jsem měl právě ve chvíli, kdy jsem něco "dělal špatně" a "od střechy" a nechápal, jak věci fungují, ale přitom jsem to vědět chtěl, protože jsem dělal něco 'reálného', ne nějakou teorii logických obvodů. Z té jako takové neleze nic, co by se dalo nějakým způsobem osahat. Příklad: Když zavzpomínám, logickým obvodům jsem poprvé aspoň trochu porozumněl na stavebnici Voltík během sestavování nějakého hračka-obvodu, tj. přesně tím způsobem, který tady kriziuješ, bylo to "jen hraní", bez řádné teoretické přípravy, a navíc jsem obvykle - ó hrůzo! - pospojoval dráty "slepě" podle návodu a teprve potom řešil, jak ta věc vlastně funguje. Čiliže naprosto nepřijatelný postup. Pokusim se připomenout, že existují takové věci jako motivace, pozornost, radost z činosti atd.
* nicméně stále platí, že jakýkoliv programovací jazyk, který dává význam bílým znakům, je sračkaAha, hmm, tak jestli pro někoho je nějakej whitespace takhle emocionálně významný prvek, pak se obávám, že tady asi nemůžeme očekávat jakoukoli smysluplnou diskusi.
(Existují např. pokusy, které dokazují, že při počítání ve vyšším věku jsou vždy zapojena i motorická centra, protože pokusné osoby se učily počítat na prstech - a je např. možné změřit rozdíl mezi Číňany a zbytkem světa, protože číňané počítají do deseti na jedné ruce, kdežto zbytek světa jen do pěti. Vtip je v tom, že tento rozdíl je možné změřit i když člověk už dávno počítá jen "v hlavě", prostě proto, že veškeré vyšší struktury jsou závislé na těch nižších, a ty nižší pořád využívají motorická centra v mozku...)Moment, přijde mi, že tohle předchozí argumentaci popírá. Je z toho vidět, že člověk přirozeně postupuje od toho konkrétního / hmatatelného / snadného (počítání na prstech, blikající dioda, teploměr) k tomu obecnému / abstraktnímu (aritmetika, matematika, teorie logických obvodů, programování MCU). Zatímco ty a trekker prosazujete opačný postup. What gives?
ne, když chcete dělat cokoliv víc, než si jenom hrátJo, protože hraní si je pro učení vyloženě škodlivé, že ano... (Jak někdo může tohle napsat a nevidět tu ironii?)
Umět „lepit“ dohromady věci je zcela legitimní, užitečná a okamžitě uplatnitelná schopnost.Než přijde konkurence, která pár milionů kusů toho samého produktu vyrobí s menším a levnějším MCU a ubije vás cenou. Nebo než přijde zaměstnavatel či ještě lépe zákazník, který požaduje použití jiných prvků, než té stavebnice, se kterou umíte.
printf
výše netrefil: co je to za overhead použít pro výstup neformátovaného řetězce funkci, která podporuje formátování, a proto ten řetězec úplně zbytečně musí projít na přítomnost %
?! A co vás to napadlo lepit k programu libc?! Správný helloworld vypadá tak, že si připravíte řetězec (pokud na to potřebujete dynamickou paměť, tak jedině ručním voláním brk
, přece nebudeme používat nějakou megabajtovou knihovnu s alokátorem) a zavoláte správný syscall.
LOL koukám že jsem svůj komentář oSprávně. Příkldádám příklad takového prográmku. Možno kompilovat sprintf
výše netrefil: co je to za overhead použít pro výstup neformátovaného řetězce funkci, která podporuje formátování, a proto ten řetězec úplně zbytečně musí projít na přítomnost%
?! A co vás to napadlo lepit k programu libc?! Správný helloworld vypadá tak, že si připravíte řetězec (pokud na to potřebujete dynamickou paměť, tak jedině ručním volánímbrk
, přece nebudeme používat nějakou megabajtovou knihovnu s alokátorem) a zavoláte správný syscall.
-nostdlib
, ale funguje pouze na Linux/x86-64 a Linux/Arm.
takže si nejsem jistý, jestli je to skutečné řešení při požadavku vyššího výkonu v aplikaci, která vyžaduje trvalý svit diody (například ta závora).Přečtěte si znovu #19 - schválně, jestli přijdete na potenciální problém u závory, která používá trvalý svit diody.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.