Station インターフェース電源管理関連APIとケースプログラムです。
Station の USB-A ポートは出力電流情報の取得のみをサポートしており、GPIO34 を通じて INA199Ax1 の出力電圧値を取得して換算することで USB-A の出力電流値を求める必要があります。この電圧値は USB-A の出力電流値とほぼ比例しています。
上記の原理図から分かるように、INA199x1 の基準電圧(REF)の理想値は:(R54\(R54+R55))MCU_VDD
,すなわち 1\2MCU_VDD
です。しかし、ハードウェア部品の許容誤差と本設計構造が精密構造ではないため、この基準電圧(REF)の実際の値は実測が必要です。
INA199 の データシートを参照すると,分流抵抗(すなわち上図の $R_{44}$)の両端の電圧差を検出して電流を測定し、内部で設定されたゲイン(INA199x1 の場合50V/V
),に基づいて、実時間で検出した電流信号を OUT ピンから対応するアナログ電圧信号(すなわち以下のコードの usb_vol
)。に変換して出力することがわかります。USB-A ポートが無負荷の場合、INA199x1 の出力電圧値は基準電圧(REF)の実際の値に近づき、すなわち以下のコードの usb_vref
です。OUT ピンの出力電圧の計算式は usb_vol = usb_vref + Io * (R44*50)
で,換算すると Io = (usb_vol - usb_vref) \ (R44*50)
となります。
具体的な実装は以下のコードを参照してください。
#include <Arduino.h>
#include "M5Unified.h"
#define USB_PIN 34
const float V_REF = 3.3; // Analog reference voltage (e.g., 5V or 3.3V) due to hardware
const float Res_BITS = 12.0; // ADC resolution (bits)
const float ADC_STEPS = (1 << int(Res_BITS)) - 1; // Number of steps (2^Res_BITS - 1)
float usb_vref;//INA199x1 REF
float get_USB_Volt(float num){
float volt;
for (size_t i = 0; i < num; i++) {
volt = volt + analogRead(USB_PIN);
delay(10);
}
volt = volt / num / ADC_STEPS * V_REF;
return volt;//unit: V
}
void setup()
{
auto cfg = M5.config();
M5.begin(cfg);
M5.Display.setTextDatum(middle_center);
M5.Display.setTextColor(TFT_BLACK);
M5.Display.setTextFont(&fonts::FreeSansOblique9pt7b);
M5.Display.setTextSize(1);
M5.Power.setExtOutput(false, (m5::ext_port_mask_t)(m5::ext_USB|m5::ext_PA|m5::ext_PB1|m5::ext_PB2|m5::ext_PC1|m5::ext_PC2));
analogReadResolution(12);//Set ADC Resolution
analogSetAttenuation(ADC_11db);//Set ADC Attenuation
M5.Lcd.clear(TFT_WHITE);
M5.Power.setExtOutput(true, (m5::ext_port_mask_t)(m5::ext_USB|m5::ext_PA|m5::ext_PB1|m5::ext_PB2|m5::ext_PC1|m5::ext_PC2));
delay(200);
usb_vref = get_USB_Volt(5);//Obtain the output voltage of INA199 when the USB is in a no-laod state. This voltage is the reference voltage.
}
void loop()
{
M5.Display.clear(TFT_WHITE);
bool isSupplying = M5.Power.getExtOutput();
if(isSupplying){
M5.Lcd.setCursor(0, 10);
float usb_vol = get_USB_Volt(5);//Obtain the real-time output voltage of INA199
float usb_current = ((usb_vol - usb_vref) / 50.0f / 0.01f * 1000.0f);//unit:mA usb_vol = usb_vref + Io(unit: A)*(0.01Ω*50)
M5.Lcd.printf("USB-A %3.0fmA", usb_current);
M5.Lcd.setCursor(0, 30);
M5.Lcd.printf("A1%3.0fmA %1.1fV A2%3.0fmA %1.1fV\n",
M5.Power.Ina3221[0].getCurrent(0) * 1000,
M5.Power.Ina3221[0].getBusVoltage(0),
M5.Power.Ina3221[0].getCurrent(1) * 1000,
M5.Power.Ina3221[0].getBusVoltage(1));
M5.Lcd.setCursor(0, 50);
M5.Lcd.printf("B1%3.0fmA %1.1fV B2%3.0fmA %1.1fV\n",
M5.Power.Ina3221[0].getCurrent(2) * 1000,
M5.Power.Ina3221[0].getBusVoltage(2),
M5.Power.Ina3221[1].getCurrent(0) * 1000,
M5.Power.Ina3221[1].getBusVoltage(0));
M5.Lcd.setCursor(0, 70);
M5.Lcd.printf("C1%3.0fmA %1.1fV C2%3.0fmA %1.1fV\n",
M5.Power.Ina3221[1].getCurrent(1) * 1000,
M5.Power.Ina3221[1].getBusVoltage(1),
M5.Power.Ina3221[1].getCurrent(2) * 1000,
M5.Power.Ina3221[1].getBusVoltage(2));
}
delay(1000);
}
このプログラムは画面上に各 Grove のリアルタイムの出力電圧と電流情報を表示します。
Station の電源管理部分では M5Unified ライブラリ内のPower_Class
を使用しています。詳細なAPIは以下のドキュメントを参照してください: