Setelah berselancar di Internet kesana-kemari mencari referensi LC meter menggunakan ESP32 tidak ketemu juga atau mungkin memang tidak ada, akhirnya memutuskan untuk membuat sendiri alat untuk mengukur Induktansi dan Capasitansi yang merupakan sarana untuk digunakan oleh para homebrower khususnya bidang radio menggunakan prosessor ESP32.
Pemanfaatan ESP32 Wroom sebagai prosessor yang saya rasa sangat mumpuni dalam mengolah perhitungan pecahan karena mempunya kecepatan prosessor 240Mhz dengan 80Mhz kristal yang digunakan sehingga secara logika ESP32 mampu memnggenerasikan Oscilator dengan Freq lumayan tinggi.
Kemampuan alat yang saya rakit ini secara percobaan adalah sebagai berikut:
1. Generasi Oscilator dengan range 0 s.d. 40 Mhz pada Pin33 dengan value melalui Serial Command komputer.
2. Frequency Counter range 0 s.d. 40 Mhz , pada Pin34 bagi saya hasil pengukuran adalah akurat.
3. Dapat mengukur Induktor secara cukup akurat +- 2% dan masih dapat di adjust.
4. Dapat mengukur Capasitor secara cukup akurat +- 2%dan masih dapat di adjust.
Pada saat baru dinyalakan alat atau ditekan tombol reset, maka ESP32 akan melakukan kalibrasi otomatis, posisi saklar pilih harus pada Cx artinya:
- Saklar SW1 harus pada posisi pengukuran Capacitor, probe ukur H2 dalam posisi kosong/tidak terpasang apapun.
- Ataupun bisa juga saklar pilih SW1 pada posisi Lx namun probe ukur H2 harus di short atau dihubungkan dengan jumper.
Gambar Pengukuran C22pf keramik
Tercantum di label Induktor 39uH
Tercantum di label Induktor 100uH
Setelah proses kalibrasi selesai, tempatkan alat yang akan diukur baik itu Induktor maupun Capasitor dengan memilih melalui saklar.
Adapun sketch Arduino yang saya buat adalah sebagai berikut, pastikan board sudah dipilih ESP32 Wroom atau Devkit atau sejenis:
#include "stdio.h" // Library STDIO#include "driver/ledc.h" // Library ESP32 LEDCextern "C" { //bikin pusing ternyata harus di extern#include "soc/pcnt_struct.h"}#include "driver/pcnt.h" // Library ESP32 PCNT#include <Wire.h>#include <LiquidCrystal.h>LiquidCrystal lcd(4, 16, 17, 5, 18, 19); // - ports RS,ENA,D4,D5,D6,D7#define PCNT_COUNT_UNIT PCNT_UNIT_0#define PCNT_COUNT_CHANNEL PCNT_CHANNEL_0#define PCNT_INPUT_SIG_IO GPIO_NUM_34 // PIN34 input freq counter dikasih C104 gapapa engga juga nggapapa#define LEDC_HS_CH0_GPIO GPIO_NUM_33 // PIN33 Oscilator output#define PCNT_INPUT_CTRL_IO GPIO_NUM_35 // digabung PIN32 utk cek keluaran oscilator sendiri#define OUTPUT_CONTROL_GPIO GPIO_NUM_32 // digabung PIN35 utk cek keluaran oscilator sendiri#define PCNT_H_LIM_VAL overflow#define IN_BOARD_LED GPIO_NUM_2 // Led indikator sinyal diukur#define RELAY GPIO_NUM_23 // Relay gausah dipasang gapapa#define LCPilih GPIO_NUM_36 // sensor pilihbool flag = true;uint32_t overflow = 20000;int16_t pulses = 0;uint32_t multPulses = 0;uint32_t sample_time = 1000000;uint32_t osc_freq = 12543; // Oscillator frequency awal 12543 Hz (bisa 1 Hz s.d. 40 MHz)uint32_t mDuty = 0;uint32_t resolusi = 0;char buf[32];double frequency, capacitance, inductance;esp_timer_create_args_t create_args;esp_timer_handle_t timer_handle;portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;#define phi 3.14159byte mode_operasi = 2;double C_calb = 1.00; //calibrasi 1.00 nF - adjust ini sangant menentukan seluruh hasil ukurdouble L_calb;bool dikalibrasi = true;void setup(){Serial.begin(115200);Serial.println(" Input Frequency - 1 sd 40 MHz");pinMode(RELAY, OUTPUT); digitalWrite(RELAY, LOW); //boleh pasang boleh tidakpinMode(LCPilih, INPUT);lcd.begin(16, 2);//lcd.print(" Frequency:");init_frequencyMeter ();}void init_osc_freq () {resolusi = (log (80000000 / osc_freq) / log(2)) / 2 ;if (resolusi < 1) resolusi = 1;mDuty = (pow(2, resolusi)) / 2;ledc_timer_config_t ledc_timer = {};ledc_timer.duty_resolution = ledc_timer_bit_t(resolusi);ledc_timer.freq_hz = osc_freq;ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;ledc_timer.timer_num = LEDC_TIMER_0;ledc_timer_config(&ledc_timer);ledc_channel_config_t ledc_channel = {};ledc_channel.channel = LEDC_CHANNEL_0;ledc_channel.duty = mDuty;ledc_channel.gpio_num = LEDC_HS_CH0_GPIO;ledc_channel.intr_type = LEDC_INTR_DISABLE;ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;ledc_channel.timer_sel = LEDC_TIMER_0;ledc_channel_config(&ledc_channel);}static void IRAM_ATTR pcnt_intr_handler(void *arg) {portENTER_CRITICAL_ISR(&timerMux);multPulses++; // increment Overflow counterPCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);portEXIT_CRITICAL_ISR(&timerMux);}void init_PCNT(void) {pcnt_config_t pcnt_config = { };pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO;pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO;pcnt_config.unit = PCNT_COUNT_UNIT;pcnt_config.channel = PCNT_COUNT_CHANNEL;pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;pcnt_config.pos_mode = PCNT_COUNT_INC;pcnt_config.neg_mode = PCNT_COUNT_INC;pcnt_config.lctrl_mode = PCNT_MODE_DISABLE;pcnt_config.hctrl_mode = PCNT_MODE_KEEP;pcnt_unit_config(&pcnt_config);pcnt_counter_pause(PCNT_COUNT_UNIT);pcnt_counter_clear(PCNT_COUNT_UNIT);pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM);pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);pcnt_intr_enable(PCNT_COUNT_UNIT);pcnt_counter_resume(PCNT_COUNT_UNIT);}void read_PCNT(void *p) {gpio_set_level(OUTPUT_CONTROL_GPIO, 0);pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);flag = true;}void init_frequencyMeter (){init_osc_freq();init_PCNT();gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO);gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT);create_args.callback = read_PCNT;esp_timer_create(&create_args, &timer_handle);gpio_set_direction(IN_BOARD_LED, GPIO_MODE_OUTPUT);gpio_matrix_in(PCNT_INPUT_SIG_IO, SIG_IN_FUNC226_IDX, false);gpio_matrix_out(IN_BOARD_LED, SIG_IN_FUNC226_IDX, false, false);}char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos) {int c;if (val >= radix) s = ultos_recursive(val / radix, s, radix, pos + 1);c = val % radix; c += (c < 10 ? '0' : 'a' - 10); *s++ = c;if (pos % 3 == 0) *s++ = ',';return s;}char *ltos(long val, char *s, int radix){if (radix < 2 || radix > 36) { s[0] = 0; } else {char *p = s;if (radix == 10 && val < 0) { val = -val; *p++ = '-'; }p = ultos_recursive(val, p, radix, 0) - 1; *p = 0;}return s;}void baca_frequensi(){if (flag == true) {flag = false;frequency = (pulses + (multPulses * overflow)) / 2 ;//printf("Frequency : %s", (ltos(frequency, buf, 10)));//printf(" Hz \n");lcd.setCursor(0, 0); lcd.print("F:");lcd.print((ltos(frequency, buf, 10))); lcd.print(" Hz ");multPulses = 0;delay (100);pcnt_counter_clear(PCNT_COUNT_UNIT);esp_timer_start_once(timer_handle, sample_time);gpio_set_level(OUTPUT_CONTROL_GPIO, 1);}}void loop(){baca_frequensi();if (dikalibrasi==true) kalibrasi();if (digitalRead(LCPilih)==LOW){capacitance = C_calb * 1e-9;inductance = (1. / (capacitance * frequency * frequency * 4.*phi * phi)) * 1.E6; inductance = inductance - L_calb;lcd.setCursor(0, 1); lcd.print("L:");if(inductance>=1000) { lcd.print( inductance/1000.0 ); lcd.print(" mH ");} else {lcd.print( inductance );lcd.print(" uH ");}}else if (digitalRead(LCPilih)==HIGH){inductance = L_calb * 1e-6;capacitance = ((1. / (inductance * frequency * frequency * 4.* phi * phi)) * 1.E9);capacitance=capacitance-C_calb;if((int)capacitance < 0) capacitance=0;lcd.setCursor(0, 1); lcd.print("C:");if(capacitance >= 100){ lcd.print(capacitance/1000.0);lcd.print(" uF "); }else if (capacitance >= 1 && capacitance <100){lcd.print(capacitance); lcd.print(" nF ");}else if (capacitance <1 ){if ((capacitance*1000)<0) {lcd.print(capacitance*0.0);} else {lcd.print(capacitance*1000.0);}lcd.print(" pF ");}}ubah_oscilator_pakeSerial();}void ubah_oscilator_pakeSerial(){String inputString = "";osc_freq = 0;while (Serial.available()) {char inChar = (char)Serial.read(); inputString += inChar;if (inChar == '\n') {osc_freq = inputString.toInt(); Serial.println(osc_freq);inputString = "";}}if (osc_freq != 0) {init_osc_freq (); }}void kalibrasi(){lcd.setCursor(0, 1); lcd.print("KALIBRASI..L");for (byte i = 1 ; i<10 ; i++){baca_frequensi();delay(500);}C_calb = 1.0 * 1e-9;L_calb = (1. / (C_calb * frequency * frequency * 4.*phi * phi)) * 1.E6;lcd.setCursor(0, 1); lcd.print("L:");if(L_calb>=1000) { lcd.print( L_calb/1000 ); lcd.print(" mH ");}else {lcd.print( L_calb );lcd.print(" uH ");}delay(1500);lcd.setCursor(0, 1); lcd.print("KALIBRASI..C");for (byte i = 1 ; i<10 ; i++){baca_frequensi();delay(500);}C_calb = ((1. / ((L_calb * 1e-6) * frequency * frequency * 4.* phi * phi)) * 1.E9);if((int)C_calb < 0) C_calb=0;lcd.setCursor(0, 1); lcd.print("C:");if(C_calb > 100){ lcd.print( (C_calb/1000));lcd.print(" uF "); }else {lcd.print(C_calb); lcd.print(" nF ");}delay(2500);dikalibrasi = false;}
3 komentar:
Ini bisa dipasang prescaler ya om.Buat UHF
Dibandingkan sama Frekuensi Counter yang memakai PIC hasilnya lebih akurat yg mana>?
untuk UHF dan VHF dapat menggunakan prescaller, keakuratan tergantung rumus pembaginya, tentunya diperlukan kalibrasi karena pasti ada selisih dan kelipatan, tetapi tidak akan jauh nilainya
Om ini skema diagramnya tidak ada yang lebih jernih ya? mohon izin , terimakasih
Posting Komentar