2023年7月24日 星期一

Servo Motors - ESP32 Bluetooth SPP control

Purpose:

ESP32 uses BT SPP Profile to connect with mobile phones or PCs and transmit strings through BT function to perform specific functional actions for functional strings to drive servo motor

This project shows how to control position of Servo Motor using ESP32 Microcontroller to move it from 0° to 180° or from 180° to 0° or set your own values. You need to download the libary that specifically works with Arduino IDE 2.

MG995 servo簡介
MG995 biped robot manipulator, remote control car, remote control boat, gasoline engine special steering gear, all metal gears, very wear-resistant! 13kg torque, very powerful!
All metal gear frosted shell products, genuine potentiometers for potentiometers, the maximum pulling force is 13 kg!
All ten procedures are tested. Unlike the plastic casing products of the sub-factory on the market, the potentiometer is also cut corners, easy to damage, short life, and the pulling force is not 13 kg!
MG995 雙足機器人機械手、遙控車、遙控船、汽油機專用舵機,全金屬齒輪,非常耐磨!13千克扭力,非常給力!
全金屬齒輪磨砂外殼產品,電位器用的正品電位器,最大拉力13公斤!全部十道工序檢測,不像市面上副廠的塑料外殼的產品,電位器也是偷工減料,很容易損壞,壽命很短,拉力也沒有13千克!
請注意:360度舵機為連續轉動舵機,相當於一個減速電機,只能控制速度,不能控制角度!
MG995 servo規格
產品尺寸:40.7*19.7*42.9mm
產品重量:55g
工作扭矩:13KG/cm
反應轉速:53-62R/M
使用溫度:-30~+60
死區設定:4微秒
插頭類型:JP、FUTABA通用
轉動角度:最大360度
工作電流:100mA
使用電壓:3-7.2V
結構材質:金屬銅齒、空心杯電機、雙滾珠軸承
無負載操作速度:
附件包含:舵盤、線長30CM、固定螺釘、減振膠套及鋁套等附件
適用範圍:1:10和1:8平跑車、越野車、卡車、大腳車、攀爬車、雙足機器人、機械手、遙控船,適合50級-90級甲醇固定翼飛機以及26cc-50cc汽油固定翼飛機等模型
ESP32 Code:

#include <ESP32Servo.h>
#include <BluetoothSerial.h>
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t LEDFlag=1;
  uint8_t BTFlag = 0;
  uint8_t ServoFlag = 0;
 
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//------------------------------------------------
#define LED_BUILTIN 2
BluetoothSerial SerialBT;
//------------------------------------------------
Servo myservo;  // create servo object to control a servo
// Recommended PWM GPIO pins on the ESP32 include 2,4,12-19,21-23,25-27,32-33
int servoPin = 13;
//-------------------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  pinMode(LED_BUILTIN, OUTPUT);
  SerialBT.begin("BT_Servo");// BTName
  myservo.setPeriodHertz(50);    // standard 50 hz servo
  myservo.attach(servoPin, 500, 2400); // attaches the servo on pin 13 to the servo object
}
//-----------------------------------------
void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if(flag.LEDFlag == 1)
    {
      digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
      vTaskDelay(300);
      digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
      vTaskDelay(300);
    }
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
          //傳輸給藍芽
          SerialBT.println(Uart.line);
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    while (SerialBT.available())
    {
      //讀取藍芽資料
      String BTdata = SerialBT.readString();
      //顯示在序列視窗
      Serial.println(BTdata);
      //char charBuf[BTdata.length() + 1];
      //BTdata.toCharArray(charBuf, BTdata.length());
      BTprocessCommand(BTdata); // do something with the command
      //processCommand(charBuf); // do something with the command
    }//while (BT.available())

  }
}
void BTprocessCommand(String data)
{
  if (data == "100")
  {
    Serial.println(F("SERVO_100"));
    myservo.write(100);
  }
  if (data == "10")
  {
    Serial.println(F("SERVO_10"));
    myservo.write(10);
    //myservo.detach();
  }
  if (data == "180")
  {
    Serial.println(F("SERVO_180"));
    myservo.write(180);
  }
  if (data == "50")
  {
    Serial.println(F("SERVO_50"));
    myservo.write(50);
    //myservo.detach();
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230710"));
  }
  //-------------- Servo --------------------
  if (strstr(data, "SERVO_5")!= NULL)
  {
    Serial.println(F("SERVO_5"));
    myservo.write(5);
    //myservo.detach();
  }
  if (strstr(data, "SERVO_10")!= NULL)
  {
    Serial.println(F("SERVO_10"));
    myservo.write(10);
  }
  if (strstr(data, "SERVO_50")!= NULL)
  {
    Serial.println(F("SERVO_50"));
    myservo.write(50);
  }
  if (strstr(data, "SERVO_100")!= NULL)
  {

    Serial.println(F("SERVO_100"));
    myservo.write(100);
  }
  if (strstr(data, "SERVO_180")!= NULL)
  {
    Serial.println(F("SERVO_180"));
    myservo.write(180);
  }
  if (strstr(data, "SERVO_270")!= NULL)
  {
    Serial.println(F("SERVO_270"));
    myservo.write(270);
  }
}
//------------------------------------------

Circuit:





Serial_demo:
利用Arduino IDE 2的serial monitor 下指令給ESP32進行角度變換
Use the serial monitor of Arduino IDE 2 to command the ESP32 to perform angle transformation

BT_demo:

利用手機APP Arduino BlueControl透過藍芽傳輸給ESP32進行角度變換
Use the mobile APP Arduino BlueControl to transmit the angle to ESP32 through Bluetooth
YouTube Demonstration:

沒有留言:

張貼留言