前回導入した小さなMCU、ATtiny85(下図)に内蔵されたRC発振器のお話です。
ATtiny85は、たった8ピンのDIP形状MCUです。詳しくは前回記事をご覧ください。
これまでに使って来たAVRマイコンには、RC発振器が内蔵されていました。以下記事を参照してください。
「#9-7 内蔵RC発振器を校正する」
「#14-4 ATtiny2313内蔵RC発振器の校正」
ATtiny85にも、同様なRC発振器が内蔵されています。
RC発振器は、抵抗Rと容量CをLSI上に作り込む事でCR回路を構成し、その時定数を使ってクロックを発振させる装置です。本ページでは昔、シュミットトリガ入力インバータとCR回路を組み合わせて作った発振器が有りました(以下記事および回路図)。
「#8-9 発振器でLEDを自動点滅する」
AVRマイコンに搭載されたRC発振器も、原理としては上の回路と同様だと思われます。
普通、MCUを動作させるクロックは、外部に水晶発振子(下図左側)等を接続して、発振させます(下図右側回路)。
水晶発振子は発振精度が高いため、狙った周波数に近い周波数で安定して発振し続けることができます。ただし、LSIのシリコン(Si)ウェハ上に水晶を集積(搭載)するのは困難なため、水晶発振器を内蔵するのは難しいのでしょう。
しかし、抵抗Rと容量Cであれば、Si半導体製造プロセスで作り込む事が可能なので、LSIチップ上に集積(内蔵)することができます。その代わり、水晶発振子と異なり、狙った周波数で安定して発振させるのは困難なのです(こちらに実測した結果が有ります)。
このためAVRマイコンは、チップを製造した後で発振周波数を測定し、工場出荷時に、仕様で決められた周波数(例えば8MHz等)で発振する様に校正してから出荷しています。
本ページでは、RC発振周波数の工場出荷時校正試験を、「自前でやって見よう」としています。
なお、RC発振器の周波数は、OSCCALレジスタに0x00〜0xffの値を設定することで、所望の周波数に設定できる様になっています。ただし、「OSCCAL=0x80では、常に8MHz」等、一意に決まっている訳ではなく、個体差が有って、OSCCAL設定値と周波数の対応表(校正表)が、ATtiny85チップの数だけ存在します。
OSCCALレジスタへの設定値と、その時の発振周波数を測定しておくと、OSCCALレジスタを設定することで、8MHz以外の周波数でCPUを動作させることが可能となります。
最初に挙げた過去記事と同様、ATtiny85でも、この校正表を取得しておこうと思います。
なお、ATtiny85データシートには、OSCCALレジスタの設定値を変更する際の注意事項が記されていますので、設定値を変更する場合には、良く確認して使用してください。
工場出荷時、AVRマイコンのRC発振器を校正した結果は、内蔵されたヒューズに書き込まれています。まずは、ヒューズ値を確認しておきましょう。
こちらを参照して、Arduino UNOとATtiny85をシリアルプログラミングモードで通信できる様、接続してください。以下、実験中の様子です。
つづいて、「#9-4 ATmega328のヒューズ書き込み」で作成した、以下のプログラムをUNOにコンパイル&書き込んでください。
通信用プログラム:ser_prog.ino
UNOのシリアルモニタから以下のコマンドを実行して、ATtiny85のヒューズ値を読み出しましょう。
実験サンプル:【 】内はシリアルモニタからの送信データ
(UNOのリセット解除後)
OK+ serial programming mode
OK+ ATtiny85 detected
RDY
【dmpb】
OK+ fuse: 0xff 0xd7 0xe2
OK+ lock: 0xff
OK+ cali: 0x59 0x34
OK: sign: 0x1e 0x93 0x0b 0xff
上の実行結果は、Arduino IDEでATtiny85のヒューズを書き込んだ後のヒューズ値(「OK+ fuse:」)です。Arduino IDEでのメニュー設定項目は以下の通りです。
内蔵RC発振器の8MHzに対する工場出荷時校正値に関しては、「OK+ cali:」として表示された項目が相当します。
なお、ここで読み出した校正値(0x59および0x34)は、手元のATtiny85での工場出荷時校正値です。個体差があるため、皆様お手元のATtiny85では、異なる値が読めるはずです。各自、ご確認ください。
OSCCALレジスタ=0x00〜0xffまで順次設定しながら、各設定値に於ける内蔵RC発振器の発振周波数を測定して、校正表(グラフ)を作る実験を進めて行きます。測定は自動化されており、256回手動測定する必要はありませんので、ご安心を。
校正表を作成するには、Arduino UNOとATtiny85に別々なプログラムを書き込んで、UNOとATtiny85を接続してください。
まず、「#14-4 ATtiny2313内蔵RC発振器の校正」の記事で、ATtiny2313用に作成したプログラム(以下にリンクします)をATtiny85用に改造して使います。
測定用プログラム(ATtiny85用):tiny_rcosc.ino
前節でヒューズ値を確認した時に、UNOとATtiny85間にシリアルプログラム可能な接続が確立されているので、そのまま使って、上のプログラム(tiny_rcosc.ino)をATtiny85に書き込んでください。
その後、UNOには、以下のプログラムを書き込んでください。
測定用プログラム(UNO用):cali_rcosc.ino
「#9-7 内蔵RC発振器を校正する」で作成した、測定用プログラムです。
プログラムの書き込みが済んだら、以下接続表の通りに、Arduino UNOとATtiny85の接続を変更してください。
Arduino UNO | 接続 | ATtiny85 | |
5V | → | 8 | VCC |
GND | ⇔ | 4 | GND |
D8(ICP1) | ← | 3 | D4(OC1B) |
A4(SDA) | ⇔ | 5 | D0(SDA) |
A5(SCL) | ⇔ | 7 | D2(SCL) |
D4 | GND |
※ATtiny85欄の数値は8DIPの端子番号です。また、ATtiny85のVCC⇔GND間にパスコンを接続しておいてください。
以下、実験中の様子を示します。
ぱっと見、こちらのシリアルプログラミングモードと同じ画像に見えますが、上図はI2C信号線(SCL,SDA)と、ATtiny85からの一定周波数PWM出力をUNOに接続しているので、配線が少し異なっています。
準備完了です。クライマックスへ進めましょう。
ATtiny2313の時にも実施した事のある実験ですので、淡々と進めてデータを取得しましょう。UNOのシリアルモニタから、以下の様に実行します。
実験サンプル:【 】内はシリアルモニタからの送信データ
【eval】
0,5045
1,5071
2,5093
3,5118
:
: (中略)
:
250,16284
251,16467
252,16537
253,16729
254,16849
255,17071
OK: eval
上の様に取得したデータをExcelに取り込んでグラフ化📈しました(下図)。
横軸にOSCCALレジスタへの設定値、縦軸に対応する発振周波数[kHz]を取ったグラフです。
手持ちの個体(ATtiny85)は、上図の通り、約5MHz〜17MHzまで発振しました。
※上の結果は、手元のATtiny85チップ1個の測定結果です。個体差があるため、皆様お手元のATtiny85が同様な周波数範囲で発振する保証はありません。
工場出荷時の校正では、OSCCAL=0x59で8MHzという結果でしたが、上の評価結果だと、OSCCAL=0x57とした時が、一番8MHzに近い値だと判りました。
当方の校正結果では:
偏差の要因として考えられる1つには、工場出荷時、周波数の精度を上げようとすると、それだけテスト時間がかかり、その分製造コストが上がってしまうため、精度を犠牲にしてコストを下げた結果、0x59という設定値で出荷された、と考えられます。その場合には、自分で校正した結果を使って、より精度の高い周波数(8MHz)で発振させることができます。
あるいは、神様としたUNOの水晶発振子に、16.000MHzからの誤差があるのかもしれません。
※一般的な水晶発振子のデータシートで確認してみると、Frequency Tolerance=±30ppm @25±3[℃]なので、スペック通りなら、そんなにズレは無いはず……。逆に、工場出荷時校正値をOSCCAL=0x59 @8.000MHzだとする神様に設定すると、UNOの発振周波数を逆算したり、上の実験で計測した校正テーブルを再校正することができたりします。「誰」を神様に祭り上げるのか?と言う、結構、根深い問題です。
前節の実験によって、手元のATtiny85は、OSCCAL>>0x59の値に設定することで最大17MHzで動作させることが可能なことが判りました。しかも、ATtiny85にはPLLも内蔵されていて、RC発振器の周波数を×2逓倍したクロックでCPUを動作させることができます。
つまり、RC発振器周波数17MHz(MAX)×2逓倍(PLL)=34MHzで動作させることができるかもしれない個体だという事です。
さすがに、たった8ピンのATtiny85を34MHzで高速動作させるアプリケーションが思いつかなかったので、当方では詳細な評価を実施していませんし、当然、ATtiny85の動作保証範囲外なので、自己責任となります。
こちらで提案した使い方を実践して、Arduino UNO等(ATmega328)で作ったアプリケーションをATtiny85へ移植する場合を考えてみましょう。ATtiny85にて16MHzの動作周波数が必要なケースでは、PLLを使って16MHz動作させることは動作保証範囲に含まれます。
Arduino IDEのメニュー設定項目:
これでUNOと同じパフォーマンスを得ることができ、しかも、動作保証範囲内での使用が可能なのです。そうなると、自己責任でクロックアップしてまで使いたいというモチベーションは、個人的には無いですね。
ATtiny85は、メモリ容量や、機能、I/Oポート数などの折り合いさえつくなら、Arduino UNOからの移植で、より省スペースに実装できるMCUだと確認できました。考えてみてください。UNOの機体が8DIPのATtiny85になって、省スペースに実装できるのですから、凄いんです。