Добрый День !
Задача
В духе AlexGyver – из Г.. и палок, т.е. из имеющихся компонентов (в условиях карантина) сделать игрушку для обучения простым арифметическим действиям ребёнка дошкольного возраста (сложение, вычитание, таблица умножения… дроби - пока не трогаем )) + освоить «Ардуинку».
Компоненты
1.- Arduino NANO
2.-Блок из 4-х матриц 8х8
3.- Пьезо зуммер
4.- Клавиатура 4х4 (4X3 - тоже можно сделать)
5.- Самый дешёвый корпус для «повербанки» под аккум 18650
6.- Соединительные провода, кнопки включения (с фиксацией) и сброса (опционально-необязательно).
Что оно умеет, описание работы устройства:
1. После включения на экране из матриц высвечивается «Кол-», необходимо ввести количество примеров, которые надо будет решить. Для подтверждения надо нажать любую кнопку без цифр (кроме «D», которая используется для стирания введённых значений, в дальнейшем назначения кнопок будет такое же).
2. Надо нажать на кнопку от 1 до 3 для выбора типа упражнений «Tun-»:
«1 – только умножение»,
«2 – сложение и вычитание»,
«3 – Умножение, сложение и вычитание».
3. Так как мы ещё не всю таблицу умножения выучили, то следующий параметр «MAX-» обозначает предел задач по таблице умножения, соответственно - от 1 до 9.
4. Дальше решаем примеры, если правильно, то весёлый смайлик и весёлое пиликанье, если неправильно – грустный смайлик и пик. В конце подводятся итоги.
ВКонтакте | ВКонтакте
vk.com
Сборка
1. Для корпуса хорошо подошла распаячная коробка 130х130.
2. В разрыв USB кабеля на провод «+5В» впаивается кнопка с фиксацией.
3. Для зарядки пришлось ещё вынести «на поверхность» гнездо с проводом до «повербанки».
4. Для удобства разборки-сборки надо предусмотреть как будет подключен шлейф клавиатуры, а всю «землю» сделал длинными проводами и собрал в зажиме «Ваго» (можно на отдельную скрутку).
5. Припаять пищалку к проводам с наконечным контактом «мама» и всё остальное можно соединить без пайки.
Схема
Фишки
1. Если количество упражнений будет 10 и более и всё правильно решить, то будет сюрприз.
2. На экран лучше положить кусочек белого картона или матового пластика, чтобы не болели ГЛАЗА и получить более «мягкое» изображение.
3. Питание заводил в USB, почему-то по «пинам» работало не стабильно.
4. В Китае продавались цилиндрические корпуса для «повербанки» и они замечательно «вщёлкиваются» в клипсы для труб диаметром 20 ;-).
5. Если (как у меня) не оказалось мелкого крепежа для «Ардуинки», то можно «пины» точащие с «ненужной» стороны воткнуть в вспененный полиэтилен (предварительно вырезав отверстие под «ресет» или припаять их к кисочку монтажной платы (но между собой не соединять!), а уже в монтажке просверлить отверстия ПОБОЛЬШЕ и прикрутить её куда надо.
Что бы я доделал…
1. Поколдовал бы со шрифтами, чтобы ужать их до 4 пксл, чтобы усложнить примеры на сложение и вычетание.
2. Завести питание по уму через пины "Vin" или "5В". И может вынести на поверхность вход USB «Ардуинки».
3. Часть настроек спрятал бы в «инженерном меню», которое вызывалось бы сочетанием горячих клавиш.
Но пока и так всё хорошо работает, ребёнка ЗАИНТЕРЕСОВАЛ! )))
Материалы дарю, но , как говорится, не для коммерческого использования, а для детей ничего не жалко ! ;-).
Код
ARIFMETIKA v1:
/[I]Разработано Zolo! Для связи [email protected][/I]/
#include <SPI.h> // Подключаем библиотеку SPI
#include <Adafruit_GFX.h> // Подключаем библиотеку Adafruit_GFX
#include <Max72xxPanel.h> // Подключаем библиотеку Max72xxPanel
#include <Keypad.h> // Подключаем библиотеку клавиатуры 4х4
#include "fonts.h"
// Подключаем Матрицк 8х32
# define pinCS 10 // Указываем к какому выводу подключен контакт CS
int numberOfHorizontalDisplays = 1; // Количество матриц по горизонтали
int numberOfVerticalDisplays = 4; // Количество матриц по-вертикали
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
// Подключаем клавиатуру 4х4
const byte ROWS = 4; // 4 строки
const byte COLS = 4; // 4 столбца
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
char numkeys[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// Подключаем Зуммер
# define beeppin A3
//Писанина
String text0;
String text1 = "Кол-";
String text2 = "Tun-";
String text3 = "MAX-";
String text4 = "Всё правильно! МОЛОДЕЦ!";
String text5 = "Надо тренироваться! Есть ошибки, целых- " ;
String text6 = ", в " ;
String text7 = " упражнениях!" ;
String text8 = " Для продолжения нажмите любую кнопку!";
// Обнуляшки
byte x = 0; // первое слогаемое (множитель)
byte y = 0; // второе слогаемое (множитель)
int z = 0; // результат действия
int z2 = 0; // ответ на задание
byte k = 0; // количество нажатий на кнопки
byte kt = 0; // количество нажатий на кнопки при вводе ответов
byte n = 1; // для цикла прогона упражнений
byte rndtest = 0;
byte vol = 0; // громкость зуммера
byte prov = 0;
char preskeys[2] = {'0', '0'}; //какие кнопочки нажаты
char preskeys2[2] = {'0', '0'}; //какие кнопочки нажаты
char znak[3] = {'x', '+', '-'}; // знаки
int result = 0; // результат ввода
int resultat = -1; // результат ввода ответа
int numtests = 0; // количество заданий
int typtests = 0; // выбор формата заданий: 1 - умножение, 2 - сложение и вычитание, 3 - микс
int predel = 0; // установить предел для упражнений для умножения от 1 до 9
int fail = 0; // подсчёт ошибок
bool flag = 0;
String str_fail;
String str_numtests;
//Бегущая строка - настройки (чужой код)
String tape; // строка для отображения
int wait = 100; // Задержка в мс перед сдвигом картинки
int spacer = 1; // расстояние в точках меджу символами
int width = 5 + spacer; // Ширина шрифта 5 точек
void setup() {
//Serial.begin(9600);
// Подготовка матрицы
matrix.setIntensity(7); // яркость от 0 до 15
matrix.setRotation(1); // Ориентация квадратиков
matrix.fillScreen(LOW); // Очистка картинки
matrix.write();
// Задаём новый отчёт для псевдослуч. последовательности из "воздуха" на пине "A0"
randomSeed(analogRead(A0));
// Подключаем Зуммер
pinMode(beeppin, OUTPUT);
vol = 130;
}
void(* resetFunc) (void) = 0; // Reset MC function
void loop() {
// Ввод значений - количество упражнений
while (numtests == 0) {
numtests = NumTest(); //количество заданий от 1 до 99
if (numtests > 0 && numtests < 100) {
delay (500);
matrix.fillScreen(LOW); // Очистка картинки
matrix.write();
//Serial.print ("Количкество тестов всего = "); Serial.println (numtests);
break;
}
}
// Ввод значений - тип упражнений
while ((typtests == 0) || (typtests > 3)) {
typtests = TypeTest();// выбор формата заданий: 1 - умножение, 2 - сложение и вычитание, 3 - микс
if ((typtests > 0) && (typtests <= 3)) {
delay (500);
matrix.fillScreen(LOW); // Очистка картинки
matrix.write();
//Serial.print ("Тип тестов выбран= "); Serial.println (typtests);
break;
}
else typtests = 0;
}
//Ввод значений - предел умножения
while ((predel == 0) || (predel > 9)) {
predel = PredelTest(); // выбор предела умножения от 1 до 9
if ((predel > 0) && (predel < 10)) {
matrix.fillScreen(LOW); // Очистка картинки
matrix.write();
//Serial.print ("Предел выбран= "); Serial.println (predel);
break;
}
else predel = 0;
}
// Решаем примеры
while (n <= numtests) { // повторяем столько сколько выбрали упражнений
n++;
switch (typtests) { // в зависимости от типа теста выбираем случайно какой набор действий выполняем
case 1: {
rndtest = 0; // - только умножение
break;
}
case 2: {
rndtest = random (1, 3); // сложение или вычитание
break;
}
case 3: {
rndtest = random (0, 3); // любое задание (+,-,*)
break;
}
}
switch (rndtest + 1) { // случайно выбираем задание (+,-,*) и условия
case 1: {// - умножение
x = random (1, predel + 1); // - только умножение
y = random (0, 10);
z = x * y;
matrix.drawChar( 0, 0, numkeys[x], HIGH, LOW, 1);
matrix.drawChar( 5, -1, 'x', HIGH, LOW, 1);
matrix.drawChar(10, 0, numkeys[y], HIGH, LOW, 1);
matrix.drawChar(15, 0, '=', HIGH, LOW, 1);
matrix.write();
break;
}
case 2: {// - сложение
x = random (0, 10);
y = random (0, 10);
z = x + y;
matrix.drawChar( 0, 0, numkeys[x], HIGH, LOW, 1);
matrix.drawChar( 5, 0, '+', HIGH, LOW, 1);
matrix.drawChar(10, 0, numkeys[y], HIGH, LOW, 1);
matrix.drawChar(15, 0, '=', HIGH, LOW, 1);
matrix.write();
break;
}
case 3: {// - вычитание
int a = random (0, 10);
int b = random (0, 10);
x = max(a, b);
y = min(a, b);
z = x - y;
matrix.drawChar( 0, 0, numkeys[x], HIGH, LOW, 1);
matrix.drawChar( 5, 0, '-', HIGH, LOW, 1);
matrix.drawChar(10, 0, numkeys[y], HIGH, LOW, 1);
matrix.drawChar(15, 0, '=', HIGH, LOW, 1);
matrix.write();
break;
}
}
//Вводим ответ и проверяем его.
while (resultat == -1) {
z2 = EnterNumTest() ;
prov = Proverka (z, z2);
}
/*
Serial.print ("x= "); Serial.println (x);
Serial.print (rndtest); Serial.println (znak[rndtest]);
Serial.print ("y= "); Serial.println (y);
Serial.print ("RESULTAT = "); Serial.println (z2);
Serial.print ("OTBET = "); Serial.println (z);
Serial.print ("Proverka = "); Serial.println (prov);
Serial.print ("FAIL = "); Serial.println (fail);
Serial.println ();
*/
// Затираем прошлый ответ
matrix.drawChar(21, 0, ' ', HIGH, LOW, 1); // Затираем
matrix.drawChar(27, 0, ' ', HIGH, LOW, 1); // Затираем
matrix.write();
resultat = -1;
kt = 0;
prov = 0;
}
matrix.fillScreen(LOW);
if (fail == 0) {
text0 = utf8rus(text4) + utf8rus(text8);
RunningString (text0);
if (numtests > 9) Movi_1();
}
else {
int xh1 = 24;
str_fail = String (fail);
str_numtests = String (numtests);
matrix.fillScreen(LOW);
//анти - Смайлик :(
matrix.drawRoundRect (-xh1 + 24, 0, 8, 8, 3, 1);
matrix.drawPixel(-xh1 + 27, 4, 1); matrix.drawPixel(-xh1 + 28, 4, 1);
matrix.drawPixel(-xh1 + 26, 5, 1); matrix.drawPixel(-xh1 + 29, 5, 1);
matrix.drawPixel(-xh1 + 26, 2, 1); matrix.drawPixel(-xh1 + 29, 2, 1);
matrix.drawChar(9, 0, '-', HIGH, LOW, 1); // тире
matrix.drawChar(15, 0, str_fail[0], HIGH, LOW, 1); // ошибки 1 символ
matrix.drawChar(21, 0, str_fail[1], HIGH, LOW, 1); // ошибки 2 символ
matrix.write();
analogWrite (beeppin, vol); delay (100); digitalWrite (beeppin, 0);
delay (5000);
// Бегущая строка
text0 = utf8rus(text5) + str_fail + utf8rus(text6) + str_numtests + utf8rus(text7);
RunningString (text0);
}
resetFunc();
}
// Спрашиваем - сколько будет упражнений?
int NumTest() {
int numtests2 = 0;
text0 = utf8rus(text1);
for ( int i = 0 ; i < text0.length(); i++ ) {
matrix.drawChar(i * 5, 0, text0[i], HIGH, LOW, 1);
matrix.write();
}
numtests2 = EnterNum();
return numtests2;
}
// Ввод значений
int EnterNum() {
char key = keypad.getKey();
if (key) {
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0);
if ((key == numkeys[0] || key == numkeys[1] || key == numkeys[2] || key == numkeys[3] || key == numkeys[4] || key == numkeys[5] || key == numkeys[6] || key == numkeys[7] || key == numkeys[8] || key == numkeys[9]) && k < 2) {
matrix.drawChar(21 + k * 6, 0, key, HIGH, LOW, 1); // Пишем название нажатой клавиши
matrix.write();
preskeys[k] = key;
k++;
}
else if ((key == keys[3][3]) && k > 0 ) { // если нажали кнопку Д и при этом хотя бы 1 символ напечатан
matrix.drawChar(21 + (k - 1) * 6, 0, ' ', HIGH, LOW, 1); // Стираем пробелом
matrix.write();
k--;
preskeys[k] = '0';
}
else if ((key == keys[0][3] || key == keys[1][3] || key == keys[2][3] || key == keys[3][0] || key == keys[3][2]) && k > 0) { // если нажали любую не цифру и не Д то считаем значение
matrix.drawChar(21, 0, 'O', HIGH, LOW, 1); // Пишем ОК
matrix.drawChar(27, 0, 'K', HIGH, LOW, 1); // Пишем ОК
matrix.write();
if (k == 1) {
result = preskeys[0] - '0';
} else {
result = (preskeys[0] - '0') * 10 + (preskeys[1] - '0');
}
return result;
}
}
else return 0;
}
int EnterNumTest() {
char key_t = keypad.getKey();
if (key_t) {
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0);
if ((key_t == numkeys[0] || key_t == numkeys[1] || key_t == numkeys[2] || key_t == numkeys[3] || key_t == numkeys[4] || key_t == numkeys[5] || key_t == numkeys[6] || key_t == numkeys[7] || key_t == numkeys[8] || key_t == numkeys[9]) && kt < 2) {
matrix.drawChar(21 + kt * 6, 0, key_t, HIGH, LOW, 1); // Пишем название нажатой клавиши
matrix.write();
preskeys2[kt] = key_t;
kt++;
}
else if ((key_t == keys[3][3]) && kt > 0 ) { // если нажали кнопку Д и при этом хотя бы 1 символ напечатан
matrix.drawChar(21 + (kt - 1) * 6, 0, ' ', HIGH, LOW, 1); // Стираем пробелом
matrix.write();
kt--;
preskeys2[kt] = '0';
}
else if ((key_t == keys[0][3] || key_t == keys[1][3] || key_t == keys[2][3] || key_t == keys[3][0] || key_t == keys[3][2]) && kt > 0) { // если нажали любую не цифру и не Д то считаем значение
matrix.drawChar(21, 0, 'O', HIGH, LOW, 1); // Пишем ОК
matrix.drawChar(27, 0, 'K', HIGH, LOW, 1); // Пишем ОК
matrix.write();
if (kt == 1) {
resultat = preskeys2[0] - '0';
} else {
resultat = (preskeys2[0] - '0') * 10 + (preskeys2[1] - '0');
}
return resultat;
}
}
else return -1; //начальное значение
}
// выбор формата заданий: 1 - умножение, 2 - сложение и вычитание, 3 - микс
int TypeTest() {
int type1 = 0;
char key1 = keypad.getKey();
for (int i = 0 ; i < text2.length(); i++ ) {
matrix.drawChar(i * 5, 0, text2[i], HIGH, LOW, 1);
matrix.write();
}
if (key1) {
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0);
if (key1 == numkeys[1] || key1 == numkeys[2] || key1 == numkeys[3]) {
matrix.drawChar(21, 0, key1, HIGH, LOW, 1); // Пишем название нажатой клавиши
matrix.write();
delay (500);
matrix.drawChar(21, 0, 'O', HIGH, LOW, 1); // Пишем ОК
matrix.drawChar(27, 0, 'K', HIGH, LOW, 1); // Пишем ОК
matrix.write();
type1 = key1 - '0';
//digitalWrite (beeppin, 1); delay (200); digitalWrite (beeppin, 0);
return type1;
}
}
else return 0;
}
// Выясняем - предел таблицы умножения?
int PredelTest() {
int predel2 = 0;
char key2 = keypad.getKey();
for ( int i = 0 ; i < text3.length(); i++ ) {
matrix.drawChar(i * 5, 0, text3[i], HIGH, LOW, 1);
matrix.write();
}
if (key2) {
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0);
if (key2 == numkeys[1] || key2 == numkeys[2] || key2 == numkeys[3] || key2 == numkeys[4] || key2 == numkeys[5] || key2 == numkeys[6] || key2 == numkeys[7] || key2 == numkeys[8] || key2 == numkeys[9]) {
matrix.drawChar(21, 0, key2, HIGH, LOW, 1); // Пишем название нажатой клавиши
matrix.write();
delay (500);
matrix.drawChar(21, 0, 'O', HIGH, LOW, 1); // Пишем ОК
matrix.drawChar(27, 0, 'K', HIGH, LOW, 1); // Пишем ОК
matrix.write();
predel2 = key2 - '0';
return predel2;
}
}
else return 0;
}
byte Proverka (int ParamZ, int ParamZ2) {
if (ParamZ == ParamZ2) {
// Затираем прошлый ответ
matrix.drawChar(21, 0, ' ', HIGH, LOW, 1); // Затираем
matrix.drawChar(27, 0, ' ', HIGH, LOW, 1); // Затираем
// СМАЙЛИК :)
matrix.drawRoundRect (24, 0, 8, 8, 3, 1);
matrix.drawPixel(27, 5, 1); matrix.drawPixel(28, 5, 1);
matrix.drawPixel(26, 4, 1); matrix.drawPixel(29, 4, 1);
matrix.drawPixel(26, 2, 1); matrix.drawPixel(29, 2, 1);
matrix.write();
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0); delay (50);
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0); delay (50);
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0); delay (50);
analogWrite (beeppin, vol); delay (50); digitalWrite (beeppin, 0); delay (50);
delay (700);
return 2;
}
else if (resultat != -1) {
// Затираем прошлый ответ
matrix.drawChar(21, 0, ' ', HIGH, LOW, 1); // Затираем
matrix.drawChar(27, 0, ' ', HIGH, LOW, 1); // Затираем
// анти-СМАЙЛИК :(
matrix.drawRoundRect (24, 0, 8, 8, 3, 1);
matrix.drawPixel(27, 4, 1); matrix.drawPixel(28, 4, 1);
matrix.drawPixel(26, 5, 1); matrix.drawPixel(29, 5, 1);
matrix.drawPixel(26, 2, 1); matrix.drawPixel(29, 2, 1);
matrix.write();
analogWrite (beeppin, vol); delay (500); digitalWrite (beeppin, 0); delay (700);
// Правильный ответ !!!!
matrix.drawChar(21, 0, ' ', HIGH, LOW, 1); // Затираем
matrix.drawChar(27, 0, ' ', HIGH, LOW, 1); // Затираем
matrix.setCursor(21, 0);
String str_otvet = String (z);
matrix.drawChar(21, 0, str_otvet[0], HIGH, LOW, 1);
matrix.drawChar(27, 0, str_otvet[1], HIGH, LOW, 1);
matrix.write();
delay (2000);
analogWrite (beeppin, vol); delay (100); digitalWrite (beeppin, 0);
fail++; // Ошибочки копятся
return 1;
}
else {
return 0;
}
}
//Бегущая строка
// стандартный вывод бегущей строки из примера библиотеки МАХ72ххPanel
String RunningString (String ParamText) {
for ( int i = 0 ; i < width * ParamText.length() + 30; i++ ) {
char key_end1 = keypad.getKey();
matrix.fillScreen(LOW); // Задание цвета фона экрана (вне букв) LOW - темный, HIGH - светлый
int letter = i / width;
int xs = 31 - i % width;;
int ys = 0; // center the text vertically
while ( xs + width - spacer >= 0 && letter >= 0 ) {
if ( letter < ParamText.length() ) {
matrix.drawChar(xs, ys, ParamText[letter], HIGH, LOW, 1); // Задание цветов вывода надписи.
}
letter--;
xs -= width;
}
matrix.write(); // Отправка на экран
delay(wait);
if (key_end1) {
analogWrite (beeppin, vol); delay (100); digitalWrite (beeppin, 0);
break;
}
}
}
// Перекодировка для поддержки русского языка в скетче
// через СОМ порт с клавиатуры и так русский работает
String utf8rus(String source) {
int i, ks;
String target;
unsigned char n;
char m[2] = { '0', '\0' };
ks = source.length(); i = 0;
while (i < ks) {
n = source[i]; i++;
if (n >= 0xC0) {
switch (n) {
case 0xD0: {
n = source[i]; i++;
if (n == 0x81) {
n = 0xA8;
break;
}
if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
break;
}
case 0xD1: {
n = source[i]; i++;
if (n == 0x91) {
n = 0xB7;
break;
}
if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
break;
}
}
}
m[0] = n; target = target + String(m);
}
return target;
}
// Анимашка
void Movi_1 () {
byte xh = 0;
byte ar[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
while (1) {
char key_end = keypad.getKey();
for (byte i = 0; i < 47; i++) {
xh = ar[i];
key_end = keypad.getKey();
//Смайлик
matrix.drawRoundRect (-xh + 24, 0, 8, 8, 3, 1);
matrix.drawPixel(-xh + 27, 5, 1); matrix.drawPixel(-xh + 28, 5, 1);
matrix.drawPixel(-xh + 26, 4, 1); matrix.drawPixel(-xh + 29, 4, 1);
matrix.drawPixel(-xh + 26, 2, 1); matrix.drawPixel(-xh + 29, 2, 1);
// Сердечко
matrix.drawLine (xh + 1, 0, xh + 2, 0, 1); matrix.drawLine (xh + 6, 0, xh + 7, 0, 1);
matrix.drawLine (xh, 1, xh + 3, 1, 1); matrix.drawLine (xh + 5, 1, xh + 8, 1, 1);
matrix.drawLine (xh, 2, xh + 8, 2, 1);
matrix.drawLine (xh, 3, xh + 8, 3, 1);
matrix.drawLine (xh + 1, 4, xh + 7, 4, 1);
matrix.drawLine (xh + 2, 5, xh + 6, 5, 1);
matrix.drawLine (xh + 3, 6, xh + 5, 6, 1);
matrix.drawPixel(xh + 4, 7, 1);
matrix.write();
delay(wait);
matrix.fillScreen(LOW);
if (key_end) {
analogWrite (beeppin, vol); delay (100); digitalWrite (beeppin, 0);
break;
}
}
if (key_end) break;
}
}
Вложения
-
116.2 KB Просмотры: 34,544
-
345 KB Просмотры: 14
Изменено: