Site icon Elektrologi

Lampu Kedip Dengan Model Finite State Machine dan FreeRTOS

Artikel ini adalah pengembangan dari artikel “Lampu Kedip Dengan Model Finite State Machine“. Pada artikel tersebut pewaktuan 1 detik menggunakan fungsi delay() dari Arduino. Pada artikel ini digunakan vTaskDelay pada sistem operasi real time FreeROTS untuk mendapatkan perioda 1 detik untuk eksekusi Finite State Machine (FSM).

Spesifikasi

Sistem yang dibuat adalah lampu kedip, dengan perioda 2 detik.

Perangkat Keras

Perangkat lunak dengan Arduino Nano ATmega328. Output dengan LED yang diseri dengan resistor pembatas arus. Nilai resistor tidak kritis. Pada percobaan ini dipakai nilai resistor 1000 ohm. LED disambung ke port D3 pada Arduino Nano.

Model Sistem

Model FSM untuk lampu kedip adalah sebagai berikut.

Perangkat Lunak

Pada sistem ini diperlukan pewaktuan (timing) agar lampu berkedip dengan frekuensi 0,5 Hz. Untuk itu diperlukan FSM yang dihitung/dipanggil setiap 1 detik. Untuk membuat pemanggilan periodik seperti ini dapat dilakukan dengan beberapa cara sebagai berikut:

Pada implementasi ini yang dibuat adalah menggunakan FreeRTOS. Delay menggunakan fungsi vTaskDelay() pada FreeRTOS. Penjelasan tentang FreeRTOS di Arduino dapat dibaca di artikel https://www.arduino.cc/reference/en/libraries/freertos/

Model diagram alir (flowchart) perangkat lunak adalah sebagai berikut.

Diagram alir perangkat lunak berbasis FreeRTOS

Aplikasi memiliki 2 super loop. Super loop pertama ada di main program, tidak berisi apa-apa. Super loop kedua ada di Task FSM.

Kode lengkap dapat dilihat di repository https://github.com/waskita/embedded/blob/master/kedip/nano-fsm-freertos/nano-fsm-freertos.ino

Bagian Awal

#include "Arduino_FreeRTOS.h"

#define ON    100
#define OFF   101

#define LED_OUTPUT 3
int state = OFF;
TaskHandle_t xHandle1 = NULL;

Inisialisasi Sistem

void setup() {
  int output = 0;
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED_OUTPUT, OUTPUT);
  Serial.begin(115200);

  Serial.print("portTICK_PERIOD_MS: ");
  Serial.print(portTICK_PERIOD_MS);
  Serial.println();

  fsm_init(&state);
  fsm_output(output);

  xTaskCreate(
    TaskFSM
    ,  "TaskFSM"  // A name just for humans
    ,  100  // stacksize
    ,  NULL
    ,  2  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  &xHandle1 );
}

Implementasi Inisialisasi Finite State Machine

Implementasi ini serupa dengan di artikel “Lampu Kedip Dengan Model Finite State Machine

void fsm_init(int *state, int *out) {
  *state = OFF;
  *out = 0;
}

Implementasi Finite State Machine

Implementasi ini serupa dengan di artikel “Lampu Kedip Dengan Model Finite State Machine

void fsm(int  *state, int *out) {
  switch (*state) {
    case ON: {
        *state = OFF;
        *out = 0;
        break;
      }
    case OFF: {
        *state = ON;
        *out = 1; // nyalakan output
        break;
      }
  }
}

Implementasi Output FSM

Implementasi ini serupa dengan di artikel “Lampu Kedip Dengan Model Finite State Machine

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

Implementasi Task / Thread

static void TaskFSM(void *pvParameters) 
{
  TickType_t xLastWakeTime;
  /* The xLastWakeTime variable needs to be initialised with the current tick
    count.  Note that this is the only time we access this variable.  From this
    point on xLastWakeTime is managed automatically by the vTaskDelayUntil()
    API function. */
  xLastWakeTime = xTaskGetTickCount();
  while (1)
  {
    int output = 0;
    fsm(&state, &output);
    if (output == 1) {
      digitalWrite(LED_OUTPUT, HIGH);
    } else {
      digitalWrite(LED_OUTPUT, LOW);
    }
    Serial.print("state: ");
    Serial.print(state);
    Serial.print(" output: ");
    Serial.print( output);
    Serial.println();
    vTaskDelayUntil( &xLastWakeTime, ( 1000 / portTICK_PERIOD_MS ) ); // perioda 1 detik
  }
}

Pengujian

Pengujian dilakukan dengan menjalankan program, kemudian mengamati kedipan lampu dan output ke port serial.

Pada output serial akan muncul tampilan seperti berikut ini:

16:23:36.204 -> state: 100 output: 1
16:23:37.280 -> state: 101 output: 0
16:23:38.302 -> state: 100 output: 1
16:23:39.324 -> state: 101 output: 0
16:23:40.390 -> state: 100 output: 1
16:23:41.415 -> state: 101 output: 0
16:23:42.427 -> state: 100 output: 1
16:23:43.466 -> state: 101 output: 0
16:23:44.534 -> state: 100 output: 1
16:23:45.557 -> state: 101 output: 0
16:23:46.581 -> state: 100 output: 1
16:23:47.652 -> state: 101 output: 0
16:23:48.674 -> state: 100 output: 1

Dari output serial tersebut nampak perubahan state dan output terjadi sesuai rancangan.

Waktu perubahan tidak tepat 1 detik, terlihat bergeser sedikit. Penyebabnya kemungkinan karena implementasi timer tick pada FreeRTOS Arduino menggunakan Watchdog Timer, bukan Timer 0, Timer 1 ataupun Timer 2. Watchdog Timer pada Arduino menggunakan osilator RC yang tidak setepat osilator kristal.

Video

Exit mobile version