Arduinoでソフトウェアからリセットをかける方法

Arduinoは大抵の基板に搭載されているボタンを押したり、RESETピンをGNDに落としたりすることでリセットをかけることができます。
また、Arduinoにはオートリセット機能があり、プログラムを書き込むときやシリアル通信を開始したときにもリセットされます。

リセットがかかればスケッチの一番最初から実行されますし、変数も初期状態になります。
それをハードウェア上のボタンを押さずにソフトからリセットできるなら便利だと思いませんか?
ここではArduinoでソフトウェアリセットをかける様々な方法を紹介していきます。

スポンサーリンク

紹介するのは関数部分だけになります。
その関数を任意の場所に記述し、実行することでリセットをかけることができます。

アセンブラで記述する

この方法はアセンブラのジャンプ命令を使ってプログラム実行位置を先頭に移動させます。
これはUnoやMega、Leonardoではちゃんと動きますが、DueのようなARMコアでは動きません。
コードは以下のとおりです。

void software_reset() {
  asm volatile ("  jmp 0");  
} 

もう1つ違う書き方があります。

void(* resetFunc) (void) = 0;

なぜかArduinoなのに呼び出しより先に宣言しなければいけませんが、これでもOKです。

完全なリセットとは言えず、うまくいかない場合がありました。
もしかしたら割り込みを使っているとダメかもしれません。

ウォッチドッグタイマを使う

ウォッチドッグタイマは定期的に割り込みをかけたりするものですが、リセットを定期的にかけることもできるのでこれを利用します。
これもDueやM0では動きません。

#include <avr/wdt.h>
void software_reset() {
  wdt_disable();
  wdt_enable(WDTO_15MS);
  while (1) {}
}

これを実行すればちゃんとリセットされます。
アセンブラよりはきれいなプログラムだと思います。
ウォッチドッグタイマのライブラリを使いますのでインクルード文を忘れず書いてください。

出力ピンをリセット端子へ接続する

これが一番わかりやすいかもしれませんね。
どこでもいいので出力ピンの1つをリセット端子へ接続してLOWにしたら、リセットがかかりますね。
完全なソフトウェアリセットとは言いづらいですが、すべてのボードで共通して使えます。

例えば13ピンをリセットピンと直結するなら、単純ですけど以下のようになります。

void software_reset() {
  digitalWrite(13, LOW);
} 

直結だとちょっと怖いので抵抗を挟んだりトランジスタを動かしたりした方がいいですね。
個人的にはポートの初期状態が不安なのでトランジスタ等をかますことをおすすめします。

Arduino Due, M0でのソフトウェアリセット

ARMコアであるDueやM0は以下のような記述になります。
私も何だかよく分かっていませんが、とりあえず動きは確認しました。

void software_reset() {
  SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk);
} 

PC側からリセット(Arduino Leonardo)

Arduino Leonardoは少し特殊で、シリアルポートを1200bpsで開けて閉じたときにリセットがかかるようにできています。
これを利用すればPC側からでもリセットをかけることができます。
リセットをかけると10秒くらいは動作できないのでそこが欠点になるかもしれませんが有効な手段だと思います。

ちなみに、LeonardoはUnoと違ってシリアルポートを開けたときに自動でリセットされません。
PCのプログラムでシリアルポートを開けた時にリセットしたい場合はこの手段を使うといいでしょう。


一応全部検証しているので、問題なく動くかと思います。
ソフトからリセットをするなんてあまり使うことはないと思いますが、参考になれば幸いです。

スポンサーリンク

Leave a Comment