Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Controlling “QuickCharge” with M5Stack / M5Stac...

Controlling “QuickCharge” with M5Stack / M5StackでUSB充電のQuickChargeを制御

Transcript

  1. Masawo Yamazaki (@tomorrow56) • 電子回路設計エンジニア Circuit designer • 趣味: ガジェットの分解

    Teardown of gadjets ◦ note: https://note.com/tomorrow56 • 最近は3Dプリンタ成分が多め ◦ I've been spending a lot of time with my 3D printer X(Twitter): @tomorrow56
  2. QuickCharge(QC)とは - What is QuickCharge? - • A proprietary fast

    charging standard from smartphone SoC manufacturer Qualcomm • QC3.0 allows a voltage of 5V or more (3.5 to 20V) to be supplied from a USB-A port • USB PD controllers often also support QC3, making it popular on the market Quick Charge version list
  3. QC3.0のプロトコル - QC3.0 Protocol - • 4つのステージで充電器が出力モードを判別する The charger determines

    the output mode in four stages Stage1: Host connects to device via USB BC1.2 Stage2: Notifies host that device is QC3.0 compatible Stage3: Notifies device that host is QC3.0 compatible Stage4: Device notifies host of the desired output voltage
  4. QC3.0のプロトコル - QC3.0 Protocol - • 連続モード: 200mVステップで出力電圧を可変するモード Continuous Mode:

    Mode to change output voltage in 200mV steps ◦ 出力電圧のインクリメント/Output Voltage Increment (+200mV) デバイスはD+を3.3Vに200usの間引き上げてパルスをホストに送り、次にD+を0.6Vに戻す The device pulses the host by raising D+ to 3.3V for 200us, then lowers D+ back to 0.6V ◦ 出力電圧のデクリメント/Decrement Output Voltage (-200mV) デバイスはD-を0.6Vに200usの間引き下げてパルスをホストに送り、次にD-を3.3Vに戻す The device sends a pulse to the host by pulling D- down to 0.6V for 200us, then returning D- to 3.3V
  5. QC3.0のプロトコルを実装する - Implementing the QC3.0 protocol - • Hardware ◦

    D+/D-端子に印加する電圧は0V/0.6V/3.3Vの3値 The voltage of D+/D- have three values: 0V/0.6V/3.3V ◦ 0.6VはIOピンを2本使用し抵抗分割で生成→D+/D-それぞれ2本のIOで制御可能 0.6V is generated by resistor division using two IO pins → It can be controlled with two IOs each for D+/D-
  6. QC3.0のプロトコルを実装する - Implementing the QC3.0 protocol - Software Pin Definition

    #define DP_H_PIN 13 //GPIO13, ADC2_CH4, 10k #define DP_L_PIN 16 //GPIO16, 2.2k #define DM_H_PIN 26 //GPIO26, DAC_2, ADC2_CH9, 10k #define DM_L_PIN 17 //GPIO17, 2.2k Setting the voltage applied to D+ (Same for D-) void set_DP(uint8_t state){ if(state == QC_HIZ){ pinMode(DP_H, INPUT); pinMode(DP_L, INPUT); }else{ 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); }else{ digitalWrite(DP_H, LOW); digitalWrite(DP_L, LOW); } } } Host port type detection uint8_t detect_Charger(){ set_DP(QC_HIZ); set_DM(QC_HIZ); /*** stage 1: Check BC1.2 DCP ***/ set_DM(QC_0V); DP_VAL = readVoltage(analogRead(DP_H)) * 1000; if(DP_VAL >= 325){ 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 ***/ DM_VAL = readVoltage(analogRead(DM_H)) * 1000; int timeout = 20000; while(true){ DM_VAL = readVoltage(analogRead(DM_H)) * 1000; if(DM_VAL < 325){ break; } delayMicroseconds(100); timeout--; if(timeout <= 0){ return BC_DCP; break; } } } return QC3; }
  7. QC3.0のプロトコルを実装する - Implementing the QC3.0 protocol - Software VBUS output

    voltage setting bool set_VBUS(uint8_t mode){ if(HOST_TYPE != QC3){ return false; } QC_MODE = mode; switch(mode){ case QC_5V: set_DP(QC_600mV); set_DM(QC_0V); VBUS_VAL = 5000; break; case QC_9V: set_DP(QC_3300mV); set_DM(QC_600mV); VBUS_VAL = 9000; break; case QC_12V: set_DP(QC_600mV); set_DM(QC_600mV); VBUS_VAL = 12000; break; case QC_20V: set_DP(QC_3300mV); set_DM(QC_3300mV); VBUS_VAL = 20000; break; case QC_VAR: set_DP(QC_600mV); set_DM(QC_3300mV); break; default: set_DP(QC_600mV); set_DM(QC_0V); VBUS_VAL = 5000; break; } return true; } Continuous mode control void var_inc(){ if(QC_MODE != QC_VAR){ return; } set_DP(QC_3300mV); delayMicroseconds(200); set_DP(QC_600mV); delay(100); VBUS_VAL = VBUS_VAL + 200; if(VBUS_VAL > QC3_VAR_MAX){ VBUS_VAL = QC3_VAR_MAX; } } void var_dec(){ if(QC_MODE != QC_VAR){ return; } set_DM(QC_600mV); delayMicroseconds(200); set_DM(QC_3300mV); delay(100); VBUS_VAL = VBUS_VAL - 200; if(VBUS_VAL < QC3_VAR_MIN){ VBUS_VAL = QC3_VAR_MIN; } }