Author Archives: pccontrol
Pengetahuan Dasar Menggunakan Timer ESP32 dgn Arduino IDE
Draft
ESP32 mempunyai 4 timer hardware, yang masing-masing merupakan counter up/down 64-bit dengan prescaler 16-bit. Kecuali ESP32-C3 yang hanya mempunyai 2 timer yang masing-masing 54 bit saja. Timer ESP32 juga memiliki kemampuan memuat ulang otomatis (auto-reloading ) di akhir periode counting.
Setiap timer ESP32 menggunakan clock APB (APB_CLK biasanya dgn frekuensi 80 MHz) sebagai clock dasar. Clock ini kemudian diperkecil (dibagi) oleh prescaler 16-bit yang menghasilkan time-base tick time . Kita bisa mengubah nilai prescaler untuk mengontrol waktu tick timer.
Prescaler 16-Bit dapat membagi APB_CLK dengan faktor dari 2 ~ 65536. Saat kita menetapkan nilai prescaler menjadi 1 atau 2, pembagi clocknya adalah 2. Ketika kita mengatur prescaler ke 0, pembagi clocknya adalah 65536. Untuk prescaler lainnya akan menyebabkan clock dibagi dengan nilai yang sama dengan nilai precaler yang kita tulis ke register prescaler.
ESP32 timers dapat mentriger Event/kejadian alarm yang menyebabkab timer reload atau terjadi interrupt tergantung konfigurasi yg kita buat. Alarm event ditrigger ketika nilai di alarm register yg kita set sama dengan nilai timer saat ini. kondisi ini digunakan untuk interupsi periodik di dalam projek kita.
Rumus durasi interupsi periodik Timer ESP32
Untuk menghasilkan event periodik , kita akan menggunakan pembangkitan event alarm serta prescaler untuk mencapai periodik interupsi yang diinginkan. Ada 3 kasus khusus untuk persamaan Timer di bawah ini, yaitu Ketika Prescaler=1 atau 2, maka rumusnya T OUT = TimerTicks x (2/APB_CLK) . Ketika Prescaler=0, maka rumusnya T OUT = TimerTicks x (65536/APB_CLK) . selain itu ( nilai presclaer bukan 0,1 dan 2) gunakan rumus di bawah.
Contoh-1
Kita akan membuat LED kedip setiap 1 ms Untuk ini, kita akan menggunakan persamaan di atas, APB_CLK default adalah 80MHz atau 80.000.000Hz. T OUT yang diinginkan untuk periode interupsi di mana kita akan mengaktifkan LED adalah 1ms, Jadi T OUT = 1ms atau 0.001s . Hanya dua yang tidak diketahui sekarang adalah nilai Prescaler dan jumlah TimerTicks yang akan kita set di event alarmnya.
Kita dapat mengatur Prescaler ke nilai apa pun yang kita inginkan tetapi untuk menyederhanakan perhitungan, kita set Prescaler =80 . sekarang tinggal nilai TimerTicks yg akan kita cari dengan rumus persamaan untuk TimerTicks:
dengan rumus diatas kita memperoleh nilai TimerTicks = 1000 .
Code programnya :
#define LED 2 // pin LED tergantung type ESP32 boardnya
hw_timer_t *Timer_LED = NULL;
void IRAM_ATTR Timer0_ISR()
{
digitalWrite(LED, !digitalRead(LED));
}
void setup()
{
pinMode(LED, OUTPUT);
Timer_LED = timerBegin(0, 80, true); //(timer0, prescalar=80, true=countUp)
timerAttachInterrupt(Timer_LED, &Timer0_ISR, true);//aktifkan interupsi
timerAlarmWrite(Timer_LED, 1000, true); // (ISR, timerTick=1000, reload =true)
timerAlarmEnable(Timer_LED);//aktifkan timer berjalan terus menerus
}
void loop()
{
}
Contoh 2 :
Kita akan membuat led berkedip tiap 1 detik
#define LED 2
hw_timer_t *My_timer = NULL;
void IRAM_ATTR onTimer()
{
digitalWrite(LED, !digitalRead(LED));
}
void setup()
{
pinMode(LED, OUTPUT);
My_timer = timerBegin(1, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, 1000000, true); //interupsi tiap 1 detik
timerAlarmEnable(My_timer);
}
void loop()
{
}
============================================
Contoh-3
const byte LED_GPIO = 2;
volatile int interruptCounter;
volatile int blinkCounter = 0;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer()
{
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter++;
blinkCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
}
void setup() {
Serial.begin(9600);
pinMode(LED_GPIO, OUTPUT);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
// Start the timer
timerAlarmEnable(timer);
}
void loop() {
if (interruptCounter > 0)
{
Serial.print(blinkCounter);
Serial.print(" ");
portENTER_CRITICAL(&timerMux);
interruptCounter--;
// timerAlarmDisable(timer);
if (blinkCounter % 2 == 0)
{
timerAlarmWrite(timer, 5000000, true);
}
else
{
timerAlarmWrite(timer, 500000, true);
}
// timerAlarmEnable(timer);
portEXIT_CRITICAL(&timerMux);
toggleLED();
}
}
void toggleLED()
{
digitalWrite(LED_GPIO, HIGH);
delay(50);
digitalWrite(LED_GPIO, LOW);
}
Berikut ini daftar lengkap fungsi yang dapat kita gunakan dalam memprogram timer ESP32 :
void timerEnd(hw_timer_t * timer);
void timerStart(hw_timer_t * timer);
void timerStop(hw_timer_t * timer);
void timerRestart(hw_timer_t * timer);
void timerWrite(hw_timer_t * timer, uint64_t val);
uint64_t timerRead(hw_timer_t * timer);
uint64_t timerReadMicros(hw_timer_t * timer);
uint64_t timerReadMilis(hw_timer_t * timer);
double timerReadSeconds(hw_timer_t * timer);
uint32_t timerGetFrequency(hw_timer_t * timer);
void timerAttachInterrupt(hw_timer_t * timer, void (*userFunc)(void));
void timerAttachInterruptArg(hw_timer_t * timer, void (*userFunc)(void*), void * arg);
void timerDetachInterrupt(hw_timer_t * timer);
void timerAlarm(hw_timer_t * timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count);1
referensi
Contoh Code Arduino Modbus RTU ESP32 sebagai Slave
Tool yang diperlukan
sotware
- Arduino IDE
Hardware :
- PC/laptop
- ESP32 yg sudah di program sbg Master
- ESP32 yg akan di program sbg Slave
- modul TTL to rs485 automatic 2 pcs
Pada contoh berikut ESP32 sebagai Modbus slave dengan ID=1.
komunikasi melalaui RX2-TX2 pada pin GPIO 16 (RX2) dan GPIO 17 (Tx2) ESP32.
#include <ModbusRTU.h>
#define RXD2 16
#define TXD2 17
#define DIR 2 // pin untuk arah modul ttl-rs485 non automatic
#define REGN 2
#define SLAVE_ID 1
ModbusRTU mb;
void setup() {
Serial.begin(9600);
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
mb.begin(&Serial2, DIR);
mb.slave(SLAVE_ID);//Initializng modbus slave device with ID 1
//buat 4 buah holding register
mb.addHreg(0); // add the register 40001
mb.addHreg(1); // add the register 40002
mb.addHreg(2); // add the register 40003
mb.addHreg(3); // add the register 40004
// mb.Hreg(1, 123); // isi register 40002 dgn nilai 123
}
unsigned long lastMillis = 0;
void loop()
{
mb.task();
yield();
long currentMillis = millis();
if (currentMillis - lastMillis > 5000)
{
//tampilkan data register
Serial.println(mb.Hreg(0x0)); //register 40001
Serial.println(mb.Hreg(0x1)); //register 40002
Serial.println(mb.Hreg(0x2)); //register 40003
Serial.println(mb.Hreg(0x3)); //register 40004
lastMillis = currentMillis;
}
}
Contoh Code Arduino Modbus RTU ESP32 sebagai Master
Tool yang diperlukan
sotware
- Arduino IDE
- ModbusSlave simulator
Hardware :
- PC/laptop
- ESP32
- modul usb to Rs485
- modul TTL to rs485 automatic
Pada contoh berikut ESP32 sebagai Modbus Master yang akan menulis nilai 700 ke Register 40003 sebuah slave dengan ID=1.
komunikasi melalaui RX2-TX2 pada pin GPIO 16 (RX2) dan GPIO 17 (Tx2) ESP32.
#include <ModbusMaster.h>
#include <Arduino.h>
#define RS485Serial Serial2
#define SLAVE_ADD 1
#define RX_PIN 16 //RX2
#define TX_PIN 17 //TX2
ModbusMaster modbus;
void setup() {
Serial.begin(115200, SERIAL_8N1);
RS485Serial.begin(9600, SERIAL_8N2, RX_PIN, TX_PIN);
modbus.begin(SLAVE_ADD, RS485Serial);
}
unsigned long lastMillis = 0;
void loop() {
long currentMillis = millis();
if (currentMillis - lastMillis > 1000)
{
Serial.println("Slave " + (String)SLAVE_ADD);
//FC 06 : writeSingleRegister(uint16_t reg, uint16_t nilai);
// contoh berikut REGISTER 40003 di slave akan diisi dgn nilai 700
uint8_t result = modbus.writeSingleRegister(0x02, 700);
if (result == modbus.ku8MBSuccess)
{
Serial.print("berhasil");
}
else{
getMsgError(&modbus, result);
Serial.print("gagal");
}
lastMillis = currentMillis;
Serial.println();
}
}
bool getMsgError(ModbusMaster *node, uint8_t result)
{
String tmpstr2 = "\r\n";
switch (result)
{
case node->ku8MBIllegalFunction:
tmpstr2 += "Illegal Function";
break;
case node->ku8MBIllegalDataAddress:
tmpstr2 += "Illegal Data Address";
break;
case node->ku8MBIllegalDataValue:
tmpstr2 += "Illegal Data Value";
break;
case node-> ku8MBSlaveDeviceFailure:
tmpstr2 += "Slave Device Failure";
break;
case node->ku8MBInvalidSlaveID:
tmpstr2 += "Invalid Slave ID";
break;
case node->ku8MBInvalidFunction:
tmpstr2 += "Invalid Function";
break;
case node->ku8MBResponseTimedOut:
tmpstr2 += "Response Timed Out";
break;
case node->ku8MBInvalidCRC:
tmpstr2 += "Invalid CRC";
break;
default:
tmpstr2 += "Unknown error: " + String(result);
break;
}
Serial.println(tmpstr2);
return false;
}
Berikut ini hasil penulisan nilai 700 ke reg 40003 esp32 master ke modbus slave simuator
Contoh Code ESP32 sebagai AP Hotspot dan web server untuk Input Data dan bisa update program Via wifi
Contoh Kode ESP32 dengan fitur:
- ESP32 sebagai Access Point / hotspot
- Authentification : login user-password
- Bisa update program via wifi (OTA )
- form input data
- On – OFF Relay
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#define LED_BUILTIN 2
AsyncWebServer server(80);
// Replace with your network credentials
const char* ssid = "ESP32";
const char* password = "123456789";
IPAddress local_ip(192, 168, 123, 4); //ip address untuk akses ESP32
IPAddress gateway(192, 168, 123, 1); //gateway
IPAddress subnet(255, 255, 255, 0); //subnet
const char* http_username = "admin";
const char* http_password = "admin";
// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* PARAM_INPUT_1 = "input1";
const char* PARAM_INPUT_2 = "input2";
const char* PARAM_INPUT_3 = "input3";
const char* PARAM_INPUT_4 = "state";
const int output = 2;
int par1=0;
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 2.6rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 10px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 34px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 68px}
input:checked+.slider {background-color: #2196F3}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body style="background-color:#2cc932;">
<h2>CounterProduksi.com</h2>
<h2>WA : 0812-1925-1068 </h2>
<table >
<tr>
<form action="/get">
<td>
PLAN:
</td>
<td>
<input type="text" name="input1">
</td>
<td>
<input type="submit" value="Submit">
</td>
</form>
</tr>
<tr>
<form action="/get">
<td>
ACTUAL:
</td>
<td>
<input type="text" name="input2">
</td>
<td>
<input type="submit" value="Submit">
</td>
</form>
</tr>
<tr>
<form action="/get">
<td>
MODEL:
</td>
<td>
<input type="text" name="input3">
</td>
<td>
<input type="submit" value="Submit">
</td>
</form>
</tr>
</table>
<br>
<br>
<button onclick="logoutButton()">Logout</button>
<p>Status Counter : <span id="state">%STATE%</span></p>
%BUTTONPLACEHOLDER%
<script>
function toggleCheckbox(element)
{
var xhr = new XMLHttpRequest();
if(element.checked){
xhr.open("GET", "/updatex?state=1", true);
document.getElementById("state").innerHTML = "ON";
}
else {
xhr.open("GET", "/updatex?state=0", true);
document.getElementById("state").innerHTML = "OFF";
}
xhr.send();
}
function logoutButton()
{
var xhr = new XMLHttpRequest();
xhr.open("GET", "/logout", true);
xhr.send();
setTimeout(function(){ window.open("/logged-out","_self"); }, 1000);
}
</script>
</body>
</html>
)rawliteral";
const char logout_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Logged out or <a href="/">kembali</a>.</p>
<p><strong>CopyRight:</strong> counterproduksi.com-2024</p>
</body>
</html>
)rawliteral";
void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found");
}
// Replaces placeholder with button section in your web page
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons ="";
String outputStateValue = outputState();
buttons+= "<p><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"output\" " + outputStateValue + "><span class=\"slider\"></span></label></p>";
return buttons;
}
if (var == "STATE")
{
if(digitalRead(output)){
return "ON";
}
else {
return "OFF";
}
}
return String();
}
String outputState(){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
return "";
}
void setup(){
// Serial port for debugging purposes
Serial.begin(115200);
pinMode(output, OUTPUT);
digitalWrite(output, LOW);
WiFi.softAP(ssid, password);
WiFi.softAPConfig(local_ip, gateway, subnet);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
request->send_P(200, "text/html", index_html, processor);
});
server.on("/logout", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(401);
});
server.on("/logged-out", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", logout_html, processor);
});
// Send a GET request to <ESP_IP>/update?state=<inputMessage>
server.on("/updatex", HTTP_GET, [] (AsyncWebServerRequest *request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
String inputMessage;
String inputParam;
// GET input1 value on <ESP_IP>/update?state=<inputMessage>
if (request->hasParam(PARAM_INPUT_4)) {
inputMessage = request->getParam(PARAM_INPUT_4)->value();
inputParam = PARAM_INPUT_4;
digitalWrite(output, inputMessage.toInt());
}
else {
inputMessage = "No message sent";
inputParam = "none";
}
Serial.println(inputMessage);
request->send(200, "text/plain", "OK");
});
//===========
// Send a GET request to <ESP_IP>/get?input1=<inputMessage>
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request)
{
String inputMessage;
String inputParam;
// GET input1 value on <ESP_IP>/get?input1=<inputMessage>
if (request->hasParam(PARAM_INPUT_1)) {
inputMessage = request->getParam(PARAM_INPUT_1)->value();
inputParam = PARAM_INPUT_1;
}
// GET input2 value on <ESP_IP>/get?input2=<inputMessage>
else if (request->hasParam(PARAM_INPUT_2)) {
inputMessage = request->getParam(PARAM_INPUT_2)->value();
inputParam = PARAM_INPUT_2;
}
// GET input3 value on <ESP_IP>/get?input3=<inputMessage>
else if (request->hasParam(PARAM_INPUT_3)) {
inputMessage = request->getParam(PARAM_INPUT_3)->value();
inputParam = PARAM_INPUT_3;
}
else {
inputMessage = "No message sent";
inputParam = "none";
}
par1= inputMessage.toInt() ; // par1=par1 + 3;
request->send(200, "text/html", "No-HP : " + inputParam +
"Usia : " + par1 +
"<br><a href=\"/\">Kembali</a>");
});
//===========
server.onNotFound(notFound);
AsyncElegantOTA.begin(&server); // Start AsyncElegantOTA update program via wifi :
// ketik http://ip_address/update
server.begin();
}
void loop() {
}
untuk upgrade program via wifi menggunakan OTA langkah langkahnya sbb:
- convert code program yg akan di upload ke esp32 ke dlm bentuk file *.bin
- hidupkan ESP32 ( yg sdh diupload contoh code diatas via USB serial )
- konek laptop ke hotspot esp32
- ketik di browser http://ipaddress/update misal http://192.168.123.4./update
- maka akan muncul halaman spt pada gb berikut ini:
Contoh Code Master dan Slave modbus dalam sebuah Arduino
Contoh Berikut ini menjadikan sebuah arduino mega250 sebagai Master Nodbus RTU (pada pin serial RX2-TX2) sekaligus Slave modbus RTU (pada pin serial RX3-TX3) .
/**
* Modbus master & slave dlm 1 arduino
*/
#include <ModbusRtu.h>
//uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
/**
* Modbus object declaration
* u8id : node id = 0 for master, = 1..247 for slave
* u8serno : serial port (use 0 for Serial)
* u8txenpin : 0 for RS-232 and USB-FTDI
* or any pin number > 1 for RS-485
*/
uint16_t au16data[16] = { 0, 1, 2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
Modbus master(0,2,0); // RX2-TX2 sebagai Modbus Master
Modbus slave(1,3,0); // RX3-TX3 sebagai modbus Slave
/**
* This is an structe which contains a query to an slave device
*/
modbus_t telegram[2];
unsigned long u32wait;
int data=0;
void setup() {
Serial.begin(9000);
Wire.begin();
lcd.init(); // lcd.begin(16, 2);
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Modbus Master");
delay(1000);
// telegram 0: read registers
telegram[0].u8id = 1; // slave address
telegram[0].u8fct = 3; // function code (this one is registers read)
telegram[0].u16RegAdd = 0; // start address in slave
telegram[0].u16CoilsNo = 4; // number of registers to read
telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino
// telegram 1: write a single register
telegram[1].u8id = 1; // slave address
telegram[1].u8fct = 6; // function code (this one is write a single register)
telegram[1].u16RegAdd = 3; // start address in slave
telegram[1].u16CoilsNo = 1; // number of elements registers to read
telegram[1].au16reg = au16data+4; // pointer to a memory array in the Arduino
master.begin( 9600 ); // baud-rate at 19200
slave.begin( 9600 ); // baud-rate at 19200
master.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over
u32wait = millis() + 500;
u8state = u8query = 0;
}
void loop() {
//=================Modbus Slave==============================
slave.poll( au16data, 16 ); //modbus slave
//===============================MOdbus Master============
switch( u8state )
{
case 0:
if (millis() > u32wait) u8state++; // wait state
break;
case 1: //
master.query( telegram[u8query] ); // send query (only once)
u8state++;
u8query++;
if (u8query > 1) u8query = 0;
break;
case 2:
master.poll(); // check incoming messages
if (master.getState() == COM_IDLE) {
u8state = 0;
u32wait = millis() + 1000;
lcd.setCursor(0,1);
lcd.print("Val :"); lcd.print(au16data[1]);// hasil baca reg 40002
Serial.print("data=");Serial.println(data);
data++;
if(data>=9999)data=0;
lcd.setCursor(8,1);
lcd.print("dat:"); lcd.print(data);
}
break;
}
//delay(100);
au16data[3] = data;
// bacaDataDariAndon();
}
Contoh Code Arduino Modbus Master RTU Menulis dan Membaca Slave
draft
#include <ModbusRtu.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query
/**
* Modbus object declaration
* u8id : node id = 0 for master, = 1..247 for slave
* u8serno : serial port (use 0 for Serial)
* u8txenpin : 0 for RS-232 and USB-FTDI
* or any pin number > 1 for RS-485
*/
Modbus master(0,3,0); // menggunakan RX3-TX3
/**
* This is an structe which contains a query to an slave device
*/
modbus_t telegram[2];
unsigned long u32wait;
int data=0;
void setup() {
Wire.begin();
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Modbus Master");
delay(1000);
// telegram 0: read registers
telegram[0].u8id = 1; // slave address
telegram[0].u8fct = 3; // function code (this one is registers read)
telegram[0].u16RegAdd = 0; // start address in slave
telegram[0].u16CoilsNo = 4; // number of elements (coils or registers) to read
telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino
// telegram 1: write a single register
telegram[1].u8id = 1; // slave address
telegram[1].u8fct = 6; // function code (this one is write a single register)
telegram[1].u16RegAdd = 4; // start address in slave
telegram[1].u16CoilsNo = 1; // number of elements (coils or registers) to read
telegram[1].au16reg = au16data+4; // pointer to a memory array in the Arduino
master.begin( 9600 ); // baudrate 9600
master.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over
u32wait = millis() + 1000;
u8state = u8query = 0;
}
void loop() {
switch( u8state ) {
case 0:
if (millis() > u32wait) u8state++; // wait state
break;
case 1:
master.query( telegram[u8query] ); // send query (only once)
u8state++;
u8query++;
if (u8query > 2) u8query = 0;
break;
case 2:
master.poll(); // check incoming messages
if (master.getState() == COM_IDLE) {
u8state = 0;
u32wait = millis() + 1000;
lcd.setCursor(0,1);
lcd.print("FC03:"); lcd.print(au16data[1]); // hasil baca FC03 di tulis ke LCD
data++;
lcd.setCursor(8,1);
lcd.print("FC06:"); lcd.print(data); // Data yg akan ditulis dgn FC03 ditampilkan di LCD
}
break;
}
delay(1000);
au16data[4] = data; // ini data nya yg akan di write dgn FC06
}
Contoh Code modbus client VB net Membaca dan Menulis Modbus TCP device Server
Pendahuluan
Berikut ini contoh mudah membaca dan menulis dgn vb net ke device yg menggunakan protokol Modbus
Imports EasyModbus
Public Class Form1
Dim ComError
Dim ModbusClient
Dim modClient As New EasyModbus.ModbusClient
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim dataku As Integer()
Try
dataku = modClient.ReadHoldingRegisters(Convert.ToInt16(TextBox7.Text), Convert.ToInt16(TextBox8.Text))
ListBox1.Items.Clear()
If dataku.Length > 0 Then
For Each value As Integer In dataku
ListBox1.Items.Add(value)
Next
End If
TextBox4.Text = "read berhasil"
Catch ex As Exception
' MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
TextBox4.Text = ex.Message
End Try
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Modbus_Client = New EasyModbus.ModbusClient(TextBox1.Text, 502)
modClient.IPAddress = TextBox1.Text
modClient.Port = TextBox2.Text
ComError = 0
Try
modClient.Connect()
TextBox4.Text = "Communication OK!"
Catch ex As Exception
' MessageBox.Show("An error occurred: " & ex.Message, "Error Occurred", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning)
TextBox4.Text = ex.Message
ComError = 1
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
modClient.Disconnect()
TextBox4.Text = "diskonek berhasil"
Catch ex As Exception
TextBox4.Text = ex.Message
End Try
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Try
modClient.WriteSingleRegister(Convert.ToInt16(TextBox6.Text), Convert.ToInt16(TextBox3.Text))
TextBox4.Text = "writw berhasil"
Catch ex As Exception
TextBox4.Text = ex.Message
End Try
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
' TextBox5.Text = EasyModbus.ModbusClient.ConvertRegistersToLong(modClient.ReadHoldingRegisters(4, 2))
' UShort[] holdingRegisters = modbusClient.ReadHoldingRegisters(100, 2)
Dim holdingRegisters As Integer() = modClient.ReadHoldingRegisters(4, 2)
' Convert the registers to a long integer
Dim value As Long = ModbusClient.ConvertRegistersToLong(holdingRegisters)
TextBox5.Text = value.ToString()
End Sub
End Class
Doownload Source Code disini
Untuk Modbus TCP Servernya Kita gunakan aplikasi Simulator counter produksi sbb:
Target akan increment 1 setiap sekian detik sesuai waktu cycleTime yg diset . misal cycle time = 5 , maka setiap 5 detik target akan bertambah 1.
Download aplikasi counter simulator disini
Referensi :
Contoh Code Arduino merubah 2 register modbus menjadi Floating Point
Pada atikel ini kita akan membuat modbus slave serial pada arduino yg akan menerima data floating point dari sebuah master modbus misalnya berupa PLC atau arduino lainnya .
Biasanya device modbus menggunakan 2 register Modbus berturut-turut untuk mengkodekan nilai floating point
Contoh: untuk nilai floating-point 50,12 representasi floating point presisi tunggal IEE 754 adalah seperti yang ditunjukkan di bawah ini.
data dibagi menjadi duabuah 16 Bit Words (Register): HIGH WORD berisi 0x4248 dan LOW WORD berisi 0x7df4. misal disimpan d Modbus Holding Register 40001 & 40002. Beberapa produsen mengirimkan High Word terlebih dahulu, baru kemudian Low Word.
Pabrikan lain mengirimkan Low Word Pertama, lalu High Word.
untuk merubah ke nilai floating point terlebih dahulu gabungkan ke dua nilai hex di register tsb, baru dirubah ke nilai floating point
Code Arduino
#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
#include <ArduinoModbus.h>
const int numHoldingRegisters = 10;
union {
float f;
uint16_t reg[2];
} u;
void setup() {
Serial.begin(9600);
while (!Serial);
// start the Modbus RTU server, with (slave) id 42
if (!ModbusRTUServer.begin(1, 9600)) {
Serial.println("Failed to start Modbus RTU Server!");
while (1);
}
ModbusRTUServer.configureHoldingRegisters(0x00, numHoldingRegisters);
// contoh modbus master menulis datanya 50,12 dlm hex = 0x42487df4 ke slave modbus arduino kita
ModbusRTUServer.holdingRegisterWrite(0, 0x7df4); // 40001
ModbusRTUServer.holdingRegisterWrite(1, 0x4248); // 40002
}
void loop() {
// poll for Modbus RTU requests
ModbusRTUServer.poll();
uint16_t lowWord = ModbusRTUServer.holdingRegisterRead(0);
uint16_t highWord = ModbusRTUServer.holdingRegisterRead(1);
u.reg[0] = lowWord; //0x7df4;
u.reg[1] = highWord; //0x4248;
// Convert the union to a float
float hasilFloat = u.f; // hasilFloat akan bernilai 50.12
int komanya = (int) (hasilFloat * 100) % 100;
// untuk melihat hasil kita simpan hasil di reg 40003 dan 40004
ModbusRTUServer.holdingRegisterWrite(2, f); // simpan nilai 50 ke register 40003
ModbusRTUServer.holdingRegisterWrite(3, komanya); // simpan nilai 12 ke register 40004
//}
}
HAsil pembacaan register akan sbg berikut ini
Cara Praktis Mengatasi Noise Pada Lingkungan Industri.
[Draft Article]
Berikut ini cara praktis mengatasi Noise pada Lingkungan Industri yang menyebabkan terganggunya rangkaian elektronik yang kita buat
- Guanakan capacitor 100nF pada VCC – Gnd untuk setiap IC.
- Tambahkan capasitor pada power dc .
- Gunakan Emi filter dan wajib kaki ground emi filternya dihubungkan ke eart ground.
- Disarankan gunakan casing berbahan metal/logam daripada plastik.
- Gunakan Power Supply yang berkualitas .
- Lakukan uji emi noise sebelum alat dipasang di lingkungan industri.
- Beri jarak antara cable data dan cable power
- gunakan kabel yg shielded
- Untuk komunikasi data serial gunakan rs485 dari pada rs232
- gunakan komponen yg berkualitas, jika ada pilihan pakai chip yg punya fitur noise imunnity
Silahkan di tambahan dikolom komentar jika ada solusi atau pendapat lain..
Cara Koneksi modbus RTU Device dengan Modbus TCP Gateway elfin EW11
Berikut inii tahapan menghubungkan serial Modbus RTU device dengan Modbus TCP gateway, pada artikel ini kita akan menggunakan modbus tcp gateway yg relatif murah yaitu Elfin EW11
Buka aplikasi IOTService atau melalui web base dgn ip yg tertera di user manual lalu Setting IP untuk gambar diatas bisa dilihat pada gambar berikut ini
isi IP Address dan IP Gateway
isi Local port dengan 502 ( ini nomor port standart modbus TCP)
isi STA_SSID atau nama akses point / hotspot
isi password STA_SSID / akses point nya
Jika sudah berhasil disetting akan tampak status sebagai berikut
untuk lebih detailnya silahkan lihat user manual nya disini http://www.hi-flying.com/elfin-ew10-elfin-ew11