見出し画像

M5StackでQC3.0を制御してみる

割引あり

このまとめは M5Stackアドベントカレンダー 2024の19日目の記事です。
本記事は有料記事ですが、全文無料で公開します。なにかのお役にたったら購入(投げ銭)していただけると筆者が喜びます。


はじめに

以前、ガジェット分解マガジンの記事でQuick Charge3.0の動作を調査してまとめました。
この記事では、調査した内容にしたがって、実際にM5Stack(ESP32)を使ってQC3.0対応USB充電器の出力電圧を制御してみます。

ハードウエアの構成

D+/D-端子に0V/0.6V/3.3Vの3値を印加するために、IOピン(3.3V)を2本使用して10kΩと2.2kΩの抵抗分割で0.6Vを生成します。実験回路はD+/D-それぞれ2本で合計4本のIOを使用したシンプルな構成です。
QC3.0ではホスト(充電器)のD+/D-電圧の監視が必要なので、DP_H/DM_HをADC入力に対応したポートに割り当てます。

D+(DP)/D-(DM)に抵抗分割で3値を印加する回路

M5Stackとブレッドボードを使用して作成した実験回路は以下です。

実際に動作確認に使用した実験回路

ソフトウエアの作成

ソフトウエアはArduino IDEで作成しました。
実際に動作に使用したスケッチから説明用に主要部分を抜粋します。

D+/D-への印加電圧設定

D+/D-への印加電圧設定はDP_H、DP_L、DM_H、DM_LのH/Lの組合せで行います。電圧監視を行う場合はポートを入力(ハイインピーダンス)に設定します。以下はD+ポートの設定例です。

void set_DP(uint8_t state){
  pinMode(DP_H, OUTPUT);
  pinMode(DP_L, OUTPUT);

  if(state == QC_0V){
    digitalWrite(DP_H, LOW);
    digitalWrite(DP_L, LOW);
  }else if(state == QC_600mV){
    digitalWrite(DP_H, HIGH);
    digitalWrite(DP_L, LOW);
  }else if(state == QC_3300mV){
    digitalWrite(DP_H, HIGH);
    digitalWrite(DP_L, HIGH);
  }
}

接続された充電器のポートタイプ検出

QC3.0のプロトコルに従い、接続された充電器のポートタイプの検出を行います。
各判定ステージで電圧の印加と確認を行います。戻り値は検出したポートタイプです。

uint8_t detect_Charger(){
  set_DP(QC_HIZ);
  set_DM(QC_HIZ);

  /*** stage 1: Check BC1.2 DCP ***/
  set_DM(QC_0V);
  DP_VAL = analogRead(DP_H);
  if(DP_VAL >= L_th){
    set_DM(QC_HIZ);
    return BC_NA;
  }else{
    /*** stage 2: set host to QC3 ***/
    set_DM(QC_HIZ);
    set_DP(QC_600mV);
    delay(1500);

    /*** stage 3: set devide to QC3 ***/
    int timeout = 20000;
    while(true){
      DM_VAL = analogRead(DM_H);
      if(DM_VAL < L_th){
        break;
      }
      delayMicroseconds(100);
      timeout--;
      if(timeout <= 0){
        return BC_DCP;
        break;
      }
    }
  }
  return QC3;
}

VBUS出力電圧設定

D+/D-電圧の組合せでVBUS出力電圧を設定します。組合せはちちらの記事にあります。

bool set_VBUS(uint8_t mode){
  QC_MODE = mode;
  switch(mode){
  case QC_5V:
    set_DP(QC_600mV);
    set_DM(QC_0V);
    break;
  case QC_9V:
    set_DP(QC_3300mV);
    set_DM(QC_600mV);
    break;
  case QC_12V:
    set_DP(QC_600mV);
    set_DM(QC_600mV);
    break;
  case QC_20V:
    set_DP(QC_3300mV);
    set_DM(QC_3300mV);
    break;
  case QC_VAR:
    set_DP(QC_600mV);
    break;
  default:
    set_DP(QC_600mV);
    set_DM(QC_0V);
    break;
 }
  return true;
}

連続可変動作モード処理

D+/D-に200usのバルスを出力することで、200mVステップで出力電圧の増減ができます。

void var_inc(){
  set_DP(QC_3300mV);
  delayMicroseconds(200);
  set_DP(QC_600mV);
}

void var_dec(){
  set_DM(QC_600mV);
  delayMicroseconds(200);
  set_DM(QC_3300mV);
}

実機動作確認

これらの関数を組み合わせて実機で動作することを確認しました

void setup() {
  detect_Charger();
}
void loop() {
  set_VBUS(QC_9V);
  delay(3000);
  set_VBUS(QC_VAR);
  delay(1000);
  for(int i = 0; i < 5; i++){
    var_inc();
   delay(1000);
  }
  for(int i = 0; i < 5; i++){
    var_dec();
   delay(1000);
  }
}

まとめ

上記のコードは例外処理等は全く配慮していない必要最低限となります。
全ソースコードは筆者のGitHubのリポジトリに置いてあります。

QC3.0対応の充電器は20W品であれば1000円程度で入手できます。
電子工作で使用できる可変電圧電源が簡単にできますので試してみてください。
メリークリスマス!

ここから先は

0字

期間限定!PayPayで支払うと抽選でお得

この記事が参加している募集

よろしければサポートお願いします。分解のためのガジェット購入に使わせていただきます!