타이머 만들기

앞서 만든 기초 소스에 타이머를 추가해 보겠습니다. 타이머는 자동화 현장에서 매우 자주 사용됩니다.

On Timer

일정 시간 신호가 들어왔을때, 비로소 출력을 하는 가장 기본적인 타이머입니다.

2개의 타이머 관련 배열이 필요합니다.

#define timerMaxLimit 20
uint8_t Tstat[timerMaxLimit];  // Timer status
uint32_t Tvalue[timerMaxLimit];  // Timer Current Value

이 예에서는 총 20개의 타이머만 사용하였습니다. 위 20이라는 숫자를 바꾸면 타이머 갯수를 조정할 수 있습니다.

  • Tstat배열 : 타이머의 상태를 저장합니다. 1이면 On, 0이면 Off라는 뜻입니다.
  • Tvalue배열 : 타이머의 증가 감소 값을 저장하는 배열입니다.

OnTimer가 어떻게 동작하는지 보겠습니다.

입력(Input)이 들어오면 지정한 시간(Time)이 경과된 뒤 비로소 출력(Tstat)가 켜집니다.

#include "CFMEGA.h"
CFNET cfnet;
 
uint8_t X[128]; // Input Coil
uint8_t Y[128]; // Output Coil
 
void distribute_value(uint16_t val, uint8_t where) {
    for (int i = 0; i < 16; i++) {
        X[where++] = val & 0x01;
        val >>= 1;
    }
}
 
void input_proc() {
    for (int i = 0; i < 8; i++) {
        distribute_value(cfnet.digitalRead(i), i * 16);
    }
}
 
uint16_t collect_value(uint8_t where) {
    uint16_t tempV = 0;
    for (int i = 0; i < 16; i++) {
        tempV |= Y[where++] << i;
    }
    return tempV;
}
 
void output_proc() {
    for (int i = 0; i < 8; i++) {
        cfnet.digitalWrite(i, collect_value(i * 16));
    }
}
 
ISR(TIMER5_OVF_vect)
{
  TCNT5 = 198; // for 20mS
 
  sei(); //  Start Gloval Interrupt
 
  timertn_proc();
  input_proc();
  logic_proc();
  output_proc();
  tick_flag = 0;
}
 
// Timer
 
uint16_t system_timer=0, tick_flag=0;
#define timerMaxLimit 20
uint8_t Tstat[timerMaxLimit];  // Timer status
uint32_t Tvalue[timerMaxLimit];  // Timer Current Value
 
void timertn_proc() {
  system_timer++;
  if (system_timer == 5) {
    tick_flag = 1; // Turn On every 100mS
    system_timer=0;
  }
}
 
void onTimer(uint8_t inputValue, uint8_t timerIndex, uint16_t timerInitValue)
{
  if (tick_flag) {
    if (inputValue) {
      if (Tvalue[timerIndex] < timerInitValue) {
        Tvalue[timerIndex]++;
        if (Tvalue[timerIndex] == timerInitValue) {
          Tstat[timerIndex] = 1;
        }
      }
    } else {
      Tvalue[timerIndex] = 0;
      Tstat[timerIndex] = 0;
    }
  }
}
 
// 
// User Source
//
 
 
void setup() { 
  TCCR5B = 5; // Clock source from system clock/1024
  TIMSK5 |= 1;	//TOV interrupt set.
  sei(); // Start Gloval Interrupt
 
  // Clear Timer array
  for (int _i=0; _i < timerMaxLimit; _i++) {
    Tstat[_i] = 0;
    Tvalue[_i] = 0;
  }
 
}
 
void loop() {
 
 
}
 
// Run every 20mS
 
void logic_proc()
{
  Y[0] = X[0];  // Main Logic Program
  onTimer(X[0],0,8); // 800mS On Timer 
  Y[1] = Tstat[0];  // Watch Tvalue
}

onTimer

이 소스에서 맨밑 logic_proc를 보면 onTimer를 사용한 부분이 보입니다.

void onTimer(입력소스, 타이머 번호, 경과시간)

입력 소스 : 여기에서는 X[0] 입력을 사용하였습니다.
타이머 번호 : 여기에서는 0번 타이머를 사용하였습니다.
경과시간 : 타이머 값입니다. 여기에서는 8 즉, 0.8S를 뜻합니다. 이 타이머는 0.1초 단위입니다.

따라서, 위 소스가 실행되면, X[0]이 입력되었을때, 0.8초후에 타이머0이 출력됩니다. 그 결과를 Y[1]에서 보실 수 있습니다.

주의

시간 지연이 필요할때 초보자분들은 delay함수를 사용하는데, 이 경우 delay를 하는 동안 다른 신호를 처리할 수 없기 때문에, 정상적인 흐름이 불가능합니다.

Modular FADUINO