Home > front end >  Running an event only once using the "Blink without delay" method in C/C
Running an event only once using the "Blink without delay" method in C/C

Time:09-30

I have an Arduino sketch that controls two different motors, a stepper motor, and a DC motor, using the Adafruit motor shield library. The main function of the sketch is to accept a string parameter on the serial input formatted as: (int motorId, int motorDirection, int motorSpeed, int degrees, int holdingTorque) and parse it into various parameters that control the behavior of the motor.

With the DC motor, I'd like it to run for a certain interval of time before it shuts off, which would translate into a specific amount of degrees moved. I am using the millis() function to check when the motor should be shut off without blocking further serial input. My problem is that I cannot figure out how to execute the command to shut off the motor only once, the if statement which checks if the delta in time is greater than the runinterval repeatedly keeps calling the function RAMOTOR->fullOff() every runinterval.

Iv'e tried using a boolean variable with an if/while wrapper around if (currentMillis - previousMillis > runinterval) to make this happen only once, however, the problem with that method is that if the variable is false then previousMillis never gets set to currentMillis.

Here is the entirety of my main loop:

unsigned long currentMillis = millis();
  if (Serial.available() > 0) {
    //Read char array input from serial monitor
    String input = Serial.readStringUntil('\n');
    /*Pass the string to the class member "ParseInput" of the parsemotorparameters object, which will
      retrieve the motor behavior parameters such as speed and steps to move and return a true boolean which sets the motor run state variable*/
    parsemotorparameters.ParseInput(input);
    //Set the runtime in seconds for the RA motor
    runinterval = parsemotorparameters.ReturnMotorRuntime(DEG_PER_SEC);
    /*If motor ID returned from "ParseInput" is 1, then run the RA motor for calculated period of time that translates to
      degrees moved*/
    if (parsemotorparameters.ReturnMotorId() == 1) {
      Serial.println(runinterval);
      //RAMOTOR->setSpeed(RASpeed);
      //RAMOTOR->run(parsemotorparameters.ReturnMotorDirection());
      CheckRAStatus = true;
    }
    else {
      //If the holding torque boolean variable is true, then apply power to the stepper motor continously even if the motor is not activley stepping
      if (parsemotorparameters.ReturnHoldingTorque()) {
        //Set the stepper motor speed
        //DECMOTOR->setSpeed(parsemotorparameters.ReturnMotorSpeed());
        /*Adafruit stepper motor class member accepts the following parameters
          step(uint8_t #steps, uint8_t direction 1 or 0, uint8_t step mode) */
        //DECMOTOR->step(parsemotorparameters.ReturnMotorSteps(), parsemotorparameters.ReturnMotorDirection(), MICROSTEP);
      }
      //If the holding torque boolean variable is false, then remove power from the stepper motor as soon as it's done moving
      else {
        //DECMOTOR->setSpeed(parsemotorparameters.ReturnMotorSpeed());
        //DECMOTOR->step(parsemotorparameters.ReturnMotorSteps(), parsemotorparameters.ReturnMotorDirection(), MICROSTEP);
        //DECMOTOR->release();
      }
    }
    debug();
  }
  if (currentMillis - previousMillis > runinterval) {
    previousMillis = currentMillis;
    //RAMOTOR->fullOff();
    Serial.println("OFF");
    CheckRAStatus = false;
  }

CodePudding user response:

Not sure what the problem is. You do need some boolean flag

bool raMotorOn = false;

Then you set it to true around RAMOTOR->run() call and modify your if

if (raMotorOn && (currentMillis - previousMillis > runinterval)) {
  raMotorOn = false;
  ...
}

CodePudding user response:

Not sure if I understood your problem statement and the code correctly, but you can use CheckRAStatus as a flag to guard against repetitive calling of fullOff().

if (CheckRAStatus && currentMillis - previousMillis > runinterval) {
    previousMillis = currentMillis;
    RAMOTOR->fullOff();
    Serial.println("OFF");
    CheckRAStatus = false;
}
  • Related