SG-90伺服馬達簡介

伺服馬達是一種可精確控制角度的馬達,常用於機器人、遙控車等各種領域,以SG90為例,接腳配置如下:

  1. 棕色:接地(GND)
  2. 紅色:電源(VCC,通常接 5V )
  3. 橙色:信號線(Signal)

伺服馬達一般透過 PWM 信號控制定位的角度,脈波寬度通常在 500μs 到 2400μs 之間,對應 0 到 180 度的定位角度。

基本範例:

#include <ESP32Servo.h>  // 引用ESP32Servo函式庫
Servo MyServo;           // 建立SERVO物件
int servoPin = 15;       // 伺服馬達信號接腳

void setup() {
  MyServo.attach(servoPin, 500, 2400);  // 初始化伺服馬達,// SG90:500us~2400us
}

void loop() {
  MyServo.write(0);    // 定位到 0 度
  delay(1000);
  MyServo.write(45);   // 定位到 45 度
  delay(1000);
  MyServo.write(90);   // 定位到 90 度
  delay(1000);
  MyServo.write(135);  // 定位到 135 度
  delay(1000);
  MyServo.write(180);  // 定位到 180 度
  delay(1000);
  MyServo.write(135);  // 定位到 135 度
  delay(1000);
  MyServo.write(90);   // 定位到 90 度
  delay(1000);
  MyServo.write(45);   // 定位到 45 度
  delay(1000);
  MyServo.write(0);    // 定位到 0 度
  delay(1000);
}

由監看視窗輸入角度範例:

//---------------------------------------------------------------------------------
#include <ESP32Servo.h>  // 引用ESP32Servo函式庫
Servo MyServo;           // 建立SERVO物件
int servoPin = 15;       // 伺服馬達信號接腳
int angle = 0;           // 伺服馬達定位角度(0~180),初始值為0
//---------------------------------------------------------------------------------
int input = 0;           // 串列埠輸入值
//---------------------------------------------------------------------------------

void setup() {
  //--------------------------------------------------------------
  Serial.begin(9600);           // 啟動串列埠監看視窗  
  //--------------------------------------------------------------  
  MyServo.attach(servoPin, 500, 2400);  // 初始化伺服馬達,// SG90:500us~2400us
  MyServo.write(angle);         // 移動到定位角度  
  //--------------------------------------------------------------    
}

void loop() {
  //----------------------------------------------------------
  //串列埠監看視窗輸入
  //----------------------------------------------------------
  if (Serial.available()) //若串列埠有輸入資料,則執行下列程式區塊
  {
    input = readNumber();
    if (input >= 0 && input <= 180)
    {
      angle = input;
      MyServo.write(angle);     // 移動到定位角度
    }
    else
    {
      //若輸入字串無效(其他)
      Serial.println("Unknown range.");
      Serial.println("Please enter an angle(0~180):");   // 輸入提示
    }
  }

}

// 讀取一個整數
int readNumber()
{
  while (!Serial.available());  // 等待串列埠輸入
  String input = Serial.readStringUntil('\n');  //讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
  input.trim();                 //去除輸入字串前後的空白字元
  Serial.println(input);        //印出輸入字串
  return input.toInt();         //轉換為整數
}

由監看視窗輸入角度,並在LCD上顯示結果範例:

//---------------------------------------------------------------------------------
#include <LiquidCrystal_I2C.h>      // 引用LiquidCrystal_I2C函式庫
LiquidCrystal_I2C lcd(0x27, 16, 2); // 建立LiquidCrystal_I2C物件,名稱為lcd
//---------------------------------------------------------------------------------
#include <ESP32Servo.h>             // 引用ESP32Servo函式庫
Servo MyServo;                      // 建立SERVO物件
int angle = 0;                      // 伺服馬達定位角度(0~180),初始值為0
//---------------------------------------------------------------------------------
int input = 0;                      // 串列埠輸入值
//---------------------------------------------------------------------------------

void setup() {
  //--------------------------------------------------------------
  Serial.begin(9600);           // 啟動串列埠監看視窗
  //--------------------------------------------------------------
  MyServo.attach(15,500,2400);  // SG90:500us~2400us
  MyServo.write(angle);         // 移動到定位角度  
  //--------------------------------------------------------------
  lcd.init();                   // 初始化lcd
  lcd.backlight();              // 開啟背光
  lcd.setCursor(0,0);           // 定位在(0,0)
  lcd.print("Angle:");          // 印出文字"Angle:"
  print_angle();                // 在LCD上顯示定位角度
  //--------------------------------------------------------------
}

void loop() {
  //----------------------------------------------------------
  //串列埠監看視窗輸入
  //----------------------------------------------------------
  if (Serial.available()) //若串列埠有輸入資料,則執行下列程式區塊
  {
    input = readNumber();
    if (input >= 0 && input <= 180)
    {
      angle = input;
      MyServo.write(angle);     // 移動到定位角度 
      print_angle();            // 在LCD上顯示定位角度
    }
    else
    {
      //若輸入字串無效(其他)
      Serial.println("Unknown range.");
      Serial.println("Please enter an angle(0~180):");   // 輸入提示
    }
  }

}

// 讀取一個整數
int readNumber()
{
  while (!Serial.available());  // 等待串列埠輸入
  String input = Serial.readStringUntil('\n');  //讀取一行的輸入資料,直到換行符號為止(按下enter鍵)
  input.trim();                 //去除輸入字串前後的空白字元
  Serial.println(input);        //印出輸入字串
  return input.toInt();         //轉換為整數
}

void print_angle()  // 印出伺服馬達定位角度
{
  lcd.setCursor(6,0);
  lcd.print("   "); 
  
  if(angle>=0 && angle<10)
  {
    lcd.setCursor(8,0);
  }
  if(angle>=10 && angle<100)
  {
    lcd.setCursor(7,0);
  }    
  if(angle>=100 && angle<=180)
  {
    lcd.setCursor(6,0);
  }    
  lcd.print(angle);         
}

作業練習:請用ESP32改寫下列題目。

01-控制科實作試題

一、試題說明:
  1.本試題使用ESP32微控制器、1602 I2C LCD顯示器、SG90伺服馬達及外接按鈕開關,由按鈕開關控制伺服馬達的啟動、停止及改變旋轉方向,由LCD顯示器呈現受控狀態。參考接線如附件電路圖。
  2.ESP32 微控制器可自行決定欲使用的I/O接腳、電源接線等位置。
  3.1602 I2C LCD顯示器隨操作狀態的不同,即時更新受控資訊。
  4.SG90伺服馬達在0 ~ 180度之間的定位角度,做順時針或逆時針方向的往復循環。
  5.外接按鈕開關請在自備的麵包板上完成接線,可自行決定使用外部或者內部Pull up、Pull Down電阻等驅動方式。
  6.硬體供電方式:可自行決定使用電腦USB供電或使用外接直流電源供應器供電,以能正常完成本試題的動作要求為主。
  7.本試題可使用相關函式庫(如:LiquidCrystal I2C、ESP32Servo等)。
二、動作要求:
  1.ESP32微控制器開機啟動後按下主板的Reset按鈕後,回復到初始狀態
    (1)伺服馬達狀態:停止。
    (2)定位角度:0度。
    (3)旋轉方向:順時針。
  2.按鈕開關短按:每按一下,伺服馬達改變運轉或停止狀態一次,不改變當下位置及旋轉方向。
  3.按鈕開關長按:每按一下(1秒以上),伺服馬達改變旋轉方向一次,不改變當下位置及運轉或停止狀態。
  4.伺服馬達運轉時,每0.3秒移動定位角度5度,在0 ~ 180度之間做順時針或逆時針方向往復循環。(0°→5°→10°→……→175°→180°→175°→……→10°→5°→0°)
  5.1602 I2C LCD顯示器隨操作狀態不同,在相對應的區塊上即時更新(平滑不停頓)顯示資訊:
    (1)伺服馬達狀態:停止顯示Stop、運轉顯示Running。
    (2)定位角度:正確顯示當下所在的位置,在0 ~ 180度之間。
    (3)旋轉方向:順時針顯示C.W.、逆時針顯示C.C.W.。

成果影片:

控制115乙 黃郁善
控制115乙 李宥嫻
控制115乙 賴品媛
控制115乙 宋允升
控制115甲 王承鈞
控制115甲 高聖棠