2018年9月21日金曜日

Nucleo(mbed)でADC_VREFを使って電圧を測定する。

STM32のmbedでは「ADC_VREF」という内部レファレンス電圧のピン名がPinNames.hで定義されています。

NucleoF446REのPinNames.h

参考「STM32_ADC_InternalChannels

この値をAnalogInで読み取れば、比較的正確な電圧が得られます。

この内部レファレンス電圧がはたして何ボルトなのかは、DATASHEETに載っていました。

Nucleo F446REの場合は、「STM32F446xC/E」のTable 16にある「V12」の値のようです。


NucleoF446REは180MHz駆動なのでtyp. 1.32Vで1.26V ~ 1.40Vだと思います。

ブレッドボード配線図


電源は可変電圧電源を使用して1.25V ~ 12Vを与え、33kΩと68kΩで分圧しました。分圧すれば、Nucleo F446REのADCの入力電圧におさまり、0.4V ~ 3.9V程度になります。

<追記:2018.09.23>

Nucleo F446REは3.3V駆動ですが、5Vトレラントになっていれば上記の電圧範囲の入力可です。5Vトレラントになっているピンは、ボードによって異なるので注意が必要です。

Nucleo F446REの場合はほとんどのピン(AnalogOutに使えるピン以外)は5Vトレラントになっていますが、Nucleo F303K8の場合は5Vトレラントで使えるピンが少なく、AnalogInに使えるピンは5Vトレラントになっていません。

参考「Nucleo F446REとNucleo F303K8の一部ピンは5Vトレラントではない模様

</追記>

ちなみに電圧の調整を可変電圧電源ではなく可変抵抗で行うと、分圧用の抵抗と干渉して33:68の分圧になりません。

テストプログラム

/*
 * ADC_VREF Test01
 *
 * 2018.09.18
 *
 */

#include "mbed.h"

#define INTERNAL_VOLTAGE  (1.23f)
#define VDIV_R1           (68.0f)   // 分圧用抵抗値1
#define VDIV_R2           (33.0f)   // 分圧用抵抗値2
#define VOLTAGE_DIVIDE    ( (VDIV_R1 + VDIV_R2) / VDIV_R2 )

Serial pc(USBTX, USBRX);

AnalogIn Ain0(A0);
AnalogIn VrefInt(ADC_VREF);

DigitalOut CheckPin1(D4);

int main()
{
 pc.baud(115200);
 pc.printf("\r\nADC_VREF Test01\r\n");
 pc.printf("%s %s\r\n", __DATE__, __TIME__);
 pc.printf("System Clock: %lu Hz\r\n\r\n", SystemCoreClock);
 
 float vref = VrefInt.read();
 float vrefFactor = INTERNAL_VOLTAGE / vref;
 printf("INTERNAL_VOLTAGE: %f\r\n", INTERNAL_VOLTAGE);
 printf("VD_R1           : %f\r\n", VDIV_R1);
 printf("VD_R2           : %f\r\n", VDIV_R2);
 printf("VOLTAGE_DIVIDE  : %f\r\n", VOLTAGE_DIVIDE);
 printf("vref            : %f\r\n", vref);
 printf("vrefFactor      : %f\r\n", vrefFactor);

 printf("\r\nvref,\tvrefFactor,\tread,\tafter div,\tbefore div\r\n");
        for (;;) {
  CheckPin1.write(1);
  vref = VrefInt.read();
  vrefFactor = INTERNAL_VOLTAGE / vref;
  float v = Ain0.read();
  CheckPin1.write(0);
  printf("%5.3f,\t%5.3f,\t%5.3f,\t%5.3f V,\t%6.3f V\r\n", 
   vref, vrefFactor, v, v * vrefFactor, v * vrefFactor * VOLTAGE_DIVIDE);
  wait(1.0);
 }
}

テスタで入力した電圧とUARTで表示させた値を比較すると「#define INTERNAL_VOLTAGE  (1.23f)」で誤差が少なくなりました。DATASHEETの値より低いので何か間違っているかもしれません。

以前VDDを基準電圧として電圧を測定しましたが、内蔵レファレンス電圧を使うと、電源電圧が変動しても影響を受けにくいというメリットがあります。

0 件のコメント:

コメントを投稿