New - Attempting a target reset system

A very good day to you all! Really happy to be apart of the community.

I am wondering if any kind folk may help me with a programming dilemma (for me, but probably a drop in the ocean for most of you).

My code won't verify and I'm not sure if I am doing it right. Please let me explain my situation.

I am trying to make a air-soft, and rim-fire targeting reset system. Now, the idea is:

at power on the system has a red light (LED) that indicates not to fire.

It start a relay to a 12v high torque motor that will in turn raise a resetting bar to pop-up all the targets in the shooting alley I have made.

It then hits a lever switch (at its highest point) which will then in turn set the motor to stop, delay, so it doesn't run straight from forward to reverse, then the the bar rotates to it's resting position (lowest point) which hits another lever switch which will then hold the motor to stop and a green LED to indicate commence firing.

At this point there are 4 targets to knockdown and on doing so completes a simple circuit which sets the reset system back off again.

Now please don't think im just getting you guys to do the hard work, I have really really spent many hours and a few days trying to figure this all out. I HAVE attempted a simple switch case code, but im not getting it to verify or prove if it works as it won't go no further than verifying in IDE :'( Im really struggling now.

#define DOWN
#define UP
#define REST

const int buttonup=3;
const int buttondown=2;
const int LEDgo=4;
const int LEDstop=5;
const int motorup=6;
const int motordown=7;
const int knockdown=8;


void setup()
{
  
  pinMode(buttonup,INPUT);
  pinMode(buttondown,INPUT);
  pinMode(LEDgo,OUTPUT);
  pinMode(LEDstop,OUTPUT);
  pinMode(motorup,OUTPUT);
  pinMode(motordown,OUTPUT);
  pinMode(knockdown,INPUT);

}

void loop()
{
    if (digitalRead(buttondown)) {
       mode=REST
    }
    if (digitalRead(buttonup)) {
       mode=DOWN
    }
    if (digitalRead(knockdown)) {
       mode=UP
    }

switch(mode)
{
       case DOWN:
           digitalWrite(motorup,LOW);
           delay(1500);
           digitalWrite(LEDgo,LOW);
           digitalWrite(LEDstop,HIGH);
           digitalWrite(motordown,HIGH);
           break;

       case UP:
           digitalWrite(LEDgo,LOW);
           digitalWrite(LEDstop,HIGH);
           digitalWrite(motordown,LOW);
           digitalWrite(motorup,HIGH);
           break;

       case REST:
           digitalWrite(LEDgo,HIGH);
           digitalWrite(LEDstop,LOW);
           digitalWrite(motordown,LOW);
           digitalWrite(motorup,LOW);
           break;
    }
}

Is this a suitable method? Or have i really got the wrong end of the stick and making a mockery of myself, Please go easy on me i respect your knowledge and help.

The bits I have (and I can purchase more if needs be to make this work) are:

*12v 15RPM torque motor, *2x Lever Switch NC,NO&COM *1x 2 relay module for the forward and reverse setup of the motor, *Red: forward voltage 2-2.2v 2000mcd *Green: forward voltage 3-3.3v 20000mcd *2x 220 Ohm resistors for LED's *meters of jumper wire to make the open circuit for the targets and the temporary breadboard setup.

Now I am aware that there is sometimes a factor of using switches and debounce but im not that advanced to know how to implement it into code as I was under the impression most use "pullup" for something to activate on button release which wouldn't work in my scenario as i need the motor to instantly stop turning the reset bar on contact with the lever switches.

Again I am so grateful for honest help.

Thank you,

Beats me if it works, no desire to figure out what you're trying to do but at least it will now compile:

#define DOWN 0
#define UP 1
#define REST 2

const int buttonup = 3;
const int buttondown = 2;
const int LEDgo = 4;
const int LEDstop = 5;
const int motorup = 6;
const int motordown = 7;
const int knockdown = 8;
int mode;

void setup()
{

  pinMode(buttonup, INPUT);
  pinMode(buttondown, INPUT);
  pinMode(LEDgo, OUTPUT);
  pinMode(LEDstop, OUTPUT);
  pinMode(motorup, OUTPUT);
  pinMode(motordown, OUTPUT);
  pinMode(knockdown, INPUT);

}

void loop()
{
  if (digitalRead(buttondown)) {
    mode = REST;
  }
  if (digitalRead(buttonup)) {
    mode = DOWN;
  }
  if (digitalRead(knockdown)) {
    mode = UP;
  }

  switch (mode)
  {
    case DOWN:
      digitalWrite(motorup, LOW);
      delay(1500);
      digitalWrite(LEDgo, LOW);
      digitalWrite(LEDstop, HIGH);
      digitalWrite(motordown, HIGH);
      break;

    case UP:
      digitalWrite(LEDgo, LOW);
      digitalWrite(LEDstop, HIGH);
      digitalWrite(motordown, LOW);
      digitalWrite(motorup, HIGH);
      break;

    case REST:
      digitalWrite(LEDgo, HIGH);
      digitalWrite(LEDstop, LOW);
      digitalWrite(motordown, LOW);
      digitalWrite(motorup, LOW);
      break;
  }
}

Nosferatu_UK: Is this a suitable method?

Indeed, it is. Most beginners would have to be led to a state machine.

Nosferatu_UK: Now I am aware that there is sometimes a factor of using switches and debounce but im not that advanced

Familiarize yourself with the first five sketches in: IDE > file/examples/digital.

Nosferatu_UK: I was under the impression most use "pullup" for something to activate on button release which wouldn't work in my scenario...

Yes, pullups, or pulldowns, are needed for mechanical switch inputs - because otherwise the inputs 'float' and any passing EMI can register as a switch actuation. Most folks use the built-in pullups since they're free. This inverts the switch logic, though.

Nosferatu_UK: ...i need the motor to instantly stop turning the reset bar on contact with the lever switches.

Define 'instantly'. At UNO speed of ~6.2 nanoseconds per instruction, the processor is executing thousands of instructions every second. The delay between switch actuation and the command to stop the motor is infinitesimal to us humans.

Karma for first post code tags.

See if this works for you. Your effort is laudable and seemed very close. This version (should!) does basically what yours intended with a smidge of polish.

The statemachine is in its own function and starts off in an initialization state that attempts to determine the state of the machine. If the state is indeterminate (e.g. no switches are closed), the state machine moves the motor “down” be default.

A note on switches: This is coded to use switches that ground the pin when closed while an internal pull-up maintains the pin in a high state when the switch is open. If you need this changed you can change the pinModes back to INPUT and changes the OPEN and CLOSED defines at the top of the code.

(Compiles, not tested…)

#define DOWN        0
#define UP          1
#define REST        2

#define OPEN        HIGH
#define CLOSED      LOW

#define UP_DELAY    1500ul      //mS delay at top
#define DN_DELAY    250ul       //mS delay at bottom

const byte buttonup=3;
const byte buttondown=2;
const byte LEDgo=4;
const byte LEDstop=5;
const byte motorup=6;
const byte motordown=7;
const byte knockdown=8;

void setup()
{  
    pinMode( buttonup,INPUT_PULLUP );
    pinMode( buttondown,INPUT_PULLUP );
    pinMode( LEDgo,OUTPUT );
    pinMode( LEDstop,OUTPUT );
    pinMode( motorup,OUTPUT );
    pinMode( motordown,OUTPUT );
    pinMode( knockdown,INPUT_PULLUP );
 
}//setup

//state machine states
#define STATE_INIT              0
#define STATE_MOVE_UP           1
#define STATE_MOVE_UP_PAUSE     2
#define STATE_MOVE_DOWN         3
#define STATE_MOVE_DOWN_PAUSE   4
#define STATE_REST              5
void MotorStateMachine( void )
{
    static unsigned long
        timeMotorDelay = 0;
    static byte
        stateMSM = STATE_INIT;

    switch( stateMSM )
    {
        case    STATE_INIT:
            //red on, green off initially
            digitalWrite(LEDgo,LOW);
            digitalWrite(LEDstop,HIGH);
            
            //determine the current state of things. If indeterminate (none of the switches pressed), 
            //force a "homing" of the system by invoking MOVE_DOWN
            if( digitalRead( buttondown ) == CLOSED )
            {
                timeMotorDelay = millis();
                stateMSM = STATE_MOVE_DOWN_PAUSE;
                
            }//if
            else if( digitalRead( buttonup ) == CLOSED )
            {
                timeMotorDelay = millis();            
                stateMSM = STATE_MOVE_UP_PAUSE;
                
            }//else if
            else if( digitalRead( knockdown ) == CLOSED )
            {
                MoveMotorUp();
                stateMSM = STATE_MOVE_UP;
                
            }//else if
            else
            {
                MoveMotorUp();
                stateMSM = STATE_MOVE_DOWN;
                
            }//else
                
        break;

        case    STATE_MOVE_UP:
            if( digitalRead( buttonup ) == CLOSED )
            {
                StopMotor();
                timeMotorDelay = millis();
                stateMSM = STATE_MOVE_UP_PAUSE;
                
            }//if
            
        break;
        
        case    STATE_MOVE_UP_PAUSE:
            if( millis() - timeMotorDelay < UP_DELAY )
                return;
                
            MoveMotorDown();
            stateMSM = STATE_MOVE_DOWN;
            
        break;

        case    STATE_MOVE_DOWN:
            if( digitalRead( buttondown ) == CLOSED )
            {
                StopMotor();
                timeMotorDelay = millis();
                stateMSM = STATE_MOVE_DOWN_PAUSE;
                
            }//if
            
        break;

        case    STATE_MOVE_DOWN_PAUSE:
            //a brief pause at the bottom before turning on the green light
            if( millis() - timeMotorDelay < DN_DELAY )
                return;

            //ready for the rest state; green on, red off
            digitalWrite( LEDgo,HIGH );
            digitalWrite( LEDstop,LOW );
                
            stateMSM = STATE_REST;
            
        break;

        case    STATE_REST:
            if( digitalRead( knockdown ) == CLOSED )
            {
                MoveMotorUp();
                stateMSM = STATE_MOVE_UP;
                
            }//if
                        
        break;
        
    }//switch
    
}//MotorStateMachine

void MoveMotorUp( void )
{
    //motor in motion; green off, red on
    digitalWrite( LEDgo,LOW );
    digitalWrite( LEDstop,HIGH );
    //
    digitalWrite( LEDgo,LOW );
    digitalWrite( LEDstop,HIGH );
    digitalWrite( motordown,LOW );
    digitalWrite( motorup,HIGH );
    
}//MoveMotorUp

void MoveMotorDown( void )
{
    //motor in motion; green off, red on
    digitalWrite( LEDgo,LOW );
    digitalWrite( LEDstop,HIGH );
    //
    digitalWrite( motorup,LOW );
    digitalWrite( LEDgo,LOW );
    digitalWrite( LEDstop,HIGH );
    digitalWrite( motordown,HIGH );
    
}//MoveMotorDown

void StopMotor( void )
{
    digitalWrite( motordown,LOW );
    digitalWrite( motorup,LOW );
    
}//StopMotor

void loop()
{
    MotorStateMachine();
    
}//loop

WattsThat Thank you kindly for cleaning the code I have attempted. I will keep this in my library to learn from time and time again.

dougp Wow, that's was very insightful and clears a lot of outstanding questions I had. Also has helped me to use the "basics" templates a bit more to help advance my education. (and word my sentences more carefully like "instantly" lol). Thank you :D

Blackfin I sincerely bow to your immense input/effort of looking at my code, understanding my idea and bettering the program further with your method. Amazed and eternally appreciative. Truly wonderful. I have yet to upload and test the system as I'm now at work this morning. But after reading all these I'm so eager to down tools and run home and try this all again.

I am honestly ecstatic for all the help :) I will hopefully be back with an update to see if it all has responded well.

**Further to my recent knowledge of doing simple activation tests on the relay (as they were not coming on when instructed), it seems as though I have purchased Active LOW (0-1v trigger) relays. I do believe I have the wrong ones and need the Active HIGH (5v trigger)? So I have put on order some dual trigger relays instead so I can change the low to high with a jumper onboard. So whilst I wait, I assume that I would now instead of have the default state LOW and change to HIGH in the code, I would need to change these around so they stay HIGH whilst idle and activate the relays by going LOW?

Nosferatu_UK: **Further to my recent knowledge of doing simple activation tests on the relay (as they were not coming on when instructed), it seems as though I have purchased Active LOW (0-1v trigger) relays. I do believe I have the wrong ones and need the Active HIGH (5v trigger)? So I have put on order some dual trigger relays instead so I can change the low to high with a jumper onboard. So whilst I wait, I assume that I would now instead of have the default state LOW and change to HIGH in the code, I would need to change these around so they stay HIGH whilst idle and activate the relays by going LOW?

That should work. I often code something like:

#define RELAY_CLOSED    LOW
#define RELAY_OPEN      HIGH

and then when something needs doing:

.
.
.
    digitalWrite( LEDgo,LOW );
    digitalWrite( LEDstop,HIGH );
    digitalWrite( motordown,RELAY_OPEN );
    digitalWrite( motorup,RELAY_CLOSED );
    
}//MoveMotorUp
.
.
.

That way, if the senses are backwards, it's just two lines that need to change instead of hunting through the code for every instance. I figured what you had worked so left it; making this change to whatever code you end up using would be a good idea.

Blackfin
Sir, that code was just a beaut, thank you! I resorted to it after many hours of failed attempts on mine.

There is a small error for me to try and work though and im literally trying to figure out what.

If the system starts up and the bottom switch IS already engaged, both relays activate. <i did a bad change of parameters, this no longer is the case.

And on initial start, it seems as though the “up” relay activates instead of the down and on doing so this causes the Hi point switch to not activate for the motor to reverse, so the motor continually rotates breaking itself from the housing lol

I will go over it again to make sure i haven’t done it wrong.

Again though, you have been a true gent in your assistance and I thank you greatly.