ラダー→Arduino(カウンタ)

カウンタ回路をラダーからArduinoの
プログラムに変換する場合、必ず立上り信号の判定が
必要になります。また、立上りのタイミングで数を増やし、
オフになっても状態は変化しません。
RSTで初めて状態が解除されます。

// 入力デバイスに関する設定部
#define X0021    (0x01 << 0) 
#define X0022    (0x01 << 1) 
#define X0034    (0x01 << 2) 
#define X0035    (0x01 << 3) 

#define   GET_X(DEVICE,NO)   (in_data & DEVICE)

byte in_no[] = { 21 , 22 , 34 , 35}; 
unsigned long in_data ;  // 入力Xの保持変数(32点数分)

// 出力デバイスに関する設定部
#define Y0018    (0x01 << 0) 
#define Y0019    (0x01 << 1) 
#define Y0025    (0x01 << 2) 
#define Y0026    (0x01 << 3) 

#define GET_Y(DEVICE,NO)   (out_data & DEVICE)
#define SET_Y_ON(DEVICE,NO)    out_data = out_data | DEVICE
#define SET_Y_OFF(DEVICE,NO)   out_data = out_data & ~DEVICE

byte out_no[] = { 18 , 19 , 25 , 26}; 
unsigned long out_data ;  // 出力Yの保持変数(32点数分)

// 内部リレーに関する設定部
#define M0000    (0x01 << (0 % 16) ) 
#define M0001    (0x01 << (1 % 16) ) 

#define GET_M(DEVICE,NO)   (m_relay[ NO / 16 ] & DEVICE)
#define SET_M_ON(DEVICE,NO)    m_relay[ NO / 16 ] = m_relay[ NO / 16 ] | DEVICE
#define SET_M_OFF(DEVICE,NO)   m_relay[ NO / 16 ] = m_relay[ NO / 16 ] & ~DEVICE

unsigned short m_relay[1]; //  内部リレーMの保持変数


#define T0000    (0x01 << (0 % 16) ) 
#define T0001    (0x01 << (1 % 16) ) 

#define GET_T(DEVICE,NO)   (t_relay[ NO / 16 ] & DEVICE)
#define SET_T_ON(DEVICE,NO)    t_relay[ NO / 16 ] = t_relay[ NO / 16 ] | DEVICE
#define SET_T_OFF(DEVICE,NO)   t_relay[ NO / 16 ] = t_relay[ NO / 16 ] & ~DEVICE

unsigned short t_relay[1]; // 
unsigned long t_count[2]; //

#define C0000    (0x01 << (0 % 16) ) 
#define GET_C(DEVICE,NO)   (c_relay[ NO / 16 ] & DEVICE)
#define SET_C_ON(DEVICE,NO)    c_relay[ NO / 16 ] = c_relay[ NO / 16 ] | DEVICE
#define SET_C_OFF(DEVICE,NO)   c_relay[ NO / 16 ] = c_relay[ NO / 16 ] & ~DEVICE

unsigned short c_relay[1]; // 
unsigned long c_count[1]; // 
 

// 立ち上がり処理に関する設定部
#define UTRG0000  (0x01 << (0 % 16) )
#define UTRG0001  (0x01 << (1 % 16) )
#define UTRG0002  (0x01 << (2 % 16) )

#define GET_UTRG(DEVICE,NO)  (u_plsg[NO/16] & DEVICE)  
#define SET_UTRG_ON(DEVICE,NO)   u_plsg[NO/16] = u_plsg[NO/16] | DEVICE
#define SET_UTRG_OFF(DEVICE,NO)  u_plsg[NO/16] = u_plsg[NO/16] & ~DEVICE

unsigned short u_plsg[1]; // 立ち上り処理用のリレー

unsigned long starttime;
unsigned long lasttime;
unsigned long spantime;
unsigned long lasttime_ms;
unsigned long spantime_ms;

// Arduino 起動時呼び出しプログラム
void setup(){
   for (byte i=0; i<sizeof(in_no); i++) {
     pinMode(in_no[i],INPUT);
   }
   for (byte i=0; i<sizeof(out_no); i++) {
     pinMode(out_no[i],OUTPUT);
   } 
}


// Arduino 繰り返しプログラム
void loop(){
  time_refresh();
  output_refresh();
  input_refresh();

/////////////////////////////////////////////////////////////
// スキャンプログラム                                      //
// この下に毎スキャン実行するプログラムを書いてくださいな。//
/////////////////////////////////////////////////////////////
   if (GET_X(X0021,21)) { 
     if (!GET_UTRG(UTRG0001,1)) { 
       if (c_count[0] <  5 ) { 
         c_count[0] ++; 
         if (c_count[0] >= 5) { 
           SET_C_ON(C0000,0);
         } 
       } else { 
         
       }
       SET_UTRG_ON(UTRG0001,1);
     } else { 
     } 
   } else {
     SET_UTRG_OFF(UTRG0001,1);
   }
   
   if (GET_X(X0022,22)){
    SET_C_OFF(C0000,0);
    c_count[0] = 0;
   }
   
  if (GET_C(C0000,0)){
    SET_Y_ON(Y0026,26);    
  } else {
    SET_Y_OFF(Y0026,26);
  }
  
/////////////////////////////////////////////////////////////
// ここまでスキャンプログラム                              //
//                                                         //
/////////////////////////////////////////////////////////////

  output_refresh();
}


// standard function
// 入力情報の更新関数
void input_refresh() {
   in_data = 0;
   for (byte i=0; i<sizeof(in_no); i++) { 
     if (digitalRead(in_no[i])==LOW) { 
       in_data = in_data & ~(0x01 << i);
     } else { 
       in_data = in_data | (0x01 << i);
     }
   }
} 

// 出力情報の更新関数
void output_refresh() {
   for (byte i=0; i<sizeof( out_no ); i++) { 
     if ( out_data & (0x01 << i) ) {
       digitalWrite( out_no[i], HIGH );
     } else {
       digitalWrite( out_no[i] , LOW );
     }
   }
}
// タイマーの時間経過関数宣言部
void time_refresh() {
   unsigned long nowtime; 
   nowtime = micros(); 
   spantime = nowtime - lasttime;
   lasttime = nowtime;
   nowtime = millis(); // 電源ON後の経過時間をmsで取得する
   spantime_ms = nowtime - lasttime_ms;
   lasttime_ms = nowtime;    
} 

システム部のプログラムは、高機能となるごとに
増えて複雑になります。ただ、ラダー部は
それほど、複雑にはなっておりません。
ポイントは、変更の必要な部分が分かればよいのです。

   if (GET_X(X0021,21)) { 
     if (!GET_UTRG(UTRG0001,1)) { 
       if (c_count[0] <  5 ) { 
         c_count[0] ++; 
         if (c_count[0] >= 5) { 
           SET_C_ON(C0000,0);
         } 
       } else { 
         
       }
       SET_UTRG_ON(UTRG0001,1);
     } else { 
     } 
   } else {
     SET_UTRG_OFF(UTRG0001,1);
   }
   
   if (GET_X(X0022,22)){
    SET_C_OFF(C0000,0);
    c_count[0] = 0;
   }
   
  if (GET_C(C0000,0)){
    SET_Y_ON(Y0026,26);    
  } else {
    SET_Y_OFF(Y0026,26);
  }