Site icon Elektrologi

Lampu On Off dengan 2 Tombol

Pada artikel ini diuraikan lampu kedip yang dapat dimatikan dan dinyalakan dengan 2 buah tombol push button.

Deskripsi sistem

Proses menggunakan input 2 tombol pushbutton, pb1 dan pb2. Lalu ada output 1 buah LED. Jika pb1 ditekan, maka LED menyala selama 10 detik, kemudian padam sendiri. Jika pb2 ditekan, maka LED langsung padam, meskipun dia menyala kurang dari 10 menit.

Model State Chart / Finite State Machine

Berikut ini model FSM dari sistem tersebut

FSM ini menggunakan konsep mesin Mealy, artinya output berubah tergantung input dan state saat itu. Jadi perubahan output mesti dinyatakan secara eksplisit pada setiap transisi.

FSM yang dipakai menggunakan konsep ‘extended state machine’ untuk memungkinkan delay 10 menit. Delay 10 menit kalau dibuat dengan FSM biasa akan memerlukan banyak sekali state. Untuk menghemat jumlah state, maka digunakan variabel ‘counter’ untuk menggantikan state yang banyak.

Kondisi awal sistem adalah LED mati (OFF), untuk itu ditandai dengan trainsisi “true / LED=OFF”. ‘true’ artinya transisi ini terjadi tanpa syarat. ‘LED=OFF’ artinya LED mati.

Ada 2 state pada sistem, yaitu OFF dan ON. OFF artinya lampu mati, ON artinya lampu menyala.

Pada state OFF, lampu tetap mati selama tombol PB1 tidak ditekan. Hal ini ditandai dengan transisi ‘PB=0 / LED=OFF’. PB=0 adalah syarat transisi tersebut.

Pada state OFF, jika tombol PB1 ditekan maka akan terjadi transisi ke state ON, dan lampu menyala. Hal ini dinyatakan dengan transisi ‘PB1=1 / LED=ON’. Transisi ini juga mereset variabel ‘counter’ menjadi 0 , untuk persiapan memulai proses menunggu maksimum 10 menit.

Setelah lampu menyala, maka lampu akan menyala selama 10 menit jika tombol PB2 tidak ditekan. Hal ini dilakukan dengan transisi ‘PB2=0 / LED=0, counter=counter+1’. Tiap kali tombol PB2 tidak ditekan, angka pada counter dinaikkan 1. Jika angka counter sudah melewati batas tertentu (10 menit), maka terjadi transisi ke state OFF. Hal ini dilakukan dengan transisi ‘counter>10*60 / LED=OFF’, artinya ini adalah transisi bersyarat nilai variabel ‘counter’. Perubahan ke state OFF juga dapat terjadi jika tombol PB2 ditekan. Untuk itu ditambahkan ‘or’ pada syarat transisi dari ON ke OFF.

Perangkat Keras

Rangkaian lampu on-off

Perangkat Lunak

Versi Interupsi

// lampu on-off dengan 2 tombol model FSM dan timer one
// https://www.arduino.cc/reference/en/libraries/timerone/
// To install, cari library timerone dari Sketch -> Include Library -> Manage Libraries

#include <TimerOne.h>
#define STATE_INITIAL    100
#define STATE_ON    101
#define STATE_OFF   102
#define SWITCH_PB1 3
#define SWITCH_PB2 2
#define LED_OUTPUT 4

#define TIMEOUT 100
int state = STATE_INITIAL;
int counter=0;

void setup() {
  int output = 0;
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED_OUTPUT, OUTPUT);
  pinMode(SWITCH_PB1, INPUT_PULLUP);
  pinMode(SWITCH_PB2, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println(__FILE__);
  fsm_output(output);
  Timer1.initialize(100000); // delay dalam microsecond
  Timer1.attachInterrupt(ISR_Timer1);
}

void loop() {
}

void fsm(int  *state, int *out, int pb1, int pb2, int *counter) {
  switch (*state) {
    case STATE_INITIAL: { // initial state
        *state = STATE_OFF;
        *out = 0;
        break;
      }
    case STATE_ON: {
        if (pb2 == 0) {
          // tetap
          if (*counter >= TIMEOUT) {
            *state = STATE_OFF;
            *out = 0;
          } else {
            *counter = *counter + 1; // tunggu timeout
            *state = STATE_ON;
            *out = 1;
          }
        } else {
          *state = STATE_OFF;
          *out = 0;
        }
        break;
      }
    case STATE_OFF: {
        if (pb1 == 0) {
          // tetap
          *state = STATE_OFF;
          *out = 0;
        } else {
          *counter = 0;
          *state = STATE_ON;
          *out = 1;
        }
        break;
      }
  }
}

void fsm_output(int output_value) {
  if (output_value == 1) {
    digitalWrite(LED_OUTPUT, HIGH);
  } else {
    digitalWrite(LED_OUTPUT, LOW);
  }
}

void ISR_Timer1(void)
{
  int output = 0;
  int pb1, pb2, switch1, switch2;
  switch1 = digitalRead(SWITCH_PB1);
  switch2 = digitalRead(SWITCH_PB2);
  if (switch1 == 1)
    pb1 = 0;
  else {
    pb1 = 1;
  }
  if (switch2 == 1)
    pb2 = 0;
  else {
    pb2 = 1;
  }
  fsm(&state, &output, pb1, pb2, &counter);
  fsm_output(output);
  Serial.print("state: ");
  Serial.print(state);
  Serial.print(" pb1: ");
  Serial.print( pb1);
  Serial.print(" pb2: ");
  Serial.print( pb2);
  Serial.print(" counter: ");
  Serial.print( counter);
  Serial.print(" output: ");
  Serial.print( output);
  Serial.println();
}

Versi Delay

Berikut ini code tanpa interupsi, hanya menggunakan delay()

// lampu on-off dengan 2 tombol model FSM dan delay

#define STATE_INITIAL    100
#define STATE_ON    101
#define STATE_OFF   102
#define SWITCH_PB1 3
#define SWITCH_PB2 2
#define LED_OUTPUT 4
#define PERIOD_MS 10 // perioda delay dalam milisecond
#define TIMEOUT 10 // TIMEOUT dalam detik
int state = STATE_INITIAL;
int counter = 0;

void setup() {
  int output = 0;
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED_OUTPUT, OUTPUT);
  pinMode(SWITCH_PB1, INPUT_PULLUP);
  pinMode(SWITCH_PB2, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println(__FILE__);
  fsm_output(output);
}

void loop() {
  mainloop();
  delay(PERIOD_MS);
}

void fsm(int  *state, int *out, int pb1, int pb2, int *counter) {
  switch (*state) {
    case STATE_INITIAL: { // initial state
        *state = STATE_OFF;
        *out = 0;
        break;
      }
    case STATE_ON: {
        if (pb2 == 0) {
          // tetap
          if (*counter >= TIMEOUT * 1000 / PERIOD_MS) {
            *state = STATE_OFF;
            *out = 0;
          } else {
            *counter = *counter + 1; // tunggu timeout
            *state = STATE_ON;
            *out = 1;
          }
        } else {
          *state = STATE_OFF;
          *out = 0;
        }
        break;
      }
    case STATE_OFF: {
        if (pb1 == 0) {
          // tetap
          *state = STATE_OFF;
          *out = 0;
        } else {
          *counter = 0;
          *state = STATE_ON;
          *out = 1;
        }
        break;
      }
  }
}

void fsm_output(int output_value) {
  if (output_value == 1) {
    digitalWrite(LED_OUTPUT, HIGH);
  } else {
    digitalWrite(LED_OUTPUT, LOW);
  }
}

void mainloop(void)
{
  int output = 0;
  int pb1, pb2, switch1, switch2;
  switch1 = digitalRead(SWITCH_PB1);
  switch2 = digitalRead(SWITCH_PB2);
  if (switch1 == 1)
    pb1 = 0;
  else {
    pb1 = 1;
  }
  if (switch2 == 1)
    pb2 = 0;
  else {
    pb2 = 1;
  }
  fsm(&state, &output, pb1, pb2, &counter);
  fsm_output(output);


  // cetak jika ada perubahan state , atau sudah 1 detik berlalu
  static int prev_state = 0;
  static int display_counter = 0;

  if (prev_state != state || display_counter > 1000 / PERIOD_MS) {
    Serial.print("state: ");
    if (state == STATE_ON) {
      Serial.print("ON  ");
    } else if (state == STATE_OFF) {
      Serial.print("OFF ");
    } else {
      Serial.print(state);
    }

    Serial.print(" pb1: ");
    Serial.print(pb1);
    Serial.print(" pb2: ");
    Serial.print(pb2);
    Serial.print(" c: ");
    Serial.print( counter);
    Serial.print(" out: ");
    Serial.print(output);
    Serial.println();
    prev_state = state;
    display_counter = 0;
  }
  display_counter++;

}

Demonstrasi

demonstrasi versi 1

Demonstrasi versi 2

Contoh lain sistem mikrokontroler dengan finite state machine: https://elektrologi.iptek.web.id/contoh-implementasi-finite-state-machine-dengan-mikrokontroler/

Exit mobile version