hi, im having an issue with a project im working on, its a display with esp32 to measure water usage in our camper. iv got the code working fine inside but when i connect it to the camper im getting timing issues and general hokey stuff. so the pump is a 12v pump on a battery with a momentary button to turn it on, the esp is powered from a 12v to 5v usb converter( supposedly regulated). the input pin for the esp comes from a simple voltage divider down to around 2.8v for input pin into the esp. there is also a 4.7k pulldown on this line because when the pump is on its a high input into the esp. i have a basic drawing. my question is, is the pump giving off some sort of interferance because the timing for the consumption calculations stops randomly even though i have the button pressed. if there is some sort of rf interferance what can i do to stop it. everything works as it should inside, so it has to be the pump doing something. this is the first time ive come across this and am unsure what to do. ive read that caps af various sizes can help. im really hoping someone nice can give me some insight.
This is not be needed if you are using a voltage divider. This makes me wonder if you understand what a voltage divider is, especially since it is not shown in your diagram.
Please draw a schematic showing all components and post that for the forum to check.
Is there a flyback diode connected to the pump motor terminals? Or a suppression capacitor?
The 4.7 k pulldown just pulling the pin low. Then when the pump button is pressed it takes it high. The voltage divider is a 10k on the 12v side and 3 k to the ground and the middle of the two is the lead that goes to the input for the esp to read. Im not sure if there is any caps on the motor as its just a commercial brought pump. I did however get a usb power bank and ran the esp from that and got much better results but thats not really practical.
Is it? How are you preventing it from affecting the voltage divider?
Isn't that 4K7 pulldown resistor, in fact, in parallel with the 3K resistor giving a combined resistance of about 1.8K?
So the output of your voltage divider, when the button is pressed will be about 1.8V. Is that enough to read HIGH?
Hi, @tezzatron81
Sorry but had to spread it out.
Can you please post your code?
Are you calculating water usage by measuring the ON time of the pump?
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
How long are your connecting wires?
Can you please post some images of your project?
So we can see your component layout.
Thanks.. Tom..
![]()
I think an opto-isolator would be a good idea.
Put a 1K or 2K2 resistor in series with the opto's anode. Connect the opto's collector to your Arduino input pin and use INPUT_PULLUP mode.
The opto's cathode would connect to -12V and it's emitter to the -5V from the regulator/converter.
Hopefully this will give your Arduino some additional protection against electrical noise from the pump.
You are probably correct and i will take it out today and report back. I did not consider it affecting the voltage divider. Im relatively new as we all were at some point.
Ive posted a pic of the circut and ill get the pic if the pump shortly. This is the so called regulated converter. Yes im measuring the flow with time the pump is on. Its accurate enough. I has a hall effect flow sensor at the start and the pulse count varied so much it made it unreliable. Ill post the code as well but reluctant as some of the geniuses here seem to berate and pull it apart, and don’t actually help.
//#define ESP32_RTOS // Uncomment this line if you want to use the code with freertos only on the ESP32
// Has to be done before including "OTA.h"
#include "OTA.h"
#include "credentials.h"
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h> // Change to ST7789 library
#include <Fonts/FreeSansBold12pt7b.h> // FreeSansBold, size 12pt
#include <SPI.h>
// adding webserial monitor 192.168.0.144/webserial
#include <Arduino.h>
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <AsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include <WebSerialLite.h>
////////////////////////////////////////////////////////////////////////////////////
#include <ESP32TimerInterrupt.h>
ESP32Timer ITimer(0); // Using Timer 0
//////----------------------------define pins to turn on or off below-------------------------------------
AsyncWebServer server(80);
const char* ssid = "TelstraA857CE"; // Your WiFi SSID
const char* password = "fuateu9u4t"; // Your WiFi Password
unsigned long lastPrintTime = 0; // Tracks the last time data was printed
const unsigned long printInterval = 60000; // Interval in milliseconds (1 second)
// TFT Pins
#define TFT_CS 38
#define TFT_RST 33
#define TFT_DC 34
#define TFT_MOSI 35
#define TFT_SCLK 36
#define TFT_BACKLIGHT 37 // Define backlight pin
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
// Button Pins
#define BUTTON_ADD_litre 9
#define BUTTON_CYCLE_DISPLAY 11
#define BUTTON_RESET 7
//#define FLOW_BUTTON 5
// Debounce settings
unsigned long debounceDelay = 100; // Debounce time in milliseconds
unsigned long lastCycleDisplayPress = 0;
unsigned long lastDebounceTime = 0;
int lastButtonState = LOW; // Last stable state
int currentButtonState = LOW; // Current stable state
//////////////////////////////////////////////////////////////////////////////////
volatile bool isFlowing = false;
volatile unsigned long flowDuration = 0; // Flow duration in milliseconds
const int FLOW_BUTTON = 5; // Example button pin for flow button (adjust accordingly)
//////////////////////////////////////////////////////////////////////////
// Inactivity timer
unsigned long lastInputTime = 0;
unsigned long inactivityTimeout = 20000; // 15 seconds of inactivity
// Long press settings
const unsigned long shortLongPressDuration = 1000; // 1 second
const unsigned long fullLongPressDuration = 3000; // 3 seconds
unsigned long addlitrePressStart = 0;
unsigned long resetPressStart = 0;
bool addlitreButtonHeld = false;
bool resetButtonHeld = false;
unsigned long flowStart = 0;
unsigned long flowStop = 0;
//unsigned long flowDuration = 0;
//bool isFlowing = false;
float timePerlitre = 18.0; // Time in seconds for 1 litre change as needed ////////////////////////////////////////////////////
float flowRateLpm = 0.0; // Global variable to store flow rate in L/min
////////////////////////////////////////////////////////////
bool IRAM_ATTR updateFlowTime(void* arg) {
if (isFlowing) {
flowDuration++; // Increment the flow timer every millisecond
}
return true; // Return true to keep the timer running
}
// Tank properties
#define TANK_CAPACITY 80.0 // Maximum capacity
float litresRemaining = 80.0; // Initial litres remaining
float litresUsed = 0.0; // Total litres used
// Display mode
int displayMode = 3;
// Thermistor Constants
#define THERMISTOR_PIN 2 // GPIO2 for thermistor
const float R_FIXED = 100000.0; // 100k resistor value
const float BETA = 3950.0; // Beta value for the thermistor
const float T0 = 298.15; // Reference temperature (25°C in Kelvin)
const float R0 = 100000.0; // Thermistor resistance at 25°C
float tempv = 1.700; // changing the temp voltage
float lastTemperature = -999.0; // Stores the last temperature reading
unsigned long lastTempRead = 0; // Timestamp for the last temperature reading
const unsigned long tempReadInterval = 5000; // Read temperature every 1 second
void handleWebSerialMessage(uint8_t *data, size_t len) {
String message = "";
for (size_t i = 0; i < len; i++) {
message += (char)data[i];
}
// Debugging: Print the received message to WebSerial
WebSerial.println("Received message: " + message);
if (message.startsWith("timeperlitre ")) { // Command to update timePerlitre
float newTime = message.substring(13).toFloat(); // Start after "timeperlitre "
if (newTime > 0) {
timePerlitre = newTime;
WebSerial.println("timePerlitre updated to: " + String(timePerlitre));
} else {
WebSerial.println("Invalid time value. Please provide a positive number.");
}
} else if (message.startsWith("tempv ")) { // Command to update tempv
float newTempv = message.substring(6).toFloat(); // Start after "tempv "
if (!isnan(newTempv)) {
tempv = newTempv;
WebSerial.println("tempv updated to: " + String(tempv));
} else {
WebSerial.println("Invalid tempv value. Please provide a valid number.");
}
} else if (message.equalsIgnoreCase("printtemp")) { // Command to call printTemp
WebSerial.println("Calling printtemp...");
printtemp();
} else if (message.equalsIgnoreCase("printwater")) { // Command to call printWater
WebSerial.println("Calling printwater...");
printwater();
} else if (message.equalsIgnoreCase("printtime")) { // Command to call printTime
WebSerial.println("Calling printtime...");
printtime();
} else {
WebSerial.println("Unknown command: " + message);
}
}
void printCommandList() {
WebSerial.println("======== Command List ========");
WebSerial.println("1. timeperlitre <value> - Update time per liter (e.g., timeperlitre 10)");
WebSerial.println("2. tempv <value> - Update tempv variable (e.g., tempv 25.5)");
WebSerial.println("3. printtemp - Print temperature data");
WebSerial.println("4. printwater - Print water flow and usage data");
WebSerial.println("5. printtime - Print system timing information");
WebSerial.println("================================");
}
void setup() {
Serial.begin(115200); // Initialize Serial
setupOTA("water flow meter", mySSID, myPASSWORD);
// setup for web seial ////////////
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
WebSerial.begin(&server);
/* Attach Message Callback */
WebSerial.onMessage(handleWebSerialMessage);
server.begin();
// Initialize buttons
pinMode(BUTTON_ADD_litre, INPUT_PULLUP);
pinMode(BUTTON_CYCLE_DISPLAY, INPUT_PULLUP);
pinMode(BUTTON_RESET, INPUT_PULLUP);
pinMode(FLOW_BUTTON, INPUT);
////////////////////////////////////////////////////////////////////////////////////
ITimer.attachInterruptInterval(1000, updateFlowTime); // 1000 ms interval = 1 second
//////////////////////////////////////////////////////////////////////////////////////
// Initialize backlight pin (set as output)
pinMode(TFT_BACKLIGHT, OUTPUT);
digitalWrite(TFT_BACKLIGHT, HIGH); // Turn on backlight initially
// Initialize thermistor pin
analogReadResolution(12); // ESP32-S2 uses a 12-bit ADC
pinMode(THERMISTOR_PIN, INPUT);
// Initialize display
tft.init(240, 320); // Initialize ST7789 with correct screen size (240x240 or 240x320)
tft.setRotation(1); // Adjust the rotation if needed
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
// Initial display
updateDisplay();
}
void handleFlowButton() {
int reading = digitalRead(FLOW_BUTTON); // Read the button state
// Debounce logic
if (reading != currentButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != lastButtonState) {
lastButtonState = reading;
if (lastButtonState == HIGH) { // Button pressed
if (!isFlowing) { // Start the flow timer
flowDuration = 0; // Reset the flow duration
isFlowing = true;
Serial.println("Flow started");
}
} else { // Button released
if (isFlowing) { // Stop the flow timer
isFlowing = false;
// Calculate the elapsed time in seconds
float elapsedSeconds = flowDuration / 1000.0;
float litresUsedThisCycle = elapsedSeconds / timePerlitre; // Convert time to litres
// Update the total litres used
litresUsed += litresUsedThisCycle;
// Update the litres remaining
litresRemaining = TANK_CAPACITY - litresUsed;
// Output the results
Serial.print("Flow Duration: ");
Serial.print(elapsedSeconds);
Serial.println(" seconds");
Serial.print("Litres Used This Cycle: ");
Serial.print(litresUsedThisCycle, 2);
Serial.println(" litres");
Serial.print("Total Litres Used: ");
Serial.print(litresUsed, 2);
Serial.println(" litres");
Serial.print("Litres Remaining: ");
Serial.print(litresRemaining, 2);
Serial.println(" litres");
// Reset flow time
flowDuration = 0;
// Update the display
updateDisplay();
}
}
}
}
currentButtonState = reading;
}
void loop() {
handleFlowButton();
unsigned long currentTime = millis();
// Check if the desired interval has passed
if (currentTime - lastPrintTime >= printInterval) {
lastPrintTime = currentTime; // Update the last print time////////////////////////////////////////////////////////////////////////////////////////////
printCommandList();
}
if (millis() - lastTempRead >= tempReadInterval) {
lastTempRead = millis();
float currentTemperature = readTemperature();
if (abs(currentTemperature - lastTemperature) > 3) { // Update if significant change
lastTemperature = currentTemperature;
updateDisplay(); // Update display only if temperature changes
}
}
#ifdef defined(ESP32_RTOS) && defined(ESP32)
#else // If you do not use FreeRTOS, you have to regularly call the handle method.
ArduinoOTA.handle();
#endif
// Handle button presses
handleAddlitreButton();
handleCycleDisplayButton();
handleResetButton();
// Check inactivity
if (millis() - lastInputTime > inactivityTimeout) {
// No input for 5 seconds, turn off the backlight
digitalWrite(TFT_BACKLIGHT, LOW);
}
}
void handleAddlitreButton() {
int buttonState = digitalRead(BUTTON_ADD_litre);
if (buttonState == LOW) { // Button is pressed
if (!addlitreButtonHeld) {
addlitreButtonHeld = true;
addlitrePressStart = millis();
// Turn on backlight on any input
digitalWrite(TFT_BACKLIGHT, HIGH);
lastInputTime = millis(); // Reset inactivity timer
}
} else if (addlitreButtonHeld) { // Button released after being held
unsigned long pressDuration = millis() - addlitrePressStart;
if (pressDuration >= fullLongPressDuration) {
addRemaininglitre(1.0);
} else if (pressDuration >= shortLongPressDuration) {
addUsedlitre(0.5);
}
addlitreButtonHeld = false;
}
}
void handleCycleDisplayButton() {
int buttonState = digitalRead(BUTTON_CYCLE_DISPLAY);
if (buttonState == LOW && (millis() - lastCycleDisplayPress > debounceDelay)) {
lastCycleDisplayPress = millis();
cycleDisplay();
digitalWrite(TFT_BACKLIGHT, HIGH); // Turn on backlight on input
lastInputTime = millis(); // Reset inactivity timer
}
}
void handleResetButton() {
int buttonState = digitalRead(BUTTON_RESET);
if (buttonState == LOW) { // Button pressed
if (!resetButtonHeld) {
resetButtonHeld = true;
resetPressStart = millis();
// Turn on backlight on any input
digitalWrite(TFT_BACKLIGHT, HIGH);
lastInputTime = millis(); // Reset inactivity timer
} else if (millis() - resetPressStart >= fullLongPressDuration) {
resetCounter();
resetButtonHeld = false;
}
} else {
resetButtonHeld = false;
}
}
void addRemaininglitre(float amount) {
litresRemaining += amount;
if (litresRemaining > TANK_CAPACITY) {
litresRemaining = TANK_CAPACITY;
}
updateDisplay();
}
void addUsedlitre(float amount) {
if (litresRemaining >= amount) {
litresUsed += amount;
litresRemaining -= amount;
updateDisplay();
}
}
void cycleDisplay() {
displayMode = (displayMode + 1) % 4; // Now cycles through 4 modes
updateDisplay();
}
void resetCounter() {
litresUsed = 0.0;
litresRemaining = TANK_CAPACITY;
updateDisplay();
}
float getAverageADC(int pin, int numSamples) {
long sum = 0;
for (int i = 0; i < numSamples; i++) {
sum += analogRead(pin);
delay(1); // Small delay between readings
}
return sum / (float)numSamples;
}
float readTemperature() {
int numSamples = 10; // Number of samples for averaging
float adcValue = getAverageADC(THERMISTOR_PIN, numSamples);
float voltage = adcValue * (tempv / 4095.0); // Convert ADC value to voltage
if (voltage == 0) return -999.0; // Avoid divide by zero
float rThermistor = R_FIXED * (3.3 / voltage - 1.0);
float temperatureK = 1 / ((1 / T0) + (log(rThermistor / R0) / BETA));
return temperatureK - 273.15; // Convert Kelvin to Celsius
}
void updateDisplay() {
tft.fillScreen(ST77XX_BLACK);
tft.setFont(&FreeSansBold12pt7b); // Set FreeSansBold as the font
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
float temp = readTemperature();
//uint16_t sunColor = temperatureToColor(temp);
switch (displayMode) {
case 0: // Percent remaining
drawSun(240, 160, 40, 15, 12, lastTemperature); // Pass color
tft.setCursor(20, 80);
tft.print("Remaining: ");
tft.print(litresRemaining / TANK_CAPACITY * 100, 1);
tft.println("%");
tft.setTextColor(ST77XX_BLACK);
tft.setCursor(202, 162);
//tft.print("Temp: ");
tft.print(readTemperature(), 1);
tft.println(" °C");
break;
case 1: // litres used and remaining
drawSun(240, 160, 40, 15, 12, lastTemperature); // Pass color
tft.setCursor(20, 40);
tft.print("Used: ");
tft.print(litresUsed, 2);
tft.println(" L");
tft.setCursor(20, 100);
tft.print("Remaining: ");
tft.print(litresRemaining, 2);
tft.println(" L");
tft.setTextColor(ST77XX_BLACK);
tft.setCursor(202, 162);
//tft.print("Temp: ");
tft.print(readTemperature(), 1);
tft.println(" °C");
break;
case 2: // Flow rate
drawSun(240, 160, 40, 15, 12, lastTemperature); // Pass color
tft.setCursor(20, 60);
tft.println("Flow Rate:");
tft.setCursor(20, 100);
tft.println("l/m"); // Replace with actual data
tft.println(flowRateLpm, 2); // Display flow rate with 2 decimal places
tft.setTextColor(ST77XX_BLACK);
tft.setCursor(202, 162);
//tft.print("Temp: ");
tft.print(readTemperature(), 1);
tft.println(" °C");
break;
case 3: // Temperature
//drawSun(120, 160, 40, 15, 12, lastTemperature); // Pass the current temperature
drawSun(240, 160, 40, 15, 12, lastTemperature); // Pass color
tft.setTextSize(2);
tft.setCursor(20, 100);
tft.print("Temp: ");
tft.print(readTemperature(), 1);
tft.println(" °C");
break;
}
}
void drawSun(int x, int y, int radius, int rayLength, int rayCount, float temperature) {
// Map temperature to color (favor yellow until 30°C, then quickly transition to red)
uint16_t color;
if (temperature < 15) {
color = tft.color565(0, 0, 255); // Blue
} else if (temperature < 30) {
float fraction = (temperature - 15) / 15.0; // Normalize temperature to range 15-30
fraction = pow(fraction, 1.5); // Apply a curve to make the gradient steeper
uint8_t red = 255 * fraction;
uint8_t green = 255 - (128 * fraction);
uint8_t blue = 0;
color = tft.color565(red, green, blue);
} else {
color = tft.color565(255, 0, 0); // Red
}
// Draw the main circle
tft.fillCircle(x, y, radius, color);
// Draw the rays
for (int i = 0; i < rayCount; i++) {
float angle = i * (360.0 / rayCount);
float rad = angle * PI / 180.0;
int x1 = x + cos(rad) * radius;
int y1 = y + sin(rad) * radius;
int x2 = x + cos(rad) * (radius + rayLength);
int y2 = y + sin(rad) * (radius + rayLength);
tft.drawLine(x1, y1, x2, y2, color);
}
}
/*
void handleFlowButton() {
int reading = digitalRead(FLOW_BUTTON); // Read the button state in each loop
// Debounce logic
if (reading != currentButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// Button press detection (LOW -> HIGH transition)
if (reading != lastButtonState) {
lastButtonState = reading;
if (lastButtonState == HIGH) { // Button pressed
if (!isFlowing) { // Start timing only if not already started
flowStart = millis();
isFlowing = true;
Serial.println("Button Pressed: Starting flow timer");
}
} else { // Button released
if (isFlowing) { // Stop timing if it was active
unsigned long flowStop = millis();
flowDuration = flowStop - flowStart; // Calculate elapsed time in milliseconds
// Convert duration to litres
float elapsedSeconds = flowDuration / 1000.0; // Convert ms to seconds
float newlitresUsed = elapsedSeconds / timePerlitre; // Calculate litres used
// Update total litres used and adjust remaining litres
litresUsed += newlitresUsed;
litresRemaining -= newlitresUsed;
// Calculate Flow Rate in litres per Minute (L/min)
float elapsedMinutes = elapsedSeconds / 60.0; // Convert seconds to minutes
flowRateLpm = newlitresUsed / elapsedMinutes; // Calculate flow rate
// Print results
WebSerial.print("Flow Duration: ");
WebSerial.print(elapsedSeconds);
WebSerial.println(" seconds");
WebSerial.print("Water Used: ");
WebSerial.print(litresUsed);
WebSerial.println(" litres");
WebSerial.print("Flow Rate: ");
WebSerial.print(flowRateLpm, 2); // Print flow rate with 2 decimal places
WebSerial.println(" L/min");
// Reset state
isFlowing = false;
displaytotal(); // Update display to show total (assuming displayTotal() is defined)
}
}
}
}
// Update the stable current state
currentButtonState = reading;
}
*/
void printtemp() {
// Read ADC value and calculate voltage
int adcValue = analogRead(THERMISTOR_PIN); // You can use any ADC pin
float adcVoltage = (adcValue / 4095.0) * 3.3; // Assuming a 12-bit ADC with a 3.3V reference voltage
WebSerial.print("Temperature: ");
WebSerial.print(readTemperature(), 1);
WebSerial.println(" °C");
WebSerial.println("ADC Value: ");
WebSerial.print(adcValue);
WebSerial.println(" | Voltage: ");
WebSerial.print(tempv, 3); // Print with three decimal places
WebSerial.println(" V");
}
void printwater(){
WebSerial.print("Flow Rate: ");
WebSerial.print(flowRateLpm, 2);
WebSerial.print("litres Used: ");
WebSerial.print(litresUsed, 2);
WebSerial.println(" L");
WebSerial.print("litres Remaining: ");
WebSerial.print(litresRemaining, 2);
WebSerial.println(" L");
WebSerial.print("Tank Capacity: ");
WebSerial.print(TANK_CAPACITY);
WebSerial.println(" L");
}
void printtime(){
WebSerial.print("Flow Duration: ");
// WebSerial.print(elapsedSeconds);
WebSerial.println(" seconds");
WebSerial.print("Water Used: ");
WebSerial.print(litresUsed);
WebSerial.println(" litres");
WebSerial.print("Flow Rate: ");
WebSerial.print(flowRateLpm, 2); // Print flow rate with 2 decimal places
WebSerial.println(" L/min");
}
void displaytotal (){
displayMode = 1;
updateDisplay();
lastInputTime = millis(); // Reset inactivity timer
digitalWrite(TFT_BACKLIGHT, HIGH);
}
here is the code. remember im not as adept at this as some.
You must be aware that RV water pumps are designed to stop when the output pressure reaches a certain amount. Is that what is happening?
No this is just on or off i believe. Its how we purchased the camper. It just runs when the button is pressed
#define THERMISTOR_PIN 2 // GPIO2 for thermistor
Probably not THE problem but GPIO2 is not a good choice for ADC.
Its a lolin s2 mini. Why is that pin not a good choice? Can you explain a bit
--ADC2_CH2 (GPIO 2)
--The ADC2 pins cannot be used when Wi-Fi is enabled. If your project requires Wi-Fi, consider
using the ADC1 pins instead.
--must be LOW during boot and also connected to the on-board LED
///disregard probably wrong esp32///
I see, i didnt think of that either. Not sure thats the reason for the interference. Ive noticed that i get better results when i took out the 4.7k pulldown as suggested and the usb plug is outside the draw as pictured earlier and plugged into that particular usb seems to work better than having it run into the terminal junction as before. Need to test more buts it’s raining right now
I just checked the docs and it says gpio2 is adc1
Yes I had the wrong esp32, sorry
This might help.
https://escapingoutdoors.com.au/fl2202-camping-pump-35psi-4-3-l-min-detail?srsltid=AfmBOoohU9L_zD-5PX5fTbFWuWPpaSMcAUzZKp7POOWFOX3psu4gaX7G
Sorry, it would be clearer if you drew it by hand.
Tom..
![]()
I did post a schematic in the original post. Ive since removed the pulldown resistor. There is only 2 wires from the pump, unless the pressure switch is inside. But its a moot point because it runs off a button right now. The pump was not causing the timing issue unless it was rf. Thanks for the info though.




