【Arduino 动手做】可爱的 Tamagotchi 电子宠物牛

在这里插入图片描述

《Arduino 手册(思路与案例)》栏目介绍:
在电子制作与智能控制的应用领域:广泛涉及了Arduino BLDC、Arduino CNC、Arduino ESP32 SPP、Arduino FreeRTOS、Arduino FOC、Arduino GRBL、Arduino HTTP、Arduino HUB75、Arduino IoT Cloud、Arduino JSON、Arduino LCD、Arduino OLED、Arduino LVGL、Arduino PID 及 Arduino TFT 等方面的相关拓展思路和众多参考案例。本专栏目前博客近2300篇。
https://blog.csdn.net/weixin_41659040/category_12422453.html

Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

在这里插入图片描述

我从来没有养过 Tamagotchi,一种小电子宠物,当它们在 80 年代后期问世时。老实说,图形相当粗糙,纽扣电池过去和现在都是一个环境问题。

但今天你可以做得更好。不是为了你的口袋,而是为了你的桌面。一头可爱的奶牛并没有错。

因此,让我们在谷仓中建造一头奶牛,您可以喂养和抚摸它(我们将跳过谷仓的清洁工作)。

在这里插入图片描述

用品与材料

• ESP32 CYD (便宜的黄色显示器) (2432S028R)
• 合适的电源 / 移动电源
• 3D 打印部件。或一些用于谷仓的木材

在这里插入图片描述

• 木材 / 胶合板和颜色
• Arduino IDE 软件
(需要具备 Arduino 的基本经验)

第 1 步:奶牛图形

对于我们的奶牛,我们需要一个带有饲喂站和水槽的舞台/谷仓,每个平台都显示不同的高度。
奶牛应该
• 站着, 微笑, 咀嚼, 看起来悲伤
• 吃、喝
• 躺下反刍, 微笑, 睡觉
这些图像作为代码存储在名为 “cow-all.h” 的额外文件中,并在需要时加载。
这些图像是自制的,您可以自由使用它们。

在这里插入图片描述

第 2 步:Cow 软件

CYD 是 ESP32 和 Touchschreeen 的完美结合。它为您省去了烦人的焊接和电缆。
诚然,我的编程有点业余。您当然可以从 CYD 的设计方面获得更多收益或为奶牛提供更多功能。但至少程序步骤很容易遵循。

该库可用于模拟各种工作表面。我们不展示背景,而是专注于奶牛、饮水处和饲养处。三个点击区域以隐藏的方式集成在一起,即它们不可见,但可以在三个地方点击:用于补充的水和饲料位置以及用于抚摸的奶牛本身。
奶牛的状态(很快)保存在 ESP32 上,以便随时关闭设备,并保持食物/情绪状态。

饥饿和口渴的值随机变化。ESP32 对毫秒数进行计数。这些值可以根据您的个人喜好进行设置。
文件 “cow-all.h” 在代码中包含了所有不同的奶牛图像,并且必须与 “demo.ino” 或 “tamagotchi_cow.ino” 存储在同一个文件夹中!

cow-all.h
演示.ino

#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>

TFT_eSPI tft = TFT_eSPI();

// touchscreen pins 
#define XPT2046_IRQ 36  // T_IRQ
#define XPT2046_MOSI 32 // T_DIN
#define XPT2046_MISO 39 // T_OUT
#define XPT2046_CLK 25  // T_CLK
#define XPT2046_CS 33   // T_CS
SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define FONT_SIZE 2

#include "cow-all.h"

// extra colors
#define NAVY tft.color565(0,0,160)   
#define DODGERBLUE tft.color565(30,144,255)
#define TURQUOISE tft.color565(64,224,208) 
#define CYAN tft.color565(0,255,255)  
#define GOLD tft.color565(255,215,0)
#define ORANGE tft.color565(255,165,0)
#define RED tft.color565(255,10,0)
#define MAROON tft.color565(123,0,0)
#define BROWN tft.color565(150,75,0)

// Global Variables
int x, y, z;     // touchscreen coordinates + pressure

// Set X and Y coordinates for center of display
int centerX, centerY;

//moodmeter & cow
 uint32_t moodcolor;
 int food, water, mood, mooddegree, waterlevel, foodlevel;
 int cowX,cowY;
 uint32_t cowImage;
 int saturation, thirst;
 int flag;

void drawStable() {
  //tft.drawRect(260, 10, 50, 14, TFT_RED);         //status
  tft.fillRoundRect(10, 80, 30, 70, 3, GOLD );          //food   TFT_DARKGREEN
  tft.fillRoundRect(10, 140, 50, 10, 5, TFT_DARKGREEN); //food

  tft.fillRoundRect(290, 80, 16, 60, 5, DODGERBLUE);  //water
  tft.drawRoundRect(290, 80, 16, 60, 5, TFT_WHITE);  //water
  tft.drawRoundRect(280, 138, 26, 2, 2, TFT_WHITE);  //water
}


void setup()
{
  Serial.begin(115200);

  // init RGB LED
  pinMode(4, OUTPUT); pinMode(16, OUTPUT); pinMode(17, OUTPUT);
  // turn off LED
  digitalWrite(4, HIGH); digitalWrite(16, HIGH); digitalWrite(17, HIGH);

  // Start the SPI for the touchscreen and init the touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  touchscreen.begin(touchscreenSPI);
  touchscreen.setRotation(3);

  // start display
  tft.init();
  tft.setRotation(3); // may be altered
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  // Set X and Y coordinates for center of display
  centerX = SCREEN_WIDTH / 2;
  centerY = SCREEN_HEIGHT / 2;

  tft.drawCentreString("Welcome to my stable", centerX, 30, FONT_SIZE);

  int x = (tft.width() - 116) / 2;
  int y = (tft.height() - 110) / 2;

food=60;
saturation = 90;
water= 80;

  //clear cow area
  tft.fillRect(40, 70, 249, 170, TFT_BLACK);
  // draw cow
  //tft.drawBitmap(40, 80, cow_well, 160, 140, TFT_WHITE);
  //tft.drawBitmap(45, 80, cow_eat, 160, 142, TFT_WHITE);
  tft.drawBitmap(70, 80, cow_neutral, 160, 147, TFT_WHITE);
  delay(2000);
  tft.fillRect(50, 0, 200, 50, TFT_BLACK); //clear area
}

void loop()  {
  // Checks if Touchscreen is touched
  if (touchscreen.tirqTouched() && touchscreen.touched()) {
    // Get Touchscreen points
    TS_Point p = touchscreen.getPoint();
    // Calibrate Touchscreen points with map function to the correct width and height
    x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    z = p.z;

    printTouchToSerial(x, y, z);

       
    //food touch
    if ((x>5)&&(x<60)&&(y>70)&&(y<160)) food=food+20;
    if (food>=100) food=100;
    //water touch
    if ((x>270)&&(x<315)&&(y>60)&&(y<155)) water=water+20;
    if (water>=100) water=100;
    
    cowX=50; cowY = 80; //start coordinates of cow bmp
    //cow touch
    if ((x>cowX)&&(x<cowX+150)&&(y>cowY)&&(y<cowY+130)) mood=mood+20;
    if (mood>=100) mood=100;

    Serial.print(food); Serial.print("  "); Serial.print(water);  Serial.print("  "); Serial.println(mood); 
    delay(80);
  }
  moodmeter(mood);
  waterfill(water);
  foodfill(food);

/*
  //  food /water levels ********************
  if (cowImage = cow_eat) {
    food--;
    saturation = saturation + 6;
    
  }
  if (cowImage = cow_drink) {
    water--;
    thirst = thirst -7;
  }

  //hunger/thirst comes up  *******************
  if (millisnow - millispast = random(480000, 900000)) {  //8-15 minutes
    saturation = saturation-3;
    thirst = thirst + 2;
    if (saturation<=0) saturation=0;
    if (thirst<=0) thirst=0;
  }
  */
  food=food - 0.5; water=water -0.5; mood=mood-0.5;
  if (food<=0) food=0;
  if (water<=0) water=0;
  if (mood<=0) mood=0;

  if ((mood> 70) && (flag!=1)) {
    tft.fillRect(54, 70, 220, 170, TFT_BLACK); //clear cow area
    tft.drawBitmap(70, 80, cow_smile2, 160, 147, TFT_WHITE);// draw cow
    flag = 1;
  }
  if ((mood<= 70) && (mood > 30) && (flag!=2)) {
    tft.fillRect(54, 70, 220, 170, TFT_BLACK); //clear cow area
    tft.drawBitmap(70, 80, cow_neutral, 160, 147, TFT_WHITE);// draw cow
    flag = 2;
  }
  if ((mood<=30) && (flag !=3)) {
    tft.fillRect(54, 70, 220, 170, TFT_BLACK); //clear cow area
    tft.drawBitmap(70, 80, cow_sad, 160, 145, TFT_WHITE);// draw cow
    flag = 3;
  }


  delay(300);
}


void waterfill(int water) {
  tft.fillRoundRect(290, 80, 16, 60, 5, TFT_BLACK); //clear area
  waterlevel = map(water, 0, 100, 140, 80);
  tft.fillRect(290, waterlevel, 16, (140-waterlevel), DODGERBLUE);  //water
  tft.drawRoundRect(289, 79, 18, 62, 5, TFT_WHITE);  //water frame
  tft.drawRoundRect(275, 138, 26, 3, 1, TFT_WHITE);  //water 
}

void foodfill(int food) {
  tft.fillRoundRect(10, 80, 40, 70, 5, TFT_BLACK); //clear area
  foodlevel = map(food, 0, 100, 150 , 80);
  tft.drawRoundRect(9, 79, 42, 72, 3, BROWN);     //food frame
  tft.fillRoundRect(10, foodlevel, 40, (150-foodlevel), 3, TFT_DARKGREEN);   //food   
  tft.fillTriangle(9, 150, 10, 157, 62, 150, BROWN);    //feeding dish
}

void moodmeter(int mood) {
  tft.fillRect(0, 0, 43, 43, TFT_BLACK); //clear area
  mooddegree = map(mood, 0, 100, 1, 360);
  if (mood < 15) moodcolor = RED;
  if ((mood >= 15) && (mood < 30)) moodcolor = ORANGE;
  if ((mood >= 30) && (mood < 60)) moodcolor = GOLD;
  if (mood >= 60) moodcolor = TFT_DARKGREEN;
  tft.drawSmoothArc(22, 22, 20, 8, 0, mooddegree, moodcolor, TFT_BLACK);
}

void printTouchToSerial(int x, int y, int z) {
  Serial.print("X = ");
  Serial.print(x);
  Serial.print(" | Y = ");
  Serial.print(y);
  Serial.print(" | Pressure = ");
  Serial.print(z);
  Serial.println();
}

tamagotchi_cow.ino

#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>

TFT_eSPI tft = TFT_eSPI();

// touchscreen pins 
#define XPT2046_IRQ 36  // T_IRQ
#define XPT2046_MOSI 32 // T_DIN
#define XPT2046_MISO 39 // T_OUT
#define XPT2046_CLK 25  // T_CLK
#define XPT2046_CS 33   // T_CS
SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define FONT_SIZE 2

#include "cow-all.h"

// extra colors
#define NAVY tft.color565(0,0,160)   
#define DODGERBLUE tft.color565(30,144,255)
#define TURQUOISE tft.color565(64,224,208) 
#define CYAN tft.color565(0,255,255)  
#define GOLD tft.color565(255,215,0)
#define ORANGE tft.color565(255,165,0)
#define RED tft.color565(255,10,0)
#define MAROON tft.color565(123,0,0)
#define BROWN tft.color565(150,75,0)

// Global Variables
int x, y, z;     // touchscreen coordinates + pressure

// Set X and Y coordinates for center of display
int centerX, centerY;

//moodmeter & cow
 uint32_t moodcolor;
 int food, water, mood, mooddegree, waterlevel, foodlevel;
 int cowX,cowY;
 uint32_t cowImage;
 int saturation, thirst;
 

void drawStable() {
  //tft.drawRect(260, 10, 50, 14, TFT_RED);         //status
  tft.fillRoundRect(10, 80, 30, 70, 3, GOLD );          //food   TFT_DARKGREEN
  tft.fillRoundRect(10, 140, 50, 10, 5, TFT_DARKGREEN); //food

  tft.fillRoundRect(290, 80, 16, 60, 5, DODGERBLUE);  //water
  tft.drawRoundRect(290, 80, 16, 60, 5, TFT_WHITE);  //water
  tft.drawRoundRect(280, 138, 26, 2, 2, TFT_WHITE);  //water
}


void setup()
{
  Serial.begin(115200);

  // init RGB LED
  pinMode(4, OUTPUT); pinMode(16, OUTPUT); pinMode(17, OUTPUT);
  // turn off LED
  digitalWrite(4, HIGH); digitalWrite(16, HIGH); digitalWrite(17, HIGH);

  // Start the SPI for the touchscreen and init the touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  touchscreen.begin(touchscreenSPI);
  touchscreen.setRotation(3);

  // start display
  tft.init();
  tft.setRotation(3); // may be altered
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  // Set X and Y coordinates for center of display
  centerX = SCREEN_WIDTH / 2;
  centerY = SCREEN_HEIGHT / 2;

  tft.drawCentreString("Welcome to my stable", centerX, 30, FONT_SIZE);

  int x = (tft.width() - 116) / 2;
  int y = (tft.height() - 110) / 2;

food=60;
saturation = 90;
water= 80;

  //clear cow area
  tft.fillRect(40, 70, 249, 170, TFT_BLACK);
  // draw cow
  //tft.drawBitmap(40, 80, cow_well, 160, 140, TFT_WHITE);
  //tft.drawBitmap(45, 80, cow_eat, 160, 142, TFT_WHITE);
  tft.drawBitmap(70, 80, cow_smile, 160, 145, TFT_WHITE);
  delay(2000);
  tft.fillRect(50, 0, 200, 50, TFT_BLACK); //clear area
}

void loop()  {
  // Checks if Touchscreen is touched
  if (touchscreen.tirqTouched() && touchscreen.touched()) {
    // Get Touchscreen points
    TS_Point p = touchscreen.getPoint();
    // Calibrate Touchscreen points with map function to the correct width and height
    x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    z = p.z;

    printTouchToSerial(x, y, z);

       
    //food touch
    if ((x>5)&&(x<60)&&(y>70)&&(y<160)) food=food+20;
    if (food>=100) food=100;
    //water touch
    if ((x>270)&&(x<315)&&(y>60)&&(y<155)) water=water+20;
    if (water>=100) water=100;
    
    cowX=50; cowY = 80; //start coordinates of cow bmp
    //cow touch
    if ((x>cowX)&&(x<cowX+150)&&(y>cowY)&&(y<cowY+130)) mood=mood+20;
    if (mood>=100) mood=100;

    Serial.print(food); Serial.print("  "); Serial.print(water);  Serial.print("  "); Serial.println(mood); 
    delay(80);
  }
  moodmeter(mood);
  waterfill(water);
  foodfill(food);

/*
  //  food /water levels ********************
  if (cowImage = cow_eat) {
    food--;
    saturation = saturation + 6;
    
  }
  if (cowImage = cow_drink) {
    water--;
    thirst = thirst -7;
  }

  //hunger/thirst comes up  *******************
  if (millisnow - millispast = random(480000, 900000)) {  //8-15 minutes
    saturation = saturation-3;
    thirst = thirst + 2;
    if (saturation<=0) saturation=0;
    if (thirst<=0) thirst=0;
  }
  */
  food--; water--; mood--;
  if (food<=0) food=0;
  if (water<=0) water=0;
  if (mood<=0) mood=0;
  delay(200);
}


void waterfill(int water) {
  tft.fillRoundRect(290, 80, 16, 60, 5, TFT_BLACK); //clear area
  waterlevel = map(water, 0, 100, 140, 80);
  tft.fillRect(290, waterlevel, 16, (140-waterlevel), DODGERBLUE);  //water
  tft.drawRoundRect(289, 79, 18, 62, 5, TFT_WHITE);  //water frame
  tft.drawRoundRect(275, 138, 26, 3, 1, TFT_WHITE);  //water 
}

void foodfill(int food) {
  tft.fillRoundRect(10, 80, 40, 70, 5, TFT_BLACK); //clear area
  foodlevel = map(food, 0, 100, 150 , 80);
  tft.drawRoundRect(9, 79, 42, 72, 3, BROWN);     //food frame
  tft.fillRoundRect(10, foodlevel, 40, (150-foodlevel), 3, TFT_DARKGREEN);   //food   
  tft.fillTriangle(9, 150, 10, 157, 62, 150, BROWN);    //feeding dish
}

void moodmeter(int mood) {
  tft.fillRect(0, 0, 43, 43, TFT_BLACK); //clear area
  mooddegree = map(mood, 0, 100, 1, 360);
  if (mood < 15) moodcolor = RED;
  if ((mood >= 15) && (mood < 30)) moodcolor = ORANGE;
  if ((mood >= 30) && (mood < 60)) moodcolor = GOLD;
  if (mood >= 60) moodcolor = TFT_DARKGREEN;
  tft.drawSmoothArc(22, 22, 20, 8, 0, mooddegree, moodcolor, TFT_BLACK);
}

void printTouchToSerial(int x, int y, int z) {
  Serial.print("X = ");
  Serial.print(x);
  Serial.print(" | Y = ");
  Serial.print(y);
  Serial.print(" | Pressure = ");
  Serial.print(z);
  Serial.println();
}

第 3 步:扬声器和 LDR 传感器

“Mooh”的扬声器是可选的。不幸的是,我还没有能够让声音功能在不复杂的情况下工作。每次 SD 卡在线时,触摸屏都无法正常工作。有什么想法吗?

mp3 文件可以保存在 SD 卡上。连接引脚位于 CYD 的背面。我从一台旧的固定电话中获得了扬声器。
内置的 LDR 传感器 (GPIO 34) 告诉奶牛何时睡觉。天黑时,她躺下。在此期间,不消耗水和食物。

附件
Cow-moo-sounds.mp3

在这里插入图片描述

第 4 步:谷仓

对于氛围,我很快就设计了一个带有 tinkercad.com 的马厩,并通过 3D 打印机将其变为现实。当然,您也可以在这里用木头建造一个美妙的微型马厩。不要忘记背面的良好通风。

3D打印件
Hay_Barn_ground.stl
Hay_Barn_roof.stl
Hay_Barn_walls.stl

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第 5 步:哞哞

功能:
当奶牛的内部水分和饲料水平下降(= 饥饿、口渴)时,奶牛会进食和饮水。如果水或饲料容器是空的,则奶牛会感到饥饿、不高兴和哞哞。
如果你点击水或饲料,补给就会得到补充,奶牛就可以吃东西了。如果你轻拍奶牛(=抚摸),它也会很开心,很舒服地哞哞叫。
当 LDR 注意到黑暗时,奶牛就会睡觉。她不吃东西,也没有太多的饥饿或口渴。
与您的新宠物一起玩得开心!

在这里插入图片描述

附录
项目链接:https://www.instructables.com/Cute-Tamagotchi-Cow/
项目作者:德国 马库斯·奥皮茨(Markus Opitz)
视频记录:https://www.bilibili.com/video/BV1EQJWzeEAA/?share_source=copy_web&vd_source=371a292a55e5ca9be994cbb4a86cc987
3D打印文件:https://content.instructables.com/FFO/YDLO/MADY883L/FFOYDLOMADY883L.stl
https://content.instructables.com/FFY/6D47/MADY883P/FFY6D47MADY883P.stl
https://content.instructables.com/F7A/3G1N/MADY883Q/F7A3G1NMADY883Q.stl
项目开源代码:https://content.instructables.com/FI1/56M8/MADY89Z5/FI156M8MADY89Z5.ino
图像到字节数组在线转换器(CPP、ARDUINO):https://mischianti.org/images-to-byte-array-online-converter-cpp-arduino/
电子宠物声音文件:https://content.instructables.com/FHP/LRK4/MADY883F/FHPLRK4MADY883F.mp3

在这里插入图片描述

【Arduino 动手做】可爱的 Tamagotchi 电子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值