本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

儿童教育机器人Educational Robot

发布时间:2022-06-17
分享到:

儿童教育机器人Educational Robot

发布时间:2022-06-17
分享到:

所有知识领域,如科学、人类或生物,都有各自的重要性。因此,负责传授知识的老师必须牢记他的使命是多么重要。

在教育机器人的教学中也必须考虑到这一点,因为对于希望达到的每个年龄组,都需要使用适当的工具和方法。教育机器人可以触及和解决各种主题,将它们与我们在学校学习的概念交织在一起。举一个例子,像是我们学习字母表的元音。

通过一些电子设备,可以鼓励和激发元音的学习,从而接触到处于这个学习阶段的孩子的听众,从而使学习变得更有活力和乐趣。

通过这种方式,可以将简单机器人的组装与各自的控制相结合,使用一些电子设备,如超声波传感器、液晶显示器和一些按钮。

由于原型将是一个教学模型,理想的情况是使用 Arduino 开发平台来控制其操作。图 1 展示了使用一些电子设备的教育机器人原型。

在这个教育机器人的开发中,使用了一个超声波传感器、一个 LCD 显示器、5 个按钮、一个 2 极跷跷板开关和 Arduino uno。

在这种情况下,Arduino 将负责触发与用户按下按钮的字母相对应的声音,然后将其直观地显示在 LCD 显示器上。

因此,通过本文,您将学习:

  • 了解使用 HC-SR04 超声波传感器、16x2 LCD 显示屏、Kcd1-101 2 极跷跷板键(开-关)按钮和 Arduino Uno 的教育机器人的结构
  • 分析机器人机箱机械结构通过螺钉、螺母和配件的固定方式
  • 了解机器人结构各部分对整个项目的重要性
  • 了解教育机器人的工作逻辑

现在,我们将开始完整介绍教育机器人项目的开发。

项目开发方法论
该项目包括展示一个使用超声波传感器的教学机器人,以及其机械结构的组装。

该项目基本上由一个类似于盒子的物理结构(即机器人的身体)和一个控件组成。机器人体内有 arduino、超声波传感器和负责通知用户按下的字母的音箱。

控制负责检测输入的字母并将信号发送到 Arduino。图 2 展示了机器人的内部区域:

在内部结构中可以观察到Arduino和机器人身体背面的跷跷板开关,已经在控制中,因为它将通过连接发送信号到arduino,它只有电线的空间。

M3 螺母和螺钉尺寸的配件设计用于固定结构

M3 螺钉具有此类项目的理想尺寸,因为高于或低于该尺寸的尺寸可能会不必要地增加原型的重量,或者使其更易碎。图 3 显示了机器人的内表面和上表面:

机器人的脖子上有一个结构,可以让它的头部绕轴旋转。

该结构由连接到机器人上表面的内部区域的圆形部分形成。

然后,在上表面上模拟另一个圆形部件,但有一个小间隙,以促进其围绕自身轴的位移。最后,在相关表面的上部区域还有另一个圆形块。

最后,颈部通过两个螺钉固定在旋转框架上。这些部件的组合使机器人的脖子可以移动。

图 4 展示了所描述的机制:

机器人有一些浮雕细节,给人以备件的外观,给人以机器人零件的印象。图 5 说明了这些部件在机器人外表面上的布置:

机器人控制基本上由一个 16x2 LCD 显示屏和 5 个按钮组成。

它还有代表每个按钮的 5 个字母。每个元音字母都有一个按钮,当用户按下相应的按钮时,信号将被发送到 arduino uno,显示屏会指示输入的字母,让学习机器人和元音变得更加容易。

图 6 展示了教育机器人控制:

教育机器人的面部基本上由三部分组成:超声波传感器所在的区域,与第一部分相关的用于分离电线且不暴露的区域,以及第三部分,即覆盖物。头部的后部区域。

前两个有一些额外的层来增加厚度(这些层可以使用胶水连接),并且它们都通过连接它们的 M3 螺钉连接。

除了这些,机器人的面部还有轮廓和眉毛,让面部更加友好。

图 7 展示了教育机器人的面部:

对于超声波传感器的固定,建模了一个结构以将其固定在机器人前面,如上图所示,它将通过传感器本身的 4 个标准螺钉及其各自的螺母连接。

图 8 说明了超声波传感器在教育机器人上的位置:

放置超声波传感器的目的是根据用户的存在做出反应。面部和眉毛的轮廓都被塑造成突出教育机器人的表情。

Arduino 主要负责两个目的:处理来自超声波传感器和按钮的信号,并进行必要的设置以将信号发送到 LCD 显示器和再现字母的声音。

Arduino 位于机器人的内部后部区域,以便于开发编程及其可能的更改,只需要安装电源线和 USB 通信。

在 arduino 连接旁边,还放置了一个跷跷板开关,用于为电路供电和断电。

图 9 说明了教育机器人上 arduino 和跷跷板连接的位置:

图 10 以渲染图像中主要部件的分解透视图说明了教育机器人的整个结构:

接下来,我们看看项目的编程逻辑:

项目编程逻辑
在下文中,我将逐步解释构建这个有趣的儿童游戏的逻辑:

#include <SoftwareSerial.h>

#define ARDUINO_RX 5  //should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6  //connect to RX of the module

SoftwareSerial mp3(ARDUINO_RX, ARDUINO_TX);

static int8_t Send_buf[8] = {0}; // Buffer for Send commands.  // BETTER LOCALLY
static uint8_t ansbuf[10] = {0}; // Buffer for the answers.    // BETTER LOCALLY

String mp3Answer;           // Answer from the MP3.

String sanswer(void);
String sbyte2hex(uint8_t b);

/************ Command byte **************************/
#define CMD_NEXT_SONG     0X01  // Play next song.
#define CMD_PREV_SONG     0X02  // Play previous song.
#define CMD_PLAY_W_INDEX  0X03
#define CMD_VOLUME_UP     0X04
#define CMD_VOLUME_DOWN   0X05
#define CMD_SET_VOLUME    0X06

#define CMD_SNG_CYCL_PLAY 0X08  // Single Cycle Play.
#define CMD_SEL_DEV       0X09
#define CMD_SLEEP_MODE    0X0A
#define CMD_WAKE_UP       0X0B
#define CMD_RESET         0X0C
#define CMD_PLAY          0X0D
#define CMD_PAUSE         0X0E
#define CMD_PLAY_FOLDER_FILE 0X0F

#define CMD_STOP_PLAY     0X16  // Stop playing continuously. 
#define CMD_FOLDER_CYCLE  0X17
#define CMD_SHUFFLE_PLAY  0x18 //
#define CMD_SET_SNGL_CYCL 0X19 // Set single cycle.

#define CMD_SET_DAC 0X1A
#define DAC_ON  0X00
#define DAC_OFF 0X01

#define CMD_PLAY_W_VOL    0X22
#define CMD_PLAYING_N     0x4C
#define CMD_QUERY_STATUS      0x42
#define CMD_QUERY_VOLUME      0x43
#define CMD_QUERY_FLDR_TRACKS 0x4e
#define CMD_QUERY_TOT_TRACKS  0x48
#define CMD_QUERY_FLDR_COUNT  0x4f

/************ Opitons **************************/
#define DEV_TF            0X02

/*********************************************************************/
int numero;      
byte estado;      
byte buzzer = 2;
byte pin = 0;
byte SortNumber = 0;

bool button = 0;

void setup()
{
  Serial.begin(9600);
  mp3.begin(9600);
  delay(500);
  
  for(pin = 8; pin < 13; pin++)
  {
    pinMode(pin, INPUT);
  }
  
  sendCommand(CMD_SEL_DEV, 0, DEV_TF);
  delay(500);
}

void loop()
{
  pin = 8;

  randomSeed(analogRead(A0));
  numero = random(8,12);
  SortNumber =  numero;
  numero = numero - 7;
  
  Serial.println(numero);
  sendCommand(0x03, 0, numero);
  delay(1000);
  
  do
  {
     button = digitalRead(pin);
     Serial.println(button);
     pin++;

     if(pin > 13)
     {
        pin = 8;
     }

     Serial.println("Varrendo...");
     Serial.println(pin);
     //delay(1000);
     
  }while(button != 1);

  Serial.println("Saiu...");

  if(button == 1 && (pin-1) != SortNumber)
  {
    sendCommand(0x03, 0, 6);
    delay(3000);
  }

  if(button == 1 && (pin-1) == SortNumber)
  {
    sendCommand(0x03, 0, 7);
    delay(3000);
  }
  
  // Check for the answer.
  if (mp3.available())
  {
    Serial.println(decodeMP3Answer());
  }
  delay(100);
  //Serial.println("Tocando musica...");
}

/********************************************************************************/
/*Function sendMP3Command: seek for a 'c' command and send it to MP3  */
/*Parameter: c. Code for the MP3 Command, 'h' for help.                                                                                                         */
/*Return:  void                                                                */

void sendMP3Command(char c) {
  
  switch (c) {
    case '?':
    case 'h':
      Serial.println("HELP  ");
      Serial.println(" p = Play");
      Serial.println(" P = Pause");
      Serial.println(" > = Next");
      Serial.println(" < = Previous");
      Serial.println(" s = Stop Play"); 
      Serial.println(" + = Volume UP");
      Serial.println(" - = Volume DOWN");
      Serial.println(" c = Query current file");
      Serial.println(" q = Query status");
      Serial.println(" v = Query volume");
      Serial.println(" x = Query folder count");
      Serial.println(" t = Query total file count");
      Serial.println(" f = Play folder 1.");
      Serial.println(" S = Sleep");
      Serial.println(" W = Wake up");
      Serial.println(" r = Reset");
      break;

    case 'p':
      Serial.println("Play ");
      sendCommand(CMD_PLAY);
      break;

    case 'P':
      Serial.println("Pause");
      sendCommand(CMD_PAUSE);
      break;

    case '>':
      Serial.println("Next");
      sendCommand(CMD_NEXT_SONG);
      sendCommand(CMD_PLAYING_N); // ask for the number of file is playing
      break;

    case '<':
      Serial.println("Previous");
      sendCommand(CMD_PREV_SONG);
      sendCommand(CMD_PLAYING_N); // ask for the number of file is playing
      break;

    case 's':
      Serial.println("Stop Play");
      sendCommand(CMD_STOP_PLAY);
      break;

    case '+':
      Serial.println("Volume Up");
      sendCommand(CMD_VOLUME_UP);
      break;

    case '-':
      Serial.println("Volume Down");
      sendCommand(CMD_VOLUME_DOWN);
      break;

    case 'c':
      Serial.println("Query current file");
      sendCommand(CMD_PLAYING_N);
      break;

    case 'q':
      Serial.println("Query status");
      sendCommand(CMD_QUERY_STATUS);
      break;

    case 'v':
      Serial.println("Query volume");
      sendCommand(CMD_QUERY_VOLUME);
      break;

    case 'x':
      Serial.println("Query folder count");
      sendCommand(CMD_QUERY_FLDR_COUNT);
      break;

    case 't':
      Serial.println("Query total file count");
      sendCommand(CMD_QUERY_TOT_TRACKS);
      break;

    case 'f':
      Serial.println("Playing folder 1");
      sendCommand(CMD_FOLDER_CYCLE, 1, 0);
      break;

    case 'S':
      Serial.println("Sleep");
      sendCommand(CMD_SLEEP_MODE);
      break;

    case 'W':
      Serial.println("Wake up");
      sendCommand(CMD_WAKE_UP);
      break;

    case 'r':
      Serial.println("Reset");
      sendCommand(CMD_RESET);
      break;
  }
}

/********************************************************************************/
/*Function decodeMP3Answer: Decode MP3 answer.                                  */
/*Parameter:-void                                                               */
/*Return: The                                                  */

String decodeMP3Answer() {
  String decodedMP3Answer = "";

  decodedMP3Answer += sanswer();

  switch (ansbuf[3]) {
    case 0x3A:
      decodedMP3Answer += " -> Memory card inserted.";
      break;

    case 0x3D:
      decodedMP3Answer += " -> Completed play num " + String(ansbuf[6], DEC);
      //sendCommand(CMD_NEXT_SONG);
      //sendCommand(CMD_PLAYING_N); // ask for the number of file is playing
      break;

    case 0x40:
      decodedMP3Answer += " -> Error";
      break;

    case 0x41:
      decodedMP3Answer += " -> Data recived correctly. ";
      break;

    case 0x42:
      decodedMP3Answer += " -> Status playing: " + String(ansbuf[6], DEC);
      break;

    case 0x48:
      decodedMP3Answer += " -> File count: " + String(ansbuf[6], DEC);
      break;

    case 0x4C:
      decodedMP3Answer += " -> Playing: " + String(ansbuf[6], DEC);
      break;

    case 0x4E:
      decodedMP3Answer += " -> Folder file count: " + String(ansbuf[6], DEC);
      break;

    case 0x4F:
      decodedMP3Answer += " -> Folder count: " + String(ansbuf[6], DEC);
      break;
  }

  return decodedMP3Answer;
}

/********************************************************************************/
/*Function: Send command to the MP3                                             */
/*Parameter: byte command                                                       */
/*Parameter: byte dat1 parameter for the command                                */
/*Parameter: byte dat2 parameter for the command                                */

void sendCommand(byte command){
  sendCommand(command, 0, 0);
}

void sendCommand(byte command, byte dat1, byte dat2){
  delay(20);
  Send_buf[0] = 0x7E;    //
  Send_buf[1] = 0xFF;    //
  Send_buf[2] = 0x06;    // Len
  Send_buf[3] = command; //
  Send_buf[4] = 0x01;    // 0x00 NO, 0x01 feedback
  Send_buf[5] = dat1;    // datah
  Send_buf[6] = dat2;    // datal
  Send_buf[7] = 0xEF;    //
  Serial.print("Sending: ");
  for (uint8_t i = 0; i < 8; i++)
  {
    mp3.write(Send_buf[i]) ;
    Serial.print(sbyte2hex(Send_buf[i]));
  }
  Serial.println();
}

/********************************************************************************/
/*Function: sbyte2hex. Returns a byte data in HEX format.                       */
/*Parameter:- uint8_t b. Byte to convert to HEX.                                */
/*Return: String                                                                */


String sbyte2hex(uint8_t b)
{
  String shex;

  shex = "0X";

  if (b < 16) shex += "0";
  shex += String(b, HEX);
  shex += " ";
  return shex;
}


/********************************************************************************/
/*Function: shex2int. Returns a int from an HEX string.                         */
/*Parameter: s. char *s to convert to HEX.                                      */
/*Parameter: n. char *s' length.                                                */
/*Return: int                                                                   */

int shex2int(char *s, int n){
  int r = 0;
  for (int i=0; i<n; i++){
     if(s[i]>='0' && s[i]<='9'){
      r *= 16; 
      r +=s[i]-'0';
     }else if(s[i]>='A' && s[i]<='F'){
      r *= 16;
      r += (s[i] - 'A') + 10;
     }
  }
  return r;
}


/********************************************************************************/
/*Function: sanswer. Returns a String answer from mp3 UART module.          */
/*Parameter:- uint8_t b. void.                                                  */
/*Return: String. If the answer is well formated answer.                        */

String sanswer(void)
{
  uint8_t i = 0;
  String mp3answer = "";

  // Get only 10 Bytes
  while (mp3.available() && (i < 10))
  {
    uint8_t b = mp3.read();
    ansbuf[i] = b;
    i++;

    mp3answer += sbyte2hex(b);
  }

  // if the answer format is correct.
  if ((ansbuf[0] == 0x7E) && (ansbuf[9] == 0xEF))
  {
    return mp3answer;
  }

  return "???: " + mp3answer;
}

首先,我们定义了 YX5300 模块的所有程序变量和访问寄存器地址。

#include <SoftwareSerial.h>

#define ARDUINO_RX 5  //should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6  //connect to RX of the module

SoftwareSerial mp3(ARDUINO_RX, ARDUINO_TX);

static int8_t Send_buf[8] = {0}; // Buffer for Send commands.  // BETTER LOCALLY
static uint8_t ansbuf[10] = {0}; // Buffer for the answers.    // BETTER LOCALLY

String mp3Answer;           // Answer from the MP3.

String sanswer(void);
String sbyte2hex(uint8_t b);

/************ Command byte **************************/
#define CMD_NEXT_SONG     0X01  // Play next song.
#define CMD_PREV_SONG     0X02  // Play previous song.
#define CMD_PLAY_W_INDEX  0X03
#define CMD_VOLUME_UP     0X04
#define CMD_VOLUME_DOWN   0X05
#define CMD_SET_VOLUME    0X06

#define CMD_SNG_CYCL_PLAY 0X08  // Single Cycle Play.
#define CMD_SEL_DEV       0X09
#define CMD_SLEEP_MODE    0X0A
#define CMD_WAKE_UP       0X0B
#define CMD_RESET         0X0C
#define CMD_PLAY          0X0D
#define CMD_PAUSE         0X0E
#define CMD_PLAY_FOLDER_FILE 0X0F

#define CMD_STOP_PLAY     0X16  // Stop playing continuously. 
#define CMD_FOLDER_CYCLE  0X17
#define CMD_SHUFFLE_PLAY  0x18 //
#define CMD_SET_SNGL_CYCL 0X19 // Set single cycle.

#define CMD_SET_DAC 0X1A
#define DAC_ON  0X00
#define DAC_OFF 0X01

#define CMD_PLAY_W_VOL    0X22
#define CMD_PLAYING_N     0x4C
#define CMD_QUERY_STATUS      0x42
#define CMD_QUERY_VOLUME      0x43
#define CMD_QUERY_FLDR_TRACKS 0x4e
#define CMD_QUERY_TOT_TRACKS  0x48
#define CMD_QUERY_FLDR_COUNT  0x4f

/************ Opitons **************************/
#define DEV_TF            0X02

/*********************************************************************/
int numero;      
byte estado;      
byte buzzer = 2;
byte pin = 0;
byte SortNumber = 0;

bool button = 0;

这些寄存器地址用于配置模块的操作。例如,请参阅下面的此注册地址。

#define CMD_PLAY_W_INDEX  0X03

地址 0x03 使用名称 CMD_PLAY_W_INDEX 定义。用于从其编号触发一首歌曲,即输入声音的编号即可播放。

我们将使用这些值并配置项目的功能。

在您定义了将使用的各种地址后,我们将进入设置功能并为我们的项目配置引脚和串行通信。

void setup() 函数
接下来看void设置函数。我做了所有按钮引脚的设置,MP3模块的串行通信,以及MP3卡模块的初始化。

void setup()
{
  Serial.begin(9600);
  mp3.begin(9600);
  delay(500);
  
  for(pin = 8; pin < 13; pin++)
  {
    pinMode(pin, INPUT);
  }
  
  sendCommand(CMD_SEL_DEV, 0, DEV_TF);
  delay(500);
}

我开始串行通信以在计算机的串行上打印数据,然后我们通过 mp3 对象开始串行通信。

Serial.begin(9600);
mp3.begin(9600);
delay(500);

mp3 模块通过 Arduino 串口接收的命令进行控制。在这个过程中,我们使用了 SoftwareSerial 库并在 Arduino 数字引脚上模拟了一个串行。

因此,您将能够使用 Arduino 通过发送给它的命令来控制 MP3 模块。

此外,我们还进行了数字管脚的配置和 MP3 卡模块的初始化。

for(pin = 8; pin < 13; pin++)
  {
    pinMode(pin, INPUT);
  }
  
  sendCommand(CMD_SEL_DEV, 0, DEV_TF);
  delay(500);

配置完成后,我们必须进入void循环函数中的主逻辑。

主函数 void loop()
代码非常简单,整个逻辑结构如下所示。下面我给大家讲解一下main函数的完整逻辑。

void loop()
{
  pin = 8;

  randomSeed(analogRead(A0));
  numero = random(8,12);
  SortNumber =  numero;
  numero = numero - 7;
  
  Serial.println(numero);
  sendCommand(0x03, 0, numero);
  delay(1000);
  
  do
  {
     button = digitalRead(pin);
     Serial.println(button);
     pin++;

     if(pin > 13)
     {
        pin = 8;
     }

     Serial.println("Varrendo...");
     Serial.println(pin);
     //delay(1000);
     
  }while(button != 1);

  Serial.println("Saiu...");

  if(button == 1 && (pin-1) != SortNumber)
  {
    sendCommand(0x03, 0, 6);
    delay(3000);
  }

  if(button == 1 && (pin-1) == SortNumber)
  {
    sendCommand(0x03, 0, 7);
    delay(3000);
  }
  
  // Check for the answer.
  if (mp3.available())
  {
    Serial.println(decodeMP3Answer());
  }
  delay(100);
  //Serial.println("Tocando musica...");
}

在循环函数循环的每个开始,我们将生成一个介于 8 和 12 之间的新值来生成元音的声音。从 8 到 12 的值是指元音的数字引脚。

生成随机值的代码如下所示:

pin = 8;

  randomSeed(analogRead(A0));
  numero = random(8,12);
  SortNumber =  numero;

此外,我们从 8 到 12 之间抽取的数量减去 7。这将允许我们指向存储卡上录制的歌曲的 1 到 5 的位置。

numero = numero - 7;

之后,我再现了在下面的线上绘制的元音的声音。

sendCommand(0x03, 0, numero);
delay(1000);

现在重要的时刻已经到来:我们要阅读孩子按下的按钮的时刻。代码部分如下所示:

do
  {
     button = digitalRead(pin);
     Serial.println(button);
     pin++;

     if(pin > 13)
     {
        pin = 8;
     }

     Serial.println("Varrendo...");
     Serial.println(pin);
     //delay(1000);
     
  }while(button != 1);

这个循环将一直执行,直到用户按下按钮。循环允许您扫描 5 个数字引脚,当孩子按下其中一个按钮时,它将退出循环并检查孩子是否正确响应。

您将使用下面的代码进行验证。

if(button == 1 && (pin-1) != SortNumber)
  {
    sendCommand(0x03, 0, 6);
    delay(3000);
  }

  if(button == 1 && (pin-1) == SortNumber)
  {
    sendCommand(0x03, 0, 7);
    delay(3000);
  }

第一个条件将在用户因按下按钮而发生错误并且引脚的触发值与绘制的引脚(SortNumber)不同时执行。

此时,您必须执行以下命令。

sendCommand(0x03, 0, 6);
delay(3000);

该命令用于触发错误的响应音。最后,我们有第二个条件,用于检查孩子是否正确。

if(button == 1 && (pin-1) == SortNumber)
  {
    sendCommand(0x03, 0, 7);
    delay(3000);
  }

如果按下按钮并且按下的数字引脚与绘制的引脚相同,系统将触发正确答案声音。

正如我向您解释的那样,此代码非常简单,将帮助任何孩子通过与 Arduino 的游戏来发展他们的元音知识。在下图中,音箱正在播放存储在 MP3 Module YX5300 的 SD 卡中的歌曲。

通过有趣和有趣的活动,您的学生或您的孩子可以边玩边学习。如果您想与学生一起玩乐,请获取带有元音的黑板,并设置此项目以获得乐趣。

结论
对结构的主要部分进行了验证和分析,以便更好地了解正确组装的重要性,观察每个部件的功能(根据安装的结构),以及机器人颈部旋转机构的功能。

因此,从教育机器人项目的发展来看,可以分析其机械结构并优化机器人本体和控制中的可用空间。

机器人的结构采用 M3 套筒和螺钉进行建模,用于固定,因此创造了更好的机械稳定性。

它的所有开发都是为了使其尽可能具有指导意义,以便以后与电子部件组装。

如果您对此项目有任何想法、意见或问题,请在下方留言。

以上内容翻译自网络,原作者:Silícios Lab,如涉及侵权,可联系删除。

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论