見出し画像

ふたまたよくばりーの 6.1

電池機器と100V機器の両方で使えるラッチ&タイマー yokubarino 五号機 のリレー出力を二股化した。


取扱説明書

作 業

すでに入れているメカニカルリレーを2連のものに入れ替え、リレー2出力用のスイッチを増設した。

sketch の書き換えはLOW-ONのリレーからHIGH-ONに入れ替えたのでそれに対応して書き換えた。リレーへのdigital.Wrightを逆にするだけでなく、setup()で小細工が必要だった。増設したリレー2は常時使うことはないので、リレー1のようにオスケーブルを出すのではなく、ジャックにした。使用時にオス-オスケーブルを挿し、リレー2用のスイッチを入れる仕様にした。
また、赤外線出力のライブラリ IRremote.h が新しいバージョンだとPin_3 から出力しないことがわかったので、古いバージョン(2.2.3)に戻した。(試行錯誤な日々を参照)

回 路

 

スケッチ

/* yokubarino_06_01

  リレー2台出力に yokubarino_05_2 から変更
  使ったリレーが LOWでONだったので反転した
  リレーのON・OFF、パルス出力の関数を新たに作る
  ON・OFFパルスモードで起動時にパルス出力されるバグを修正
  使用する<IRremote.h>はver2.2.3を使うこと。新しいバージョンでは動かない
  赤外線出力PinはD3だが<IRremote.h>の中で定義されてる。Pinの指定、setup()でのpinMode設定は不要

  Arduino NANO
                      1・     ・VIN              serial port is COM11 for hp_PC.
                      0・     ・GND
                 Reset・     ・Reset            3,11 is interfered by tone().
                    GND・     ・5V               A6,A7 is analog only.
                      2・     ・A7               0,1 is not for use.
 100ohm + IR LED <--  3・     ・A6
                      4・     ・19/A5
      dip1000_Pin --> 5・     ・18/A4
       dip100_Pin --> 6・     ・17/A3
        dip10_Pin --> 7・     ・16/A2 --> RELAY_2
         dip1_Pin --> 8・     ・15/A1
                      9・     ・14/A0 --> RELAY
                     10・     ・AREF
                     11・     ・3.3V
       input_Pin --> 12・ USB ・13 --> LED(for indicate)

  dip  [リレー出力]
  0000 ダイレクトモード
  0001 ラッチモード
  0010 ONパルスモード(ON時にパルス)
  0011 ON・OFFパルスモード(ON時とOFF時にパルス)
  0100 タイマーモード(2秒)
  0101 タイマーモード(5秒)
  0110 タイマーモード(7秒)
  0111 タイマーモード(10秒)
  1000 タイマーモード(15秒)
       [赤外線出力]
  1001 ダイレクトモード
  1010 ラッチモード
  1011 タイマーモード(2秒)
  1100 タイマーモード(5秒)
  1101 タイマーモード(7秒)
  1110 タイマーモード(10秒)
  1111 タイマーモード(15秒)   */

#include <IRremote.h> // 赤外線送信のライブラリ
                      // ver2.2.3を使用のこと 新しいバージョンでは動かない
#define ON 1
#define OFF 0

//Pin番号の指定
#define input_Pin 12    //外部スイッチ
#define dip1000_Pin 5   //ディップスイッチ  千位(dip3)
#define dip100_Pin 6    //ディップスイッチ  百位(dip4)
#define dip10_Pin 7     //ディップスイッチ  十位(dip2)
#define dip1_Pin 8      //ディップスイッチ  一位(dip1)
#define LED 13          //LED出力
#define RELAY A0        //リレー出力
#define RELAY_2 A2      //リレー2出力
// 赤外線出力 3 → IRremote.h(2.2.3)で定義されている

//状態の定義
#define dip_SW_ON HIGH    //ディップスイッチの入力:ONのときHIGH(pullup抵抗)
#define dip_SW_OFF LOW    //                        OFFのときLOW
#define SW_ON LOW         //外部スイッチの入力:ONのときLOW(pullup抵抗なので)
#define SW_OFF HIGH       //                   OFFのときHIGH
#define OUT_ON HIGH       //リレー、LEDの出力:HIGHでON
#define OUT_OFF LOW       //                  LOWでOFF
#define FLG_ON 1          //フラグ
#define FLG_OFF 0

#define RELAY_mode 1        //timer関数用パラメータ
#define IR_LED_mode 2       //timer関数用パラメータ
#define ON_pulse_mode 1     //pulse関数用パラメータ
#define ON_OFF_pulse_mode 2 //pulse関数用パラメータ
#define IR_signal_mode 3    //pulse関数用パラメータ

//変数の定義
int khz = 38;   //赤外線出力関係
IRsend irsend; //  〃
int mode = 0;             //入力モード(4ケタの値、ディップスイッチで決定)
int SW_state = SW_OFF;    //外部スイッチ入力の入力状態
int old_SW_state = SW_OFF;// 古い外部スイッチの状態 (初期設定はOFF)
int LED_state = FLG_OFF;  // LED点滅の状態 (初期設定はOFF)
int pulse_time = 100;     //パルス出力時間(ミリ秒)

//  赤外線信号を出す関数の定義
void send_signal(int ONorOFF) {
  switch (ONorOFF) {  // シリアルモニター出力用
    case (ON): Serial.println("ON"); break;
    case (OFF): Serial.println("OFF"); break;
  }
  if ( ONorOFF == ON) {   //ONの赤外線信号を送信する
    unsigned int irSignal[59] = {2572, 2660, 832, 852, 832, 852, 832, 1892, 832, 1892, 828, 1892, 832, 1916, 808, 848, 836, 848, 836, 53960, 2572, 2692, 804, 852, 832, 852, 832, 1916, 808, 1920, 800, 1920, 804, 1916, 804, 852, 836, 848, 836, 53972, 2572, 2692, 804, 852, 836, 848, 836, 1920, 804, 1916, 804, 1920, 804, 1920, 804, 852, 836, 848, 832, };

    irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz);
  }
  if ( ONorOFF == OFF) {  //OFFの赤外線信号を送信する
    unsigned int irSignal[39] = {2572, 2688, 808, 852, 832, 1916, 808, 852, 832, 852, 832, 1916, 808, 880, 804, 1920, 808, 1912, 812, 53968, 2572, 2692, 804, 852, 832, 1916, 808, 852, 832, 852, 832, 1916, 808, 848, 836, 1916, 804, 1916, 808, };
    irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz);
  }
}

void RELAY_ON_OFF(int ON_OFF) { // 2台のリレーのON、OFF
  if (ON_OFF == 1) {            // LOWで出力ON、  HIGHでOFF
    digitalWrite(RELAY, LOW);   //リレー出力ON
    digitalWrite(RELAY_2, LOW); //リレー2出力ON
  } else if (ON_OFF == 0) {
    digitalWrite(RELAY, HIGH);  //リレー出力ON
    digitalWrite(RELAY_2, HIGH);//リレー2出力ON
  }
}

void pulse_ON() { // パルス出力(リレー、LED)
  digitalWrite(LED, OUT_ON);    //LED出力ON
  RELAY_ON_OFF(ON);             //リレー出力ON
  delay(pulse_time);
  digitalWrite(LED, OUT_OFF);   //LED出力OFF
  RELAY_ON_OFF(OFF);            //リレー出力OFF
}

//パルス関数の定義
//  1 ONパルス(スイッチON時にリレーにパルス)
//  2 ON・OFFパルス(スイッチON時とOFF時にリレーにパルス)
//  3 赤外線ダイレクト(スイッチON時に赤外線ONシグナル、OFF時にOFFシグナル)
void pulse(int PULSE_mode) {
  //    Serial.println("void pulse() start. SW_state = ");
//  Serial.println(SW_state);

  if (digitalRead(input_Pin) == SW_ON) { //外部スイッチが押されて、かつ
    if (SW_state == 0) { //OFFからONになったときだけパルス出力する
      SW_state = 1;
      if (PULSE_mode == ON_pulse_mode) {  //ONパルスモード
        pulse_ON();
      } else if (PULSE_mode == ON_OFF_pulse_mode) { //ON・OFFパルスモード
        pulse_ON();
      } else if (PULSE_mode == IR_signal_mode) {  //赤外線ダイレクトモード
        send_signal(ON);  //赤外線ON出力
      }
    }
  }
  else if (SW_state == 1) { //ONからOFFになったとき
    SW_state = 0;
    delay(50);    //チャタリング対策
    if (PULSE_mode == ON_OFF_pulse_mode) { //ON・OFFパルスモード
      pulse_ON();
    } else if (PULSE_mode == IR_signal_mode) {  //赤外線ダイレクトモード
      send_signal(OFF);  //赤外線OFF出力
    }
  }
}
//ラッチ関数の定義
//  外部スイッチをONするたびに出力のON・OFFが切り替わる
// 押し続けてもON・OFFの繰り返しがおこらない
void latch(int OUT_mode) {
  SW_state = digitalRead(input_Pin);    // 外部スイッチの状態を読み取る
  //スイッチがON、前回がOFFだったとき
  if ( SW_state == SW_ON && old_SW_state == SW_OFF ) {
    //LED点滅の状態を切り替える
    if (LED_state == FLG_ON) {  // フラグがONのとき
      LED_state = FLG_OFF;        // OFF
    }
    else {                  // フラグがOFFのとき
      LED_state = FLG_ON;        // ON
    }
    delay(100);                // チャタリング防止のウエイト
  }
  old_SW_state = SW_state;        // スイッチの状態をold_SW_stateへ保存
  if (LED_state == FLG_ON) {      // LEDの点滅状態がONのとき
    if (OUT_mode == RELAY_mode) {
      digitalWrite(LED, OUT_ON);    //LED出力ON
      RELAY_ON_OFF(ON);            //リレー出力ON
    } else if (OUT_mode == IR_LED_mode) {
      send_signal(ON);  //赤外線ON出力
    }
  }
  else {                          // OFFのとき
    if (OUT_mode == RELAY_mode) {
      digitalWrite(LED, OUT_OFF);   //LED出力OFF
      RELAY_ON_OFF(OFF);           //リレー出力OFF

      // digitalWrite(RELAY, OUT_OFF); //リレー出力OFF
      // digitalWrite(RELAY_2, OUT_OFF); //リレー2出力OFF
    } else if (OUT_mode == IR_LED_mode) {
      send_signal(OFF);  //赤外線OFF出力
    }
  }
}

//LEDとリレー出力、赤外線LED信号のタイマー関数の定義
//    スイッチを押し始めてから指定時間(秒)の間出力を続ける。
//  指定時間をすぎて押し続けていても指定時間が来たら出力をやめる。
void timer(int sec, int OUT_mode) {
  if (digitalRead(input_Pin) == SW_ON) { //外部スイッチが押されて、かつ
    if (SW_state == 0) {      //OFFからONになったときだけ動作する
      SW_state = 1;
      if (OUT_mode == RELAY_mode) {
        digitalWrite(LED, OUT_ON);  //LED出力ON
        RELAY_ON_OFF(ON);            //リレー出力ON
      } else if (OUT_mode == IR_LED_mode) {
        send_signal(ON);  //赤外線ON出力
      }
      int kaisuu = sec / 30; //delay関数の引数が32767以下になるように分割
      for (int i = 0; i < kaisuu; i++) {
        delay(30 * 1000);
      }
      delay((sec - kaisuu * 30) * 1000);
      if (OUT_mode == RELAY_mode) {
        digitalWrite(LED, OUT_OFF); //LED出力OFF
        RELAY_ON_OFF(OFF);           //リレー出力OFF
      } else if (OUT_mode == IR_LED_mode) {
        send_signal(OFF); //赤外線OFF出力
      }
    }
  }
  else if (SW_state == 1) { //ONからOFFになったとき
    SW_state = 0;
  }
}

void setup() {
  Serial.begin(9600);
  //Pinモードの設定(赤外線LED(Pin 3)への出力はライブラリで定義されている)
  pinMode(input_Pin, INPUT_PULLUP);   //外部スイッチ用入力
  pinMode(dip1000_Pin, INPUT_PULLUP); //ディップスイッチ
  pinMode(dip100_Pin, INPUT_PULLUP);  //ディップスイッチ
  pinMode(dip10_Pin, INPUT_PULLUP);   //ディップスイッチ
  pinMode(dip1_Pin, INPUT_PULLUP);    //ディップスイッチ
  pinMode(LED, OUTPUT);   //LEDに出力、インジケーター
  pinMode(RELAY, OUTPUT); //リレーに出力
  pinMode(RELAY_2, OUTPUT); //リレー2に出力

  //出力Pinの初期化
  digitalWrite(LED, OUT_OFF);   //LED出力をOFFに
  digitalWrite(RELAY, HIGH); //リレー出力をOFFに
  digitalWrite(RELAY_2, HIGH); //リレー2出力をOFFに

  //ディップスイッチの状態を読みこみ変数modeに4ケタの整数として格納
  if (digitalRead(dip1000_Pin) == dip_SW_ON) {
    mode = mode + 1000;   // pin5がONならmodeの千位を1にする
  }
  if (digitalRead(dip100_Pin) == dip_SW_ON) {
    mode = mode + 100;   // pin6がONならmodeの百位を1にする
  }
  if (digitalRead(dip10_Pin) == dip_SW_ON) {
    mode = mode + 10;    // pin7がONならmodeの十位を1にする
  }
  if (digitalRead(dip1_Pin) == dip_SW_ON) {
    mode = mode + 1;    // pin8がONならmodeの一位を1にする
  }
   SW_state = 0;
  Serial.print("mode = ");Serial.println(mode);
}

void loop() {
  switch (mode) {
    //  リレー出力
    case 0:  //ダイレクトモード
      if (digitalRead(input_Pin) == SW_ON) {
        digitalWrite(LED, OUT_ON);  //LED出力ON
        RELAY_ON_OFF(ON);            //リレー出力ON
      }
      else {
        digitalWrite(LED, OUT_OFF); //LED出力OFF
        RELAY_ON_OFF(OFF);            //リレー出力OFF
      }
      break;
    case 1: //ラッチモード
      //  外部スイッチをONするたびに出力のON・OFFが切り替わる
      latch(RELAY_mode);
      break;
    case 10:  //ONパルスモード
      pulse(ON_pulse_mode);
      break;
    case 11:  //ON・OFFパルスモード
      pulse(ON_OFF_pulse_mode);
      break;
    case 100:  //タイマーモード(2秒)
      timer(2, RELAY_mode);
      break;
    case 101:  //タイマーモード(5秒)
      timer(5, RELAY_mode);
      break;
    case 110:  //タイマーモード(7秒)
      timer(7, RELAY_mode);
      break;
    case 111:  //タイマーモード(10秒)
      timer(10, RELAY_mode);
      break;
    case 1000:  //タイマーモード(15秒)
      timer(15, RELAY_mode);
      break;
    //  以下、赤外線出力
    case 1001:  //赤外線出力ダイレクト
      pulse(IR_signal_mode);
      break;
    case 1010://赤外線出力ラッチ
      //  外部スイッチをONするたびに赤外線出力のオン・オフを繰り返す
      // 押し続けてもON・OFFの繰り返しがおこらない
      latch(IR_LED_mode);
      break;
    case 1011:  //タイマーモード(2秒)
      timer(2, IR_LED_mode);
      break;
    case 1100:  //タイマーモード(5秒)
      timer(5, IR_LED_mode);
      break;
    case 1101:  //タイマーモード(7秒)
      timer(7, IR_LED_mode);
      break;
    case 1110:  //タイマーモード(10秒)
      timer(10, IR_LED_mode);
      break;
    case 1111:  //タイマーモード(15秒)
      timer(15, IR_LED_mode);
      break;
  }
}

いいなと思ったら応援しよう!