diff --git a/src/dev/esp32/lanbonl8.cpp b/src/dev/esp32/lanbonl8.cpp index f2f50ad9..215779ce 100644 --- a/src/dev/esp32/lanbonl8.cpp +++ b/src/dev/esp32/lanbonl8.cpp @@ -8,13 +8,32 @@ #include "Arduino.h" #include "dev/esp32/esp32.h" +#include "driver/pcnt.h" // Pulse count driver #include "driver/adc.h" #include "esp_adc_cal.h" #include "hasp_conf.h" #include "hasp_debug.h" -#define BACKLIGHT_CHANNEL 0 +#define BACKLIGHT_CHANNEL 15 + +// https://esp32.com/viewtopic.php?t=14660 +#define PCNT_FREQ_UNIT PCNT_UNIT_0 // Pulse Count Unit 0 +#define PCNT_H_LIM_VAL 10000 // upper limit of counting max. 32767, write +1 to overflow counter, when reached +#define PCNT_L_LIM_VAL -10000 // lower limit of counting max. 32767, write +1 to overflow counter, when reached +#define PCNT_INPUT_SIG_IO 35 // Pulse Input GPIO +#define PCNT_INPUT_CTRL_IO 36 // Pulse Control GPIO +#define PCNT_FILTER_VAL 300 // filter (damping, inertia) value for avoiding glitches in the count, max. 1023 +#define MEASURED_WATTS 1580 +#define MEASURED_PULSES_PER_SECOND 281 +// Per second + +int16_t PulseCounter = 0; // pulse counter, max. value is 32535 +int OverflowCounter = 0; // pulse counter overflow counter +uint32_t totalPulses; + +pcnt_isr_handle_t user_isr_handle = NULL; // interrupt handler - not used +hw_timer_t* timer = NULL; // Instancia do timer #define REF_VOLTAGE 1100 esp_adc_cal_characteristics_t* adc_chars = @@ -51,8 +70,49 @@ static void print_char_val_type(esp_adc_cal_value_t val_type) } } +//------------------------------------------------------------------------------------ +void IRAM_ATTR energy_pulse_counter_overflow(void* arg) +{ // Interrupt for overflow of pulse counter + OverflowCounter = OverflowCounter + 1; // increase overflow counter + PCNT.int_clr.val = BIT(PCNT_FREQ_UNIT); // clean overflow flag + pcnt_counter_clear(PCNT_FREQ_UNIT); // zero and reset of pulse counter unit +} + +//------------------------------------------------------------ +void energy_pulse_counter_init() +{ + pcnt_config_t pcntFreqConfig = {}; // initialise pulse counter + pcntFreqConfig.pulse_gpio_num = PCNT_INPUT_SIG_IO; // pin assignment for pulse counter + pcntFreqConfig.ctrl_gpio_num = PCNT_INPUT_CTRL_IO; // pin assignment for control + pcntFreqConfig.channel = PCNT_CHANNEL_0; // select channel 0 of pulse counter unit 0 + pcntFreqConfig.unit = PCNT_FREQ_UNIT; // select ESP32 pulse counter unit 0 + pcntFreqConfig.pos_mode = PCNT_COUNT_INC; // count rising edges (=change from low to high logical level) as pulses + pcntFreqConfig.neg_mode = PCNT_COUNT_DIS; // Conta na subida do pulso + pcntFreqConfig.lctrl_mode = PCNT_MODE_REVERSE; + pcntFreqConfig.hctrl_mode = PCNT_MODE_KEEP, + pcntFreqConfig.counter_h_lim = PCNT_H_LIM_VAL; // set upper limit of counting + pcntFreqConfig.counter_l_lim = PCNT_L_LIM_VAL; // set lower limit of counting + + pcnt_unit_config(&pcntFreqConfig); // configure rigisters of the pulse counter + + pcnt_counter_pause(PCNT_FREQ_UNIT); // pause puls counter unit + pcnt_counter_clear(PCNT_FREQ_UNIT); // zero and reset of pulse counter unit + + pcnt_event_enable(PCNT_FREQ_UNIT, PCNT_EVT_H_LIM); // enable event for interrupt on reaching upper limit of counting + pcnt_isr_register(energy_pulse_counter_overflow, NULL, 0, + &user_isr_handle); // configure register overflow interrupt handler + pcnt_intr_enable(PCNT_FREQ_UNIT); // enable overflow interrupt + + pcnt_set_filter_value(PCNT_FREQ_UNIT, PCNT_FILTER_VAL); // set damping, inertia + pcnt_filter_enable(PCNT_FREQ_UNIT); // enable counter glitch filter (damping) + + pcnt_counter_resume(PCNT_FREQ_UNIT); // resume counting on pulse counter unit +} + void LanbonL8::init() { + energy_pulse_counter_init(); + // Check if Two Point or Vref are burned into eFuse check_efuse(); @@ -64,6 +124,30 @@ void LanbonL8::init() print_char_val_type(val_type); } +void LanbonL8::loop_5s() +{ // function for reading pulse counter (for timer) + pcnt_get_counter_value(PCNT_FREQ_UNIT, &PulseCounter); // get pulse counter value - maximum value is 16 bits + uint32_t newPulses = OverflowCounter * 10000 + PulseCounter; + uint32_t delta = newPulses - totalPulses; + totalPulses = newPulses; + int16_t watt_10 = DEC / 5 * delta * MEASURED_WATTS / MEASURED_PULSES_PER_SECOND; + int16_t kwh_10 = DEC * totalPulses * MEASURED_WATTS / MEASURED_PULSES_PER_SECOND / 3600 / 1000; + LOG_VERBOSE(TAG_DEV, F("Pulse Counter %d.%d W / %d / %d.%d kWh"), watt_10 / DEC, watt_10 % DEC, totalPulses, + kwh_10 / DEC, kwh_10 % DEC); +} + +//------------------------------------------------------------ +void Read_Reset_PCNT() +{ // function for reading pulse counter (for timer) + pcnt_get_counter_value(PCNT_FREQ_UNIT, &PulseCounter); // get pulse counter value - maximum value is 16 bits + + // resetting counter as if example, delet for application in PiedPiperS + OverflowCounter = 0; // set overflow counter to zero + pcnt_counter_clear(PCNT_FREQ_UNIT); // zero and reset of pulse counter unit + // conterOK = true; // not in use, copy from example code + // ######################################## +} + } // namespace dev dev::LanbonL8 haspDevice; diff --git a/src/dev/esp32/lanbonl8.h b/src/dev/esp32/lanbonl8.h index f32e1fa4..b4e205cd 100644 --- a/src/dev/esp32/lanbonl8.h +++ b/src/dev/esp32/lanbonl8.h @@ -8,11 +8,14 @@ #if defined(LANBONL8) +void Read_PCNT(); + namespace dev { class LanbonL8 : public Esp32Device { public: void init(); + void loop_5s(); }; } // namespace dev