Activity Forums Tutorials DC motor control with doubled outputs

  • DC motor control with doubled outputs

     Lukas updated 3 years, 5 months ago 1 Member · 1 Post
  • Lukas

    Member
    September 4, 2020 at 4:06 pm

    CONTROLLINO MEGA offers 12 outputs driven by Half-bridges. These outputs may be used to run the DC motor directly. As all these outputs also support PWM, the speed of the motor can be controlled by standard Arduino function AnalogWrite.

    But – what if the maximum current defined for one CONTROLLINO output is not enough? Then one wants to drive the motor from two interconnected outputs. This solution is possible from electrical side, but cannot be controlled by AnalogWrite from software side. It is necessary to use outputs which are connected to the same micrcontroller port to be able to control them really synchronously.

    I have used TimerThree library to run the Timer3 to have interrupt once per 100 microseconds. All the rest is done in the interrupt service routine.

    Please see my code below. Plus some photos and ocsilloscope pictures (pictures were taken when the D6 and D7 outputs were not interconnected – just to see if they are really synchronous).

    The speed can be simply controlled from Serial Monitor (-20 … 0 .. 20).

    Enjoy!

    Lukas

    #include <TimerThree.h>

    #include <Controllino.h> /* Usage of CONTROLLINO library allows you to use CONTROLLINO_xx aliases in your sketch. */

    /*

    CONTROLLINO - DC motor control MAXI, Version 01P01

    The sketch is relevant only for CONTROLLINO variant MAXI!

    Please, see https://www.arduino.cc/en/Reference/PortManipulation for some theoretical background.

    IMPORTANT INFORMATION!

    Please, select proper target board in Tools->Board->Controllino MAXI before Upload to your CONTROLLINO.

    (Please, refer to https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library if you do not see the CONTROLLINOs in the Arduino IDE menu Tools->Board.)

    https://controllino.biz/

    (Check https://github.com/CONTROLLINO-PLC/CONTROLLINO_Library for the latest CONTROLLINO related software stuff.)

    */

    volatile int gTargetSpeed = 0; /* may be set from 0 = stop, to 20 = full speed */

    volatile int gCurrentSpeed = 0;

    volatile int gTargetDirection = 0; /* may be set to 0 or 1 */

    volatile int gCurrentDirection = 0;

    String readString;

    void setup() {

    /* DC motor is connect to 4 digital outputs.

    To be able to source more current each pole is connected to two CONTROLLINO outputs D4 with D5 to (+) and D6 with D7 to (-) */

    /* Please note that there must be used Half-Bridge outpus (D0 to D11) and all outputs must be at the same microcontroller port to

    keep precise timing. */

    PORTH = PORTH & B10000111; /* sets Digital Outputs in one shot to LOW Port H - pins 3,4,5,6 */

    DDRH = DDRH | B01111000; /* logical "1" (HIGH) in the "direction" register configures the appropriate pin as an output */

    /* configure Timer3 to generate interrupt */

    Timer3.initialize(100); /* period 100 microseconds - leads to frequency 10 kHz, with 20 speed steps we have PWM speed of 500 Hz */

    Timer3.attachInterrupt(pwmTickRoutine); /* attach interrupt service routine to this source of interrupts */

    Serial.begin(9600);

    }

    // the loop function runs over and over again forever

    void loop() {

    while (Serial.available()) {

    char c = Serial.read(); //gets one byte from serial buffer

    readString += c; //makes the String readString

    delay(2); //slow looping to allow buffer to fill with next character

    }

    if (readString.length() >0) {

    Serial.println(readString); //so you can see the captured String

    int n = readString.toInt(); //convert readString into a number

    int dir = 0;

    if (n < 0) {dir = 1;} else {dir = 0;}

    n = abs(n);

    if (n > 20) {n = 20;}

    /* Critical section - BEGIN */

    noInterrupts();

    /* gTargetSpeed and gDirection may be modified only inside the critical section */

    gTargetSpeed = n;

    gTargetDirection = dir;

    interrupts();

    /* Critical section - END */

    readString="";

    }

    }

    void pwmTickRoutine( void )

    {

    static int mPWMCounter = 0; /* counts permanently from 0 to 255 */

    mPWMCounter ++;

    if (mPWMCounter > 20)

    {

    mPWMCounter = 0;

    /* smoothly change the speed */

    if (gCurrentSpeed > gTargetSpeed) {gCurrentSpeed--;}

    if (gCurrentSpeed < gTargetSpeed) {gCurrentSpeed++;}

    if (gCurrentDirection != gTargetDirection)

    {

    /* switch off the power for both */

    PORTH = PORTH & B10000111; /* sets Digital Outputs in one shot to LOW */

    gCurrentDirection = gTargetDirection;

    }

    }

    if (mPWMCounter <= gCurrentSpeed && gCurrentSpeed != 0)

    {

    /* switch on the proper direction */

    if (gCurrentDirection == 0)

    {

    /* switch on one side */

    PORTH = PORTH | B01100000; /* sets Digital Outputs in one shot to HIGH */

    }

    else

    {

    PORTH = PORTH | B00011000; /* sets Digital Outputs in one shot to HIGH */

    }

    }

    else

    {

    /* switch off the power for the remaining part of the PWM pulse */

    PORTH = PORTH & B10000111; /* sets Digital Outputs in one shot to LOW */

    }

    return;

    }

    /* END OF THE SKETCH */


    [img]https://i.ibb.co/FWhhwkw/DS1-Z-Quick-Print5.png[/img] [img]https://i.ibb.co/VNz9BLY/DS1-Z-Quick-Print6.png[/img] [img]https://i.ibb.co/3YsnRXc/DS1-Z-Quick-Print7.png[/img] [img]https://i.ibb.co/XFr2jx1/IMG-20200904-174736.jpg[/img] [img]https://i.ibb.co/xY7NbZ5/IMG-20200904-174744.jpg[/img]

Viewing 1 of 1 replies

Log in to reply.

Original Post
0 of 0 posts June 2018
Now