桌面电子小狗--调狗系统(esp8266版本)

1 篇文章 0 订阅
1 篇文章 0 订阅

目录

1.先上代码

2.使用方法:

3.配置管脚

4.串口数据解析:

5.val为什么要转换?

6.舵机位置判断

7.舵机控制

8.结果展示


1.先上代码


        本文章用于调试B站的桌面电子小狗腿部动作,因为调试小狗的动作时,不知动作幅度是否符合位置,每次改代码重新下载太占用时间也不方便。所以通过串口调试大大减少难度,方便得出符合自己的电子小狗动作。各位可以运行成功后,哪里不懂的,可以再看一下下面的解释。

int myangle;//定义角度变量
int pulsewidth;//定义脉宽变量

int Front_left = 4;//前左,IO4(D2)引脚
int Front_right = 14;//前右,IO14(D5)引脚
int rear_right = 12;//后右,IO12(D6)引脚
int rear_left = 15;//后左,IO15(D8)引脚


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

  pinMode(Front_left,OUTPUT);//设置前左的IO为舵机
  pinMode(Front_right,OUTPUT);//设置前右的IO为舵机
  pinMode(rear_right,OUTPUT);//设置后右的IO为舵机
  pinMode(rear_left,OUTPUT);//设置后左的IO为舵机       
}

void loop() 
{
  separate();//分离
}

String letters = "";//分离的字母
String numbers = "";//分离的数字
void separate()//分离
{
  if (Serial.available() > 0) //检查串口缓冲区中是否有可用的数据
  {
    String input = Serial.readStringUntil('\n');//读取串口数据直到遇到换行符'\n'

    for (int i = 0; i < input.length(); i++) {
      if (isDigit(input[i])) //判断当前字符是否是数字(0-9)
      {
        numbers += input[i];
      } else if (isAlpha(input[i])) //判断当前字符是否是字母
      {
        letters += input[i];
      }
    }
    // Serial.print("字母: ");
    // Serial.println(letters);
    // Serial.print("数字: ");
    // Serial.println(numbers);
    Action1();
    
    letters = "";//清除字母
    numbers = "";//清除数字
  }

}
//判断字母(letters)是什么,这里设定z为前左舵机,x为前右舵机,c为后右舵机,v为后左舵机,b为全部舵机
//例如串口输入为z90,就是前左舵机转90度,b90就是全部舵机转90度
void Action1()
{
  int val = numbers.toInt();//将String 类型的数据转换为 int 类型

  if(letters == "z")
  {   
    for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
    {
      servopulse1(Front_left,val);//前左舵机动作
    }
    Serial.print("前左: ");
    Serial.print(val,DEC);
    Serial.println();
  }
  if(letters == "x")
  {   
    for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
    {  
      servopulse2(Front_right,val);//前右舵机动作
    }
    Serial.print("前右: ");
    Serial.print(val,DEC);
    Serial.println();
  }
  if(letters == "c")
  {
    for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
    {
      servopulse3(rear_right,val);//后右舵机动作
    }
    Serial.print("后右: ");
    Serial.print(val,DEC);
    Serial.println();
  }
  if(letters == "v")
  {
    for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
    {
      servopulse4(rear_left,val);//后左舵机动作
    }
    Serial.print("后左: ");
    Serial.print(val,DEC);
    Serial.println();
  }

  if(letters == "b")
  {
    for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
    {
      servopulse1(Front_left,val);//前左舵机动作
      servopulse2(Front_right,val);//前右舵机
      servopulse3(rear_right,val);//后右舵机
      servopulse4(rear_left,val);//后左舵机
    }
    Serial.print("全部: ");
    Serial.print(val,DEC);
    Serial.println();
  }
}


void servopulse1(int Front_left,int myangle)//定义一个脉冲函数
{
  pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
  digitalWrite(Front_left,HIGH);//将舵机接口电平至高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(Front_left,LOW);//将舵机接口电平至低
  delay(20-pulsewidth/1000);
}
void servopulse2(int Front_right,int myangle)//定义一个脉冲函数
{
  pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
  digitalWrite(Front_right,HIGH);//将舵机接口电平至高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(Front_right,LOW);//将舵机接口电平至低
  delay(20-pulsewidth/1000);
}
void servopulse3(int rear_right,int myangle)//定义一个脉冲函数
{
  pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
  digitalWrite(rear_right,HIGH);//将舵机接口电平至高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(rear_right,LOW);//将舵机接口电平至低
  delay(20-pulsewidth/1000);
}
void servopulse4(int rear_left,int myangle)//定义一个脉冲函数
{
  pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
  digitalWrite(rear_left,HIGH);//将舵机接口电平至高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(rear_left,LOW);//将舵机接口电平至低
  delay(20-pulsewidth/1000);
}

2.使用方法:

arduino 软件的串口监视器输入対应的字母加数字,舵机対应作出相应的动作,方便我们调试电子小狗的各个腿。设定z为前左舵机,x为前右舵机,c为后右舵机,v为后左舵机,b为全部舵机。

例如串口输入为z90,就是前左舵机转90度,b90就是全部舵机转90度

 

3.配置管脚

 舵机与8266引脚连接,电源可以直接连接板子上的G/VIN。这个是与下载线连接的,输出电压为5V。

int Front_left = 4;//前左,IO4(D2)引脚
int Front_right = 14;//前右,IO14(D5)引脚
int rear_right = 12;//后右,IO12(D6)引脚
int rear_left = 15;//后左,IO15(D8)引脚

 小狗正上方图(有点丑,有点乱------------------------不要笑(威胁))

根据小狗正上方图,设定左上方为前左舵机,设定右上方为前右舵机,设定左下方为后左舵机,设定右下方为后右舵机。

4.串口数据解析:

  if (Serial.available() > 0) //检查串口缓冲区中是否有可用的数据
  {
    String input = Serial.readStringUntil('\n');//读取串口数据直到遇到换行符'\n'

    for (int i = 0; i < input.length(); i++) {
      if (isDigit(input[i])) //判断当前字符是否是数字(0-9)
      {
        numbers += input[i];
      } else if (isAlpha(input[i])) //判断当前字符是否是字母
      {
        letters += input[i];
      }
    }
    // Serial.print("字母: ");
    // Serial.println(letters);
    // Serial.print("数字: ");
    // Serial.println(numbers);
    Action1();
    
    letters = "";//清除字母
    numbers = "";//清除数字
  }

  1. 首先通过条件判断 if (Serial.available() > 0) 来检查串口缓冲区是否有数据可供读取。如果有数据,程序进入后续处理流程。
  2. 使用 String input = Serial.readStringUntil('\n'); 语句读取串口数据直到遇到换行符,将数据存储在 input 字符串变量中。
  3. 接着通过 for 循环 for (int i = 0; i < input.length(); i++) 遍历 input 字符串中的每一个字符。
    • 在循环体内,利用条件判断语句来区分字符的类型。
    • 如果 isDigit(input[i]) 返回 true,说明当前字符是数字,就将其添加到 numbers 字符串中,即 numbers += input[i];
    • 如果 isAlpha(input[i]) 返回 true,表示当前字符是字母,就把它添加到 letters 字符串中,即 letters += input[i];
  4. 最后通过 Serial.print() 和 Serial.println() 函数将分离出来的字母和数字分别输出到串口监视器上,方便我们查看结果。

5.val为什么要转换?

  int val = numbers.toInt();//将String 类型的数据转换为 int 类型
String letters = "";//分离的字母
String numbers = "";//分离的数字

原始数据是从串口读取分离出来的字符串,其中的数字部分存储在 String 类型的 numbers 变量中。后续的数学运算(如乘法、比较等)和与角度相关的操作通常需要使用整数类型的数据。

toInt() 是 String 类的一个成员函数。它的主要作用是将 String 类型中存储的数字字符串转换为整数(int 类型)。

转换过程如下:

        1.首先,它会读取 numbers 字符串中的字符。

        2.然后,根据数字字符的 ASCII 值,将其转换为对应的整数值。例如,字符 '0' 到 '9' 的 ASCII 值是连续的,通过减去 '0' 的 ASCII 值,就可以将其转换为相应的整数 0 到 9。

        3.如果字符串中包含多个数字字符,它会根据数字的位置和权值进行计算。例如,对于字符串 "123",百位上的 '1' 转换为 1,十位上的 '2' 转换为 2,个位上的 '3' 转换为 3,最终得到的整数值就是 123 = 1 * 100 + 2 * 10 + 3。

6.舵机位置判断

这里使用if不用switch/case是因为我懒。

判断根据不同的字母来确定要控制哪个舵机。z为前左舵机,x为前右舵机,c为后右舵机,v为后左舵机,b为全部舵机。

例如 if(letters == "z") 表示当接收到的字母是 "z" 时,控制前左舵机。

当接收到的字母是 "b" 时,同时控制所有的舵机(前左、前右、后右、后左)旋转到相同的角度。但是我们安装的舵机方向都不相同,所以串口输入“b+数字”时,舵机会转动不同的方向,当串口输入“b90”时,舵机都转到90度,电子小狗成立正状态。

  if(letters == "z")
  {   

  }
  if(letters == "x")
  {   

  }
  if(letters == "c")
  {

  }
  if(letters == "v")
  {

  }

  if(letters == "b")
  {

  }

7.舵机控制

不用arduino库中的舵机库(Servo.h)的原因是:舵机库(Servo.h)不好用,转动角度达不到理想状态。

void servopulse2(int Front_right,int myangle)//定义一个脉冲函数
{
  pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
  digitalWrite(Front_right,HIGH);//将舵机接口电平至高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(Front_right,LOW);//将舵机接口电平至低
  delay(20-pulsewidth/1000);
}

根据输入的角度 myangle 计算出对应的脉冲宽度 pulsewidth。(角度myangle就是串口输入的字母+数字中的数字),这里的 (myangle * 11) + 500 是一种特定的计算方式,将角度值映射到一个合适的脉冲宽度范围(通常舵机的控制脉冲宽度在一定范围内与角度有对应关系)。

之后开始发送控制舵机的脉冲信号(引脚设置为高电平),延时后,引脚设置为低电平,完成一个脉冲周期。

delayMicroseconds(pulsewidth);//延时脉宽值的微秒数

延时 pulsewidth 微秒数。这个延时时间就是控制舵机的脉冲高电平持续时间,不同的脉冲宽度会使舵机转动到不同的角度。

delay(20-pulsewidth/1000);

再次进行延时,这里的延时时间是 20 - pulsewidth / 1000 毫秒。是为了确保脉冲发送的节奏和稳定性,满足舵机控制的时序要求。

8.结果展示

调试结果记录,后面开发根据动作记录进行进一步开发,比如加入语音模块,触摸按键等等,来完成相对应的动作。

      case 'a': //站立
      { 
        for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
        {
          servopulse1(Front_left,90);//设置前左的IO为舵机
          servopulse2(Front_right,90);//设置前右的IO为舵机
          servopulse3(rear_right,90);//设置后右的IO为舵机
          servopulse4(rear_left,90);//设置后左的IO为舵机
        }                    
        break;
      }
      case 's'://后趴
      {
        for(int i=0;i<=50;i++) //给予舵机足够的时间让它转到指定角度
        {
          servopulse1(Front_left,180);//设置前左的IO为舵机
          servopulse2(Front_right,0);//设置前右的IO为舵机
          servopulse3(rear_right,180);//设置后右的IO为舵机
          servopulse4(rear_left,0);//设置后左的IO为舵机
        }                    
        break;
      }

 参考文章,感谢大神:用 Arduino 控制舵机 – Arduino 实验室

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值