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  OUT = TimerTicks x (2/APB_CLK)  . Ketika Prescaler=0, maka rumusnya  OUT = TimerTicks x (65536/APB_CLK) . selain itu ( nilai presclaer bukan 0,1 dan 2) gunakan rumus di bawah.

ESP32 Timer Equation - Arduino Example

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. OUT yang diinginkan untuk periode interupsi di mana kita akan mengaktifkan LED adalah 1ms, Jadi 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:

Contoh Pengatur Waktu ESP32 Arduino

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

  1. Arduino IDE

Hardware :

  1. PC/laptop
  2. ESP32 yg sudah di program sbg Master
  3. ESP32 yg akan di program sbg Slave
  4. 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.

Contoh Code Arduino Modbus RTU ESP32 sebagai Master

Tool yang diperlukan

sotware

  1. Arduino IDE
  2. ModbusSlave simulator

Hardware :

  1. PC/laptop
  2. ESP32
  3. modul usb to Rs485
  4. 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.

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

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 :

  1. http://easymodbustcp.net
  2. http://counterproduksi.com

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.

Tidak ada teks alt yang disediakan untuk gambar 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.

Tidak ada teks alt yang disediakan untuk gambar ini

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