I am working on a project which includes an automated water sampling pump. One of my unresolved issues includes the ADS1115 and its behavior when the motor runs. When the motor runs, the battery charge percent I get from the ADS1115 drops by 80-90%. I've added a few capacitors to the circuit but that wasnt much help. I would like to get advice on how to stop the ADC from reading data while the motor is running. I tried to make an if statement that blocks the ADC from reading or analyzing data, but that doesnt work as the if statement is completely ignored. I am atttachng the schematic I am using, the bit of code which tries to control the ADC, and the full script. Help would be very much appreciated as I have been stuck on this issue since october.
Code: Select all
if (!state == PumpState || ReverseState || PurgeState) {
ads.begin();
adc0 = ads.readADC_SingleEnded(0);
battVoltage = ads.computeVolts(adc0) * dividerRatio * calFactor;
battVolt = battVoltage * 3.7;
battmV = (battVolt * 1000) + 30;
Val = battmV;
// int percent;
percent = multiMap(Val, in, out, 13);
}
Code: Select all
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#include <Wire.h>
#include <OneWireNg.h>
#include <DallasTemperature.h>
#include <ezButton.h>
#include <Adafruit_ADS1X15.h>
#include <MultiMap.h>
#define ONE_WIRE_BUS 4
/***********************************GPRS/SMS STUFF ****************************************/
#define LED 2
#define SIGNAL_PIN 36 // ESP32 pin GIOP36 (ADC0) connected to sensor's signal pin
#define samplingRate2 3000UL // the time between sensor readouts
uint8_t type;
unsigned long counter = 0;
unsigned long counter2 = 0;
/**** BOOL VARIABLES FOR SMS ALERTS ****/
bool bat = false;
bool opened = false;
bool cold = false;
/**** FLOAT SWITCH ****/
const int buttonPin = 33;
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
const int FloatSwitchLED = 15;
const int ResetLED = 2;
int value = 0; // variable to store the sensor value
const int LeakLED = 19;
volatile int count; //This integer needs to be set as volatile to ensure it updates correctly during the interrupt process.
float tLimit = 30.0; //the amount of liquid in mL that the pump is supposed to collect during pump cycle
int Threshold; //the threshold for amount of liquid collected before pump returns to OffState
bool ThresholdLimit = false; // flag for Threshold
/**********************************************************************************************************************************/
Adafruit_ADS1115 ads;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;
unsigned long startMillis; // Keeps track of millis() when the pumping cycle starts.
unsigned long currentMillis; // millis() of the current loop.
// constants for Arduino IO-Pins with SELF-explaining names
const byte samplingBtnPin = 12;
const byte primeBtnPin = 13;
const byte purgeBtnPin = 14;
const byte resetBtnPin = 32;
ezButton button1(12); // create ezButton object that attach to pin 12;
ezButton button2(32); // create ezButton object that attach to pin 12;
const byte DRV8876_IN1_PIN = 26;
const byte DRV8876_IN2_PIN = 27;
int flowPin = 25; //This is the input pin on the Arduino, flow switch
float calibrationFactor = 107; //107 CAL FACTOR GOOD FOR 1000ML
float tempC;
float tempF;
int percent;
/**************************************************** Battery stuf **************************************************/
int R1 = 27, R2 = 10; // 10k and 27k ; the resistor ratio
float dividerRatio; // pre-calculate in setup
float calFactor = 1.01; // calibrate if needed
int in[] = {
10000, 12000, 12500, 12800, 12900, 13000, 13100, 13200, 13300, 13400, 13600, 14600, 14900
}; // [13] IN holds the mV inputs
int out [] = {
0, 9, 14, 17, 20, 30, 40, 70, 90, 99, 100, 110, 120
}; // [13] OUT holds the percentage outputs
float bLimit = 20; // the lower limit of the percentage, if battery percent falls below 20, lowbatsMs is sent
int Val; // holds input and output values for multimap
float vLimit = 32.0;
int adc0;
float battVoltage;
float battVolt;
int battmV;
/*********************************************************************************************************************/
volatile byte pulseCount; // counts the pulses of flow sensor
float flowRate;
unsigned int flowMilliLitres; //totaltotalMilliLitres used for the interrupts
unsigned long totalMilliLitres;
unsigned long oldTime;
unsigned long cloopTime; // to count pulses per second
unsigned long vol; //vol tracks total volume throughout loop
// constants for the states with SELF-explaining names
const byte OffState = 0;
const byte PumpState = 1;
const byte PausingState = 2;
const byte ReverseState = 3;
const byte RestState = 4;
const byte FullState = 5;
const byte PurgeState = 6;
byte state;
#define pressed HIGH
#define released LOW
#define closed HIGH
#define open LOW
// bool primeBtnPinHasBeenPressed = true;
bool purgeBtnPinHasBeenPressed = false;
void pulseCounter()
{
// Increment the pulse counter
pulseCount++;
}
void setup() {
Serial.begin(115200);
lcd.begin();
button1.setDebounceTime(50); // set debounce time to 50 milliseconds
button2.setDebounceTime(50); // set debounce time to 50 milliseconds
Serial.println("ESP32 PUMP");
pinMode(primeBtnPin, INPUT_PULLUP); // pinMode(5, INPUT);
pinMode(purgeBtnPin, INPUT_PULLUP); // pinMode(6, INPUT);
pinMode(samplingBtnPin, INPUT_PULLUP); // pinMode(7, INPUT);
pinMode(resetBtnPin , INPUT_PULLUP);
pinMode(FloatSwitchLED, OUTPUT);
pinMode(ResetLED, OUTPUT);
pinMode(DRV8876_IN1_PIN, OUTPUT); // pinMode(A0, OUTPUT);
pinMode(DRV8876_IN2_PIN, OUTPUT); // pinMode(A1, OUTPUT);
pinMode(flowPin, INPUT_PULLUP);
digitalWrite(flowPin, LOW);
pinMode(LeakLED, OUTPUT) ;
Threshold = 3400.0; //Threshold limit
pulseCount = 0;
flowRate = 0.0;
flowMilliLitres = 0.0;
totalMilliLitres = 0;
vol = 0;
cloopTime = currentMillis;
attachInterrupt(digitalPinToInterrupt(flowPin), pulseCounter, FALLING);
dividerRatio = (R1 + R2) / R1;
ads.setGain(GAIN_ONE);
// ads.begin();
/************************************************GRPS/SMS STUFF*************************************************/
// adc0 = ads.readADC_SingleEnded(0);
// battVoltage = ads.computeVolts(adc0) * dividerRatio * calFactor;
// battVolt = battVoltage * 3.7;
// battmV = (battVolt * 1000) + 30;
// Val = battmV;
// // int percent;
// percent = multiMap(Val, in, out, 13);
/************************************************GRPS/SMS STUFF end*********************************************/
Serial.print("Locating devices...");
sensors.begin();
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
//if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer");
// show the addresses we found on the bus
Serial.print("Device 0 Address: ");
printAddress(insideThermometer);
Serial.println();
// set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(insideThermometer, 9);
Serial.print("Device 0 Resolution: ");
}
void loop() {
button1.loop(); // MUST call the loop() function first
button2.loop(); // MUST call the loop() function first
int btn1State = button1.getState();
int btn2State = button2.getState();
// if (digitalRead(primeBtnPin) == released) primeBtnPinHasBeenPressed = false;
if (digitalRead(purgeBtnPin) == released) purgeBtnPinHasBeenPressed = true;
currentMillis = millis(); // Get the current value of millis().
buttonState = digitalRead(buttonPin);
if (digitalRead(samplingBtnPin) == released)
if (state > OffState) // Are we already in a pumping cycle?
state = OffState;
else
state = PumpState;
// delay(200); // Small delay to debounce the button.
value = analogRead(SIGNAL_PIN); // read the analog value from sensor
// adc0;
// battVoltage;
// battVolt;
// battmV;
// Val;
// percent;
if (!state == PumpState || ReverseState || PurgeState) {
ads.begin();
adc0 = ads.readADC_SingleEnded(0);
battVoltage = ads.computeVolts(adc0) * dividerRatio * calFactor;
battVolt = battVoltage * 3.7;
battmV = (battVolt * 1000) + 30;
Val = battmV;
// int percent;
percent = multiMap(Val, in, out, 13);
}
sensors.requestTemperatures(); // Send the command to get temperatures
// Serial.println("DONE");
printTemperature(insideThermometer); // Use a simple function to print out the data
tempC = sensors.getTempCByIndex(0);
tempF = (tempC * 1.8) + 32;
lcd.setCursor(0, 3);
lcd.print("B%");
lcd.setCursor(3, 3);
lcd.print(percent);
lcd.setCursor(7, 3);
lcd.print("TEMP:");
lcd.setCursor(13, 3);
lcd.print(tempF);
if (percent < 100) { //if battery percent falls below 100, erase the third digit
lcd.setCursor(5, 3);
lcd.print(" ");
}
if (percent < 10) {
lcd.setCursor(4, 3); //if battery falls below 10 percent, erase second and third digit
lcd.print(" ");
}
if (digitalRead(buttonPin) == HIGH) {
digitalWrite(FloatSwitchLED, LOW);
}
else {
digitalWrite(FloatSwitchLED, HIGH);
}
/********************************* read sensor stats and print on serial monitor *************************/
if (currentMillis - counter2 > samplingRate2) {
Serial.println("-----------------------------------------------------------");
Serial.print("Batt Volts: "); Serial.print(battVoltage, 3); Serial.print(" "); Serial.print("AIN0: "); Serial.print(adc0 ); Serial.print(" "); Serial.print(" BatVolt: "); Serial.println(battVolt, 3);
Serial.print("Battery mV: "); Serial.print(battmV); Serial.print(" "); Serial.print("Battery level [%]: "); Serial.println(percent);
Serial.println(sensors.getResolution(insideThermometer), DEC);
Serial.print("Temp C: "); Serial.print(tempC); Serial.print(" "); Serial.print(" Temp F: "); Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
Serial.print("FLOW ML: "); Serial.println(flowMilliLitres);
if (ThresholdLimit == true) {
Serial.print("THRESHOLD REACHED"); Serial.println(Threshold);
} else
{
Serial.println("THRESHOLD NOT REACHED");
}
if (digitalRead(buttonPin) == HIGH) {
Serial.println("FLOAT SWITCH OPEN!");
}
Serial.print("The water sensor value: ");
Serial.println(value);
Serial.println("-----------------------------------------------------------");
counter2 = millis();
currentMillis = millis();
}
/****** flow rate math ********/
if (currentMillis >= (cloopTime + 1000))
{
cloopTime = currentMillis;
if (pulseCount != 0) {
flowRate = (pulseCount / calibrationFactor);
//oldTime = millis();
flowMilliLitres = (flowRate / 60) * 1000;
totalMilliLitres += flowMilliLitres;
vol += flowMilliLitres;
Serial.print(flowRate); Serial.println(" :L/min");
Serial.print(totalMilliLitres); Serial.println(" :mL");
// lcd.setCursor(0, 1);
// lcd.print(flowRate);
// lcd.setCursor(5, 1);
// lcd.print(":L/min");
lcd.setCursor(0, 2);
lcd.print(vol);
lcd.setCursor(6, 2);
lcd.print(": mL");
pulseCount = 0;
}
else {
Serial.print(flowRate); Serial.println(" :L/min");
Serial.print(vol); Serial.println(" :mL");
// lcd.setCursor(0, 1);
// lcd.print(flowRate);
// lcd.setCursor(6, 1);
// lcd.print(":L/min");
lcd.setCursor(0, 2);
lcd.print(vol);
lcd.setCursor(6, 2);
lcd.print(": mL");
flowRate = 0;
}
}
///////////Leak Detection/////////////
if (value > 1) {
digitalWrite(LeakLED, HIGH);
delay(500);
digitalWrite(LeakLED, LOW);
delay(500);
Serial.println("LEAK DETECTED!");
}
else {
digitalWrite(LeakLED, LOW);
}
/////////////////////////////////////
switch (state) // Check which state we are in.
{
case OffState:
// manualMode();
if (digitalRead(primeBtnPin) == pressed) {
pumpOff();
}
else {
manualMode();
break;
}
if (purgeBtnPinHasBeenPressed = true) {
state = PurgeState;
}
else {
break;
}
if (digitalRead(resetBtnPin) == released) { // keep this button in OffState case so that if accidently pressed it wont hurt anything
resetData();
digitalWrite(ResetLED, HIGH);
}
else {
digitalWrite(ResetLED, LOW);
break;
}
startMillis = currentMillis; // Keep resetting the start time of the pumping sequence.
pumpOff();
break;
case PurgeState:
if (digitalRead(purgeBtnPin) == pressed)
state = OffState;
else
manualPurge();
break;
case PumpState:
if (totalMilliLitres > vLimit || currentMillis - startMillis > 60000) /// did we collect XmL? if not, go to next stage after X millis
state = PausingState;
else
PumpForward();
break;
case PausingState:
if (currentMillis - startMillis > 63000) // Have we been in this state too long?
state = ReverseState;
else
pumpOff();
Serial.println("PAUSE!");
lcd.setCursor(0, 0);
lcd.print("PAUSED! ");
break;
case ReverseState:
if (currentMillis - startMillis > 123000) // Have we been in this state too long?
state = RestState;//state++;
else
PumpReverse();
break;
case RestState:
if (currentMillis - startMillis > 900000) // has it been X minutes?
{
state = FullState;
startMillis = currentMillis; // Reset the start time of the pumping sequence.
totalMilliLitres = 0; //reset totalMilliLitres so it can start counting up from 0 again
}
else
pumpOff();
Serial.println("REST!");
lcd.setCursor(0, 0);
lcd.print("RESTING!");
break;
case FullState:
if (ThresholdLimit == true) { //|| (digitalRead(buttonPin) == HIGH))
state = OffState;
}
else {
Serial.println(state);
state = PumpState;
}
break;
}
/***************************SMS ALERTS***************************************************/
if (buttonState == HIGH && lastButtonState == LOW || vol > 3100 && vol - flowMilliLitres <= 3100) {
opened = false;
ThresholdLimit = true;
lastButtonState = buttonState;
pumpOff();
lcd.setCursor(0, 0);
lcd.print("FULL ");
}
if (tempF < tLimit && cold == false) {
cold = true;
}
else if (tempF > tLimit + 2.0 && cold == true) {
cold = false;
}
if (percent < bLimit && bat == false) {
bat = true;
}
/***************************SMS ALERTS END***************************************************/
/**************************** DATA POST TO DWEET *********************************************/
}
void Full() {
lcd.setCursor (0, 0);
lcd.print("FULL");
digitalWrite(DRV8876_IN1_PIN, LOW);
digitalWrite(DRV8876_IN2_PIN, LOW);
}
void manualMode() {
digitalWrite(DRV8876_IN1_PIN, HIGH); // comment is obsolete code epxlains ITSELF Turn on the pump (forward).
digitalWrite(DRV8876_IN2_PIN, LOW);
// Serial.println("PUMPING!");
lcd.setCursor(0, 0);
lcd.print("PUMPING!");
}
void manualPurge() {
digitalWrite(DRV8876_IN1_PIN, LOW); // comment is obsolete code epxlains ITSELF Turn on the pump (forward).
digitalWrite(DRV8876_IN2_PIN, HIGH);
// Serial.println("PUMPING!");
lcd.setCursor(0, 0);
lcd.print("PURGING!");
}
// senseful SUB-unit of code with a SELF-explaining name
void PumpForward() {
digitalWrite(DRV8876_IN1_PIN, HIGH); // comment is obsolete code epxlains ITSELF Turn on the pump (forward).
digitalWrite(DRV8876_IN2_PIN, LOW);
// Serial.println("PUMPING!");
lcd.setCursor(0, 0);
lcd.print("PUMPING!");
}
void resetData() {
currentMillis = millis();
startMillis = currentMillis;
cloopTime = currentMillis;
totalMilliLitres = 0;
flowRate = 0;
vol = 0;
flowMilliLitres = 0;
ThresholdLimit = false;
Serial.println("Data Reset");
lcd.setCursor(0, 2);
lcd.print(vol);
lcd.setCursor(1, 2);
lcd.print(" ");
pulseCount = 0;
}
// senseful SUB-unit of code with a SELF-explaining name
void PumpReverse() {
digitalWrite(DRV8876_IN1_PIN, LOW); // comment is obsolete code epxlains ITSELF Reverse the pump.
digitalWrite(DRV8876_IN2_PIN, HIGH);
Serial.println("PURGING!");
lcd.setCursor(0, 0);
lcd.print("PURGING!");
}
// senseful SUB-unit of code with a SELF-explaining name
void pumpOff()
{
digitalWrite(DRV8876_IN1_PIN, LOW);
digitalWrite(DRV8876_IN2_PIN, LOW);
lcd.setCursor(0, 0);
lcd.print("PUMP OFF");
}
void printTemperature(DeviceAddress deviceAddress)
{
// method 1 - slower
//Serial.print("Temp C: ");
//Serial.print(sensors.getTempC(deviceAddress));
//Serial.print(" Temp F: ");
//Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit
// method 2 - faster
float tempC = sensors.getTempC(deviceAddress);
if (tempC == DEVICE_DISCONNECTED_C)
{
Serial.println("Error: Could not read temperature data");
return;
}
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
[/size]