Cant alternate the outputs

Ok so a big thanks to scruffr for helping with my code along the way.
What i am trying to do is each time a pump runs then stops, the next time a pump is required it picks the next pump as long as it is available.in my code
If the level etc is not in a state that req’s the pump it ++ to the next available pump

what i am finding is that when the level is lower than the req level it alternates through the pumps each time the loop is run however i just want it to move to the next pump and only change to the next once this one has run but i am unable to do this as i do not know how. i have tried however i am getting results i want.

here is my code

struct Pump {
  int Auto;
  int running;
  int run;
  int tripped;
};
int B;

//-------------------------Level Varibles
const int LevelReading = A0;
float Level; // to hold the reading from ana
int CycleCount = 1;
//boolean RepeatStop = false;
//RepeatStop = false;


float StartSetpoint; // Holds the setpoing for turning on the pump
float StopSetpoint;// Holds the setpoint for turning off the pump

Pump pumpPins[] = {
  {D0, D1, D3, D2},
  {D4, D5, D6, D7}
};
 
const int pumpCount = sizeof(pumpPins) / sizeof(pumpPins[0]);

int actPump = 0;

void setup() {
  for (int i=0; i < pumpCount; i++)
  {
    pinMode(pumpPins[i].Auto, INPUT_PULLDOWN);
    pinMode(pumpPins[i].tripped, INPUT_PULLDOWN);
    pinMode(pumpPins[i].run, OUTPUT);
  }
  
   // Particle.function("rearmAlarm", rearm); 
  Serial.begin(9600); // begin serial for displaying reading
StartSetpoint =15;  
}

void loop()
{
 
  //---------------------------------------------------------------------------------
//---------------Running the pump on level----------------------------------------
//Serial.println(StartSetpoint);
delay(250);
Serial.print("Level Is....");
Serial.print(Level);
Serial.println(" Metres");
Serial.println(" acting pump");
Serial.println(actPump);
Serial.println(" Cyclecount is  ");
Serial.println(CycleCount);
//GetOverloadStatus();
delay(250);
Level = analogRead(LevelReading);
//Level = constrain(Level, 0, 2000);
Level = map(Level, 0, 4095, 0, 20);


  if ((Level)>= (StartSetpoint)&&digitalRead(pumpPins[actPump].Auto) == HIGH &&digitalRead(pumpPins[actPump].tripped)== LOW)
    //runPump(actPump);
   // pumpPins[0].run
 //  {
    digitalWrite(pumpPins[actPump].run, HIGH);
  //  CycleCount = 10;
   //}
  
else  if ((Level)<(StartSetpoint)||digitalRead(pumpPins[actPump].Auto) == LOW ||(pumpPins[actPump].tripped, HIGH))
  {
     digitalWrite(pumpPins[actPump].run, LOW);
    // CycleCount++;
  //}  
  // if ((CycleCount)>=12)
   //{ 
        actPump++;             // assign next pump to start next time
        actPump %= pumpCount;  // wrap round after last pump
   }
  
//}
}
//pumpPins[0].auto == D0
//pumpPins[1].auto == D2

any advice would be great

thanks…BEn

`

It is still very difficult to understand what you are trying to do. Plus it seems to me you have too many variables or you haven't explained what all of the other pins are doing.

You clearly want to ALTERNATE the two pumps, as to ease the duty cycle of either. So you can alternate which pump comes on very simply. But, I think you want a STATE CHANGE detection program flow, allowing only one of the pumps on at a time. That means you only want to activate one of the two pumps when the sensor reads the high value and turns off the pump once the level is reduced below the low value.

I would approach it like this:

#define LEVEL_PIN A0
#define ON_READING 15  // a pump will come on when the sensor detects level higher than 15
#define OFF_READING 5  // the active pump will turn off when the sensor detects level lower than 5

enum PumpState{
  PUMP_STOPPED = 0,
  PUMP_ACTIVE
};

struct Pump{
  int pin;
  PumpState pumpState;
};

Pump pump[] = {
  { D1, PUMP_STOPPED},
  { D2, PUMP_STOPPED}
};

int cycleCount = 0;
int lastLevelReading;

void setup() 
{
  Serial.begin(9600); 
  for(int i = 0; i < (sizeof(pump) / sizeof(pump[0])); i++)
  {
    pinMode(pump[i].pin, OUTPUT);
  }
}

void loop() 
{
  int currentLevel = map(analogRead(LEVEL_PIN), 0, 4095, 0, 20);
  if(currentLevel >= ON_READING && lastLevelReading < ON_READING && pump[0].pumpState == PUMP_STOPPED && pump[1].pumpState == PUMP_STOPPED)
  {
    startPump();
  }
  else if(currentLevel <= OFF_READING && lastLevelReading > OFF_READING && (pump[0].pumpState == PUMP_ACTIVE || pump[1].pumpState == PUMP_ACTIVE))
  {
    stopPump();
  }
  lastLevelReading = currentLevel;
  //
  static int lastMillis = 0;
  if(millis() - lastMillis > 1000)
  {
    Serial.print("Level Is....");
    Serial.print(currentLevel);
    Serial.println(" Metres");
    Serial.println(" acting pump");
    Serial.println(pump[0].pumpState == PUMP_ACTIVE? "zero" : pump[1].pumpState == PUMP_ACTIVE? "one" : "none");
    Serial.println(" Cyclecount is  ");
    Serial.println(cycleCount);
    lastMillis += 1000;
  }
}

void startPump(void)
{
  static int pumpNumber = 0;
  pumpNumber = ++pumpNumber % (sizeof(pump) / sizeof(pump[0]));
  pump[pumpNumber].pumpState = PUMP_ACTIVE;
  digitalWrite(pump[pumpNumber].pin, HIGH);
  cycleCount++;
}

void stopPump(void)
{
  for(int i = 0; i < (sizeof(pump) / sizeof(pump[0])); i++)
  {
    pump[i].pumpState = PUMP_STOPPED;
    digitalWrite(pump[i].pin, LOW);
  }
}

You can try this untested code above (compiles).

I don't think so. As I understood his other post he wants the "other" pump also to kick in if the level touches the next threshold switch, since the first one alone obviously can't cope with the inflow.

But @benjiiiiuk, if you want to switch pumps on a "more restrictive" condition, you just need to adapt the condition in this part

else  if ((Level)<(StartSetpoint)||digitalRead(pumpPins[actPump].Auto) == LOW ||(pumpPins[actPump].tripped, HIGH))
  {
     digitalWrite(pumpPins[actPump].run, LOW);
    // CycleCount++;
  //}  
  // if ((CycleCount)>=12)
   //{ 
        actPump++;             // assign next pump to start next time
        actPump %= pumpCount;  // wrap round after last pump
   }

BTW, to save yourself the hassle if explaining things over and over again, why not just add a link to your original thread (which also should show my code without alteration)

Sorry, I struggle a bit when trying to explain what I am trying to achieve.
When the else if statment runs and adds 1 to act pump as the loop runs over and over when I print the act pump in the serial monitor it constantly changes from 0 to 1 so when the level comes back up its ramdom which pump is the actpump instead of alternating.
Hope this clears it up.

This (pumpPins[actPump].tripped, HIGH) will most likely cause your else if() to be true always.

Replace the comma (,) with an equality check (==)!

And you should add a check for change of state (as @BulldogLowell already suggested).
This means to set a flag or other “variable” inside the conditional branch and check in the condition if that state was already set before or not and only execute if not.

Thanks for the reply’s so this seems to be doing what i require for now, it took me a few days to get here but i seemed to have learned a little bit on the way.

  int Auto;
  int running;
  int run;
  int tripped;
};
int B;

//-------------------------Level Varibles
const int LevelReading = A0;
float Level; // to hold the reading from ana
int PumpJustRan = 0;


float StartSetpoint; // Holds the setpoing for turning on the pump
float StopSetpoint;// Holds the setpoint for turning off the pump

Pump pumpPins[] = {
  {D0, D1, D3, D2},
  {D4, D5, D6, D7}
};
 
const int pumpCount = sizeof(pumpPins) / sizeof(pumpPins[0]);

int actPump = 0;

void setup() {
  for (int i=0; i < pumpCount; i++)
  {
    pinMode(pumpPins[i].Auto, INPUT_PULLDOWN);
    pinMode(pumpPins[i].tripped, INPUT_PULLDOWN);
    pinMode(pumpPins[i].run, OUTPUT);
  }
  
 
Serial.begin(9600); // begin serial for displaying reading
StartSetpoint =15;  
}

void loop()
{
 
  //---------------------------------------------------------------------------------
//---------------Running the pump on level----------------------------------------
delay(250);
Serial.println("V6");
Serial.print("Number of Pumps is.........");
Serial.print(pumpCount);
Serial.print("Level Is....");
Serial.print(Level);
Serial.println(" Metres");



delay(500);
Level = analogRead(LevelReading);
Level = map(Level, 0, 4095, 0, 20);

//***********************************Check to see if pump should run***********************************************************
  if ((Level)>= (StartSetpoint)&&digitalRead(pumpPins[actPump].Auto) == HIGH &&digitalRead(pumpPins[actPump].tripped)== LOW)
   { 
    digitalWrite(pumpPins[actPump].run, HIGH);
    Serial.println("Pump Running");
    PumpJustRan = actPump;
    Serial.println("Acting Pump");
    Serial.println(actPump);

     
     
   }
   
   if ((Level)< (StartSetpoint)||digitalRead(pumpPins[actPump].Auto) == LOW ||digitalRead(pumpPins[actPump].tripped)== HIGH)
   {
       digitalWrite(pumpPins[actPump].run, LOW);
       if (PumpJustRan == actPump ) // run this if statement once so we switch the next pump to run when conditions are right
        {
            actPump++;             // assign next pump to start next time
            actPump %= pumpCount;  // wrap round after last pump
        }
        Serial.println("pump stopped");
        Serial.println("Acting Pump");
        Serial.println(actPump);


  
}

}
1 Like