arduino를 장시간 움직이면 멈추기 때문에 정기적으로 리셋을 걸도록 했다.

19542 단어 ArduinoGoogleHomeIRKit
이 기사에 썼지만 현재 집에서는 IRKit과 Arduino를 사용하여 (매우 물리적인) 홈 오토메이션을 실현하고 있다.
Google Home, IRKit 및 Arduino로 홈 오토메이션
↓Youtube입니다
똑똑하지 않은 벽 스위치를 arduino, IRKit 및 Google Home에서 이동합니다.
スマートでない壁スイッチをarduinoとIRKitとGoogleHomeで動かす。

하지만.



arduino로 벽 스위치를 물리적으로 밀고 있는 것이지만, 이 arduino, 장시간 움직이면 고확률로 멈춘다.
흐름적으로는, Google Home→IRKit→적외선 발신→arduino로 서보 모터를 이동한다
라는 느낌이지만, IRKit로 적외선을 내는 곳까지는 움직이고 있지만, 중요한 arduino가 적외선을 인식해주지 않는다.

대체로 반나절 정도 움직이면 멈추는 일이 많은 것 같다. (시간은 편차가 있는 것 같다.)
원인은 다수 생각된다,
· 프로그램적으로 뭔가 메모리 누수? 일이 일어나고 있습니까?
・전력이 부족하다(서보 모터 2개와 다른 스위치 컨트롤용으로 릴레이를 움직이고 있으므로, 당연히 부족하다. 당연하다.)

아마 전력이 부족한 것이 원인이지만, 멈추면 리셋 버튼을 누르면 다시 고치므로,
정기적으로 리셋을 걸고 싶다.

워치독 타이머를 사용한다.



이쪽의 기사를 참고로 했다. (원형 파크리)
Arduino에서 소프트웨어에서 재설정하는 방법
#include <Servo.h>
#include <avr/wdt.h>

Servo servo1;
Servo servo2;

#define IR_PIN      11    // 赤外線受信モジュール接続ピン番号
#define DATA_POINT  3           // 受信したデータから読取る内容のデータ位置

// 初期化処理
void setup()
{
  pinMode(7, OUTPUT);
  pinMode(2, OUTPUT);
  Serial.begin(9600) ; // パソコン(ArduinoIDE)とシリアル通信の準備を行う
  pinMode(IR_PIN, INPUT) ; // 赤外線受信モジュールに接続ピンをデジタル入力に設定
  software_reset();
}
// メインの処理
void loop()
{
//なにもしましぇーーーーん
}

//リセット用
void software_reset() {
  wdt_disable();
  wdt_enable(WDTO_8S);
  Serial.print("リセットしました");
  while (1) {

  int ans ;
  ans = IRrecive() ;                      // 赤外線リモコンのデータを受信する
  if (ans != 0) Serial.println(ans, HEX) ; // リモコンからデータを受信したら表示する
  if (ans != 0) {
    switch (ans) {
      case 0x84: // スクリーンを下げる
        digitalWrite(7, 1);
        delay(500);
        digitalWrite(7, 0);
        break ;
      case 0x85: //スクリーンを上げる
        digitalWrite(2, 1);
        delay(500);
        digitalWrite(2, 0);
        break ;
      case 0x86: //ライトオン
        servo1.attach(9);
        servo1.write(105);
        delay(500);
        servo1.write(90);
        delay(100);
        servo1.detach();
        break ;
      case 0x87: //ライトオフ
        servo1.attach(9);
        servo1.write(70);
        delay(500);
        servo1.write(90);
        delay(100);
        servo1.detach();
        break ;
        case 0xE: //調光暗く
        //dim down
        servo2.attach(5);
        servo2.write(180);
        delay(500);
        servo2.detach();
        delay(100);
        break ;
        case 0x1A: //調光明るく
        //dim up
        servo2.attach(5);
        servo2.write(0);
        delay(500);
        servo2.detach();
        break ;

        default:
        return 0;
        break;
    }
  }
 }
}

// 赤外線リモコンのデータを受信する処理関数
int IRrecive()
{
  unsigned long t ;
  int i , j ;
  int cnt , ans ;
  char IRbit[64] ;

  ans = 0 ;
  t = 0 ;
  if (digitalRead(IR_PIN) == LOW) {
    // リーダ部のチェックを行う
    t = micros() ;                          // 現在の時刻(us)を得る
    while (digitalRead(IR_PIN) == LOW) ;  // HIGH(ON)になるまで待つ
    t = micros() - t ;          // LOW(OFF)の部分をはかる
  }
  // リーダ部有りなら処理する(3.4ms以上のLOWにて判断する)
  if (t >= 3400) {
    i = 0 ;
    while (digitalRead(IR_PIN) == HIGH) ; // ここまでがリーダ部(ON部分)読み飛ばす
    // データ部の読み込み
    while (1) {
      while (digitalRead(IR_PIN) == LOW) ; // OFF部分は読み飛ばす
      t = micros() ;
      cnt = 0 ;
      while (digitalRead(IR_PIN) == HIGH) { // LOW(OFF)になるまで待つ
        delayMicroseconds(10) ;
        cnt++ ;
        if (cnt >= 1200) break ;    // 12ms以上HIGHのままなら中断
      }
      t = micros() - t ;
      if (t >= 10000) break ;      // ストップデータ
      if (t >= 1000)  IRbit[i] = (char)0x31 ;  // ON部分が長い
      else            IRbit[i] = (char)0x30 ;  // ON部分が短い
      i++ ;
    }
    // データ有りなら指定位置のデータを取り出す
    if (i != 0) {
      i = (DATA_POINT - 1) * 8 ;
      for (j = 0 ; j < 8 ; j++) {
        if (IRbit[i + j] == 0x31) bitSet(ans, j) ;
      }
    }
  }
  return ( ans ) ;
}

리셋 부분의 메인은 여기 같다.
#include <avr/wdt.h>//ライブラリのインクルード
//リセット用
void software_reset() {
  wdt_disable();
  wdt_enable(WDTO_8S);
  Serial.print("リセットしました");
  while (1) {}
}

software_reset()이라는 함수를 만들고,wdt_disable(); → 워치독 타이머를 무효로 (초기화 처리)wdt_enable(WDTO_8S); → 워치독 타이머를 활성화합니다. ()의 내용은 시간을 지정한다. 이번에는 8S(8초)Serial.print("リセットしました"); → 리셋하면 로그를 토한다while (1) {} → 평상시는 loop 함수를 메인에 사용하지만, 이번에는 워치독 타이머를 루프 시키므로, 여기가 메인 루프가 된다. {} 안에 좋아하는 처리를 쓰자! !
#include <avr/wdt.h>→avr/wdt.h라는 라이브러리를 잡자! 잊지 않고 포함합시다!

그리고, 나머지는 이것을 void setup() 안에서 불러 주면, 이 워치독 타이머의 루프가 스타트한다.

이제 8초마다 스스로 리셋을 걸어 초기화할 수 있게 되었다! ! 해야.

잠시 운용해 보십시오.

좋은 웹페이지 즐겨찾기