Skip to content
  • Add anything here or just remove it...
yesio.netyesio.net
  • yesio
  • GoSUMO相撲擂台
  • 創新應用與紀實
    • 2026太平洋盃X華紙公益
    • 2025華紙盃支援專頁
  • 應用速查
  • 獎項與肯定

dual2s基礎使用手冊

4
  • 【簡介】dual2s-mini控制器(2026)
  • 【簡介】dual2s-v2控制器(2025)
  • 【基礎】韌體程式學習 | How To
  • 【SWSP】dual2s快速應用系統

程式開發環境設定

3
  • 2026 競賽技術資料
  • dual2s函數庫與開發環境
  • 【進階】dual2s.h函數庫說明

Vibe - dual2s開發版

5
  • 【Vibe】Vibe教學,選用Agent還是Browser呢?
  • 【Vibe】U01. AI 寫韌體容易「翻車」,WHY?
  • 【Vibe】U02. 一位稱職的韌體架構師
  • 【Vibe】U03. 建立你的AI韌體助手/專屬家教
  • 【Vibe】U04. 硬體控制變換練習

ros32控制器

1
  • GoYak – 4Dof全向輪式智慧機器手臂

社群開源專題

9
  • 競賽/活動地圖開源模型說明
  • 【活動】地圖開源模型
  • 【機構】獨角仙主動防禦 / RhinoSUMO
  • 【GoSUMO】外掛套件_機械鏟
  • 【GoSUMO】外掛護甲_2023年式
  • 【車體】ezBot專題/dual2s/esp32
  • 【機構】GoARM組裝-社群創作版
  • 【GoSUMO】外掛護甲_2025年式
  • 【船體】aquaBot雙體船型/SDGs永續

競賽活動相關

2
  • 【活動】地圖開源模型
  • 2026 太平洋盃場地與設備

dual2s單元控制

12
  • 【顯示】狀態燈使用 | ws2812b
  • 【聲音】蜂鳴器 | buzzer
  • 【感測】超音波 | HCSR04
  • 【感測】近紅外線感測 – line | IR3CH
  • 【感測】近紅外線感測 – 相撲 | IR3CH
  • 【制動】DC馬達 | Motor
  • 【制動】舵機 MG995/SG90s | ServoMotor
  • 【感測】電壓監控 | Power
  • 【通訊】PS3搖桿 | PS3 GamePad
  • 【通訊】P3x搖桿控制MG995歸90度
  • 【運動】APP控制模式 | dual2s (2025)
  • 【運動】P3x搖桿(鎖址式) | dual2s (2025)

dual2s微專題

3
  • 【微專題】RFID門控基礎 / dual2s/mini
  • 【組裝】GoSUMO 組裝程序 2025
  • 【組裝】GoARM 2025 組裝程序
View Categories
  • Home
  • 應用速查
  • dual2s基礎使用手冊
  • 程式開發環境設定
  • 【進階】dual2s.h函數庫說明

【進階】dual2s.h函數庫說明

6 min read

簡介 #

我們依據DUAL22-2s的電路規劃特性,提供專用的函數庫以方便【快速應用與學習】的用途。當然,你也可以選擇不使用此函數庫,一樣可以完整地控制DUAL22-2s硬體功能。我們的函數庫完全開放、使用簡明的C/C++語法撰寫,你也可以據此修改更加適合你使用需求的函數庫。

備註:若您已經依據【ArduinoIDE-ESP32編輯環境】一文,完成程式環境的設定,則不需要另外再下載本篇程式碼進行匯入與編譯的工作。


編譯與使用 #

設定:

dual2s函數庫下載、Arduino IDE編譯環境使用方式,請參考此文【ArduinoIDE-ESP32編輯環境】。

範例:

dual2s函數庫的使用範例,請參照【DUAL22-2s開發板】相關應用範例。dual2s函數庫亦可使用於DUAL22 / e32DUAL,以及其他esp32環境中,使用時注意GPIO腳位定義。

程式說明 #

dual2s.h程式碼 #

#ifndef DUAL2S_H
  #define DUAL2S_H
  #include <Arduino.h>
  
  //Buzzer Pitch define
  struct Pitch{
    uint16_t Do_3=131, Re_3=147, Mi_3=165, Fa_3=175, Sol_3=196, La_3=220, Si_3=247;
    uint16_t Do_4=262, Re_4=294, Mi_4=330, Fa_4=349, Sol_4=392, La_4=440, Si_4=494;
    uint16_t Do_5=523, Re_5=587, Mi_5=659, Fa_5=698, Sol_5=784, La_5=880, Si_5=988;
  };
  
/*** MOTOR ***/
  class Motor{
    private:
      uint16_t _m_frequency = 1000;
      uint8_t _m_resolution = 10;
      uint8_t _pin_a;
      uint8_t _pin_b;
      uint8_t _channel_a;
      uint8_t _channel_b;

    public:
      typedef enum{
        STOP,
        CW,
        CCW
      } Motor_Action;

      Motor(uint8_t pin_a, uint8_t pin_b, uint8_t channel_a, uint8_t channel_b);
      void act(uint8_t dir, uint16_t speed);
      void stop();
  };

/*** BUZZER ***/
  class Buzzer{
    private:
      byte _pin;
      byte _channel;  //esp32 pwm channel 0 - 15

    public:
      Buzzer(byte pin, byte channel);
      void noTone();
      void tone(uint16_t frequency, uint16_t duration, uint8_t volume);
      void alarm();
  };

/*** UltraSonic ***/
  class HCSR04{
    private:
      uint8_t _pin_echo;
      uint8_t _pin_trig;

    public:
      typedef enum{
        USC_FRONT,
        USC_LEFT,
        USC_RIGHT
      } USC_DIR;

      HCSR04(uint8_t pin_echo, uint8_t pin_trig);
      bool ObjSeeking(uint8_t thresh);
      float ObjDistance();
      unsigned long probing();
  };  

/*** IR3CH ***/
  class IR3CH{
    private:
      uint8_t _pin_L;
      uint8_t _pin_M;
      uint8_t _pin_R;

    public:
      IR3CH(uint8_t pin_L, uint8_t pin_M, uint8_t pin_R);
      byte ReadTCRT(uint8_t TH, bool DEBUG);

  }; 

/*** POWER ***/
  class Power{
    private:
      uint8_t _pin;
    public:
      Power(uint8_t pin);
      float voltage();
  };   

/*** GoSUMO ***/
  class GoSUMO{
    private:
      uint16_t _m_frequency = 1000;
      uint8_t _m_resolution = 10;
      uint8_t _pin_m1A = 14;  uint8_t _pin_m1B = 32;
      uint8_t _pin_m2A = 12;  uint8_t _pin_m2B = 33;
      uint8_t _pin_m3A = 25;  uint8_t _pin_m3B = 26;
      uint8_t _pin_m4A = 23;  uint8_t _pin_m4B = 22;

      uint8_t _channel_1a = 8; uint8_t _channel_1b = 9; 
      uint8_t _channel_2a = 10; uint8_t _channel_2b = 11;
      uint8_t _channel_3a = 12; uint8_t _channel_3b = 13;
      uint8_t _channel_4a = 14; uint8_t _channel_4b = 15;

    public:
      typedef enum{
        FORWARD,
        BACKWARD,
        GO_LEFT,
        GO_RIGHT
      } Motion;

      GoSUMO();
      void act(uint8_t motion, uint16_t speed);
      void stop();

  };


#endif

dual2s.cpp程式碼

#include <dual2s.h>


/*** GoSUMO ***/
GoSUMO::GoSUMO(){
  pinMode(_pin_m1A, OUTPUT); pinMode(_pin_m1B, OUTPUT);
  pinMode(_pin_m2A, OUTPUT); pinMode(_pin_m2B, OUTPUT);
  pinMode(_pin_m3A, OUTPUT); pinMode(_pin_m3B, OUTPUT);
  pinMode(_pin_m4A, OUTPUT); pinMode(_pin_m4B, OUTPUT);

  ledcSetup(_channel_1a, _m_frequency, _m_resolution);   ledcSetup(_channel_1b, _m_frequency, _m_resolution);
  ledcAttachPin(_pin_m1A, _channel_1a);  ledcAttachPin(_pin_m1B, _channel_1b);
  ledcSetup(_channel_2a, _m_frequency, _m_resolution);   ledcSetup(_channel_2b, _m_frequency, _m_resolution);
  ledcAttachPin(_pin_m2A, _channel_2a);  ledcAttachPin(_pin_m2B, _channel_2b);
  ledcSetup(_channel_3a, _m_frequency, _m_resolution);   ledcSetup(_channel_3b, _m_frequency, _m_resolution);
  ledcAttachPin(_pin_m3A, _channel_3a);  ledcAttachPin(_pin_m3B, _channel_3b);
  ledcSetup(_channel_4a, _m_frequency, _m_resolution);   ledcSetup(_channel_4b, _m_frequency, _m_resolution);
  ledcAttachPin(_pin_m4A, _channel_4a);  ledcAttachPin(_pin_m4B, _channel_4b);
}

void GoSUMO::act(uint8_t motion, uint16_t speed){
  if(motion == FORWARD){
    ledcWrite(_channel_1a, 0); ledcWrite(_channel_1b, speed); //Moto-1
    ledcWrite(_channel_3a, 0); ledcWrite(_channel_3b, speed); //Moto-3
    ledcWrite(_channel_2a, speed); ledcWrite(_channel_2b, 0); //Moto-2
    ledcWrite(_channel_4a, speed); ledcWrite(_channel_4b, 0); //Moto-4 
  }
  else if(motion == BACKWARD){
    ledcWrite(_channel_1a, speed); ledcWrite(_channel_1b, 0); //Moto-1
    ledcWrite(_channel_3a, speed); ledcWrite(_channel_3b, 0); //Moto-3
    ledcWrite(_channel_2a, 0); ledcWrite(_channel_2b, speed); //Moto-2
    ledcWrite(_channel_4a, 0); ledcWrite(_channel_4b, speed); //Moto-4 
  }
  else if(motion == GO_LEFT){
    ledcWrite(_channel_1a, speed); ledcWrite(_channel_1b, 0); //Moto-1
    ledcWrite(_channel_3a, speed); ledcWrite(_channel_3b, 0); //Moto-3
    ledcWrite(_channel_2a, speed); ledcWrite(_channel_2b, 0); //Moto-2
    ledcWrite(_channel_4a, speed); ledcWrite(_channel_4b, 0); //Moto-4  
  }
  else if(motion == GO_RIGHT){
    ledcWrite(_channel_1a, 0); ledcWrite(_channel_1b, speed); //Moto-1
    ledcWrite(_channel_3a, 0); ledcWrite(_channel_3b, speed); //Moto-3
    ledcWrite(_channel_2a, 0); ledcWrite(_channel_2b, speed); //Moto-2
    ledcWrite(_channel_4a, 0); ledcWrite(_channel_4b, speed); //Moto-4 
  }
}
void GoSUMO::stop(){
    ledcWrite(_channel_1a, 0); ledcWrite(_channel_1b, 0); //Moto-1
    ledcWrite(_channel_3a, 0); ledcWrite(_channel_3b, 0); //Moto-3
    ledcWrite(_channel_2a, 0); ledcWrite(_channel_2b, 0); //Moto-2
    ledcWrite(_channel_4a, 0); ledcWrite(_channel_4b, 0); //Moto-4  
}

/*** MOTOR ***/
Motor::Motor(uint8_t pin_a, uint8_t pin_b, uint8_t channel_a, uint8_t channel_b){
  _pin_a = pin_a; 
  _pin_b = pin_b;
  _channel_a = channel_a;
  _channel_b = channel_b;

  //The _channel was used.
  if (ledcRead(_channel_a)) { log_e("channel %d is already in use", ledcRead(_channel_a)); return; }
  if (ledcRead(_channel_b)) { log_e("channel %d is already in use", ledcRead(_channel_b)); return; }

  pinMode(_pin_a, OUTPUT);
  pinMode(_pin_b, OUTPUT);

  ledcSetup(_channel_a, _m_frequency, _m_resolution);
	ledcSetup(_channel_b, _m_frequency, _m_resolution);
  ledcAttachPin(_pin_a, _channel_a);    
  ledcAttachPin(_pin_b, _channel_b);
}

void Motor::act(uint8_t dir, uint16_t speed){
  if(dir == CW){  ledcWrite(_channel_a, speed); ledcWrite(_channel_b, 0);  }
  else if(dir == CCW){  ledcWrite(_channel_a, 0); ledcWrite(_channel_b, speed);  }
}

void Motor::stop(){  ledcWrite(_channel_a, 0); ledcWrite(_channel_b, 0);  }



/*** ULTRASONIC ***/
HCSR04::HCSR04(uint8_t pin_echo, uint8_t pin_trig){
  _pin_echo = pin_echo;
  _pin_trig = pin_trig;
  pinMode(_pin_trig, OUTPUT); 
  pinMode(_pin_echo, INPUT);   
}

unsigned long HCSR04::probing(){
  digitalWrite(_pin_trig, HIGH);
  delayMicroseconds(5);      //維持trig腳位在高電位5微秒
  digitalWrite(_pin_trig, LOW);
  return pulseIn(_pin_echo, HIGH);
}

float HCSR04::ObjDistance(){
  float d = 0.0;
  d = probing()/58.0; //計算物件的距離
  return d;
}

bool HCSR04::ObjSeeking(uint8_t thresh){
  //int fightThresh = thresh*58; //單位為公分
  //long distance = probing(); //讀取障礙物的距離
  if(probing() < (thresh*58)) { return true; } //物體進入範圍
  else { return false; }  //物體不在範圍之內
}

/*** IR3CH ***/
IR3CH::IR3CH(uint8_t pin_L, uint8_t pin_M, uint8_t pin_R){
  _pin_L = pin_L;
  _pin_M = pin_M;
  _pin_R = pin_R;

  pinMode(_pin_L, INPUT);
  pinMode(_pin_M, INPUT);
  pinMode(_pin_R, INPUT);
}

byte IR3CH::ReadTCRT(uint8_t TH, bool DEBUG){
  byte _bTrace = 0;
  
  if(analogRead(_pin_R) > TH) { _bTrace = _bTrace | B001; }
  else { _bTrace = _bTrace & B110; }
  
  if(analogRead(_pin_M) > TH) { _bTrace = _bTrace | B010; }
  else { _bTrace = _bTrace & B101; }
  
  if(analogRead(_pin_L) > TH) { _bTrace = _bTrace | B100; }
  else { _bTrace = _bTrace & B011; }
  
  /* 讀取類比數值,並將3CH結果輸出至串列視窗  */
  if (DEBUG){
  Serial.print(analogRead(_pin_L));
  Serial.print("(LEFT) / ");
  Serial.print(analogRead(_pin_M));
  Serial.print("(Middle) / ");
  Serial.print(analogRead(_pin_R));
  Serial.print("(RIGHT)");
  Serial.println(_bTrace);
  Serial.println("----");
  delay(1000);
  }
  /*-------------------------------------------------------------*/
  
  return _bTrace;
}

/*** BUZZER ***/
Buzzer::Buzzer(byte pin = 15, byte channel = 15){
  _pin = pin;
  _channel = channel;
  pinMode(_pin, OUTPUT);
}

void Buzzer::alarm(){
  tone(800, 200, 30); 
}

void Buzzer::noTone(){
   ledcDetachPin(_pin);
   ledcWrite(_channel, 0); 
}

void Buzzer::tone(uint16_t frequency, uint16_t duration, uint8_t volume){
  ledcSetup(_channel, frequency, 8);
  ledcAttachPin(_pin, _channel);
  ledcWrite(_channel, volume);
  if (duration) {
    delay(duration);
    noTone();
  } 
}

/*** POWER ***/
Power::Power(uint8_t pin){
  _pin = pin;
  pinMode(_pin, INPUT);
  analogSetAttenuation(ADC_11db); //衰減值3.6v
  analogSetWidth(12); //解析度10bits
}

float Power::voltage(){
  //ADC解析度為12bits (4096階)
  //ADC衰減值為3.6V
  //分壓比為~0.25 (目標端電阻100 / 量測端電阻33)
  float _fVal = (analogRead(_pin)*0.0009)/0.25;
  return _fVal;
}
Updated on 24 8 月, 2026

What are your Feelings

  • Happy
  • Normal
  • Sad

Share This Article :

  • Facebook
  • X
  • LinkedIn
  • Pinterest
dual2s函數庫與開發環境2026 競賽技術資料

Powered by BetterDocs

發佈留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

大綱 outlines
  • 簡介
  • 編譯與使用
  • 程式說明
    • dual2s.h程式碼
Copyright 2026 © 宏川智控有限公司
  • yesio
  • GoSUMO相撲擂台
  • 創新應用與紀實
    • 2026太平洋盃X華紙公益
    • 2025華紙盃支援專頁
  • 應用速查
  • 獎項與肯定
  • -
  • Newsletter