モータの鳴らし方byHanDen

電子工作の初心者がモータを演奏したりVVVF音を再現したりする方法を紹介するブログ ホビー向けの電子工作を基礎から書いていきます 記事のミス等のお問い合わせはTwitterにてお願いします。 当ブログを参考に製作をする際は必ず自己責任にて行ってください 当ブログを参考にしたことによる損害等の責任は一切負いません ドメイン取得につきURLを http://vvvf.blog.jp から http://blog.henden.net に変更しました

2018年03月

NT京都に出展した

まえおき
 去年の9月にVVVFの設計ノウハウ蓄積のために、一旦高圧を抜けて低圧の基板を作ろうとしてステッピングモータを演奏する基板を作り始めてから、はや半年。高専祭でステッピング演奏を展示した後はオリジナルなものを演奏しようということで、ケースファンを演奏することに切り替えました。
 それから、ちょっとずつ基板を増やして、1月ごろにはNT京都に出展することに決めて、ニコ技にも動画を投稿。この時は、いろいろ演奏できることをアピールするためにケースファンのほかに、ステッピングモータやDCブラシモータも演奏していました。
 そのころからは卒業関連のイベントやらテストやらでばたばたして、NT京都に出す予定だった5枚目の基板が完成したのは、3月の中旬。
P_20180322_163554_vHDR_On
完成した基板はこんな感じに。高々ケースファンを演奏するだけなのにディスクリートのMOSFETを使うというバカ仕様だけど、重ねたらかっこいいなという当初のコンセプトを満たせたので満足!
それから、調整を進めて、NT京都の2日前にやっと音量アップの作戦を開始。結局音量アップ作戦は間に合わないままNT京都に行くことに…

本題
前日の24日に準備で春日神社に入り、設営準備。
P_20180325_084652_vHDR_On
こんな感じに設営完了。だが、音量が小さい…

結局当日は耳を澄まさないと聞こえないと聞こえない音量に…
まあ、なんとかなんとか乗り切れましたと…

展示会に出展するのは今回が初めてで、いろいろとわからないことも多かったですが、他の方にいろいろと教えていただいて、無事展示できました。いろいろ交流できて楽しかったです。ありがとうございました。

制御編 第12回 AVRマイコンの割り込みのまとめ

前回まででタイマー割り込みの使い方について紹介してきました。今回は割り込みの種類とそれぞれに使うISR関数の引数(マクロ)を紹介したいと思います。

 Atmega系のマイコンのISR関数の引数はC:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATmega_DFP\1.2.150\include\avrのフォルダ内のiom****.h」(****にはマイコンの型番の数字が入る)のヘッダーファイルの下部に書かれています。それぞれ、「*****_vect(*****は割り込みごとに異なる)の形で表します。(それ以外の形で書かれているのは別物です)Atmega328Pの場合は「C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATmega_DFP\1.2.150\include\avr\iom328p.h」になります。(Atmega以外のマイコンの場合、上記のパスの「atmel」フォルダに戻り、それぞれのマイコンの種類を選択して同じように進んでください。(attiny2313の場合「C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATtiny_DFP\1.3.147\include\avr\ iotn2313.h」です。))今回は例として「atmega328P」の割り込みの種類とマクロ名を紹介します。

 

タイマー割り込み

割り込みの種類

マクロ名

タイマー0溢れ割り込み

TIMER0_OVF_vect

タイマー0比較A割り込み

TIMER0_COMPA_vect

タイマー0比較B割り込み

TIMER0_COMPB_vect

タイマー1溢れ割り込み

TIMER1_OVF_vect

タイマー1比較A割り込み

TIMER1_COMPA_vect

タイマー1比較B割り込み

TIMER1_COMPB_vect

タイマー1捕獲割り込み

TIMER1_CAPT_vect

タイマー2溢れ割り込み

TIMER2_OVF_vect

タイマー2比較A割り込み

TIMER2_COMPA_vect

タイマー2比較B割り込み

TIMER2_COMPB_vect

 

外部割込み

割り込みの種類

マクロ名

外部割込み1

INT0_vect

外部割込み2

INT1_vect

ピン変化割り込み0

PCINT0_vect

ピン変化割り込み1

PCINT1_vect

ピン変化割り込み2

PCINT2_vect

以上の2種類(タイマー、外部)の割り込みがマイコンの割り込みの代名詞ともいえるよく使われる割り込みとなっています。外部割込みの設定はatmega328Pの場合データシート(https://avr.jp/user/DS/PDF/mega328P.pdf )P50~53にかけて書かれています。軽くまとめておくと以下のようになります。

外部割込み

EICRAレジスタ:割り込みの条件(ピンの状態がどのように変化した時に割り込みを行うか)の設定

EIMSKレジスタ:外部割込みを許可するレジスタ

外部割込みは以上の2つのレジスタを設定して使います。EIFRレジスタは通常使いません。

ピン変化割り込み

PCICRレジスタ:ピン変化割り込みを許可するレジスタ

PCMSK0レジスタ:ピン変化割り込み0群のうち、変化を読み取るピンを選択するレジスタ

PCMSK1レジスタ:ピン変化割り込み1群のうち、変化を読み取るピンを選択するレジスタ

PCMSK2レジスタ:ピン変化割り込み2群のうち、変化を読み取るピンを選択するレジスタ

ピン変化割り込みは以上の4つのレジスタを設定して使います。PCIFRレジスタは通常使いません。

続いて、通信系の割り込みを紹介します。

通信系割り込み

割り込みの種類

マクロ名

シリアル通信受信完了割り込み

USART_RX_vect

シリアル通信送信完了割り込み

USART_TX_vect

シリアル通信データレジスタ空割り込み

USART_UDRE_vect

SPI通信転送完了割り込み

SPI_STC_vect

TWI(I2C)動作完了割り込み

TWI_vect

以上が通信系の割り込みとなります。「データレジスタ空割り込み」を除いて、通信の動作が完了し次のデータを送受信できる状態になった時がトリガーとなります。この割り込みを使うことでデータを受信したら、そのデータを読み込むといった動作が可能になります。なお、次回の記事でシリアル通信の使い方について紹介します。

 

その他割り込み

割り込みの種類

マクロ名

A/D変換完了割り込み

ADC_vect

アナログ比較器出力遷移

ANALOG_COMP_vect

ウォッチドッグ計時完了割り込み

WDT_vect

EEPROM操作可

EE_READY_vect

SPM命令操作可

SPM_READY_vect

最後のその他の割り込みは使う機会はあまりないと思います。使うとしてもA/D変換完了割り込みぐらいだと思います。

 

以上がatmega328Pにおける割り込みの種類とそれに対応するマクロです。マイコンの種類が変わっても、同様に考えれば割り込み処理は使えると思います。次回はatmega328Pにおけるシリアル通信の使い方を紹介します。



制御編 第11回 マイコンのタイマー割り込み その2

文字数の関係の記事を2つに分けています。今回は前回の続きです。

サンプルプログラム

 今回のサンプルプログラムは、「frequency」変数に入力した周波数(パルス)数でステッピングモータを回転させるプログラムです。回転数に応じてduty比を変化させており、2相励磁となっています。

 

#include <avr/io.h>

#include <avr/interrupt.h>//割り込みのライブラリ

 

void setSquareWave(int freq); //矩形波の周波数設定

 

volatile uint8_t vect = 0;//角度

volatile uint8_t duty_h = 0;//duty125以上

volatile int frequency = 500;

 

volatile double duty = 0;

uint8_t PD[5] = {0x08, 0x20, 0x00, 0x40, 0x08};//ステッピングモータ励磁状態の配列

uint8_t PB[5] = {0x00, 0x00, 0x08, 0x00, 0x00};//この値をPORTに入れる

 

int main(void)

{

         DDRD = 0x68;//PWMピンを出力設定

         DDRB = 0x0F;

               

         //矩形波生成タイマー設定

         TCCR1A = 0x03; //PWM出力なし位相/周波数基準 OCR1A max

         TCCR1B = 0x1B; // 64分周

         TIMSK1 = 0x00; //割り込み停止

         setSquareWave(frequency);//周波数セット

         sei();//割り込み開始

       

    while (1)

    {

    }

}

 

void setSquareWave(int freq) {

  if (freq < 500) duty = 80; //duty比設定//90

  else if (freq < 1000) duty = 120;//120

  else if (freq < 1500) duty = 190;//150

  else duty = 230;//200

 

  if (freq != 0) { //動作

    TIMSK1 = 0x00;  //割り込み禁止

    //TCCR1B = 0x1B;//64分周 /2 250,000回カウント

    OCR1A = (unsigned int)(250000 / freq) ; //割り込み周波数

        if(duty <= 125){ //duty比が低い時(実質1相励磁)

                OCR1B = OCR1A * (duty / 125.0);

                duty_h = 0;//duty

        }else {//duty比が高い時(2相励磁)

                OCR1B = OCR1A * ((duty -125.0) / 125.0);

                duty_h = 1;//duty

        }

   

    TIMSK1 = 0x05;//OVFと比較Bの割り込み許可

   

    DDRC = 0x00;//出力オフ(Hi-Z)

 

  } else  { //停止

    TIMSK1 = 0x00;  //割り込みなし

    PORTD &= ~0x68;

    PORTB &= ~0x08;//出力L

    DDRC = 0x0F;//出力ダウン

  }

}

 

ISR(TIMER1_OVF_vect) { //オーバーフロー割り込み

        vect++; //進める

        if (vect > 4) vect = 1; //OVF

        PORTD |= PD[vect];

        PORTB |= PB[vect]; //出力

 

}

 

ISR(TIMER1_COMPB_vect) { //矩形波割り込み

        if(duty_h){

                PORTD &= ~PD[vect - 1];//1つ前の出力OFF

                PORTB &= ~PB[vect - 1];//1相励磁

        }else{

                PORTD &= ~PD[vect];//出力OFF

                PORTB &= ~PB[vect];//1相励磁

        }

       

}

 基本的なレジスタ設定はPWM出力に準じています。また、ステッピングモータのduty比の設定は溢れ割り込みと比較一致割り込みを組み合わせることで実現しています。ステッピングモータの励磁状態は配列に入れた値を使うことで処理の簡略化を実現しています。

そして、割り込みを使用するにあたって注意しなければならないのが、割り込み用のライブラリである<avr/interrupt.h>を読み込まなければならないことと、割り込み処理はISR(*****)」の関数を使う必要があるということです。また、ISR関数の引数(*****)(マクロともいう)は割り込みの種類ごとに異なるので注意しなければなりません。Atmega328Pにおけるタイマー割り込みの場合はISR関数の引数は以下の表のようになります。

8

割り込み処理の内容はISR関数に上の表の引数を入れること(サンプルプログラム参照)で実行ができます。ここで引数を間違うと割り込み処理ができないので注意が必要です。(コンパイルが通る場合もあるので注意)

以上でタイマー割り込みの設定は終わりです。次回は割り込み処理の引数(マクロ名)の探し方を紹介したいと思います。

制御編 第10回 マイコンのタイマー割り込み その1

前回はマイコンからPWMを出力するお話をしましたが、今回はタイマー割り込みのお話です。前回のPWMはマイコンのタイマー機能を利用していましたが、今回のタイマー割り込みもタイマーを使っています。とはいえ「割り込みってなんやねん」って思う方もいると思うので最初に軽く割り込みについて紹介します。

 

割り込みとは

 割り込みは、設定したトリガが発生した時に強制的に特定の処理をさせることを意味しています。トリガが発生した時にたとえ他の処理を行っていたとしても、割り込みに指定された処理を強制的に実行するため、トリガ発生時に確実な処理が可能になるというわけです。これを図示すると下の図のようになります。
1

 図からも、通常の処理を行っているときにトリガが入ると強制的に割り込み処理を開始し、割り込み処理が終了するまでは他の処理が中断されることがわかりますね。(Atmega328Pなどの1スレッドのマイコンの場合)

 

タイマー割り込みとは

タイマー割り込みでは、このトリガが「タイマー」によって発生します。つまり、一定の時間ごとに割り込み処理を行えるということです。ステッピングモータを回すパルスを発生させるときなど正確な時間間隔で似た処理を行いたいときなどに非常に使い勝手の良い処理と言えますね。それでは、続いてAtmega328Pにおけるタイマー割り込みの原理を紹介していきます。

タイマー割り込みは前回紹介したPWMと同様にマイコンのタイマー機能を使っており、マイコンのタイマーのカウンタがある状態になった時に、トリガを発生させるという仕組みです。ここでの、ある状態とは、タイマーがカウントの数がオーバーフロー(溢れ)した時比較値PWM生成の時の閾値 OCR0Bなど)と一致した時などを指します。つまり、タイマーのカウントが特定の値に達した時に、割り込み処理が実行されるというわけです。このタイミングを図示してみます。
2

 上の図がタイマーのカウンタがオーバーフローしたときの割り込み(マイコンではこれを溢れ割り込みと言います)を示しており、タイマーのカウンタがオーバーフローする↓で示したタイミングで割り込み処理が行われます。ただし、この溢れ割り込みのタイミングはタイマーの動作種別によりタイミングが変わります。(詳細は次の節)また、同様に下の図はタイマーのカウンタが比較Aに達した時の割り込み(比較A割り込み)を示しており、↓で示したタイミングで割り込み処理が実行されます。

 

タイマー割り込みの注意点

 先ほどの節でタイマー割り込みの原理を紹介しましたが実際にタイマー割り込みを使用するにあたって注意しなければならない点が複数あります。1つ目は溢れ割り込みのタイミングで2つ目は比較・捕獲割り込みのタイミング、3つ目はTOP値と比較・捕獲値の関係です。

溢れ割り込みのタイミング

 溢れ割り込みは定義上はカウンタの値がオーバーフローした時の割り込みです。しかし、溢れ割り込みでオーバーフローした時に割り込みが入るのはデータシート上「標準動作」と「比較一致タイマ/カウンタ解除(CTC)動作」のみであるということに注意しなければなりません。すなわちよく使われる、「高速PWM動作」「位相基準PWM動作」、「位相/周波数基準PWM動作」においてはタイマーのカウンタがオーバーフローした時に割り込みが実行されないというわけです。Atmega328pのデータシート(https://avr.jp/user/DS/PDF/mega328P.pdf )P.99(タイマー1)を確認すると、このことの記載がされており、タイマーの動作種別によりタイミングが異なると書かれています。そのタイミングはタイマー動作種別の表(以下に引用)に書かれています。
3
4

上が8ビットタイマーで下が16ビットタイマーの場合です。それぞれの表の右端の赤で囲んだ「TOV1設定時」の項目に溢れ割り込みが入るタイミングが書かれています。これより「高速PWM動作」ではタイマーのカウンタが「TOP値」に達した時、「位相基準PWM動作」「位相/周波数基準PWM動作」ではタイマーのカウンタが「BOTTOM(0)に達した時に割り込みが動作することがわかります。これを図示してみます。
4-1
 図を見れば「高速PWM動作」はTOP値で割り込みが入っていますが、TOP値は同時にBOTTOM値でもあるのでどちらかというと溢れ割り込みは、タイマーのカウンタが0になったタイミングで入ると考えても問題はないでしょう。以上が溢れ割り込みの動作のタイミングの注意点です。

 

比較・捕獲割り込みのタイミング

 比較A,B割り込みや捕獲割り込みはタイマーのカウンタの値が比較A,B(OCR*A,B)や捕獲値(ICR1)と一致した時をトリガとして割り込みが入ります。原理上はこれだけなのですが、タイマーの動作種別により割り込みが入るタイミングや回数が変わることに注意しなければなりません。割り込みが入るタイミングを図示してみます。
4-2
 この図を見れば、高速PWM動作ではカウンタ1周期の間に割り込みが1回で等間隔に割り込みが入るのに対して、位相(/周波数)基準PWM動作ではカウンタ1周期の間に2回割り込みが入り割り込みが入るタイミングが等間隔でないことがわかります。割り込み動作の時はカウンタが上昇時と下降時の区別がされずに単に値が一致した時がトリガとなるためこのような動作となります。

 

TOP値と比較値との関係

 この関係はタイマーのカウンタのTOP値と比較値が一定の関係にならないと割り込みが入らないことを示しています。割り込みが正しく入る条件はこのような関係です。

比較値≦TOP

この関係も原理から考えると非常にやさしいものですが2つの値の関係よってどのようになるかを図示してみます。
5

比較値とTOP値の関係を「比較値>TOP値」「比較値=TOP値」「比較値<TOP値」の3つの場合を図示してみました。この図を見れば、「比較値>TOP値」の時に割り込みが一切入らなくなることは明らかですね。また、「比較値=TOP値」はカウンタがTOP値に達した時に割り込みが入るため、カウンタ1周期につき1しか割り込みが入らないこともわかると思います。

 

以上の3つが割り込みを使うときの大きな注意点となります。続いて、各種レジスタの設定方法ですが、波の形と最大高さ関連の設定は前回のPWMの記事http://vvvf.blog.jp/archives/7662206.html)を参考に行ってください。ここではタイマー割り込みにおいてPWM出力時と異なるレジスタ設定の項目を紹介します。

 

割り込みのレジスタ設定

 6

初めに、各出力ポートの設定です。今回はPWM出力を利用しないので、すべて「標準ポート動作」(COM*x: 0 0)を選択します。TCCR0A,BTCCR1A,BTCCR2A,Bのその他の設定はPWMの時と同じようにしてください。

続いて、割り込み動作の許可の設定です。
7

この割り込み許可レジスタで、各種割り込みを許可する設定を行っています。利用する割り込みのビットを立てることで、割り込みが使用できるようになります。なお、捕獲割り込みは「ICR1」と一致時、比較一致割り込みは「OCR*A」「OCR*B」と一致した時に割り込みが入ります。

以上でレジスタの設定は終了ですが、割り込みを使用するにはプログラムですこし変わった書き方が必要となります。各レジスタの実際の設定値と合わせて、次のサンプルプログラムのところで紹介します。

 

文字数の関係でサンプルプログラムはその2に続きます

制御編 第9回 マイコンのPWM出力 その2

前回は任意の周波数のPWMを生成するためのパラメータを決定しました。今回はその決定したパラメータを実際にプログラムに落とし込む方法を紹介します。

レジスタの設定

いままでの計算で目的の周波数のPWMを出力する設定は見つかりました。今度は実際にその設定をレジスタに入力していきます。設定情報は毎度のごとくAtmega328Pのデータシート(https://avr.jp/user/DS/PDF/mega328P.pdf )から探します。タイマー0のレジスタ設定はP76~78、タイマー1のレジスタ設定はP94~96、タイマー2のレジスタ設定はP112~114に書かれています。なお、8ビットタイマーの「タイマー0,1」と16ビットタイマーの「タイマー1」は分けて紹介したいと思います。

 

8ビットタイマー

8ビットタイマーは「タイマー0」と「タイマー2」に搭載されていますがほぼ設定内容は同一なので「タイマー0」を基準に紹介していきます。(分周のところだけ違うのでそこだけ別途説明します)タイマー0における、PWM出力の設定レジスタは「TCCR0A」と「TCCR0Bです。また、可変周波数PWMを行う場合の波の高さは「OCR0Aレジスタに、duty比を設定する閾値は「OCR0Bレジスタに入力します。それでは、各レジスタの中身を見ていきましょう。

1
2
3
4

PWMを生成するのに使用するレジスタはこの4つですが、下の2つのレジスタは数値を入力するだけなので、詳細な説明は省略します。上の2つのレジスタは各ビットの状態を使ってさまざまな、設定を行っています。それぞれの設定項目別に紹介をしていきます。

OC0Aの端子の出力設定(比較A出力選択)TCCR0Aの第6,7ビット」
5

この項目で確認する必要があるのは、図の赤で囲んだところです。PWMの動作種別(波の形)によって「高速PWM比較A出力選択」か「位相基準PWM動作比較A出力選択」を確認して下さい。波の高さを可変する可変周波数PWMを出力する場合は、ここで出力設定をするOC0A」端子に対応する、比較レジスタ(PWM生成の閾値)が波の高さを設定するレジスタそのものであるため、この端子からPWMを出力することはできません。そのため、可変周波数PWMを使用する場合は図の赤で示した「標準ポート動作(OC0A切断)」を選択します。つまり、COM0A1,COM0A0ともに0となります。

可変周波数PWMを使わず、限られた周波数のPWMのみを出力する場合は「OC0A端子もPWM出力が可能となり、その場合は図の青←で示した「比較一致でLow…」「上昇計数時の比較一致でLow…」の設定を選択します。

 

OC0Bの端子の出力設定(比較B出力選択) TCCR0Aの第4,5ビット」

 6

この項目の中身自体は先ほどの設定と大差なく、確認する箇所も同じですが、可変周波数PWMを使用する場合は設定する内容が違うことに注意が必要です。ここで設定を行う「OC0B」端子は、可変周波数PWMを行う場合ではPWMが出力される端子です。そのため、図の赤←で示した「比較一致でLow…」「上昇計数時の比較一致でLow…」、つまり「COM0B1:1, COM0B2:0」を選択しなければなりません(データシートのレジスタの項目名は間違いです)この設定をしないとPWMが正しく出力されないので注意が必要です。(なお、COM0A1,2:11を選ぶと出力波形が反転します)

 

タイマー波形選択TCCR0Aの第0,1ビット、TCCR0Bの第4ビット」
7

ここの項目ではタイマーで生成される波形の種類を選択します。可変周波数のPWMを生成する場合は波の高さを変更できるようにする必要があるため、TOP値をレジスタで設定できる項目を選ばなければなりません。そのため、図の赤の←で示したTOP値が「OCR0A」で定義できる設定を選択します。波形が三角波の「位相基準PWM動作」を選択する場合赤←1で示した「TOP:OCR0Aの位相基準PWM動作」(WGM02:1 WGM01:0 WGM00:1)を選択します。また、波形がのこぎり波の「高速PWM動作」を選択する場合赤←2で示した「TOP:OCR0Aの高速PWM動作」(WGM02:1 WGM01:1 WGM00:1)を選択します。

可変周波数のPWMを使用しない場合は図の青←で示したTOP値が「$FF(255)」の項目を選択します。

 また、この設定項目を保存するレジスタはWGM01WGM00が「TCCR0A」、WGM02が「TCCR0B」と2つに分かれていることに注意しなければなりません。

 

分周選択
8

この項目では、タイマーに使う分周の値を選択します。必要な分周に応じた項目を選択してください。ただし、この項目は同じ8ビットタイマーでも「タイマー0」と「タイマー2」で選択肢が異なるので注意してください。上の画像は「タイマー0」の設定です。「タイマー2」の場合は以下のような選択肢に変わります。
9

このように、同じ分周数でもレジスタに設定する値が変わってくるので注意が必要です。

 

レジスタの設定例

これまでに説明した、手順で実際に任意の周波数のPWMを出力する設定を紹介します。

今回はシステムクロック16Mhzで出力PWM1kHzとし、タイマーの波形は位相基準PWMとした場合です。また、duty比は0.5としておきます。

初めに、分周値とTOP値を選定します。(分周は64として代入)
式

計算結果より、TOP値は125となり使用可能範囲であるため、設定パラメータは分周64TOP125とします。

各レジスタに設定した値を入力していくと以下のようなパラメータとなります。なお、赤字は関係ないor設定できない項目なので0にしています。
10
11
TOP値を定義する「OCR0A」とduty比を設定する閾値を定義する「OCR0B」には以下のように値をそのまま入力させます。

OCR0A=125

OCR0B=OCR0A*0.5=62

このように設定することで任意の周波数のPWMを生成することができます。

 

16ビットタイマー

 16ビットタイマー(タイマー1)の場合も8ビットタイマーと同様に設定を行っていきます。データシートのP94~96より、PWMの設定レジスタは「TCCR1A」と「TCCR0B」となっています。そして、可変周波数PWMを使う場合の波の最大値は「OCR1AorICR1」、PWM生成の閾値は「OCR1B」となっています。後者の3つのレジスタは値を設定するレジスタです。16ビットタイマーなので設定できる値は16ビットとなりますが、あくまでAtmega328P8ビットマイコンなので8ビットのレジスタを2つ使う形となっています。

 8ビットタイマーとシステムが近いので違いがある点を絞って紹介をしていきたいと思います。まずは、設定レジスタである「TCCR1A」と「TCCR1B」の中身を見てみます。

 12
13

設定レジスタの中身はこのようになっており、タイマーの波形選択である「WGMn」以外の設定は8ビットタイマーと同じ設定です。今回は8ビットタイマーと設定が異なる波形の形の設定を見てみましょう。

タイマー波形の選択TCCR1Aの第0,1ビット TCCR1Bの第3,4ビット」
14

8ビットタイマーに比べて設定項目が非常に多くなっています。8ビットタイマーとの違いは主にTOP値の選択項目が多くなっているということで、0x00FF」「0x01FF」「0x3FF」「OCR1A」「ICR1」と5種類のなかから選ぶことが可能になります。可変周波数PWMを使う場合は赤色の←示した「TOPOCR1Aの位相/周波数基準PWM動作」(WGM1: 1 0 0 1)TOPOCR1Aの高速PWM動作」(WGM0: 1 1 1 1)を選択すると良いでしょう。また、可変周波数PWMを使わない場合でほかの8ビットタイマーと同様に使いたい場合は青←で示した「TOP0x00FF8ビット位相基準PWM動作」(WGM1: 0 0 0 1)や「TOP0x00FF8ビット高速PWM動作」(WGM1: 0 1 0 1)を選択すると良いでしょう。

16ビットタイマーでもほかの設定は8ビットタイマーと同じなので省略します。次に波の高さ(TOP値)やPWMを生成する閾値を設定するレジスタを見てみます。
15

Atmega328Pはあくまで8ビットマイコンなので16ビットの値を1つのレジスタとして扱うことができません。そのため、内部的には下位バイトと上位バイトの2つのレジスタに分けられていますが、Atmel Studioではこれら2つをまとめて「OCR1A」として扱うことが可能になっています。そのため、ほかの8ビットタイマーなどと同様の感覚で使うことが可能です。(この書き方ができない環境の場合はビット演算とビットシフトを使って、それぞれのレジスタに書き込みをする必要があります)

 

レジスタの設定は、8ビットタイマーの時と同様に行います。

 

サンプルプログラム

今回は、ある変数に入力された周波数のPWMを生成するプログラムをサンプルとして紹介したいと思います。今回はタイマー0を使用しDuty比は31%に固定としています。

#include <avr/io.h>

 

volatile int freq = 1000; //出力周波数

volatile double duty = 80; // 80/2550.31331%

 

int main(void)

{

         DDRD = 0x68;//PWMピンを出力設定

         DDRB = 0x08;

         //矩形波生成タイマー設定

         TCCR0A = 0x01; //PWM出力停止 位相基準 OCR0A max

         TCCR0B = 0x0C; // 256分周

 

TCCR0A &= ~0x20;//PWM停止

if((freq > 125) && (freq < 2000)){

                TCCR0B = 0x0C;//256分周

                OCR0A = (unsigned int)(31250 / freq) ; //割り込み周波数

                OCR0B = OCR0A * (duty / 250.0);

                TCCR0A |= 0x20;//PWM起動 OCR0Bのみ

}else if((freq > 50) && (freq < 125)){

                TCCR0B = 0x0D;//1024分周

                OCR0A = (unsigned int)(7812 / freq) ; //割り込み周波数

                OCR0B = OCR0A * (duty / 250.0);

                TCCR0A |= 0x20;//PWM起動 OCR0Bのみ

}else if((freq > 2000) && (freq < 7000)){

                TCCR0B = 0x0B;//64分周

                OCR0A = (unsigned int)(125000 / freq) ; //割り込み周波数

                OCR0B = OCR0A * (duty / 250.0);

                TCCR0A |= 0x20;//PWM起動 OCR0Bのみ

}

 

    while (1)

    {

}

 

プログラムとしては、TOP値が8ビットに収まる範囲で場合分けをして分周を区切っています。また、プログラム実行中の周波数を変更も視野に入れたため、念のためPWM周波数を変更する処理を行うときはPWM出力を一旦停止させています。TOP値の計算は前回紹介したものをあらかじめ計算可能な場所のみ計算したものを使用しています。

 

以上で任意の周波数のPWMを出力する方法の紹介は終わりです。次はタイマー割り込みのお話を予定しています。


ギャラリー
  • HDDを演奏する楽器を作ってみた
  • HDDを演奏する楽器を作ってみた
  • HDDを演奏する楽器を作ってみた
  • HDDを演奏する楽器を作ってみた
  • 制作日記5 細かな基板を注文してみた
  • 制作日記5 細かな基板を注文してみた
  • 制作日記5 細かな基板を注文してみた
  • 制作日記5 細かな基板を注文してみた
  • 制作日記5 細かな基板を注文してみた
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計: