< All Topics
Print

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

簡介

我們依據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;
}
Tags:
Table of Contents