Arduino Controlled 12V DC motor controls PWM issues

Larry, what program did you use to create that schematic? It seems to be more Arduino friendly. Right now I am using Multisim to make my schematics, but many components have to be custom made, I.E.: Multisim doesn’t have an Arduino UNO as a selectable component.

Thanks!

Here is the link to the MOSFET board, https://www.digikey.com/short/bw4c8t3z

The door switch was an after thought, and may not even be used. It was a limit switch I found and thought it may be interesting to include, since power cabinets to chairlifts often have limit switches on the door, faulting the lift when the door is open.(My day job until I am done school is currently as a chair lift mechanic)

I threw it in the schematics quickly, thinking the lack of ground would stop the motor, but I understand it was shotty.

I really like the idea of the led to be used for diagnostics, I may add one for when the stop button is in, as well as the door switch(if used). It would tell the operator why the lift wont start.

Thank you!

  • Schematic program I use isn’t available any more :frowning: .

  • It allows the users to easily design new components in a very short time.

  • Programs like KiCad and EasyEDA allow you to make your own components, such as Arduino UNO.




  • For motor control, all you need is a low side logic-level MOSFET switch.

  • Thought you might like to see an oscilloscope screen of the motor control PWM pin 9.
    At the opening, the Arduino is reset.
    The switch sequence was: START, FAST, SLOW, FAST, STOP.

  • The code for this YouTube video is attached below.
    If you have questions about the sketch, ask them.

//
//================================================^================================================
//                              M o d e l   S k i   C h a i r l i f t
//================================================^================================================
//
//  https://forum.arduino.cc/t/arduino-controlled-12v-dc-motor-controls-pwm-issues/1401388
//
//
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ========================================================================
//  1.00       25/08/09    Running code.
//  1.20       25/08/09
//  1.30       25/08/09
//  1.40       25/08/10
//
//
//  Notes:
//
//
//
//

//================================================
#define PRESSED               LOW   //N.O. switch goes to GND, pull ups are ON.
#define RELEASED              HIGH

#define ENABLED               LOW   //N.C. switch goes to GND, pull ups are ON.
#define DISABLED              HIGH

#define UP                    true
#define DOWN                  false

//Creates a timing pulse for oscilloscope measurements.
//Each additional asm("nop\n") adds 62.5ns to the pulse.
#define PULSE126D12        cli(); PINB = bit(PINB4); asm("nop\n"); PINB = bit(PINB4); sei()

//================================================
enum SystemState
{
  STATE_IDLE,
  STATE_SLOW,
  STATE_FAST,
  STATE_RAMPDOWN,
};

//Initialize with a starting state.
SystemState currentState     = STATE_IDLE;

//================================================
struct defineInput
{
  const byte pin;
  byte lastState;
};

defineInput StartSwitch      = {14, RELEASED};
defineInput SlowSwitch       = {15, RELEASED};
defineInput FastSwitch       = {16, RELEASED};

defineInput StopSwitch       = {17, ENABLED};

//================================================
const byte MOTORCONTROL      = 9;    //PWM output for motor.
const byte heartbeatLED      = 13;   //LED should toggle every 500ms.

const int pwmMax             = 255;  //Maximum PWM value.

bool directionFlag           = UP;

int brightnessLevel          = 0;

//================================================
//Timing stuff
unsigned long heartbeatTime;
unsigned long heartbeatInterval   = 500ul;   //milliseconds

unsigned long checkSwitchTime;
unsigned long switchInterval      = 50ul;    //milliseconds

unsigned long machineTime;
unsigned long machineInterval     = 1000ul;  //microseconds

unsigned long commonTime;
unsigned long commonInterval      = 10ul;    //milliseconds


//                                            s e t u p ( )
//================================================^================================================
//
void setup()
{
  //Pin initializations and other setup.
  pinMode(StopSwitch.pin,  INPUT_PULLUP);
  pinMode(StartSwitch.pin, INPUT_PULLUP);
  pinMode(FastSwitch.pin,  INPUT_PULLUP);
  pinMode(SlowSwitch.pin,  INPUT_PULLUP);

  digitalWrite(MOTORCONTROL, 0);
  pinMode(MOTORCONTROL, OUTPUT);

  //Gives us an idea if there is code blocking happening.
  pinMode(heartbeatLED, OUTPUT);

  //Used in oscilloscope timing execution of code.
  //pinMode(12, OUTPUT);

} // END of   setup()


//                                            l o o p ( )
//================================================^================================================
//
void loop()
{
  //loop() runs every 7.6us
  //
  //Generate an oscilloscope timing pulse.
  //PULSE126D12;

  //========================================================================  T I M E R  heartbeatLED
  //Is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatTime >= heartbeatInterval)
  {
    //Restart this TIMER.
    heartbeatTime = millis();

    //Toggle the heartbeat LED.
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //========================================================================  T I M E R  check switches
  //Is it time to scan our switches ?
  if (millis() - checkSwitchTime >= switchInterval)
  {
    //Restart this TIMER.
    checkSwitchTime = millis();

    //Check for switch change in state.
    checkSwitches();
  }

  //========================================================================  T I M E R  check machine
  //Is it time to check the State Machine ?
  if (micros() - machineTime >= machineInterval)
  {
    //Restart this TIMER.
    machineTime = micros();

    //Generate an oscilloscope timing pulse.
    //PULSE126D12;

    //Service the State Machine.
    checkMachine();

    //Generate an oscilloscope timing pulse.
    //PULSE126D12;
  }

  //================================================
  //     Other non-blocking code goes here
  //================================================

} // END of   loop()


//                                    c h e c k M a c h i n e ( )
//================================================^================================================
//
void checkMachine()
{
  //Service the current State in our State Machine.
  switch (currentState)
  {
    //========================
    case STATE_IDLE:
      {
        //We will go from 0 to SLOW speed.
        directionFlag = UP;

        //Start out with a brightness of zero.
        brightnessLevel = 0;

        analogWrite(MOTORCONTROL, brightnessLevel);
      }
      break;

    //========================
    case STATE_SLOW:
      {
        //Are we increasing speed ?
        if (directionFlag == UP)
        {
          //Has the common TIMER expired ?
          if (millis() - commonTime >= commonInterval)
          {
            //Restart this TIMER.
            commonTime = millis();

            //Update the PWM output.
            analogWrite(MOTORCONTROL, brightnessLevel);

            //Next PWM brightness level.
            brightnessLevel++;

            //Are we finished ? i.e. are we sitting at 1/2 brightness ?
            if (brightnessLevel > pwmMax / 2)
            {
              //Re-adjust.
              brightnessLevel = pwmMax / 2;
            }
          }
        }

        //Are we decreasing speed ?
        else if (directionFlag == DOWN)
        {
          //Has the common TIMER expired ?
          if (millis() - commonTime >= commonInterval)
          {
            //Restart this TIMER.
            commonTime = millis();

            //Update the PWM output.
            analogWrite(MOTORCONTROL, brightnessLevel);

            //Next PWM brightness level.
            brightnessLevel--;

            //Are we finished ? i.e. are we sitting at 1/2 brightness ?
            if (brightnessLevel < pwmMax / 2)
            {
              //Re-adjust.
              brightnessLevel = pwmMax / 2;
            }
          }
        }
      }
      break;

    //========================
    case STATE_FAST:
      {
        //Has the common TIMER expired ?
        if (millis() - commonTime >= commonInterval)
        {
          //Restart this TIMER.
          commonTime = millis();

          //Update the PWM output.
          analogWrite(MOTORCONTROL, brightnessLevel);

          //Next PWM brightness level.
          brightnessLevel++;

          //Are we finished ? i.e. are we sitting at full brightness ?
          if (brightnessLevel > pwmMax)
          {
            //Re-adjust.
            brightnessLevel = pwmMax;
          }
        }
      }
      break;

    //========================
    case STATE_RAMPDOWN:
      {
        //Ramp down motor.
        //
        //Has the common TIMER expired ?
        if (millis() - commonTime >= commonInterval)
        {
          //Restart this TIMER.
          commonTime = millis();

          //Update the PWM output.
          analogWrite(MOTORCONTROL, brightnessLevel);

          //Next PWM brightness level.
          brightnessLevel--;

          //Are we finished ? i.e. are we sitting at zero brightness ?
          if (brightnessLevel < 0)
          {
            //Re-adjust.
            brightnessLevel = 0;

            //Transition to IDLE.
            currentState = STATE_IDLE;
          }
        }
      }
      break;

  } //END of   switch/case

} //END of    checkMachine()


//                                   c h e c k S w i t c h e s ( )
//================================================^================================================
//
void checkSwitches()
{
  byte state;

  //========================================================================  StartSwitch
  state = digitalRead(StartSwitch.pin);

  //================================================
  //Has this switch changed state ?
  if (StartSwitch.lastState != state)
  {
    //Update to the new state.
    StartSwitch.lastState = state;

    //========================
    //Interlock with the STOP switch,
    //are we sitting in IDLE ?
    if (StopSwitch.lastState == ENABLED && currentState == STATE_IDLE)
    {
      //Was the switch pushed ?
      if (state == PRESSED)
      {
        //We will go from 0 to SLOW speed.
        directionFlag = UP;

        //Go to State SLOW.
        currentState = STATE_SLOW;

        //Reset the TIMER.
        commonTime = millis();
      }
    }

  } //END of this switch.

  //========================================================================  SlowSwitch
  state = digitalRead(SlowSwitch.pin);

  //================================================
  //Has this switch changed state ?
  if (SlowSwitch.lastState != state)
  {
    //Update to the new state.
    SlowSwitch.lastState = state;

    //========================
    //Interlock with the STOP switch,
    //are we sitting in FAST ?
    if (StopSwitch.lastState == ENABLED && currentState == STATE_FAST)
    {
      //Was the switch pushed ?
      if (state == PRESSED)
      {
        //We will go from FAST to SLOW speed.
        directionFlag = DOWN;

        //Go to State SLOW.
        currentState = STATE_SLOW;

        //Reset the TIMER.
        commonTime = millis();
      }
    }

  } //END of this switch.

  //========================================================================  FastSwitch
  state = digitalRead(FastSwitch.pin);

  //================================================
  //Has this switch changed state ?
  if (FastSwitch.lastState != state)
  {
    //Update to the new state.
    FastSwitch.lastState = state;

    //========================
    //Interlock with the STOP switch,
    //are we sitting in SLOW ?
    if (StopSwitch.lastState == ENABLED && currentState == STATE_SLOW)
    {
      //Was the switch pushed ?
      if (state == PRESSED)
      {
        //We will go from SLOW to FAST speed.
        directionFlag = UP;

        //Go to State FAST.
        currentState = STATE_FAST;

        //Restart the TIMER.
        commonTime = millis();
      }
    }

  } //END of this switch.

  //========================================================================  StopSwitch
  state = digitalRead(StopSwitch.pin);

  //================================================
  //Has this switch changed state ?
  if (StopSwitch.lastState != state)
  {
    //Update to the new state.
    StopSwitch.lastState = state;

    //========================
    //Are we sitting in SLOW or FAST ?
    if (currentState == STATE_SLOW || currentState == STATE_FAST)
    {
      //=============
      //Was the switch pushed/disabled ?
      if (state == DISABLED)
      {
        //Go to State RAMPDOWN.
        currentState = STATE_RAMPDOWN;

        //Restart the TIMER.
        commonTime = millis();
      }
    }

  } //END of this switch.


  //========================================================================  nextSwitch

} //END of   checkSwitches()



//================================================^================================================

The middle pin on the gravity connector is not conneced to anything so you don't need the 3.3V connection, which does not make sense anyway since the Uno I/O is 5V

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