Produk-produk tersebut tidak memiliki fitur DIY (Do It Yourself) seperti MINIR2. Jadi jika ingin dipakai sebagai perangkat IoT (Internet of Things) sendiri, kita mesti mengganti firmware di dalamnya (flashing)
Berikut ini daftar teknik flashing untuk produk tersebut
Arduino Nano dapat melakukan komunikasi serial baik transmit (mengirim) maupun receive (menerima). Pada library Arduino, sudah disiapkan buffer FIFO (First In First Out) pada data yang dikirimkan maupun data yang diterima. Pada tulisan ini dilakukan pengecekan berapa ukuran buffer tersebut. Pengujian ini dilakukan pada Arduino Nano dengan prosesor ATmega328. Untuk prosesor lain, ada kemungkinan ukuran buffernya berbeda.
Library Arduino untuk komunikasi serial memiliki buffer FIFO untuk outgoing maupun incoming.
Hardware yang diperlukan:
Komputer Desktop PC / Laptop
Arduino Nano Atmega328
Kabel USB
Buffer Pengiriman
Ukuran buffer pengiriman yang tersisa dapat dicek dengan fungsi Serial.availableForWrite() . Pada kondisi awal seharusnya buffer yang tersisa adalah maksimal, karena belum ada karakter yang dikirim.
Contoh program:
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
int incomingByte ;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
incomingByte = Serial.availableForWrite();
Serial.print("jumlah available: ");
Serial.println(incomingByte, DEC);
}
Output seperti sebagai berikut
14:42:26.343 -> jumlah available: 63
Artinya ukuran bufffer outgoing adalah 63 karakter
Buffer Penerimaan
Ukuran buffer data masuk (receive) dapat dicek dengan fungsi Serial.available
Contoh program
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
int incomingByte ;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000);
incomingByte = Serial.availableForWrite();
Serial.print("jumlah available: ");
Serial.println(incomingByte, DEC);
}
Setelah itu kirimkan beberapa karakter dari PC ke Arduino. Angka yang ditampilkan akan naik, namun akan berhenti di suatu batas tertentu. Angka inilah yang menunjukkan ukuran buffer FIFO incoming.
Dari hasil percobaan didapatkan rekaman komunikas serial sebagai berikut
14:37:37.062 -> jumlah available: 0
14:37:39.051 -> jumlah available: 0
14:37:41.043 -> jumlah available: 30
14:37:43.038 -> jumlah available: 43
14:37:45.064 -> jumlah available: 54
14:37:47.057 -> jumlah available: 63
14:37:49.050 -> jumlah available: 63
14:37:51.042 -> jumlah available: 63
14:37:53.067 -> jumlah available: 63
14:37:55.058 -> jumlah available: 63
14:37:57.050 -> jumlah available: 63
Artinya jumlah data yang menunggu untuk dibaca oleh software adalah maksimum 63 karakter.
Pada tulisan ini akan diuraikan bagaimana membuat filter digital dalam bahasa C dari persamaan filter dalam transformasi Laplace. Contoh ini diadaptasi dari Example 8.4 di buku “Lizhe Tan, Digital Signal Processing, Fundamentals and Applications” halaman 324.
Misal diketahui suatu filter dalam domain s (Laplace) dengan persamaan sebagai berikut:
\(H(s)=\frac{10}{s+10} \)
Untuk mengubah ke bentuk digital, kita perlu tentukan perioda sampling. Misal dipilih perioda sampling T=0.01 detik
Persamaan transformasi s ke z sebagai berikut
\( s=\frac{2(z -1) }{Tz + 1} \)
H(s) diubah ke H(z) dengan cara substitusi s pada H(s). T=0.01 dimasukkan ke persamaan transformasi. Maka didapat persamaan berikut:
Selanjutnya terapkan teknik di Bab 6 (Example 6.5) untuk mengubah persamaan dalam domain (z) ke domain waktu (n).
Akan didapat persamaan difference dalam n sebagai berikut:
y(n)=0.0476 x(n) + 0.0476 x(n-1) + 0.9048 y(n-1)
Simulasi
Tahap selanjutnya adalah simulasi persamaan difference tersebut dengan input fungsi step.
Tahap simulasi ini penting untuk mengecek apakah filter digital yang dihasilkan memiliki perilaku yang sama dengan filter analog di awal. Jika hasilnya berbeda, ada kemungkinan salah perhitungan atau salah koding.
Simulasi dapat dilakukan dengan bahasa pemrograman apa saja, misal C, C++, Matlab, Python, dan sebagainya.
Simulasi di bawah ini dibuat dengan bahasa Python. GUI yang dipakai adalah Jupyter Notebook
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import AutoMinorLocator
from matplotlib import gridspec
import matplotlib.ticker as ticker
%matplotlib inline
t=-1 # start time at -1
xn=0
xn1=0
yn1=0
period=0.01
times=np.linspace(-1, 10, 111).reshape(111, 1)
xs=[]
ys=[]
ts=[]
for counter in range(0,200):
if t<0:
xn=0
else:
xn=1
t=t+period
xs.append(xn)
y=0.04676 * xn + 0.0476 * xn1 + 0.9048 * yn1
ys.append(y)
ts.append(t)
yn1=y
xn1=xn
Berikut ini output sistem (merah) terhadap input step (warna hijau).
time constant = 1/10
Titik biru adalah t = time constant, dengan value = 63.2%. Posisi titik biru ini pada grafik merah, sehingga dapat disimpulkan respon sistem ini cocok dengan yang diharapkan.
Selanjutnya adalah memberi sinyal sinusoidal dengan frekuensi = frekuensi cut-off ke filter tersebut . Menurut teori, amplitudo pada steady state adalah 0.707 x amplitudo maksimum.
Berikut ini kode untuk memberikan sinyal sinusoida.
t=-1 # start time at -1
xn=0
xn1=0
yn1=0
period=0.01
times=np.linspace(-1, 10, 111).reshape(111, 1)
xs=[]
ys=[]
ts=[]
w=10
for counter in range(0,200):
t=t+period
xn=math.sin(w*t)
xs.append(xn)
y=0.04676 * xn + 0.0476 * xn1 + 0.9048 * yn1
ys.append(y)
ts.append(t)
yn1=y
xn1=xn
Grafik tersebut menunjukkan amplitudo output (merah) ada di sekitar 0.7 dari amplitudo sinyal input (hijau). Terjadi pergeseran fasa sekitar 45 derajat.
Implementasi Bahasa C di Windows
Tahap selanjutnya adalah membuat implementasi filter dengan bahasa C.
Pada tulisan ini diuraikan cara mengendalikan lampu secara wireless dengan ThingsBoard. Mikroprosesor yang dipakai adalah ESP32. Metode yang dipakai adalah RPC (Remote Procedure Call)
TOKEN adalah kode token dari perangkat. Diambil dari ThingsBoard
#include <WiFi.h> // WiFi control for ESP32
#include <ThingsBoard.h> // ThingsBoard SDK
// Helper macro to calculate array size
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
// WiFi access point
#define WIFI_AP_NAME "WIFI_AP_NAME "
// WiFi password
#define WIFI_PASSWORD "WIFI_PASSWORD "
// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
#define TOKEN "yd8R3K3GE61Drm7TtvgF"
// ThingsBoard server instance.
#define THINGSBOARD_SERVER "192.168.0.90"
#define ONBOARD_LED 22
// Baud rate for debug serial
#define SERIAL_DEBUG_BAUD 115200
// Initialize ThingsBoard client
WiFiClient espClient;
// Initialize ThingsBoard instance
ThingsBoard tb(espClient);
// the Wifi radio's status
int status = WL_IDLE_STATUS;
// Array with LEDs that should be controlled from ThingsBoard, one by one
uint8_t leds_control[] = { 12, 13, 27 };
// Main application loop delay
int quant = 20;
// Initial period of LED cycling.
int led_delay = 1000;
// Period of sending a temperature/humidity data.
int send_delay = 2000;
// Time passed after LED was turned ON, milliseconds.
int led_passed = 0;
// Time passed after temperature/humidity data was sent, milliseconds.
int send_passed = 0;
// Set to true if application is subscribed for the RPC messages.
bool subscribed = false;
// LED number that is currenlty ON.
//int current_led = 0;
// Processes function for RPC call "setGpioStatus"
// RPC_Data is a JSON variant, that can be queried using operator[]
// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
RPC_Response processSetGpioState(const RPC_Data &data)
{
Serial.println("Received the set GPIO RPC method");
int pin = data["pin"];
bool enabled = data["enabled"];
if (pin < COUNT_OF(leds_control)) {
Serial.print("Setting LED ");
Serial.print(pin);
Serial.print(" to state ");
Serial.println(enabled);
digitalWrite(leds_control[pin], enabled);
}
return RPC_Response(data["pin"], (bool)data["enabled"]);
}
// RPC handlers
RPC_Callback callbacks[] = {
{ "setGpioStatus", processSetGpioState },
};
// Setup an application
void setup() {
// Initialize serial for debugging
Serial.begin(SERIAL_DEBUG_BAUD);
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
InitWiFi();
for (size_t i = 0; i < COUNT_OF(leds_control); ++i) {
pinMode(leds_control[i], OUTPUT);
}
pinMode(ONBOARD_LED, OUTPUT); \
// LED check
digitalWrite(leds_control[0], HIGH);
delay(500);
digitalWrite(leds_control[1], HIGH);
delay(500);
digitalWrite(leds_control[2], HIGH);
delay(500);
digitalWrite(leds_control[0], LOW);
delay(500);
digitalWrite(leds_control[1], LOW);
delay(500);
digitalWrite(leds_control[2], LOW);
delay(500);
}
// Main application loop
void loop() {
delay(quant);
led_passed += quant;
send_passed += quant;
// Reconnect to WiFi, if needed
if (WiFi.status() != WL_CONNECTED) {
reconnect();
return;
}
// Reconnect to ThingsBoard, if needed
if (!tb.connected()) {
subscribed = false;
// Connect to the ThingsBoard
Serial.print("Connecting to: ");
Serial.print(THINGSBOARD_SERVER);
Serial.print(" with token ");
Serial.println(TOKEN);
if (!tb.connect(THINGSBOARD_SERVER, TOKEN)) {
Serial.println("Failed to connect");
return;
}
}
// Subscribe for RPC, if needed
if (!subscribed) {
Serial.println("Subscribing for RPC...");
// Perform a subscription. All consequent data processing will happen in
// callbacks as denoted by callbacks[] array.
if (!tb.RPC_Subscribe(callbacks, COUNT_OF(callbacks))) {
Serial.println("Failed to subscribe for RPC");
return;
}
Serial.println("Subscribe done");
subscribed = true;
}
if (send_passed > send_delay) {
send_passed = 0;
}
// Process messages
tb.loop();
static int blink_counter = 0;
if (blink_counter < 50) {
digitalWrite(ONBOARD_LED, LOW);
} else {
digitalWrite(ONBOARD_LED, HIGH);
}
blink_counter++;
if (blink_counter >= 100) {
blink_counter = 0;
}
}
void InitWiFi()
{
Serial.println("Connecting to AP ...");
// attempt to connect to WiFi network
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
void reconnect() {
// Loop until we're reconnected
status = WiFi.status();
if ( status != WL_CONNECTED) {
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
}
Berikut ini software PHP untuk mengendalikan LED dari Windows/Ubuntu
Skema rangkaian NodeMCU Devkit V1.0 KonektorSkema rangkaian NodeMCU Devkit V1.0 Catu DayaSkema rangkaian NodeMCU Devkit V1.0 SerialSkema rangkaian NodeMCU Devkit V1.0 Inti
Referensi
Situs Resmi NodeMCU https://www.nodemcu.com/index_en.html
Masuk ke ThingsBoard web interface (misal alamatnya http://192.168.0.90:8080)
Klik di “Devices”
Klik di tanda “+”, kemudian “Add new device” untuk membuat device baru
Masukkan nama device. Misal “iot-gateway-93”
Klik di checkbutton “is gateway” untuk menandakan bahwa device yang dibuat adalah IoT gateway
Klik “Add”. Maka pembuatan Device IoT Gateway selesai.
Selanjutnya adalah mengambil Access Token.
Klik di menu “Devices”. Akan muncul daftar devices yang ada
Klik di device IoT gateway yang baru dibuat
Klik di “Copy access token”, maka access token akan tersimpan di clipboard Windows.
selanjutnya masuk ke console Ubuntu untuk mengedit file konfigurasi ThingsBoard Gateway.
edit file /etc/thingsboard-gateway/config/tb_gateway.yaml dengan teks editor editor, misalnya dengan ‘nano’.
Ganti “host” dengan alamat dari server ThingsBoard. Defaultnya adalah demo.thingsboard.io. Misal pada contoh ini alamat server ThingsBoard adalah 192.168.0.90, sehingga alamat host diganti menjadi 192.168.0.90
port tetap di 1883 (MQTT) . Umumnya tidak ada perubahan.
Ganti string PUT_YOUR_GW_ACCESS_TOKEN_HERE dengan access token yang dicopy di atas. Misal access token adalah KbllULqUCAj1PWt1pvCQ
Pesan itu normal, karena memang MQTT belum dikonfigurasi.
Selanjutnya lihat di web interface ThingsBoard untuk melihat apakah sudah ada koneksi dari thingsboard gateway.
Caranya:
Masuk ke daftar devices dengan cara klik “Devices” di menu web ThingsBoard
Klik di IoT gateway yang baru dibuat, misal tadi namanya adalah “iot-gateway-93”
Klik di “Latest telemetry”. Seharusnya akan muncul beberapa key berikut ini, dengan “last update time” sesuai dengan waktu start thingsboard gateway di console Ubuntu
eventsProduced
eventsSent
LOGS
mqttbrokerconnectorEventsProduced
mqttbrokerconnectorEventsSent
Jika muncul data telemetry seperti di atas, maka artinya ThingsBoard gateway sudah berhasil berkomunikasi dengan ThingsBoard Server.
Tahap selanjutnya adalah melakukan konfigurasi connector di ThingsBoard Gateway supaya dapat menerima / mengirim data ke devices yang ada. Contohnya untuk REST API dapat dilihat di artikel “Koneksi REST API ke ThingsBoard IoT Gateway“
Pada contoh ikni script thingsboard-gateway perlu dijalankan secara manual. Jika ingin dijalankan secara otomatis, dapat dibuat menjadi service atau ditambahkan ke crontab ataupun etc/rc.local
Konfigurasi File Log
Pada contoh file konfigurasi yang diberikan, file log disimpan di “./log”, jadi relatif terhadap dari mana kita menjalankan thingsboard-gateway. Supaya rapi, file log disimpan di /var/log/thingsboard-gateway. Untuk itu edit file /etc/thingsboard-gateway/config/logs.conf untuk mengubah lokasi file log sesuai keinginan.
Berikut ini bagian dari file logs.conf yang mengatur lokasi file log
Setting host di contoh aslinya menggunakan 127.0.0.1, namun kalau pakai IP ini tidak dapat dikontak dari komputer lain. Supaya dapat dikontak dari IP lain, maka menggunakan 0.0.0.0 , atau bisa juga menggunakan IP address dari IoT Gateway tersebut
“port”
Port yang dipakai bebas. Pada contoh ini menggunakan port 5000 seperti sesuai contoh file aslinya.
“SSL”
konfigurasi ini tidak menggunakan security
“mapping”
Bagian ini berisi konfigurasi penerimaan data dari client dan juga pemetaan data untuk dikirim ke ThingsBoard Core.
“endpoint”: untuk mendefinisikan URL dari REST API
IoT Gateway ini misalnya menggunakan IP address 192.168.0.92. Jadi alamat dari REST API adalah http://192.168.0.92:5000/device1
“HTTPMethods”: konfigurasi ini menggunakan HTTP POST. Sesuai contoh dari Thingsboard
“security”: anonymous, tidak menggunakan password samsekali
“converter”: berisi pemetaan data yang diterima, ke parameter yang akan dikirim ke ThingsBoard Core
“deviceNameExpression”: “Device ${name}”, : baris ini artinya mengharapkan adanya parameter “name” dari data yang masuk. Data ini kemudian akan dikirim sebagai string “Device $name” ke ThingsBoard Core.
“attributes”: berisi atribut dari device di client
“timeseries”: berisi entry data yang akan dimasukkan sebagai data telemetri di Device di ThingsBoard Core.
Pada contoh ini ada 2 entry data, yaitu temperatur dan humidity. Parameter yang diharapkan diterima adalah “temp” dan “hum”. Parameter “temp” akan dipetakan ke parameter “temperature”, dan parameter “hum” akan dipetakan ke parameter “humidity”.
Client Dengan PHP CURL
Berikut ini contoh client menggunakan PHP Curl
<?php
// API URL
$url = 'http://192.168.0.92:5000/device1';
// Create a new cURL resource
$ch = curl_init($url);
// Setup request to send json via POST
$body_array = array();
$body_array["name"] = "123123";
$body_array["sensorModel"] = "CX811";
$body_array["hum"] = 78;
$body_array["temp"] = 65;
$body = json_encode($body_array);
// Attach encoded JSON string to the POST fields
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
// Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute the POST request
$result = curl_exec($ch);
// Close cURL resource
curl_close($ch);
print_r($payload);
print_r($result);
Berikut ini data yang masuk ke ThingsBoard sebagai latest telemetry
Jika koneksi berhasil, pada console thingsboard dan file log “connector.log” akan muncul pesan seperti berikut ini:
Berikut ini antar muka minimalis antara ESP32 dengan sensor lingkungan BMP280
Pin yang dipakai:
VCC di ESP32 dihubungkan ke VCC di BMP280
GND di ESP32 dihubungkan ke GND di BMP280
SCL di ESP32 dihubungkan ke SCL di BMP280
SDA di ESP32 dihubungkan ke SDA di BMP280
Software juga dibuat minimalis
// https://bitbucket.org/christandlg/bmx280mi/src/master/examples/BMx280_I2C/BMx280_I2C.ino
// BMx280_I2C.ino
//
// shows how to use the BMP280 / BMx280 library with the sensor connected using I2C.
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the AS3935 to the Arduino like this:
//
// Arduino - BMP280 / BME280
// 3.3V ---- VCC
// GND ----- GND
// SDA ----- SDA
// SCL ----- SCL
// some BMP280/BME280 modules break out the CSB and SDO pins as well:
// 5V ------ CSB (enables the I2C interface)
// GND ----- SDO (I2C Address 0x76)
// 5V ------ SDO (I2C Address 0x77)
// other pins can be left unconnected.
#include <Arduino.h>
#include <Wire.h>
#define I2C_SDA 15
#define I2C_SCL 13
#include <BMx280I2C.h>
#define I2C_ADDRESS 0x76
//create a BMx280I2C object using the I2C interface with I2C Address 0x76
BMx280I2C bmx280(I2C_ADDRESS);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(1000);
//wait for serial connection to open (only necessary on some boards)
while (!Serial);
// Wire.begin();
Wire.begin(I2C_SDA, I2C_SCL);
I2C_Scan() ; // just for verifying
//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
//and reads compensation parameters.
if (!bmx280.begin())
{
Serial.println("begin() failed. check your BMx280 Interface and I2C Address.");
while (1);
}
if (bmx280.isBME280())
Serial.println("sensor is a BME280");
else
Serial.println("sensor is a BMP280");
//reset sensor to default parameters.
bmx280.resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280.isBME280())
bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
void loop() {
float temperature = 0;
float pressure = 0;
float humidity = 60; // default humidity
float co2 = 0;
float tvoc = 0;
delay(1000);
//start a measurement
if (!bmx280.measure())
{
Serial.println("could not start measurement, is a measurement already running?");
return;
}
//wait for the measurement to finish
do
{
delay(100);
} while (!bmx280.hasValue());
// Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
// Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
// Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());
pressure = bmx280.getPressure();
temperature = bmx280.getTemperature();
//important: measurement data is read from the sensor in function hasValue() only.
//make sure to call get*() functions only after hasValue() has returned true.
if (bmx280.isBME280())
{
// Serial.print("Humidity: ");
// Serial.println(bmx280.getHumidity());
humidity = bmx280.getHumidity();
}
Serial.print("Temp\t");
Serial.print(temperature);
Serial.print("\t");
Serial.print("Humidity\t");
Serial.print(humidity);
Serial.print("\t");
Serial.print("Pressure\t");
Serial.print(pressure);
Serial.print("\t");
Serial.println("");
}
void I2C_Scan() {
byte error, address;
int nDevices;
Serial.println("I2C Scanning...");
nDevices = 0;
for (address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.println(address, HEX);
nDevices++;
}
else if (error == 4) {
Serial.print("Unknow error at address 0x");
if (address < 16) {
Serial.print("0");
}
Serial.println(address, HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
}
else {
Serial.println("done\n");
}
}
Pada percobaan ini dilakukan pengiriman data telemetri dari ESP32 ke Thingsboard. Sensor yang dipakai adalah sakelar on-off. Percobaan ini adalah bagian dari pembuatan sistem IoT (Internet of Things) yang terdiri dari beberapa ESP32 dan software ThingsBoard.
Pada percobaan ini , tidak semua komponen ThingsBoard dipakai. Yang dipakai adalah sebagai berikut
Devices: menggunakan ESP32 dan sakelar sebagas sensor
Protokol HTTP sebagai ThingsBoard Transports
ThingsBoard Core
SQL Database
External Systems
Aliran data pada sistem yang dibuat adalah sebagai berikut:
Sakelar bertindak sebagai sensor. Besaran yang dihasilkan oleh sakelar adalah 0 dan 1. ESP32 membaca status sensor setiap interval tertentu, dan kemudian mengirimkannya ke ThingsBoard menggunakan protokol HTTP. Data ini kemudian disimpan di Database.
Data dari database ini dapat ditampilkan menggunakan Dashboard pada Thingsboard, dan juga dapat diambil oleh aplikasi eksternal menggunakan REST API (REpresentational State Transfer Application Program Interface)
Hardware yang dipakai adalah sebagai berikut:
ESP32 Lolin Wemos
2 buah sakelar. Pada percobaan ini digunakan sakelar geser SPDT dan push button.
ESP32 Lolin Wemos
Daftar pin ESP32 yang dipakai adalah sebagai berikut
pin 13 sebagai input digital, diberi nama SW0. Input active low.
pin 15 sebagai input digital, diberi nama SW1. Input active low.
Berikut ini foto rangkaian setelah dirakit
Perangkat lunak yang dipakai
Arduino versi 1.8.19 (Windows)
ThingsBoard versi 3.3.4.1
Ubuntu Linux 20.04.04 LTS
Wireshark versi 3.02
Setting ThingsBoard
[under construction]
Perangkat Lunak ESP32
Perangkat lunak ESP32 dibuat dengan Arduino
Library yang dipakai di Arduino adalah sebagai berikut
// demo switch telemetry to Thingsboard
// adapted from https://thingsboard.io/docs/samples/esp32/gpio-control-pico-kit-dht22-sensor/
#include <WiFi.h> // WiFi control for ESP32
#include <ThingsBoard.h> // ThingsBoard SDK
// onboard LED
#define BUILTIN_LED 22
// switch pin definition
#define SW0 13
#define SW1 15
// Helper macro to calculate array size
// #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
// WiFi access point
#define WIFI_AP_NAME "ACCESS_POINT_NAME"
// WiFi password
#define WIFI_PASSWORD "ACCESS_POINT_PASSWORD"
// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
#define TOKEN "QdqSrxBAjBvxAoJyeoXN"
// ThingsBoard server instance.
#define THINGSBOARD_SERVER "192.168.0.90"
// Baud rate for debug serial
#define SERIAL_DEBUG_BAUD 115200
// Initialize ThingsBoard client
WiFiClient espClient;
// Initialize ThingsBoard instance
ThingsBoard tb(espClient);
// the Wifi radio's status
int status = WL_IDLE_STATUS;
// main application loop delay (ms)
int quant = 20;
// Period of sending a temperature/humidity data.
int send_delay = 2000;
// Time passed after telemetry data was sent, milliseconds.
int send_passed = 0;
char mac_str[20]; // storing MAC address string
byte mac_byte[6]; // storing MAC address bytes
int led_counter = 0; //blinking built int led
// Setup an application
void setup() {
pinMode(SW0, INPUT_PULLUP); // input switch
pinMode(SW1, INPUT_PULLUP);
pinMode(BUILTIN_LED , OUTPUT);
// Initialize serial for debugging
Serial.begin(SERIAL_DEBUG_BAUD);
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
InitWiFi();
WiFi.macAddress(mac_byte);
sprintf(mac_str, "%02x%02x%02x%02x%02x%02x", mac_byte[0], mac_byte[1], mac_byte[2], mac_byte[3], mac_byte[4], mac_byte[5]);
Serial.print("ESP board MAC address: ");
Serial.println(WiFi.macAddress());
Serial.print("ESP board IP address: ");
Serial.println(WiFi.localIP());
}
// Main application loop
void loop() {
delay(quant);
send_passed += quant;
// Reconnect to WiFi, if needed
if (WiFi.status() != WL_CONNECTED) {
reconnect();
return;
}
// Reconnect to ThingsBoard, if needed
if (!tb.connected()) {
// Connect to the ThingsBoard
Serial.print("Connecting to: ");
Serial.print(THINGSBOARD_SERVER);
Serial.print(" with token ");
Serial.println(TOKEN);
if (!tb.connect(THINGSBOARD_SERVER, TOKEN)) {
Serial.println("Failed to connect");
return;
}
}
// Check if it is a time to send switch data
if (send_passed > send_delay) {
int switch0, switch1;
switch0 = digitalRead(SW0);
switch1 = digitalRead(SW1);
Serial.print("Sending telemetry data...");
Serial.print(" SW0:");
Serial.print(switch0);
Serial.print(" SW1:");
Serial.println(switch1);
tb.sendTelemetryInt("switch00", switch0);
tb.sendTelemetryInt("switch01", switch1);
send_passed = 0;
}
// Process messages
tb.loop();
led_counter++; // LED blink at 1 Hz
if (led_counter > 50) {
led_counter = 0;
}
if (led_counter > 25) {
digitalWrite(BUILTIN_LED , LOW);
} else {
digitalWrite(BUILTIN_LED , HIGH);
}
}
void InitWiFi()
{
Serial.println("Connecting to AP ...");
// attempt to connect to WiFi network
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
void reconnect() {
// Loop until we're reconnected
status = WiFi.status();
if ( status != WL_CONNECTED) {
WiFi.begin(WIFI_AP_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
}
Pengecekan Telemetri
Setelah sistem dirakit dan ESP32 diprogram, perlu dilakukan pengecekan apakah sistem berfungsi dengan baik. Pengecekan pengiriman data telemetri dilakukan dengan cara:
Memantau output dari port serial ESP32
Mengecek data telemetri di server Thingsboard
Berikut ini output dari serial monitor ESP32.
19:45:30.745 -> Connecting to AP ...
19:45:31.225 -> ......Connected to AP
19:45:33.738 -> ESP board MAC address: 3C:71:BF:03:41:4C
19:45:33.738 -> ESP board IP address: 192.168.0.124
19:45:33.773 -> Connecting to: 192.168.0.90 with token QdqSrxBAjBvxAoJyeoXN
19:45:35.798 -> Sending telemetry data... SW0:1 SW1:1
19:45:37.819 -> Sending telemetry data... SW0:1 SW1:1
19:45:39.850 -> Sending telemetry data... SW0:1 SW1:1
Dari output tersebut dapat disimpulkan:
ESP32 berhasil terhubung ke access point
ESP32 berhasil mendapatkan IP address
ESP32 berhasil mengirim data ke ThingsBoard
Untuk mengecek data yang masuk ke server, prosedurnya sebagai berikut:
Login ke ThingsBoard sebagai tenant. username: [email protected], password: tenant (jika belum diganti)
Klik di “Devices”
Klik di “ESP32 Dual Switch”
Klik di “Latest telemetry”
Jika pengiriman data normal, maka status sakelar terakhir akan muncul di Device details, seperti gambar berikut ini.
Angka di kolom “Value” akan sesuai dengan status sakelar. Pada percobaan ini pengiriman data dilakukan dengan interval 2 detik, jadi selambatnya dalam 2 detik status sakelar terakhir akan masuk.
Dashboard di ThingsBoard
Setelah data dicek masuk, kita dapat membuat dashboard di Thingsboard untuk menampilkan data dari sensor. Berikut ini contoh tampilan dashboard.
Pengambilan Data Telemetri Dengan REST API
Data telemetri di server ThingsBoard dapat diambil menggunakan REST API dari aplikasi lain.
Pada percobaan ini data diambil dengan menggunakan software ‘curl’ di Ubuntu Linux.
Berikut ini beberapa kecelakaan yang terjadi karena kegagalan pada sistem mikroprosesor, terutama yang disebabkan kesalahan di perangkat lunak (software).
Toyota Unintended Acceleration
Mobil Toyota melakukan akselerasi sendiri tanpa diperintah oleh pengemudi. Korban total 89 orang. Penyebab: kesalahan pada software ETCS (Electronic Throttle Control) pada mobil Camry,Lexus ES, Tacoma buatan Toyota.
Therac-25 adalah mesin untuk melakukan terapi radiasi pada pasien. Bugs pada software menyebabkan dosis radiasi melebihi batas. Korban 6 orang: 3 pasien meninggal, 3 pasien luka.
Pesawat A400M jatuh karena 3 dari 4 mesin mati. “The key scenario being examined by investigators is that the torque calibration parameter data was accidentally wiped on three engines as the engine software was being installed at Airbus facilities, which would prevent the FADECs from operating”
Software MCAS (Maneuvering Characteristics Augmentation System) menyebabkan 2 buah pesawat Boeing 737 MAX jatuh. Softwarenya sendiri tidak bermasalah, namun proses engineering pada pembuatannya yang bermasalah.
Pada era perang dingin, USSR memiliki sistem pendeteksi (early warning) peluncuran rudal antar benua (ICBM) dari Amerika. Sistem ini gagal bekerja karena terjadi false positive. “the false alarm was eventually traced to the satellite, which picked up the sun’s reflection off the tops of clouds and mistook it for a missile launch. The computer program that was supposed to filter out such information was rewritten.”
Patriot Missile adalah Surface to Air Missile (SAM). Pada perang teluk (Gulf War), Rudal Patriot ini gagal menembak misil Scud yang ditembakkan dari Iraq. Akibatnya 28 orang tentara meninggal dan 100 orang luka.