Make it fun to remember relative names by M5Stack for children
2022-12-01 | By M5Stack
License: General Public License Bluetooth / BLE Drivers / Controllers Arduino
* Thanks for the source code and project information provided by @Mame Tarou
background
I think that the frequency of meeting with relatives has decreased in the flow of self-restraint due to the corona wreck. However, grandparents want their grandchildren to remember their names as soon as possible. Therefore, I developed a product that allows families to remember their relative's names without having to meet.
As a reference for how children learn things, I heard that if you connect pictures and sounds with the child's action, such as "Children's books that learn with sounds and pictures", children will learn things quite quickly.
Therefore, I thought of developing a product that would play the name of the relative when the child tapped a photo of the relative.
parts
- M5Paper
- Grove MP3 Module v2.0
- speaker
- microSD card
image preparation
I wanted to display about 6 relative images on the screen. M5Paper is 540x960, so prepare 6 square images of 250x250.
- create a resources folder
- Place 1 to 6 png files of 250x250 in the resources folder
- Execute image2gray.py under resources folder → Create ImageResouce.hfolder<Program>
┣Program.ino
┗Program<resources>
┣1.png
┣2.png
┣3.png
┣4.png
┣5.png
┣6.png
┣image2gray.py
┗ageResource.h
*image2gray.py is located at https://github.com/m5stack/M5EPD/tree/main/tools/image2gray
Preparing the microSD card
- Create audio corresponding to the designation 1 to 6.png
- Data will be written to the SD card "in order from 1"
*Grove MP3 module v2.0 can specify the index number in the order in which the audio is written
connection
- Insert microSD card into Grove MP3 Module v2.0
- Connect Port.A of M5Paper and Grove MP3 module v2.0 with Grove cable
- Write program to M5Paper
How it works
When you touch the face of a relative, the name will be played by voice.
program
Write the following program to M5Paper.
#include <SoftwareSerial.h>
#include <MP3Player_KT403A.h>
#include <M5EPD.h>
#include "./resources/ImageResource.h"
// edp
#define PIC_SIZE 250
#define LEFT_INDEXX 10
#define RIGHT_INDEXX 280
#define UPPER_INDEXY 50
#define MIDDLE_INDEXY 320
#define LOWER_INDEXY 590
#define BUTTON_RESET_MSEC 1000
#define DELAY_MSEC 10
int preIndex = 0;
// mp3
#define swtxPin 25
#define swrxPin 32
// Note: You must define a SoftwareSerial class object that the name must be mp3,
// but you can change the pin number according to the actual situation.
SoftwareSerial mp3(swrxPin, swtxPin);
M5EPD_Canvas canvas(&M5.EPD);
void setup()
{
M5.begin();
M5.EPD.SetRotation(90);
M5.EPD.Clear(true);
// 写真の表示
canvas.createCanvas(540, 960);
canvas.setTextSize(3);
canvas.pushImage(LEFT_INDEXX, UPPER_INDEXY ,PIC_SIZE,PIC_SIZE,ImageResource_1_250x250);
canvas.pushImage(RIGHT_INDEXX, UPPER_INDEXY ,PIC_SIZE,PIC_SIZE,ImageResource_2_250x250);
canvas.pushImage(LEFT_INDEXX, MIDDLE_INDEXY ,PIC_SIZE,PIC_SIZE,ImageResource_3_250x250);
canvas.pushImage(RIGHT_INDEXX, MIDDLE_INDEXY ,PIC_SIZE,PIC_SIZE,ImageResource_4_250x250);
canvas.pushImage(LEFT_INDEXX, LOWER_INDEXY ,PIC_SIZE,PIC_SIZE,ImageResource_5_250x250);
canvas.pushImage(RIGHT_INDEXX, LOWER_INDEXY ,PIC_SIZE,PIC_SIZE,ImageResource_6_250x250);
canvas.pushCanvas(0,0,UPDATE_MODE_GC16);
// タッチパネルの準備
M5.TP.SetRotation(90);
// mp3初期設定
pinMode(swrxPin, INPUT);
pinMode(swtxPin, OUTPUT);
mp3.begin(9600);
delay(100);
SelectPlayerDevice(0x02); // Select SD card as the player device.
SetVolume(0x1E); // Set the volume, the range is 0x00 to 0x1E.
}
// 写真番号に応じた動作
void touchAction(int picNumber){
SpecifyMusicPlay(picNumber);
Serial.printf("x:%d\r\n", picNumber);
}
// 領域内をタッチしたかどうか判定
bool InsideSquare(int squareIndexX, int squareIndexY, int picSize, int touchX , int touchY)
{
if(touchX < squareIndexX) return false;
if((squareIndexX + picSize) < touchX) return false;
if(touchY < squareIndexY) return false;
if((squareIndexY + picSize) < touchY) return false;
return true;
}
// どの写真を押したかチェック
int CheckTouchPicture(int touchX , int touchY)
{
int index = 0;
if(InsideSquare(LEFT_INDEXX, UPPER_INDEXY ,PIC_SIZE, touchX, touchY)) index = 1;
else if(InsideSquare(RIGHT_INDEXX, UPPER_INDEXY ,PIC_SIZE, touchX, touchY)) index = 2;
else if(InsideSquare(LEFT_INDEXX, MIDDLE_INDEXY ,PIC_SIZE, touchX, touchY)) index = 3;
else if(InsideSquare(RIGHT_INDEXX, MIDDLE_INDEXY ,PIC_SIZE, touchX, touchY)) index = 4;
else if(InsideSquare(LEFT_INDEXX, LOWER_INDEXY ,PIC_SIZE, touchX, touchY)) index = 5;
else if(InsideSquare(RIGHT_INDEXX, LOWER_INDEXY ,PIC_SIZE, touchX, touchY)) index = 6;
return index;
}
// 0:タッチなし
// 1~6:写真をタッチ
int checkTouch(void){
int index = 0;
if(M5.TP.avaliable()){
if(!M5.TP.isFingerUp()){
M5.TP.update();
tp_finger_t FingerItem = M5.TP.readFinger(0);
index = CheckTouchPicture(FingerItem.x,FingerItem.y);
}
if(index != 0 && preIndex != index){
preIndex = index;
return index;
}else{
// 更新なし
return 0;
}
}
return 0;
}
int totalMsec;
void loop()
{
int picIndex = checkTouch();
if(picIndex != 0){
touchAction(picIndex);
totalMsec = 0;
}
// 押したことを初期化
if(preIndex != 0){
if(totalMsec < BUTTON_RESET_MSEC){
totalMsec = totalMsec + DELAY_MSEC;
}else{
preIndex = 0;
totalMsec = 0;
}
}else{
preIndex = 0;
totalMsec = 0;
}
delay(DELAY_MSEC);
}