Bottle filling line

Hello everyone, first post although I've been reading and lurking for quit some time!!

Have a bottle filling line that I control with switches manually and would like to automate, Just want some ideas as to timing functions or should I use more sensors to see stages etc. It needs to start by dropping gantry, purges co2 in first two bottles(curently uses a delay relay that could still be used just needs to close a contact) then raise gantry, actuate cylinder to advance bottles, lower gantry, purge co2 in next bottles and open fill valves for beer going into two bottles, when full raise gantry and advance again. Valves etc. are 24v now, so I would use a relay board to actuate. Any ideas questions comments etc, are what I am looking for, as well as a basic Idea of how to start ie. timed process or sensors etc.

You have provided a summary of the steps. Write them down for yourself in detail, use them as comments in the program, and have at it.

Also produce a list of all the input and output signals to make sure you know how many and of what type are being used and that you have enough I/O pins.

I would suggest SSR instead of discrete relays due to the constant repetitive actuation.

Running your processes by time alone may be risky - what happens when something goes wrong? Just running out of bottles would be a catastrophe - think of all that spilled beer! Can the bottles get jammed? Break? fall off the gantry? Some sensors would seem to be sensible unless your mechanicals already have fail safes in place.

Red1316:
as well as a basic Idea of how to start ie. timed process or sensors etc.

In the end it will probably be some combination of the two. My philosophy is don't stint on sensors. Of course, they cost more than a software timer but having positive knowledge (as far as such a thing is possible) of the position of an object is better than assuming thing A has moved to point C in 1. X seconds. This isn't to say that timers don't have their place. If an expected switch closure doesn't happen in some interval then a timer can flag a fault/hangup. You also don't want a 'line full' sensor to stop the line just because a bottle passes by - it should be blocked for X seconds before 'full' is declared.

Investigate state machines and the switch/case statements.

If you're not committed to a controller, consider a brick size PLC. Two advantages there are that most modern PLCs will directly accept 24V I/O and they usually have some built-in sequencer/drum instructions to simplify applications like yours. One downside is you may have to get familiar with ladder logic.

Thanks guys,
I did go ahead today with a sketch using timing for now, there is a back story to this project....we have a canning line that works great but we can not purchase cans right now due to a supplier shortage so we are using stubbies for now which led me to throwing together this line as we need 2500 bottles of beer for this weekend!
Got everything as I thought would work but running the code it drops the gantry but the nothing, I'm sure its something stupid as I am new to this and have now 20hrs straight reading and writing!
Also need a hand as the best way to make it loop endlessly but be able to stop at any time possibly with a second push of start button or another button.
doug, I am eventually going to use a plc and hmi for this and two other machines but for now my sons uno was closer and cheaper and great way to show him something......hopefully.
Thanks again in advance.

#define startButton   2
#define gantryValve   3
#define co2PurgeVlv   4
#define fillValve1    5
#define fillValve2    6
#define bottleAdvance 7
#define co2FillVlv    8

#define idle 0
#define gantryLower 1
#define purge 2
#define fill 3
#define gantryRaise 4
#define advanceBottles 5

//set initial state idle
//idle waits for start button
byte state = idle;

boolean stateChange = false;
byte buttonState = HIGH;
byte lastButtonState = HIGH;

unsigned long currentMillis = millis();
unsigned long stateStartMillis = millis();
unsigned long timeRemaining = 0;


void setup() {
  digitalWrite (gantryValve, HIGH);
  digitalWrite (co2PurgeVlv, HIGH);
  digitalWrite (fillValve1, HIGH);
  digitalWrite (fillValve2, HIGH);
  digitalWrite (bottleAdvance, HIGH);
  digitalWrite (co2FillVlv, HIGH);
  pinMode (startButton, INPUT_PULLUP);
  pinMode (gantryValve, OUTPUT);
  pinMode (co2PurgeVlv, OUTPUT);
  pinMode (fillValve1, OUTPUT);
  pinMode (fillValve2, OUTPUT);
  pinMode (bottleAdvance, OUTPUT);
  pinMode (co2FillVlv, OUTPUT);


}

void loop() {
  currentMillis = millis();

  switch (state) {
    case idle: {
        buttonState = digitalRead(startButton);
        if (buttonState == LOW && lastButtonState == HIGH)
        {
          state = gantryLower;
        }
          break;
    }
        case gantryLower: {
            digitalWrite(gantryValve, LOW);
            break;
          }
        case purge: {
            unsigned long purgeTime = 1000UL;
            if (stateChange == false)
            {
              stateStartMillis = millis();
              stateChange = true;
              digitalWrite (co2PurgeVlv, LOW);
              digitalWrite (co2FillVlv, LOW);
            }
            if (stateChange == true)
              timeRemaining = stateStartMillis + purgeTime - currentMillis;
            if (currentMillis - stateStartMillis >= purgeTime)
            {
              digitalWrite (co2PurgeVlv, HIGH);
              digitalWrite (co2FillVlv, HIGH);
              stateChange = false;
              state = fill;
            }
            break;
          }
        case fill: {
            unsigned long fillTime = 20000UL;
            if (stateChange == false)
            {
              stateStartMillis = millis();
              stateChange = true;
              digitalWrite (fillValve1, LOW);
              digitalWrite (fillValve2, LOW);
            }
            if (stateChange == true)
              timeRemaining = stateStartMillis + fillTime - currentMillis;

            if (currentMillis - stateStartMillis >= fillTime)
            {
              digitalWrite (fillValve1, HIGH);
              digitalWrite (fillValve2, HIGH);
              stateChange = false;
              state = gantryRaise;
            }
            break;
          }
        case gantryRaise: {
            digitalWrite (gantryValve, HIGH);
            break;
          }
        case advanceBottles: {
            unsigned long advanceTime = 500UL;
            if (stateChange == false)
            {
              stateStartMillis = millis();
              stateChange = true;
              digitalWrite (bottleAdvance, LOW);
            }
            if (stateChange == true)
              timeRemaining = stateStartMillis + advanceTime - currentMillis;
            if (currentMillis - stateStartMillis >= advanceTime)

              digitalWrite (bottleAdvance, HIGH);
            stateChange = false;
            state = idle;
          }
          break;
        }
}

There's nothing in the gantry_lower state that will ever advance the code to another state - all it does is a digitalWrite to (presumably) lower the gantry.

Thanks wildbill, I knew it was dumb...got it works good now but could use some time to lower the gantry before purge, and at the end it does not retract the advanceBottle cylinder and needs a reset to continue operation. I'm learning alot today and just need these last bits figured before we go live with liquid!

Looks like you're missing some braces here:

        if (currentMillis - stateStartMillis >= advanceTime)

          digitalWrite (bottleAdvance, HIGH);
        stateChange = false;
        state = idle;

Probably supposed to be:

        if (currentMillis - stateStartMillis >= advanceTime)
          {
          digitalWrite (bottleAdvance, HIGH);
          stateChange = false;
          state = idle;
          }

Wait a second....... beer?
You said there was beer?
Not sure what part of the world you are in, but you might find a few people to help you "test" you code.....

Thanks again wildbill, I had honestly let the auto format show me mistakes and tried correcting them( there were alot!! before it would compile so I thought that was it.) As stated I'm catching on slowly my son and I are loving this!
Ran liquid last night and timing is hard to play with! But I kinda knew that. Need to add liquid sensors, but for now I need beer in bottles! Next week I'll tackle adding sensors.
Could a simple wire sensing continuity be used as an input for liquid level?

Red1316:
...
Could a simple wire sensing continuity be used as an input for liquid level?

You could do that but it means inserting a sensor into the bottle which is not ideal for hygiene.
Here is an article on four bottle filling techniques;

One issue with switches, when i have a start switch, reset switch or switches to turn fill valves off wired in the board acts wierd! Do I need to isolate the switches or something? If I just use a jumper wire to ground the start pin all works good.

Red1316:
One issue with switches, when i have a start switch, reset switch or switches to turn fill valves off wired in the board acts wierd! Do I need to isolate the switches or something? If I just use a jumper wire to ground the start pin all works good.

You need to show the schematic for suggestions to help address.