任务13 蓝牙控制双路舵机并OLED显示角度值(arduino程序)

本文详细介绍了伺服电机的工作原理,包括其内部结构和控制方式,并以MG995型号为例,提供了舵机的参数信息。此外,还展示了如何通过蓝牙模块控制舵机,给出了单路、双路及多路伺服电机驱动的Arduino程序示例,解释了如何通过不同信号控制伺服电机转动角度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

硬件:

舵机(伺服电机)伺服电机就是带有反馈环节的电机,我们可以通过伺服电机进行精确的位置控制或者输出较高的扭矩。

内部结构:

  • ①:信号线:接收来自微控制器的控制信号;

  • ②:电位器:可以测量输出轴的位置量,属于整个伺服机构的反馈部分;

  • ③:内部控制器:处理来自外部控制的信号,驱动电机以及处理反馈的位置信号,是整个伺服机构的核心;

  • ④:电机:作为执行机构,输出多少转速,转矩,位置;

  • ⑤:传动机构/舵机系统:该机构根据一定传动比,将电机输出的行程缩放到最终输出的角度上;

    因此舵机是伺服电机的一种,整体电机就是一个闭环系统,输入相应的信号,就能控制舵机输出对应的位置量;

控制原理:

产品型号 MG995
产品重量 55g
工作扭矩 13KG/cm
反应转速 53-62R/M
使用温度 -30~+60°
死区设定 4微秒
插头类型 JR、FUTABA通用
转动角度 最大180度
舵机类型 模拟舵机
工作电流 100mA
使用电压 3-7.2V
结构材质 金属铜齿、空心杯电机、双滚珠轴承 无负载
操作速度 0.17秒/60度(4.8V);0.13秒/60度(6.0V)
 

接线:

使用原理:

舵机的控制一般需要一个20ms的脉冲,角度对应如下:
t = 0.5ms——————-舵机会转动 0 °
t = 1.0ms——————-舵机会转动 45°
t = 1.5ms——————-舵机会转动 90°
t = 2.0ms——————-舵机会转动 135°
t = 2.5ms——————-舵机会转动180°

所以转的角度也就取决于高电平在这段20ms周期中的时间(占空比)。

蓝牙控制双路舵机程序:

/*******************************************
 * 蓝牙控制两路舵机
 * 蓝牙发送 1-180 表示:舵机1-180度
 *******************************************/
#include <SoftwareSerial.h>
#include <Servo.h>
#include "U8glib.h"

int pos, pos1, pos2;             //舵机角度
uint8_t dataIndex = 0;           //初始状态

Servo myServo1, myServo2;         //创建Servo对象myServo
SoftwareSerial BTserial(10, 11); // 建立SoftwareSerial对象,RX引脚2, TX引脚3
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);  // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)

static unsigned char deng[] U8G_PROGMEM = {0x00,0x00,0x7E,0x3E,0x40,0x22,0x40,0x12,0x42,0x12,0x24,0x0A,0x28,0x12,0x10,0x12,
0x10,0x22,0x28,0x22,0x28,0x22,0x44,0x16,0x42,0x0A,0x01,0x02,0x00,0x02,0x00,0x02,/*"邓",0*/};
static unsigned char zhao[] U8G_PROGMEM = {0x00,0x00,0xBE,0x3F,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x29,0xBE,0x10,0x22,0x3F,
0x22,0x21,0x22,0x21,0x22,0x21,0x3E,0x3F,0x00,0x00,0x12,0x11,0x22,0x22,0x21,0x22,/*"照",1*/};
static unsigned char quan[] U8G_PROGMEM = {0x08,0x00,0xC8,0x3F,0x88,0x20,0x88,0x20,0xBF,0x20,0x08,0x11,0x0C,0x11,0x1C,0x11,
0x2A,0x0A,0x2A,0x0A,0x09,0x04,0x08,0x04,0x08,0x0A,0x08,0x11,0x88,0x20,0x68,0x40,/*"权",2*/};

void draw0(void) {
  u8g.drawXBMP( 0, 0, 16, 16, deng);
  u8g.drawXBMP( 16, 0, 16, 16, zhao);
  u8g.drawXBMP( 32, 0, 16, 16, quan);
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 50, 14, "190306238");
  u8g.drawStr( 0, 45, "Servo2:");
  u8g.drawStr( 0, 30, "Servo1:");
  //舵机1
  u8g.setPrintPos(60,30);
  u8g.print(pos1);
  //舵机2
  u8g.setPrintPos(60,45);
  u8g.print(pos2);
  //默认
  if(dataIndex == 0){
    u8g.drawStr( 0, 60, "Please Open BLE!");
  }
}

void LED_Show(void)
{
  u8g.firstPage();  
  do {
    draw0();
  } while( u8g.nextPage() );    
}
 
void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  digitalWrite(8, HIGH);
  digitalWrite(9, LOW);
  Serial.begin(9600);
  BTserial.begin(9600); // HC-06 默认波特率 9600
  Serial.print("HC-05 DEMO/TEST  ");
  BTserial.print("AT");   //可在此处输入设置HC-06蓝牙模块的AT指令。
                          //此AT指令须在HC-06未连接蓝牙状态输入。 
  pinMode(13, OUTPUT);       

  myServo1.attach(3);     //舵机1
  myServo2.attach(5);     //舵机2
  LED_Show();
}
 
void loop(){
    // 通过串口监视器显示HC-06发送的数据
    if( BTserial.available()>0 ){            //如果软件串口有HC-06发来的数据
      String BTserialData = BTserial.readStringUntil('-');  //将软件串口中的数据赋值给变量BTserialData
      Serial.println( BTserialData );         //通过硬件串口监视器显示HC-06发来的数据
      if (BTserialData == "1") {             //判断HC-06发来的数据是否是字符1
        pos = BTserial.parseInt();   // 解析串口数据中的整数信息并赋值给变量pos
        pos1 = pos;
        Serial.println(pos);           // 通过串口监视器显示变量pos数值
        myServo1.write(pos);
        dataIndex = 1;
        LED_Show();
      } 
      else if (BTserialData == "2") {      //第二个舵机
        int pos = BTserial.parseInt();   // 解析串口数据中的整数信息并赋值给变量pos
        Serial.println(pos);           // 通过串口监视器显示变量pos数值
        pos2 = pos;
        myServo2.write(pos);
        dataIndex = 2;
        LED_Show();                     //LED显示
      }
    }
    
    // 将用户通过串口监视器输入的数据发送给HC-06
    if (Serial.available()>0) {            //如果硬件串口缓存中有等待传输的数据
      char serialData =  Serial.read();    //将硬件串口中的数据赋值给变量serialData
      BTserial.print( serialData );         //将硬件串口中的数据发送给HC-06
    }
}

多路程序驱动:

#include <Servo.h>
 
Servo base, fArm, rArm, claw;  //建立4个电机对象
 
int dataIndex = 0;
void setup() {
  base.attach(11);     // base 伺服电机连接引脚11 电机代号'b'
  rArm.attach(10);     // rArm 伺服电机连接引脚10 电机代号'r'
  fArm.attach(9);      // fArm 伺服电机连接引脚9  电机代号'f'
  claw.attach(6);      // claw 伺服电机连接引脚6  电机代号'c'
  Serial.begin(9600);
  Serial.println("Please input serial data.");
}
 
void loop() {
  if (Serial.available()) {  // 检查串口缓存是否有数据等待传输 
    char servoName = Serial.read();   //获取电机指令中电机编号信息
 
    Serial.print("servoName = ");
    Serial.print(servoName);    
    Serial.print(" , ");      
    
    int data = Serial.parseInt();   //获取电机指令中电机角度信息
 
    switch(servoName){ //根据电机指令中电机信息决定对哪一个电机进行角度设置
      case 'b':   // 电机指令b,设置base电机角度
        base.write(data);
        Serial.print("Set base servo value: ");
        Serial.println(data);
        break;
      case 'r':  // 电机指令r,设置rArm电机角度  
        rArm.write(data);
        Serial.print("Set rArm servo value: ");
        Serial.println(data);
        break;
      case 'f':   // 电机指令f,设置fArm电机角度  
        fArm.write(data);
        Serial.print("Set fArm servo value: ");
        Serial.println(data);
        break;
      case 'c':   // 电机指令c,设置claw电机角度  
        claw.write(data);  
        Serial.print("Set claw servo value: ");
        Serial.println(data);
        break;
    }
  }
}


单路程序驱动: 

Servo myservo;  // 创建Servo对象用以控制伺服电机
                 // 很多开发板允许同时创建12个Servo对象
 
int pos = 0;    // 存储伺服电机角度信息的变量
 
void setup() {
  myservo.attach(9);  // Servo对象连接在9号引脚 
  Serial.begin(9600);
}
 
void loop() {
  for (pos = 0; pos <= 180; pos += 45) { // 0度转到180度
    // 每一步增加1度
    myservo.write(pos);              // 告诉伺服电机达到'pos'变量的角度
    Serial.println(pos);
    delay(1000);                       // 等待15毫秒以确保伺服电机可以达到目标角度
  }
  for (pos = 180; pos >= 0; pos -= 45) { // 180度转到0度
    myservo.write(pos);              // 告诉伺服电机达到'pos'变量的角度
    Serial.println(pos);
    delay(1000);                       // 等待15毫秒以确保伺服电机可以达到目标角度
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值