Start and Stop Stepper with Accel Library

I am working on a class project that is a rotating wheel like a Ferris wheel, instead of chairs it has dixie cups. There are a total of 12 positions. Here are the logical steps.

  1. Rotate wheel 30 degrees and stop.
  2. Turn on Solid State Relay ,which is attached to a small pump, the pump stays on for 2 seconds adds some water.
  3. Wait 5 seconds for drips to stop.
  4. Rotate to next position and repeat above.
  5. Do this for all 12 positions.

After all cups have water.

  1. Rotate wheel 360 for X number of times.
  2. Start fill sequence again.

I am new to the Arduino platform and have been running into some issues with the stepper motor being able to start and stop. I am using the AccelStepper with the following hardware.

Arduino Uno
Spark Fun Solid State Relay Kit (KIT-10684)
Spark Fun Stepper Motor - 125 oz.in (200 steps/rev) (ROB-10847)
Big Easy Driver (ROB-10735)

I have everything together and working. I can’t seem to figure out the code to get the pause to happen for 5 seconds between when the pump turns off and the motor indexes to next position or how to get the second phase to integrated. I have provided the code I am using below. Can one of you pro’s take a look and make some suggestions? It seems pretty straight forward.

Thanks in advance for any help or suggestions.

#include <AccelStepper.h>

#define relayPin 2                         //Output Pin for the SSR
#define dirPin 9                            //Direction Output on pin 8
#define stepPin 8                          //Step Output on pin 9
#define relayOn 8000                     //Amount of time the SSR stays on
#define relayOff 4000                    //Amount of time the SSR stays off
#define maxSpeed 4000
#define shaftSpeed 4000

const int steps = 200;                             
AccelStepper stepper(1, dirPin, stepPin);

int Distance;
unsigned long ms;                           //time from millis()
unsigned long msLast;                     //last time the relay changed state
boolean relayState;                         //current state of relay on or off

void setup()
{
    Serial.begin(9600);
    stepper.setMaxSpeed(maxSpeed);
    stepper.setSpeed(shaftSpeed); 
    relayState = 0;
}

void loop()
{
   ms = millis();
   changeRelayState();
    
    if (relayState == 0)
  {
    stepper.runSpeed();
  }
    else
  {
    digitalWrite(dirPin, LOW);        
    digitalWrite(stepPin, LOW);
    
  }   
}

void changeRelayState()
{
    if (ms - msLast > (relayState ? relayOn : relayOff))
    {
      digitalWrite(relayPin, relayState = !relayState);
      msLast = ms;
    }
}

Read this before posting a programming question

Please edit your post, select the code, and put it between [code][/code] tags.

You can do that by hitting the # button above the posting area.

This part is wrong.

      digitalWrite(relayPin, relayState = !relayState);

It won't change between the two states like you seem to think.

Better be explicit than this fancy "alter a variable in the middle of a function call" stuff.

  if (relayState == relayOn)
     relayState = relayOff;
  else
     relayState = relayOn;

  digitalWrite(relayPin, (relayState == relayOn) ? HIGH : LOW);

Thanks Nick. I will try the new code. Can you explain why the fancy “alter a variable in the middle of a function call” stuff is not properly done?

For a start, an assignment in the middle of a function call is generally a bad idea. A similar problem is this:

if (a = 5)
  // do something

That assigns 5 to a, not tests if it is 5.


Similarly, something like:

      digitalWrite(relayPin, relayState = !relayState);

... has a side-effect of changing relayState. People might wonder if you meant to test rather than change it.


Your definitions are:

#define relayOn 8000                     //Amount of time the SSR stays on
#define relayOff 4000                    //Amount of time the SSR stays off

If relayState is currently relayOn, then negating it will not give you relayOff.

Negation is a boolean operation. If the original value is non-zero, the new value is zero, and vice-versa.

Thus:

relayState = !relayOn;  // relayState is now zero, not 4000

That's an argument against using relayState = !relayState, rather than against using that expression in the arguments to a function call.

There's nothing fundamentally wrong (IMO) in using expressions that modify variables in a function call.

OK, but I would still wonder whether this is a typo:

      digitalWrite(relayPin, foo = HIGH);

I would think, does he mean:

      digitalWrite(relayPin, foo == HIGH);

After supplying the code Nick suggested above the relay no longer turns on and off? Hmmm.

Let's see the new code, huh?

[quote author=Nick Gammon link=topic=128754.msg970076#msg970076 date=1351120775] I would think, does he mean: [/quote]

I think that's approaching certainty.

Hi Nick. All I did was substitute your recommended code change into my changeRelayState and the relay wouldn't come on afterwards. I put original code back and it comes on. As you are probably aware I am new to all this. So please go easy on me.

Original Code

void changeRelayState()
{
    if (ms - msLast > (relayState ? relayOn : relayOff))
    {
      digitalWrite(relayPin, relayState = !relayState);
      msLast = ms;
    }
}

New Code

void changeRelayState()
{
    if (relayState == relayOn)
     relayState = relayOff;
  else
     relayState = relayOn;
     digitalWrite(relayPin, (relayState == relayOn) ? HIGH : LOW);
     msLast = ms;
}

We are missing a brace here. Can you post the code that actually compiles please?

I took one out.

Can you post the code that actually compiles please?

They both compile fine on my system. See attached images.

originalcode.jpg

nickcode.jpg

What Nick is asking is that you post (in it's entireity) the latest sketch that you're having problems with. It's too hard to help if we're guessing what you changed.

Ok. Sorry.

The comments on the #define statements indicate that relayOn and relayOff are times, not states. So, comparing relayState to relayOn or relayOff doesn't make a lot of sense.