Help with calling a value for another function to use

I am working on a project that takes in a PWM signal produced from an RC receiver and I need to use the high/low value as if/else conditions to turn on/off a stepper motor. I currently have the code working to read and print the PWM signal (low-1000, high-2000) and have working code to control the stepper motor. I am having trouble meshing the two programs and need some help.

Below is my code for the PWM read. I am using AttachInterrupt which is supposed to allow me to perform other functions while reading the signal.

#define BUTTON_PIN 2

volatile unsigned long pulseInTimeBegin = micros();
volatile unsigned long pulseInTimeEnd = micros();
volatile bool newPulseDurationAvailable = false;

void buttonPinInterrupt()
{
  if (digitalRead(BUTTON_PIN) == HIGH) {
    // start measuring
    pulseInTimeBegin = micros();
  }
  else {
    // stop measuring
    pulseInTimeEnd = micros();
    newPulseDurationAvailable = true;
  }
}
void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN),
                  buttonPinInterrupt,
                  CHANGE);
}
void loop() {
  if (newPulseDurationAvailable) {
    newPulseDurationAvailable = false;
    unsigned long pulseDuration = pulseInTimeEnd - pulseInTimeBegin;
    Serial.println(pulseDuration);  
  }
}

Below is my stepper motor code.

#include <Stepper.h>

#define STEPS 2038

Stepper stepper(STEPS, 8, 10, 9, 11);


void step() {
  if (pulseDuration>1900){
  stepper.setSpeed(10);
  stepper.step(2038);
} else {
  stepper.setSpeed(0);
  stepper.step(2038);
}
}

My goal was to read the pulseDuration value that is being printed and use the value as the condition for an if/else statement. When I tried merging and putting anything else in the void loop() function, it froze and wouldn't keep reading. Any suggestions to what I can do?

Can you show the code that doesn't work.

Apologies should have added that.

#include <Stepper.h>

#define BUTTON_PIN 2
#define STEPS 2038

Stepper stepper(STEPS, 8, 10, 9, 11);

volatile unsigned long pulseInTimeBegin = micros();
volatile unsigned long pulseInTimeEnd = micros();
volatile bool newPulseDurationAvailable = false;
unsigned long pulseDuration;
void buttonPinInterrupt()
{
  if (digitalRead(BUTTON_PIN) == HIGH) {
    // start measuring
    pulseInTimeBegin = micros();
  }
  else {
    // stop measuring
    pulseInTimeEnd = micros();
    newPulseDurationAvailable = true;
  }
}
void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN),
                  buttonPinInterrupt,
                  CHANGE);
}
void loop() {
  if (newPulseDurationAvailable) {
    newPulseDurationAvailable = false;
    unsigned long pulseDuration = pulseInTimeEnd - pulseInTimeBegin;
    step();
    //Serial.println(pulseDuration);
    
  }
 // step(pulseDuration);
}

void step() {
  if (pulseDuration>1900){
  stepper.setSpeed(10);
  stepper.step(2038);
} else {
  stepper.setSpeed(0);
  stepper.step(2038);
}
}

I have tried calling the pulse() function within the loop() function, creating a global variable for pulseDuration, calling it within pulse(), and then running pulse within the loop(). Nothing I've done has worked. I also tried calling it in different location to no avail as well.

Currently you have pulseDuration declared twice.

Remove the 2nd one... just make it

pulseDuration = pulseInTimeEnd - pulseInTimeBegin;
1 Like

I removed the 2nd declaration as mentioned and uncommented the serial.println(pulseDuration) to see if it would work and update in the console but it still isn't working.

EDIT: I tried moving step() in different spots within loop() and it isn't updating. Below is a screenshot showing how the console reacts when it is commented out and I flip the RC switch. You can see the number is updating and changing. When trying to call step() the number isn't updating at all.

Screenshot 2022-08-25 001733

What if you comment out the contents of step{} and just replace with a print pulseDuration statement?

Seems like it is fine with that. So it seems that the if/else statements may be the issue with calling the stepper.setspeed and stepper.step

Screenshot 2022-08-25 002527

screenshot shows a test print, but when I used pulseDuration it would print that value and update with the switch change.

Have you tried the stepper statements by themselves?

As in to test if the statements work to turn on/off the stepper motor? I have a separate program using the same values and it starts/stops the motor if that is what you mean.

Maybe it cannot keep up with the pulses ?

Would adding in some delays help?

You realize the step() function is blocking right? In other words it does not return until all of the steps have been taken. At 10 RPM this function will block for 6 seconds since 2038 is a full rotation of your stepper. During that 6 seconds your code cannot do anything else.

Also, if this is an Arduino UNO (or any other 8-bit Arduino) then multibyte variables, such as pulseInTimeBegin and pulseInTimeEnd, should not be accessed in loop(), or any other non-interrupt code, unless interrupts are disabled. This is because the processor could be interrupted while you are reading or writing those variables. You can disable interrupts while you calculate pulseDuration or while you make copies of pulseInTimeBegin and pulseInTimeEnd.

The problem I was having was that it wasn't running anything within the step function when I added the stepper functions. Is there a way to make it non blocking so it can be constantly reading the pulseDuration value and be able to start/stop the stepper motor when the value changes?

EDIT: I am using an Arduino Nano if that makes a difference

Any suggestions to fix it? It seems like the stepper functions cause a blocking.

Any suggestions on making it non blocking?

You could use the AccelStepper Library. It doesn't block but the caveat is that you must call the runSpeed() method to poll the motor and step it if a step is due. You must call this as frequently as possible, but at least once per step interval. Which means you should NOT have any delay() calls in your code!

Thanks for the reply. Will test this later today when I get to my setup.

So how would I go about changing the speed value from say 500 to 0 to stop the motor? Since the setSpeed is in the setup, how am I able to change the value in the main loop?

void AccelStepper::setSpeed(float speed)

There was a link to the documentation in the link I provided.
http://www.airspayce.com/mikem/arduino/AccelStepper/

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.