右辺はpinModeと同様です。, loop関数内の3行目が、digitalWrite(13, LOW);に対応します。 どこのピンで使えるかというと、12ピンがRX(受信)で10ピンがTX(送信)となります。, ただ10ピンと12ピンはSPIにも使われていますので、SPI通信を犠牲にしてしまうことになります。, 今度は先と同じようにSerial3というものを使えるようにします。 使い分けをしなくてもいいのでそちらに置き換えることをおすすめします。, これはただの注意事項ですが、Arduino M0はADCの基準電圧がデフォルトでは1.65Vになっています。 時間を操作するときにdelay関数をよく使いますが、これを使うとdelayで指定した時間が経過するまで、プログラムが止まってしまいます。メインのプログラムは動かし続けた状態で、 時間を計測したい場合は、割り込みタイマーを使うと良いです。, Arduino Unoは、AVR ATmega328Pというマイコンを搭載しており、このマイコンにはTimer0, Timer1, Timer2の3つのタイマーがあります。このタイマーを利用して、時間を計測することが出来ます。ただし、使用する際には注意が必要です。各タイマーは、PWM波形を出力するために使用したり、delay関数などに使用します。各タイマーの割当を以下に記載します。, Timer0はdelay関数で使うので、これを使用できる機会はなかなか無いと思います。よく使われるのはTimer2です。今回はTimer2を使用したプログラムを書きます。, Timerのライブラリはいくつかありますが、ここでは「MsTimer2」を紹介します。MsTimer2は、Arduino-IDEの[ツール]->[ライブラリを管理]からインストールできます。下記のウィンドウが開いたら、検索ボックスにmstimer2と入力すれば、下記のように表示されると思いますので、クリックしてインストールして下さい。, ①MsTimer2::set(unsigned long ms, void (*f)())  第一引数にタイマーの時間をミリ秒単位で入力します。第二引数は、タイマーの時間が経過したとき(割り込み)に呼び出す関数です。. Arduinoでタイマー割り込み 前回の記事(Arduinoを使ってみよう)で簡単な時間計測プログラムを作成しましたが実は正確ではありません。 なぜならば、デッドラインを意識したリアルタイム設計が成されていないからです。 また、5ピンがRX(受信)で4ピンがTX(送信)となります。, ちなみにこれと同じような感じでSPIやI2Cも複数チャンネルにできるそうです。 Unoの3倍というわけにはいかないですけど、高速化はできています。, M0ではシリアル通信はSerialUSBとSerial5が使えますが、SoftwareSerialライブラリが使えません。 2020.05.20 2020.08.27. Arduino.orgのものは何気に初めてだったりします。 欠点として入力トレラント機能がなかったり、最大出力電流が小さかったりするのですが。 比較するプログラムはArduino Unoの時と同じです。 シリアル通信によって、データを受信したり送信したりする関数です。 Serial.readBytes()などはこれらの拡張ですので、とりあえずこの2つから。 Serial.write()でArduinoからシリアル通信によってデータを1byte分送信します。Serial.read()で逆に1byte分受信します。 小型にしたいけど、小さい記号菅がないんだよなあ これ以上増やせないのはちょっと不便なときも出てくるのではないでしょうか。 ただ、どこまで複雑にしても使えるのかが心配です、SRAM結構食いそうですしね。 ArduinoでSTEM教育 応用編:割り込みタイマーで時間を計測する 2020年1月25日 by STEMSHIP 1 コメント 時間を操作するときにdelay関数をよく使いますが、これを使うとdelayで指定した時間が経過するまで、プログラムが止まってしまいます。 © 2020 エンため All rights reserved. ここの値で呼び出される間隔を変えることができます。 Arduino DueのIOは3.3V入力ですが,エンコーダの5V出力を直接つなぎました.推奨しません. プログラム. P制御だと定常偏差が残ってしまう理由を「最終値の定理」を使わずに解説. 周波数は1.6MHz程度になっています。 そのためライブラリが動かなかったり専用になってしまうところもあるそうで・・・ 2020.05.07 2020.08.20. ただ、もう1つ使えるようにするには次のファイルを編集する必要があります。, このファイルの中のPinDescription g_APinDescription[]という配列の最後に以下の記述を加えます。, 書き換えたらSerial2と同じような記述で使えるようになります。 そのため回路図からどのポートを使うか調べる必要があります。 Copyright© 物を作る者 , 2020 All Rights Reserved. タイマー割り込みでLEDを点滅させます 〔Arduinoの動かせ方入門に戻る〕 タイマー(TIMER2)割り込みを利用してボードに付属(搭載)の 13番ピン接続LED を点灯させます。 それでも私は高性能なArduino M0をもっと使ってやりたいのです。, 基本的にArduino UnoなどとはMCUがまったく違うのでアーキテクチャも異なります。 Arduinoでプログラムを開始してからの時間を調べたり、一定周期ごとに割り込みを行う方法について解説します。delayを使うと他の処理を実行できなくなるので、なるべく使わないほうが良いでしょう。デジタル時計のように時間を表示させるプログラム例も紹介しています。 タクトスイッチを押すと点滅していたLEDの処理が中断され、圧電スピーカが1秒間音を鳴らす。, ・Arduinoメインボード(https://amzn.to/2vkPIUH) ・USBケーブル(https://amzn.to/2UHhntl) ・ブレッドボード(https://amzn.to/38eNi8u) ・ジャンパワイヤ (https://amzn.to/39uBU8T) ・タクトスイッチ(https://amzn.to/3aVZe0k) ・LED(https://amzn.to/2TvEPGc) ・圧電スピーカ(https://amzn.to/2CkhvnO), 外部から割り込みの命令を受けた際、実行している処理を中断して他のプログラムを実行することを割り込み処理といいます。, 割り込み処理が終了後元のループに戻り、中断された処理のところから処理が再開されます。, 時間ごとに決まった処理をするためや、これから起こりうる可能性のある要求を別の処理をしながら待機するときなどに使用されます。, Arduinoの割り込み処理として、割り込み処理関数「attachInterrupt」が存在するので、これを使用します。, 今回のプログラムはこれまで記事にした圧電スピーカ、LED、タクトスイッチのプログラムを利用して書いています。, マイコンボードに書き込んでスイッチを押すと以下の動画のように割り込み処理が行われていることがわかると思います。. タイマー割り込みを使用すると、コード内で他に何が起こっているかに関係なく、非常に具体的な時間間隔でタスクを実行できます。この命令では、比較一致またはCTCモードのクリアタイマーで割り込みを設定して実行する方法を説明します。サンプルコードをお探しの場合は、手順2に進んでください。, 通常、Arduinoスケッチを書くとき、Arduinoはloop(){}関数にカプセル化されたすべてのコマンドをそれらが書かれた順序で実行しますが、イベントをloop()内でタイミングを合わせることは困難です。いくつかのコマンドは他のものより実行に時間がかかり、あるものは条件文(if、while …)に依存し、いくつかのArduinoライブラリ関数(digitalWriteやanalogReadのような)は多くのコマンドで構成されています。 Arduinoのタイマー割り込みを使用すると、loop()関数内で発生する通常のイベントシーケンスを正確な時間間隔で瞬間的に一時停止しながら、別のコマンドセットを実行できます。これらのコマンドが実行されると、Arduinoはloop()内のどこに戻ったかを再びピックアップします。, 等間隔で入力信号を測定する(一定のサンプリング周波数) 2つのイベント間の時間を計算する 特定の周波数の信号を送信する 定期的に着信シリアルデータをチェックする もっと…, 割り込みを行う方法はいくつかありますが、ここでは、最も有用で柔軟性の高いタイプ(比較一致またはCTCモードでのクリアタイマー)に焦点を当てます。さらに、このインストラクターでは、Arduino Uno(およびATMEL 328/168 … Lilypad、Duemilanove、Diecimila、Nanoなどを含む他のArduino)へのタイマーについて具体的に説明します。ここに提示された主な考えはメガとより古いボードにも同様に当てはまります、しかしセットアップは少し異なっていて、そして下のテーブルはATMEL 328/168に特定です。, Unoには、timer0、timer1、timer2という3つのタイマーがあります。各タイマーには、タイマーのクロックの各チックでインクリメントされるカウンターがあります。カウンタがコンペアマッチレジスタに格納された指定値に達すると、CTCタイマ割り込みがトリガされます。タイマ / カウンタがこの値に達すると、そのタイマ / カウンタの次の刻時で解除(0に再設定)され、その後再び比較一致値まで計数を続けます。コンペアマッチ値を選択し、タイマがカウンタをインクリメントする速度を設定することで、タイマ割り込みの頻度を制御できます。 最初に説明するパラメータは、タイマーがカウンターを増分する速度です。 Arduinoのクロックは16MHzで動作します。これはタイマーがカウンターをインクリメントできる最も速い速度です。 16MHzでは、カウンタの各ティックは1 / 16,000,000秒(〜63ns)を表します。したがって、カウンタの値が9になるまでに10 / 16,000,000秒かかり(カウンタのインデックスは0)、値に達するまでに100 / 16,000,000秒かかります。 99の 多くの場合、カウンタ速度を16MHzに設定するのは速すぎることがわかります。 Timer0とtimer2は8ビットタイマーで、最大カウンター値255を格納できます。Timer1は16ビットタイマーで、最大カウンター値65535を格納できます。カウンターが最大値に達すると、ゼロに戻ります。 (これはオーバーフローと呼ばれます)。つまり、16MHzでは、コンペアマッチレジスタを最大カウンタ値に設定しても、8ビットカウンタの場合は256 / 16,000,000秒(約16us)、割り込みの場合は65,536 / 16,000,000(約4 ms)秒ごとに割り込みが発生します。 16ビットカウンタ明らかに、これは1秒に1回だけ割り込みたい場合にはあまり役に立ちません。 代わりに、プリスケーラと呼ばれるものを使用して、タイマーカウンタの増分速度を制御できます。プリスケーラは次の式に従ってタイマーの速度を決定します。(タイマー速度(Hz))=(Arduinoクロック速度(16MHz))/プリスケーラ そのため、1プリスケーラは16MHzでカウンタをインクリメントし、8プリスケーラは2MHzでカウンタをインクリメントし、64プリスケーラは250kHzとなります。上の表に示されているように、プリスケーラは1、8、64、256、および1024に等しい場合があります(次のステップでCS12、CS11、およびCS10の意味を説明します)。 これで、次の式で割り込み頻度を計算できます。割り込み周波数(Hz)=(Arduinoのクロック速度16,000,000Hz)/(プリスケーラ*(コンペアマッチレジスタ+ 1)) コンペアマッチレジスタのインデックスが0であるため、+ 1が入ります。 上記の式を整理すると、希望の割り込み周波数を与えるコンペアマッチレジスタの値を求めることができます。コンペアマッチレジスタ= 16,000,000Hz /(プリスケーラ×希望割込み周波数) - 1 あなたがタイマー0と2を使うとき、この数は256未満でなければならず、timer1のために65536未満でなければならないことを覚えていてください あなたが毎秒割り込み(周波数1Hz)が欲しいならば: コンペアマッチレジスタ= 16,000,000 /(プリスケーラ* 1) -1 1024のプリスケーラを使用すると、あなたが得る: コンペアマッチレジスタ= 16,000,000 /(1024 * 1) -1 = 15,624 256 <15,624 <65,536なので、この割り込みにはtimer1を使用する必要があります。, //http://www.instructables.com/id/Arduino-Timer-Interrupts/ void setup()=(1 << OCIE2A); sei(); //割り込みを許可する//セットアップを終了する OCR#Aの値(コンペアマッチ値)がこれらの各タイマー設定でどのように変わるかに注目してください。最後のステップで説明したように、これは次の式に従って計算されました。 コンペアマッチレジスタ= 16,000,000Hz /(プリスケーラ×希望割込み周波数) - 1 あなたがタイマー0と2を使うとき、この数は256未満でなければならず、timer1のために65536未満でなければならないことを覚えていてください CTCモードをオンにする行では、3つのタイマー間の設定がわずかに異なることにも注意してください。 TCCR0A | =(1 << WGM01); // timer0の場合 TCCR1B | =(1 << WGM12); // timer1の場合 TCCR2A | =(1 << WGM21); // timer2の場合 これはATMEL 328/168のデータシートから直接続きます。 最後に、最後のステップでプリスケーラの設定がテーブルにどのように従っているかに注目してください(上記のタイマー0のテーブルが繰り返されます)。 TCCR2B | =(1 << CS22)。 //タイマー2の64プリスケーラにCS#2ビットを設定 TCCR1B | =(1 << CS11); //タイマ1の8プリスケーラにCS#1ビットを設定 TCCR0B | =(1 << CS02)| (1 << CS00)。 // CS#2およびCS#0ビットをタイマー0の1024プリスケーラに設定 最後のステップでは、タイマーごとに異なるプリスケールオプションがあることに注意してください。たとえば、timer2には1024プリスケーラのオプションはありません。 これらのタイマー割り込み中に実行したいコマンドは、以下にカプセル化されたArduinoスケッチにあります。 ISR(TIMER0_COMPA_vect){// timer1の0を1に、timer2の2を変更 //割り込みコマンド } このコードは、setup()およびloop()関数の外側に配置する必要があります。また、特にあなたが高頻度で割り込んでいる場合は、割り込みルーチンをできるだけ短くするようにしてください。 digitalWrite()およびdigitalRead()関数を使用する代わりにATMELチップのポート/ピンを直接アドレス指定する価値があるかもしれません。あなたはそれに関するより多くの情報をここで見つけることができます。 例 - 次のスケッチは、3つのタイマー割り込みを設定して実行します。, //タイマー割り込み// by Amanda Ghassaei // 2012年6月//http://www.instructables.com/id/Arduino-Timer-Interrupts/ / * *このプログラムはフリーソフトウェアです。あなたはそれを再配布したり、Free Software Foundationによって発行されたGNU General Public Licenseの条件の下で変更することができます。ライセンスのバージョン3、またはそれ以降のバージョン*(お客様の選択による)。 * * / // timer0、timer1、timer2のタイマー設定。 // arduinoのunoまたはATMEL 328/168を持つボードの場合.. diecimila、duemilanove、lilypad、nano、mini … //このコードは3つすべてのarduinoタイマー割り込みを有効にします。 // timer0は2kHzで中断する// timer1は1Hzで中断する// timer2は8kHzで中断する//記憶域変数boolean toggle0 = 0; boolean toggle1 = 0。 toggle2 = 0です。 void setup()=(1 << OCIE0A); //タイマ1割り込みを1Hzに設定TCCR1A = 0; // TCCR1Aレジスタ全体を0に設定TCCR1B = 0; // TCCR1Bと同じTCNT1 = 0; //カウンタ値を0に初期化// // 1hzインクリメント用コンペアマッチレジスタを設定OCR1A = 15624; // =(16 * 10 ^ 6)/(1 * 1024) - 1(<65536である必要があります)// CTCモードをオンにしますTCCR1B //セットアップを終了しますISR(TIMER0_COMPA_vect){// timer0割り込み2kHzトグルピン8 //(toggle0){digitalWrite(8、HIGH); //周波数2kHz / 2 = 1kHzのパルス波を生成します(全波トグルがハイ、次にトグルがローになるには2サイクルかかります)。 toggle0 = 0;その他{digitalWrite(8、LOW); toggle0 = 1; ISR(TIMER1_COMPA_vect){// timer1割り込み1Hzトグルピン13(LED)//周波数1Hz / 2 = 0.5kHzのパルス波を発生(全波トグルがハイ、トグルがローになるまで2サイクルかかります) digitalWrite(13、HIGH); toggle1 = 0; } else {digitalWrite(13、LOW); toggle1 = 1; ISR(TIMER2_COMPA_vect){// timer1割り込み8kHzピン9を// // 8kHz / 2 = 4kHzの周波数のパルス波を発生させます(全波トグルがハイ、その後トグルがローになるには2サイクルかかります)場合、(toggle2){digitalWrite(9、高い); toggle2 = 0; } else {digitalWrite(9、LOW); toggle2 = 1; void loop(){//ここで他のことをする} 上の画像は、これらのタイマー割り込みからの出力を示しています。図1は0〜5Vで1kHzで振動する方形波(timer0割り込み)を示し、図2は13番ピンに接続されたLEDが1秒間点灯し、次に1秒間消灯する(timer1割り込み)、図3はパルス波振動を示します4kHzの周波数で0と5Vの間(timer2割り込み)。, //バイクスピードメーター// Amanda Ghassaei 2012 //http://www.instructables.com/id/Arduino-Timer-Interrupts/ //http://www.instructables.com/id/Arduino-Timer-Interrupts/ / * *このプログラムはフリーソフトウェアです。あなたはそれを再配布したり、Free Software Foundationによって発行されたGNU General Public Licenseの条件の下で変更することができます。ライセンスのバージョン3、またはそれ以降のバージョン*(お客様の選択による)。 * * / //サンプル計算//タイヤ半径〜13.5インチ//円周= pi * 2 * r = 〜85インチ//最大速度35mph = 〜616インチ/秒//最大rps = 〜7.25 #define reed A0 / //読み取りスイッチに接続された//ストレージ変数float radius = 13.5; //タイヤ半径(インチ) - 自分の自転車用にこれを変更するint reedVal; long time = 0; // 1回転の間の時間(ミリ秒)float mph = 0.00;フロート円周ブールバックライト。 int maxReedCounter = 100; // 1分の回転の最小時間(ミリ秒単位)(デバウンス用)int reedCounter; void setup()=(1 << WGM12); // 8プリスケーラのCS11ビットをセットTCCR1B void checkBacklight(){バックライト= digitalRead(2); if(バックライト){Serial.write(17); //バックライトをオンにする} else {Serial.write(18); //バックライトをオフにする}} ISR(TIMER1_COMPA_vect){//リードスイッチを測定するために1kHzの周波数で割り込みreedVal = digitalRead(reed); //(reedVal){//リードスイッチが閉じている場合は(reedCounter == 0){//パルス間の最小時間が経過した場合、A0の値を取得mph =(56.8 * float(周囲)) )/ float(time); //毎時マイルの計算time = 0; //タイマーのリセットreedCounter = maxReedCounter; // reset reedCounter} else {if(reedCounter> 0){// reedCounterを負の値にしないreedCounter - =(1; // reedCounter}} else {//(r​​eedCounter> 0)の場合にリードスイッチが開いている場合{// reedCounterを負の値にしないreedCounter - = 1; // // reedCounter}}の場合(time> 2000){mph = 0; //リードスイッチからの新しいパルスがまだ残っていない場合は、mphを0に設定してください。else {time + = 1; // // increment timer}} void displayMPH(){Serial.write(12) ; // Serial.write( "Speed =")をクリアします。 Serial.write(13); //改行しますSerial.print(mph); Serial.write( "MPH"); //Serial.write ("0.00 MPH "); } void loop(){// mphを2回表示する。遅延(1000)。 checkBacklight(); }, // BUTTON TEST w / 74HC595と74HC165およびシリアル通信// Amanda Ghassaei // 2012年6月//http://www.instructables.com/id/Arduino-Timer-Interrupts/ / * *このプログラムはフリーソフトウェアです。あなたはそれを再配布したり、Free Software Foundationによって発行されたGNU General Public Licenseの条件の下で変更することができます。ライセンスのバージョン2、または*(あなたの選択による)それ以降のバージョン。 * * / //このファームウェアはmaxmspパッチ「ビートスライサ」でデータを送受信します//ピンの接続#define ledLatchPin A1 #define ledClockPin A0 #define ledDataPin A2 #define buttonLatchPin 9 #define buttonClockPin 10 #define buttonDataPin A3 / /ループ変数バイトi。バイトj;バイトk;バイトledByte。 // LED状態用ストレージ、4バイトbyte ledData = {0、0、0、0}; //ボタン用ストレージ、4バイトbyte buttonCurrent = {0,0,0,0}; byte buttonLast = {0,0,0,0}; byte buttonEvent = {0,0,0,0}; byte buttonState = {0,0,0,0}; //ボタンデバウンスカウンタ - 16バイトbyte buttonDebounceCounter 4 4; void setup()=(1 << WGM21); // 8プリスケーラのCS21ビットを設定TCCR2B // buttonCheck - 指定されたボタンの状態をチェックします。 //このボタンチェック関数は、brian crabtreeとjoe lakeによってmonome 40hファームウェアから主にコピーされています。void buttonCheck(byte row、byte index){if(((buttonCurrent row ^ buttonLast row)&(1 << index) )&& //現在の物理ボタンの状態が((buttonCurrent row ^ buttonState row)&(1 << index)))){//最後の物理ボタンの状態および(buttonCurrentの場合は現在のデバウンスされた状態) row&(1 << index))//現在の物理ボタンの状態が押された場合buttonEvent row = 1 << index; // buttonイベントをすぐにキューに入れるbuttonState row else {buttonDebounceCounter row index = 12; //それ以外の場合は、ボタンは以前に押されていて//現在リリースされているので、デバウンスカウンタを設定します。 else if((((buttonCurrent row ^ buttonLast row)&(1 << index))== 0 && //現在の物理ボタンの状態が(buttonCurrent row ^ buttonState rowと同じ場合) )&(1 << index)){//最後の物理的なボタンの状態ですが、現在の物理的な//ボタンの状態は現在のデバウンスとは異なります//状態… if(buttonDebounceCounter row index> 0 && - -buttonDebounceCounter row index == 0){//デバウンスカウンタが// 0にデクリメントされた場合(//ボタンは// //ボタンの最大表示時間まで// // //繰り返し回数/// buttonEvent row = 1 << index; //(buttonCurrent row&(1 << index))//ボタンの状態変更イベントをキューに入れ、//ボタンのデバウンス状態を切り替えますbuttonState row else {buttonState row& =〜(1 << index);}}}} void shift(){(i = 0; i <4; i ++){buttonLast i = buttonCurrent i; byte dataToSend =(1 <<(i) +4))|(15&〜ledData i); //ビットの送信中にLEDが変化しないようにラッチピンをローに設定するdigitalWrite(ledLatchPin、LOW); // sh dataToSendのビット数shiftOut(ledDataPin、ledClockPin、LSBFIRST、dataToSend)を取り出します。 // LEDが新しいデータを受け取るようにラッチピンをハイに設定するdigitalWrite(ledLatchPin、HIGH); // 1行がハイに設定されたら、ボタンからデータを受信します//ラッチピンをハイに設定しますdigitalWrite(buttonLatchPin、HIGH); //データをシフトインbuttonCurrent i = shiftIn(buttonDataPin、buttonClockPin、LSBFIRST)>> 3; //ラッチピンが低いdigitalWrite(buttonLatchPin、LOW); (k = 0; k <4; k ++){buttonCheck(i、k); if(buttonEvent i <> 1)&3;バイトledx =(ledバイト>> 3)&3; if(ledstate)ledData ledy else {ledData ledy&=〜(8 >> ledx); (Serial.available()> 8);}}} //シリアルが利用可能な場合は終了します。 void loop(){shift(); //ボタンを更新してボタンからデータを受け取る} 下記のMaxMSPパッチをダウンロードしてください(Max Runtimeでも動作します)。, // 63Hz正弦波// by Amanda Ghassaei 2012 //http://www.instructables.com/id/Arduino-Timer-Interrupts/ / * *このプログラムはフリーソフトウェアです。あなたはそれを再配布したり、Free Software Foundationによって発行されたGNU General Public Licenseの条件の下で変更することができます。ライセンスのバージョン3、またはそれ以降のバージョン*(お客様の選択による)。 * * / // 63Hzの正弦波をarduinoのPORTD DACに送信します。float t = 0; void setup()=(1 << OCIE2A); sei(); //割り込みを許可するISR(TIMER2_COMPA_vect){//インクリメントt t + = 1; if(t == 628){// 40kHz / 628 =〜63Hz t = 0; void loop(){//周波数〜63Hzの正弦波// 0から255までの正弦波の値をPORTDに送信するPORTD = byte(127 + 127 * sin(t / 100)); } 私は40kHzの周波数で変数tを増加させるタイマー割り込みを設定しました。 tが627に達すると、ゼロにリセットされます(これは40,000 / 628 = 63Hzの周波数で発生します)。一方、メインループでArduinoは0(2進数で00000000)から255(2進数で11111111)までの値をデジタルピン0から7(PORTD)に送信します。次の式でこの値を計算します。PORTD =バイト(127 + 127 * sin(t / 100))。 したがって、tが0から627まで増加するにつれて、サイン関数は1つの完全なサイクルを通過します。 PORTDに送信される値は、周波数63Hz、振幅127の正弦波で、127を中心に発振します。これが8ビット抵抗ラダーDACを介して送信されると、振幅2.5V、周波数63Hzの約2.5Vの発振信号を出力します。 正弦波の周波数は、(t / 100)項に2を掛けることによって2倍にすることができ、4を掛けることによって4倍にすることができます。 また、プリスケーラまたはOCR2Aを下げてタイマ割り込みの頻度を上げすぎると、正弦波が正しく出力されません。これは、sin()関数が計算コストが高く、高い割り込み頻度では実行するのに十分な時間がないためです。割り込みルーチン中に計算を実行する代わりに、高頻度割り込みを使用している場合は、値を配列に格納し、これらの値をある種のインデックスを使用して呼び出すことを検討してください。私のarduinoの波形ジェネレータではその一例を見つけることができます。20,000のsinの値を配列に格納することによって、100kHzのサンプリング周波数で正弦波を出力することができました。, 最後に注意すべきことは、特定のタイマー設定は実際にはArduinoライブラリ関数のいくつかを無効にすることです。 timer0は関数millis()およびdelay()によって使用されます。timer0を手動で設定した場合、これらの関数は正しく機能しません。 さらに、3つのタイマーすべてが関数analogWrite()を引き継いでいます。手動でタイマーを設定すると、analogWrite()が機能しなくなります。 あなたが中断したくないコードの部分があるなら、グローバルに割り込みを無効にし有効にするためにcli()とsei()を使うことを検討してください。 これについてはArduinoのWebサイトで確認できます。.