5
$\begingroup$

I've got a code where I have a motor running back and forth and buttons connected to a scanner, when I press the buttons it causes the motor to stop and over rides it. I would like them to run parallel to each other so the codes don't interrupt each other.

Here is my code

#include <AccelStepper.h>

// Define some steppers and the pins they will use

AccelStepper stepper1(AccelStepper::FULL2WIRE, 2, 3);

const int buttonPin = 4;
const int button2Pin = 14;
const int pulseopto1 = 9;
const int startScan = 11;

int buttonState = 0;
long previousMillis = 0;
long interval = 5;

void setup()
{
    pinMode(buttonPin, INPUT);
    pinMode(button2Pin, INPUT);
    pinMode(pulseopto1, OUTPUT);
    pinMode(startScan, OUTPUT); 
    stepper1.setMaxSpeed(40000.0);
    stepper1.setAcceleration(100000.0);
    stepper1.moveTo(25000);
}

void loop()
{
    buttonState = digitalRead(buttonPin);

    if (buttonState == LOW)
    {
        digitalWrite(startScan, HIGH);
    }
    else (buttonState == HIGH);
    {
        digitalWrite(startScan, LOW);
    }

    {
        buttonState = digitalRead(button2Pin);

        if (buttonState == LOW)
        {
            // turn LED on:
            digitalWrite(pulseopto1, HIGH);
            delay(5);
            digitalWrite(pulseopto1, LOW);
            delay(5);
        }
        else
        {
            // turn LED off:
            digitalWrite(pulseopto1, LOW);
        }
    }

    // Change direction at the limits
    if (stepper1.distanceToGo() == 0)
    {
        stepper1.moveTo(-stepper1.currentPosition());
    }

    stepper1.run();
}
$\endgroup$
4
  • $\begingroup$ What is the granularity of delay? Could it be that your delays are making the motor stop? $\endgroup$ – Shahbaz Nov 6 '13 at 14:21
  • $\begingroup$ I think the delays override the motor running, since when I push the button the motor stops, but I don't know how to solve it. $\endgroup$ – hollander Nov 6 '13 at 15:13
  • $\begingroup$ You would need a timer to keep track of time (or maybe there are already functions that give the "current time" in Arduino?) and a state machine to keep track of state. So what happens is that in your loop, upon button press, you go to for example WAIT_STATE_1 and set start time to current time, next time in the loop, you check if enough time has passed. If so, you go next state which writes tp pulseopto1 and gotes to WAIT_STATE_2 for example again setting start time to current time. Later again in the loop function, you check if enough time has passed to enter the next state (END_STATE) $\endgroup$ – Shahbaz Nov 6 '13 at 15:23
  • $\begingroup$ The classic way for an Arduino to "do two things at once" is described as "Blink Without Delay". $\endgroup$ – David Cary Nov 7 '13 at 1:06
6
$\begingroup$

The short answer is yes, but the long answer is that you're approaching the code the wrong way and will need to rewrite things a bit.

It looks like you're attempting to read a button and have it flash some LEDs while at the same time having your stepper move back and forth. The problem is your delay(5); commands, which pause the execution of your code.

Instead, you'll have to make use of the millis(); function to read the current time at each iteration through the loop. Both the stepper movement and the LED flashes are functions of time, so just write those functions and set them on every iteration.

long stepperPosition(long t)
{
    // YOUR CODE GOES HERE, like a sine or triangular waveform
    // it might also depend on stepper1.distanceToGo() == 0
    return sine(t * TIME_SCALE_FACTOR) * MAGNITUDE;
}

bool ledState(long t)
{
    // return HIGH if we're in the first "interval" millis after pressing
    // after that, return LOW to turn off the LED
    return (t < buttonPressTime + interval) ? HIGH : LOW;
}

void loop()
{
    long now = millis();

    // set the LED directly from the button state
    digitalWrite(startScan, LOW == digitalRead(buttonPin));

    // record the time of the button press for use in our function
    if (digitalRead(button2Pin) == LOW) {
        buttonPressTime = now;
    }

    // set LED based on time function
    digitalWrite(pulseopto1, ledState(now));

    // set stepper based on time function
    stepper1.moveTo(stepperPosition(now));
    stepper1.run();
}

In this code, both the LED and stepper are controlled "in parallel" -- they are both set during each iteration, with no conditional delays.

$\endgroup$
2
$\begingroup$

I think you should look into the Arduino's attachInterrupt function. You would connect the buttons to a specific interrupt pin on the Arduino and then write a small simple interrupt handler that would be called when that interrupt fires. You can configure the interrupt to fire while low, on a rising edge, on a falling edge, or on a change of the interrupt pin. This way you don't have to poll your buttons, and it will make your main loop cleaner/easier to write.

Here's the arduino webpage for attachInterrupt(): http://arduino.cc/en/Reference/attachInterrupt

edit: You should also comment your code so we know what you are trying to do, and possibly give us a description of your hardware setup (what are pins of Arduino actually connected to).

Given the syntax error that TheRussian pointed out, I don't understand how this code compiles.

$\endgroup$
2
$\begingroup$

It looks like the reason (one of) why the motor stops is due to the following code:-

if (buttonState == LOW)
    {
        digitalWrite(startScan, HIGH);
    }
    else (buttonState == HIGH); --> this is a statement due to the semicolon.
    {
        digitalWrite(startScan, LOW); --> this statement will get executed even when buttonState is LOW.
    }

CHange this to the following and check.

if (buttonState == LOW)
    {
        digitalWrite(startScan, HIGH);
    }
    else if (buttonState == HIGH)
    {
        digitalWrite(startScan, LOW);
    }

Try splitting the 2 activities using a task scheduler. My $0.02.

$\endgroup$
1
$\begingroup$

What do you mean by override? Does the motor stop or does it start turning in the wrong direction?

There is something weird going on with the brackets in the loop() function

if (buttonState == LOW)
{
    digitalWrite(startScan, HIGH);
}
else (buttonState == HIGH);  //This shouldn't be here. Just use else
{
    digitalWrite(startScan, LOW); 
}

I'm not sure, but I don't think you need to call stepper1.run() in the loop function. Try placing it at the end of the setup() function instead.

$\endgroup$
1
  • $\begingroup$ The motor stops while I press the button for the blink function. $\endgroup$ – hollander Nov 6 '13 at 15:05
0
$\begingroup$

I have been looking for the same thing and I messed around in the IDLE and found has you put a space next to the first code or the code that you want to do two actions with and type the code.

Example:

Void loop 
{
  Serial.print("Hello"); 
  Serial.print("World"); 
}

And put the semi-colons where I place it on the code.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.