← zpět na zápisky z Arduino projektů
Zkoušení matematiky pomocí infra
Program, který zkouší děti ze sčítání a odčítání v předem zvoleném rozsahu. Příklady se generují náhodně, program dokonce počítá body. Při dobrém výsledku rozsvítí zelenou LED, při chybě červenou (a odečte bod). Je možné mít i záporné body. Výstup přes LCD, vstupem je infračervený dálkový ovladač.
Tento projekt vám nebude fungovat ihned po zapojení a nahrátí programu. Je potřeba si jej upravit na svůj vlastní dálkový infra ovladač. My jsme vzali ten, který si nejlépe rozuměl s naším přijímačem, sepsali jsme si kódy, kterými jsme chtěli hru ovládat. Budete muset postupovat stejně, nepředpokládám, že byste doma našli náš dálkový ovladač od 20 let staré mikrověže Aiwa :-) Program pro zjištění kódů ovladače přikládám.
Co je potřeba umět
Tento projekt je z velké části postaven na pokusech s LCD a infra, tedy je dobré mít nějaké zkušenosti s displejem i s příjmem infra signálu. Z pohledu programování jde taktéž trochu o pokročilejší úlohu, ale dospělý může obtížná místa pomoci dítěti překonat.
Foto
Hardware
- LCD, my jsme použili Qapass 1602A, 16 znaků × 2 řádky (Aliexpress, specifikace)
- infračervený sensor, my jsme použili AX-1838HS (Aliexpress, specifikace)
- 10 kΩ potenciometr
- 3× 330 Ω rezistor
- červená a zelená LED
- jako vysílač signálu jsme využili dálkový ovladač k mikrověži Aiwa, ale lze využít prakticky cokoliv
Schéma zapojení pro detekci kódů ovladače
Program pro detekci kódů ovladače
Program slouží k detekci jednotlivých kódů. Je založen na demo programu IRrecvDump.ino, který vypisuje hodnoty, které detekuje na infrasenzoru. Tímto způsobem je možné zjistit, jaké kódy vysílá váš ovladač, zapsat si je a dále je využít pro ovládání vašich projektů. V případě dálkových ovladačů k zařízením jako je televize nebo rádio je dobré vybírat tlačítka, která je nespustí, aby pak šlo ovládat Arduino v jejich přítomnosti a nezapínat u toho televizi.
/*
* IRremote: IRrecvDump - dump details of IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and
* other people at the original blog post)
* LG added by Darryl Smith (based on the JVC protocol)
*/
#include <IRremote.h>
// pin, na kterém je připojen infra sensor
int RECV_PIN = 13;
// nastartovani IR knihovny
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup() {
Serial.begin(9600); // konzole, kam se pisou vysledky
irrecv.enableIRIn(); // nastartovani IR prijimace
}
void dump(decode_results *results) {
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
int count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.print("Unknown encoding: ");
} else if (results->decode_type == NEC) {
Serial.print("Decoded NEC: ");
} else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: ");
} else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: ");
} else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: ");
} else if (results->decode_type == PANASONIC) {
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->address, HEX);
Serial.print(" Value: ");
} else if (results->decode_type == LG) {
Serial.print("Decoded LG: ");
} else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
} else if (results->decode_type == AIWA_RC_T501) {
Serial.print("Decoded AIWA RC T501: ");
} else if (results->decode_type == WHYNTER) {
Serial.print("Decoded Whynter: ");
}
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 1; i < count; i++) {
if (i & 1) {
Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
} else {
Serial.write('-');
Serial.print((unsigned long)results->rawbuf[i] * USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println();
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
// vypis, co jsi prijal, co jsi rozpoznal
dump(&results);
// tady jsme si zapisovali nase kody z dalkoveho ovladace k mikrovezi Aiwa
switch (results.value) {
case 0x76044FD4:
Serial.println("NULA");
break;
case 0x76044FE0:
Serial.println("JEDNICKA");
break;
case 0x76044FD0:
Serial.println("DVOJKA");
break;
case 0x76044FF0:
Serial.println("TROJKA");
break;
case 0x76044FC8:
Serial.println("CTYRKA");
break;
case 0x76044FE8:
Serial.println("PETKA");
break;
case 0x76044FD8:
Serial.println("SESTKA");
break;
case 0x76044FF8:
Serial.println("SEDMICKA");
break;
case 0x76044FC4:
Serial.println("OSMICKA");
break;
case 0x76044FE4:
Serial.println("DEVITKA");
break;
case 0x76044FC7:
Serial.println("DESITKA");
break;
case 0x76044FDE:
case 0x76044FF4:
Serial.println("ENTER");
break;
case 0x76044FFE:
Serial.println("DELETE");
break;
}
irrecv.resume(); // prijmi dalsi hodnotu
}
}
Schéma zapojení infra matematiky
Program infra matematiky
#include <LiquidCrystal.h>
#include <IRremote.h>
// inicializace LCD
// 1. parametr = pin Arduina, na ktery je pripojen RS pin LCD
// 2. parametr = pin Arduina, na ktery je pripojen enable pin LCD
// 3. - 6. parametr = piny Arduina, na ktere jsou pripojeny datove piny d4 - d7 z LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// pin, na kterem prijimame infra signal
const int RECV_PIN = 13;
// pin pro cervenou LED
const int LED_CHYBA = 9;
// pin pro zelenou LED
const int LED_OK = 10;
// pocitadlo bodu
int body = 0;
// inicializace infracervene knihovny
IRrecv irrecv(RECV_PIN);
decode_results results;
// do kolika vymysli priklady
int max = 0;
void setup() {
// testovaci konzole
// Serial.begin(9600);
randomSeed(analogRead(0));
irrecv.enableIRIn(); // nastartuj IR prijimac
// nastartovani LCD displeje, pocet radek, pocet sloupcu
lcd.begin(16, 2);
// zeptame se, do kolika budeme generovat priklady
lcd.print("Do kolika?");
max = ctiDalkac(0, 1);
lcd.clear();
// pokud je to vice nez, tak to zarizneme
if (max > 100) {
lcd.print("To je moc,");
lcd.setCursor(0, 1);
lcd.print("jedeme do 100");
max = 100;
delay(3000);
lcd.clear();
}
//text pro pocitani
lcd.print("Vypocitej");
}
// precte hodnotu z dalkoveho ovladace Aiwa
// x = pozice x na displeji
// y = pozice y na displeji
// vraci cislo, ktere nacetl, ocekava na konci enter, podporuje backspace pro mazani znaku
int ctiDalkac(int x, int y) {
bool enter = false;
int vysledek = 0;
int cisloDalkac = 0;
int cislic = 0;
lcd.setCursor(x, y);
do {
bool backspace = false;
if (irrecv.decode(&results)) {
switch (results.value) {
case 0x76044FD4:
cisloDalkac = 0;
break;
case 0x76044FE0:
cisloDalkac = 1;
break;
case 0x76044FD0:
cisloDalkac = 2;
break;
case 0x76044FF0:
cisloDalkac = 3;
break;
case 0x76044FC8:
cisloDalkac = 4;
break;
case 0x76044FE8:
cisloDalkac = 5;
break;
case 0x76044FD8:
cisloDalkac = 6;
break;
case 0x76044FF8:
cisloDalkac = 7;
break;
case 0x76044FC4:
cisloDalkac = 8;
break;
case 0x76044FE4:
cisloDalkac = 9;
break;
case 0x76044FC7:
cisloDalkac = 10;
break;
// backspace
case 0x76044FFE: {
if ((x > 0) && (cislic > 0)) {
backspace = true;
vysledek = vysledek / 10;
x = x - 1;
cislic = cislic - 1;
lcd.setCursor(x, y);
lcd.print(" ");
lcd.setCursor(x, y);
}
break;
}
// enter
case 0x76044FDE:
case 0x76044FF4:
enter = true;
}
if (!enter && !backspace && (cislic < 4)) {
lcd.print(cisloDalkac);
x = x + 1; // posun kurzor doprava
vysledek = vysledek * 10 + cisloDalkac;
cislic = cislic + 1;
}
irrecv.resume(); // nacti dalsi hodnotu
}
} while (!enter); // dokud jsi nedostal enter
return vysledek; //vrat, co jsi nacetl (cislo)
}
// porovna zadane cislo se spravnym vysledkem
// spravnyVysledek = kolik to melo byt
// x = pozice na LCD
void porovnej(int spravnyVysledek, int x) {
int vysledek = ctiDalkac(x, 1);
// Serial.println(vysledek);
// Serial.println(spravnyVysledek);
// Serial.println("----");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
if (spravnyVysledek != vysledek) {
lcd.print("CH Y B A !!!");
digitalWrite(LED_CHYBA, HIGH);
body = body - 1;
} else {
lcd.print("SPRAVNE");
digitalWrite(LED_OK, HIGH);
body = body + 1;
}
// chvilku pockej
delay(800);
digitalWrite(LED_CHYBA, LOW);
digitalWrite(LED_OK, LOW);
}
// vypis body
void vypisBody() {
lcd.setCursor(12, 0);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(body);
}
// vypis priklad
String vypisPriklad(int a, int b, String znak) {
lcd.setCursor(0, 1);
String text = "";
text = text + a;
text = text + znak;
text = text + b;
text = text + "=";
lcd.print(text);
return text;
}
void scitani() {
int scitanec1 = random(max + 1);
int scitanec2 = random(max + 1 - scitanec1);
int soucet = scitanec1 + scitanec2;
vypisBody();
String text = vypisPriklad(scitanec1, scitanec2, "+");
porovnej(soucet, text.length());
}
void odcitani() {
int mensenec = random(max + 1);
int mensitel = random(mensenec + 1);
int rozdil = mensenec - mensitel;
vypisBody();
String text = vypisPriklad(mensenec, mensitel, "-");
porovnej(rozdil, text.length());
}
// hlavni smycka
void loop() {
// vymysli si nahodne, co budes zkouset, zda priklad na scitani nebo odcitani
int co = random(2);
if (co == 0) {
scitani();
} else {
odcitani();
}
// vymazani casti displeje
lcd.setCursor(0, 1);
lcd.print(" ");
}
Možná vylepšení
- Další typy příkladů, např. násobení a dělení.
Poznatky
Velmi oblíběný projekt, který rozvíjel dále nápady, co by se dalo ještě vylepšit. Od samého počátku to byla dobrodružná akce, když jsme vybírali infra ovladač, kterým budeme hru ovládat, následně zapisovali kódy. Na přání dětí jsme přidali červenou a zelenou LED a mnoho vylepšení do kódu (např. ošetření maximálního počtu na otázku do kolika se budou příklady generovat). Výsledek sloužil opravdu k procvičování matematiky a to po dlouhé týdny, kdy to děti odmítaly rozebrat.