LoginSignup
6
3

More than 1 year has passed since last update.

ArduinoでPWMの周期に同期してAD変換する。

Last updated at Posted at 2020-01-25

はじめに

 導体をPWMで制御しているとき、電流を測定したい。(DCブラシモータの電流計測に使える?→知らん)
 →PWMのON時間中にAD変換をしたい。(シャント抵抗の電圧値を測定→電流計測)

 今回想定するような回路を以下に示す。
image.png
 右の回路はFETによる駆動回路とシャント抵抗による電流計測。
 右上の銅線まきまきは、導体。←この導体の電流や抵抗値が知りたい、制御したい。
 左の抵抗2つは、電源電圧測定用、導体の抵抗値や消費電力を測定したい場合必要。

まず結果
 PWMが1[kHz]、デューティ比0.05以上の場合、良好な結果が得られた。(Arduino Nanoを使用)
 位相/周波数PWM動作で、PWMは反転で出力がいい感じ
 電源電圧とアクチュエータの電流を同時には測定できませんでした。(PWMの周期ごとに交互に測定した{Arduinoの限界})

検索すべきワード
 Arduino PWM周波数変更 
 Arduino タイマ割り込み
 など

なにをすれば実現できそうか

1. タイマでPWMを発生させる

 Arduino標準のPWM(analogWrite())の機能では、周波数の設定が機能がなく、どのみちタイマ割り込みの設定で、タイマを設定するため、PWMはAVRの機能で実装する。

2. タイマ割り込みを使う

 PWMを発生させているタイマを利用して、PWMがONになっているときに、AD変換を行う。

3. 割り込み中にAD変換する

 今回は、Arduino標準のAD変換であるanalogRead()を利用する。
    → 分周を変更し、高速化してもよいが、最高の精度は得られないかも。

 このとき、割り込みで多くの時間を消費することになる。AD変換完了割込みを使うことで回避できるが、今回はほっとく。

実験環境

使用器具

  • Arduino Nano
  • シャント抵抗(カーボン抵抗1/4[W])
  • 電流を計測したいもの
  • Nch MOSFET 2SK4017
  • その他FETゲート電流制限抵抗など

補足

 今回はArduino Nanoを使用しました。これにはATmega328pが搭載されており、Arduino Unoも同じMCUで構成されているため、同じプログラムが実行できます。(AVRの機能を利用するためMCUが変わると利用できない)
 Arduino Nanoは16[Mhz]だよ
今回はPWMの出力に9番ピンをつかったよ
 

具体的に方法の検討

タイマは何を使うか→Timer1

 ArduinoでPWMを利用できるPINは6本存在しています。それらは3, 5, 6, 9, 10, 11ピンです。
 今回はPWM出力ピンを9または10を前提に開設します。以下に理由を書きます。

 Arduino Nanoに搭載されているATmega328pには、タイマとよばれるカウンタが存在します。
 これらはクロックごとに自動的に加算されていきます。このカウンタは1クロックに1加算ということも可能ですが、分周によって、2クロックごと、8クロックごとなど、加算の仕方を変更することができます。

 ATmega328pにはタイマが3つ(Timer0,Timer1,Timer2)搭載されており、個別に数値を加算させていくことが可能です。また、それぞれカウンタの上限値、分周を個別に設定することが可能です。それぞれのタイマが対応したピンにPWMを出力可能です。

 各タイマとPWM出力ピンの関係、Arduino内で使用されている関数を以下の表に示します。

タイマ ピン番号 bit数[bit] すでにArduinoで使用されている機能
Timer0 5, 6 8 delay(),millis(),micros()
Timer1 9, 10 16 Servoライブラリ
Timer2 3, 11 8 タイマ割込みライブラリ

 ここでTimer0の設定を変更すると、delay()など、Arduinoで利用されている関数の時間がくるいます。
 Timer2でもいいけど、まあ今回はTimer1で説明します。

 これらの理由から今回は、設定を変更しても影響の少ないTimer1を利用してPWMを発生させます。
 

PWM周波数の決定

→今回は1[kHz]以下で、最小デューティ比とのバランス

AD変換の実行時間について

 ATmega328pのAD変換機は1つ内臓されており、ArduinoのA0~A7までのピンの電圧を10[bit]で測定することができる。なお、同時に測定することはできない。(ADCが1つしか内臓されていないため)
 なお、あるピンを測定時、104[us]よりも後に、他のピンを変換することはできる。

 Arduino NanoのAD変換は、変換開始から理論値で104[us]で完了する。また、測定には104[us]の時間がかかるが、AD変換開始直後に、測定するピンの電圧を保持する機構が内蔵されているため、電圧を保持した後は、電圧が変換しても、AD変換開始直後の電圧値を測定できる。

 また、AD変換の電圧保持にはAD変換クロックの約2クロックの時間が必要であり、これは(1/16[MHz])×128[分周]×2[クロック]=16[us]の時間、電圧が変化しなければ、イイ感じに電圧を測定できる。(ハズ  ここは詳しく知らない
   (AD変換クロックは、Arduinoでは標準で128分周されている)
 

PWMとAD変換のタイミング

 PWMのON時に、AD変換をするために、Timer1により、PWMの発生とタイマ割り込みを行う。
 また、PWMには高速PWM動作や位相/周波数基準PWM動作など存在するが、今回は位相/周波数基準PWM動作、出力を反転で構成した。以下説明
 

タイマの動作の種類

ここでは、比較AなどをPWMしきい値と表しています。

高速PWM動作

 高速PWM動作ではカウンタが加算されていき、TOP値になると0に戻る。
image.png

位相/周波数基準PWM動作

 位相/周波数基準PWM動作ではカウンタが加算されていき、TOP値になると、減算されていく。

image.png

なぜ位相/周波数基準PWM動作を選択するのか

 今回タイマ割り込みを利用するばあい、割り込み要求ができるのが、比較一致した場合か、TOP値と一致した場合です。

 ここで、位相/周波数基準PWM動作の反転出力(黄)に注目すると、PWM出力がONのとき、かつON時間の1/2の時に、カウンタがTOP値と一致し、割り込みが発生することが分かる。

 では、高速PWM動作ではどうなのかというと、高速PWM動作の非転出力では、カウンタがTOP値での割り込みの時、同時に出力が立ち上がり、電圧が上昇する。

 もしFETの立ち上がりが遅く、AD変換の電圧保持時、電圧が安定していない場合などを考え、位相/周波数基準PWM動作を選択した。
   →もしかしたら、そこまで考えなくてもいいのかもしれない。実際これをすると必要なON時間が2倍になる(ちょっと損かも)。

デューティ比とPWM周波数の決定

 まず、必要なON時間を求め、その後最小デューティ比と、PWM周波数を求める。
 
 必要ON時間は32[us]である。
 →AD変換では開始後16[us]は、測定したい電圧である必要があり、位相/周波数基準PWM動作では、ON時間の半分しか使えないことがわかったため。
 
 最小デューティ比を決める。これはアクチュエータの動作にさほど影響を与えない程度に決定する。(物による)例えばデューティ比0.05(5[%])
 
 必要なON時間と最小デューティ比からPWM周波数を決定する。
 →必要なON時間32[us]、最小デューティ比0.05から、32[us]/0.05=640[us]→1562[Hz]以下となる。
image.png

 もし、最小デューティ比を倍の0.1にすると、PWM周波数は約3[kHz]以下となる。

実際にやっていく

 やること

  • タイマの設定
  • タイマ割り込みの設定
  • AD変換

タイマの設定

指定した周波数でPWMを出力できるようにする

 今回は9番ピンをPWMの出力に割り当てる。
 Timer1のTOP値を自由に指定できるレジスタICR1(捕獲レジスタ)に設定する。

  pinMode(9, OUTPUT);
//Timer1 変更
TCCR1A &= B11111100;
TCCR1A |= B00000000;              //WGM11,10, TOP値ICR1:00  

位相/周波数基準PWM動作に設定する

TCCR1B &= B11100111;
TCCR1B |= B00010000;              //位相,周波数基準  WGM13,12 位相/周波数基準:10

分周なしに設定

TCCR1B &= B11111000;
TCCR1B |= B00000001;              //1分周:001 

PWMの周波数を設定する。

top = (muc_frq / frq/2);        //マイコンの周波数/PWMの設定周波数/2(←この2は位相/周波数基準PWM動作であるため)
ICR1 = top;                     //レジスタに代入

デューティ比を設定する。

OCR1A = (unsigned int)(top * duty);

ここでdutyは0~1

最後にPWMを出力させる(反転動作)

TCCR1A &= B00111111;
TCCR1A |= B11000000;              //PWM動作 pin9出力

この時点で9番ピンから指定したPWMが出力される。

タイマ割り込みの設定 

//カウンタがTOP値になったときこの関数が呼ばれる。 この関数はloopやsetuoではない、外に記述する。
ISR(TIMER1_CAPT_vect) {
    //AD変換
}

setup関数内にTimer1の捕獲割込みを有効化する。+全割込み許可

//タイマ1 捕獲割込み 有効
TIMSK1 &= B11011111;
TIMSK1 |= B00100000;
sei();                            //割込み 許可

おわりに

 電流値を測定するには、シャント抵抗の電圧値と抵抗値から、電流を導出する。
 電源電圧を利用することで、導体の抵抗値がわかる。(ハズ

参考サイト

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3