I am having a problem with my flowsensor circuit as show in the figure.
where SF800 is the flow sensor I am using. It's a pulse sensor PNP/NPN contact. Hence the pulse signal pin in pull up using a 2.2 kΩ resistor as the manufacturer says. The K - Factor of the sensor given by the manufacturer is around 5600 pulses per litre. SF800 sensor is provided with a 3/8-inch NPT male threaded connection.
// Interrupt handler
static void IRAM_ATTR flow_sensor_isr_handler(void* arg) {
if (PULSE_TASK_FLAG) {
PULSE_COUNTER++;
}
}
void init_flow_sensor() {
// Configure GPIO
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_PULSE_SENSOR_IO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_NEGEDGE // Falling edge trigger
};
gpio_config(&io_conf);
// Install ISR service
gpio_install_isr_service(ESP_INTR_FLAG_NMI);
// Attach interrupt handler
gpio_isr_handler_add(GPIO_PULSE_SENSOR_IO, flow_sensor_isr_handler, NULL);
}
static void pulse_task (void *arg) {
const char * tag = "PULSE Task ";
char packet[64];
// Initialize flow sensor
init_flow_sensor();
// Initialize last time
lastTime = esp_timer_get_time();
while (1) {
// ESP_LOGI(tag, "Pulse Test");
if (PULSE_TASK_FLAG) {
int64_t currentTime = esp_timer_get_time();
int64_t deltaTime = currentTime - lastTime;
if (deltaTime >= 100000) { // Update every 1 second (in microseconds)
uint32_t currentPULSE_COUNTER = PULSE_COUNTER;
PULSE_COUNTER = 0; // Reset counter
// Calculate flow rate and total flow
FLOW_RATE = (currentPULSE_COUNTER / (float) K_FACTOR) * 600; // Convert pulses/sec to LPM
TOTAL_FLOW += FLOW_RATE * (deltaTime / 60000000.0); // Add to total flow (convert us to minutes)
// ESP_LOGI(TAG, "Delta: %lld, Flow Rate: %.2f LPM | Total Flow: %.2f L", deltaTime, FLOW_RATE, TOTAL_FLOW);
lastTime = currentTime;
}
// Send FUEL Data to the HMI
gen_packet("FUEL", "PUL", TOTAL_FLOW, packet, sizeof(packet)); // Generate packet
sendData(tag, packet);
vTaskDelay(pdMS_TO_TICKS(10));
if (DEF_SET_VALUE && TOTAL_FLOW >= DEF_SET_VALUE) {
pump_stop();
ESP_LOGI(tag, "Set value %.2f reached! --- %.2f", DEF_SET_VALUE, TOTAL_FLOW);
}
} else {
// Pause counting when the flag is not set
//
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
The problem I am facing is that when I test it for 5 litres I am getting an error of (+/-)30 ml. (Say for 5 litres I get from 4.98 to 5.10 litres. Also when I go for 10 litres the error buildup is also increasing (but no linearly). Also it varies if I decrease the flow through the sensor using a valve). Hence this error is not at all acceptable. I need the error to be minimal say 20 ml max.
I am getting a doubt that there should be some mistake in my code. SF800 is said to be an accurate sensor [No Detailed Datasheet is available for the sensor other than its connection diagram]. The code is done based on ESP IDF framework. The code block containing the pulse task is attached above. The Pulse task is a FreeRTOS Task which run independantly.
The PULSE_TASK_FLAG
is set high when the motor is switched ON
, which causes the water to flow through the sensor. Then the task starts calculating the TOTAL_FLOW
through the sensor until the motor is Switched OFF
. flow_sensor_isr_handler
is an interrupt handler which counts the pulses.
I would be grateful for any recommendations of alternative sensors that you have successfully implemented in previous projects.
If there is a requirement for any more information I can provide it.