Add power pulse counter

This commit is contained in:
fvanroie 2021-05-15 12:35:20 +02:00
parent e77a1d14d3
commit d42749703e
2 changed files with 88 additions and 1 deletions

View File

@ -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;

View File

@ -8,11 +8,14 @@
#if defined(LANBONL8)
void Read_PCNT();
namespace dev {
class LanbonL8 : public Esp32Device {
public:
void init();
void loop_5s();
};
} // namespace dev