Open5

megaAVR 0-seriesで電源電圧を測る方法

しごぶしごぶ

環境
IDE:Arduino IDE
ボードパッケージ:MegaCoreX

Arduino IDE を使っているので、ADCの初期化は設定済?

unsigned int getVrefValue() {
  // 内部基準電圧を1.1Vに設定
  VREF.CTRLA = VREF_AC0REFSEL_1V1_gc;

  // 読み取る値を内部基準電圧に設定
  ADC0.MUXPOS = ADC_MUXPOS_DACREF_gc;
  // 変換開始
  ADC0.COMMAND = ADC_STCONV_bm;

  // 結果待ち
  while (!(ADC0.INTFLAGS & ADC_RESRDY_bm))
  {
    ;
  }

  // 結果を返す
  return ADC0.RES;
}
しごぶしごぶ

読み取ったVrefの値を電圧に変えて返す。

#define INT_REF_VOLT 1.1

float cpuVcc(){
  long sum=0;
  for(int n=0; n < 10; n++){
    // adcの値を読んで積分
    sum = sum + getVrefValue();
  }
  float adcAverage = sum / 10.0;
  return (1023.0 / adcAverage) * INT_REF_VOLT;
}

しごぶしごぶ

ADC採取累積器なるものが存在していて、自動で値を累積してくれるらしい。

#define ADC_SHIFT_DIV32 (5)

uint16_t getVrefValue() {
  // 内部基準電圧を1.1Vに設定
  VREF.CTRLA = VREF_AC0REFSEL_1V1_gc;

  // 採取累積設定
  ADC0.CTRLB = ADC_SAMPNUM_ACC32_gc;

  // 読み取る値を内部基準電圧に設定
  ADC0.MUXPOS = ADC_MUXPOS_DACREF_gc;
  // 変換開始
  ADC0.COMMAND = ADC_STCONV_bm;

  // 結果待ち
  while (!(ADC0.INTFLAGS & ADC_RESRDY_bm))
  {
    ;
  }

  // 値を読み取って32で割る
  uint16_t adcVal = ADC0.RES;
  adcVal = adcVal >> ADC_SHIFT_DIV32;

  // フラグ解除
  ADC0.INTFLAGS = ADC_RESRDY_bm;  

  // 結果を返す
  return adcVal ;
}
しごぶしごぶ

megaAVR 0-series では、内部基準電圧を直接測ることはできず、AC0にあるDAC経由の電圧しか測れない。
しかし、tinyAVR 0-Series と tinyAVR 1-Series は直接内部基準電圧を測ることができるっぽい。