Motor Pwm2

Embed Size (px)

Citation preview

  • 7/31/2019 Motor Pwm2

    1/18

  • 7/31/2019 Motor Pwm2

    2/18

  • 7/31/2019 Motor Pwm2

    3/18

    Figure 2: Pulse Width Modulation with Time-Varying Duty (D) Cycles in a pulse train

    Some very simple - self explaining - math behindFormula

    = fP

    frequencyPeriod

    = + titp

    time period impulsetime period pause

    = D pulse-duty factor = =

    = +

    g grade of pulse-duty

    This very efficient technique employs pulses which are width modulated to generate the

    current through the coil of a motor. A 50% D (duty cycle) results in a perfect square wave

    (see below - Figure 3).

    Figure 3: PWM Duty Cycles

    http://dict.leo.org/ende?lp=ende&p=thMx..&search=pulse-dutyhttp://dict.leo.org/ende?lp=ende&p=thMx..&search=pulse-dutyhttp://dict.leo.org/ende?lp=ende&p=thMx..&search=pulse-dutyhttp://dict.leo.org/ende?lp=ende&p=thMx..&search=factorhttp://dict.leo.org/ende?lp=ende&p=thMx..&search=factorhttp://dict.leo.org/ende?lp=ende&p=thMx..&search=pulse-duty
  • 7/31/2019 Motor Pwm2

    4/18

    = 1 ()

    0

    If the duty cycle is 25% the power reaching the driven device is nearly as high, too. If you

    drive a 12 Volt DC motor it is the same as if you drive 3 Volts (at 25% duty cycle). At 50% itslike 6 V effective, at 75% its 9 V effective and at 100% are (nearly) the full 12 Volts present.PWM Effective Voltage

    Figure 4: Relationship between duty cycles and effective voltage reaching of the driven

    device.

    Motor speed response to this signal shall be a continuous and monotonic function of the dutycycle of the signal, from 100% to the minimum RPM. The motor RPM (as a percentage ofmaximum RPM) should match the PWM duty cycle within 5%. The undetermined zonewhere a PWM signal is present while the motor isnt turning has to be found throughexperiments. It depends on the implemented motor or motor type, if it is gearless or not andon the retention force working against the power produced through the cyclic PWM signal.Speed versus PWM duty cycles

  • 7/31/2019 Motor Pwm2

    5/18

    Figure 5: Schematically relationship between RPM and PWM.

    H-Bridge theoryH-Bridge The H-Bridge is a very simple device. As you

    can see in the schematic all you need tobuild one, are four switches. This is possible

    with relays, too but the current that canflow in such a relay application is not sohigh. A typical relay can drive approximatelyabout 1-5 Amps depending on the type -and is pretty voluminous. Power MOSFETslike the once used in the H-Bridge designshown later, are much better for high currentapplications and also smaller. Currentsabove 5 Amps are possible and we can drivepretty nice and powerful motors with orwithout gears, too. These motors can bebuilt in robots for motion control or into

    crawler vehicles. If the H-Bridge is designedwith SMDs (Surface Mounted Devices) thewhole bridge will be very small and can bebuild in devices with few space left.

    Figure 6: H-Bridge Function System

    An illegal state in a full quadrant H-bridge is one that turns on the upper source and lowersink on the same side (see Figure 7). This combination causes a direct short circuit to becreated between the battery terminals or power source and usually causes one or both of thetransistors that are on to go up in smoke. The current has only to flow through the motor (seeFigure 8). The H-Bridge design (with friendly permission of Mr. Chuck McManis) shown and

    used in this article is avoiding this situation and the software cant produce such an illegalstate. Turning the motor motion from clockwise to counter-clockwise or vice versa can lead tothis not recommended state, too but only for the very short time the transistor is switching.

    http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html
  • 7/31/2019 Motor Pwm2

    6/18

    So please be aware of this, if you are changing the H-Bridge design to use other Transistorsor POWER MOSFETs. First take a look into the design specifications of your Transistor orFET of choice underneath the switching behavior chapter for the falling and rising edges. The.NET Micro Framework is not very fast in execution of the code for the moment so problemsare not expected here for now. But if the hardware gets more performant the code executiontime and the transistor switching time will go down. Then maybe the source code has to bechanged and some short wait states are necessary. So be aware of that, if you are using thiscode on faster hardware or if you are writing an own PWM driver.

    Illegal state left Illegal state right

    Figure 7: Not recommended shorting the power source - producing a very high current

    In Figure 8 you can see, how the rotation can be changed from clockwise to counter-clockwise or vice versa. All we need now for controlling the motion and speed of the motor isthe PWM signal switching on and off.Rotation clockwise Rotation counter-clockwise

    Figure 8: Working H-Bridge

  • 7/31/2019 Motor Pwm2

    7/18

    Figure 9 shows how the whole stuff is working together: The .NET Micro Framework system,the H-Bridge and the motor - wired up like shown below.Arrange all together

    Figure 9: Block schematic of the whole system

    What kind of signals do we need to control the motor in speed and motion? Forward (FWD)and Reverse (REV) are necessary for rotation control. Sending a high signal to FWD and alow signal to REV the motor isnt rotating. Even when the PWM signal is sent out to ENA the

    motor is going to rotate clockwise. The duty cycle of the pulse is equivalent to the motorspeed.

    Figure 10: Clockwise motion

    A low signal at FWD and a high signal at REV in conjunction with a PWM signal at ENA willforce the motor to spin counter-clockwise.

  • 7/31/2019 Motor Pwm2

    8/18

    Figure 11: Counter-clockwise motion

    With the PWM signal (ENA*) the speed of rotation (RPM: Rotations per Minute) can becontrolled. The pulse width duty cycles are equivalent to the percentage of the voltagereaching the DC motor like explained before.

    The real H-BridgeIf you buy the parts in quantities of 1, all parts together cost less than 10 Euros (excluding

    shipping and the DC motor of course) for a 1 to nearly about 8 Ampere capable H-bridge.This keeps the final circuit "cheap". The complete schematic for the bridge is shown below

    (Figure 12). I want to give kudos to the great work done by Mr. Chuck McManis for his

    brilliant H-Bridge design. You can read more about this very easy to build bridge on his

    wonderful home page:http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html

    http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html
  • 7/31/2019 Motor Pwm2

    9/18

    Figure 12: H-Bridge schematic (with friendly permission ofMr. Chuck McManis)

    The fast recovery diodes (shown in light blue) are optional when you are using the

    TIP102/107 as those transistors have a diode assembled. However you can include them for

    greater protection at higher currents. If size is an issue, you'll rather go with surface mounted

    devices than this type of circuits.

    Qty Description

    2 TIP107, PNP Power Darlington Transistor (TO-220AB)

    2 TIP102, NPN Power Darlington Transistor (TO-220AB)

    4 10K Ohm, Resistors

    4 470 Ohm, Resistors

    4 1K Ohm, Resistors

    4 Opto-coupler CNY17 III

    4 1N4936, 1A Fast Recovery Rectifier (Optional if included in the transistor or FET)

    Table 1) Parts List for the Simple H-Bridge

    You can notice that the opto-isolator LEDs are connected to the three previous describedwires labeled "FWD" (forward), "REV" (reverse), and "ENA* (enable all)." These wiresdeserve a little bit more detailed explanation and notice.

    Now the Interfacing in detailThe FWD, REV, and ENA* lines are the interface between the bridge and the .NET MicroFramework controller. You will notice there is no "ground" signal. When you connect these

    pins, combinations of 1's and 0's on the line turn on different pairs of transistors. Thefollowing table lists all possible combinations of input.

    http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html
  • 7/31/2019 Motor Pwm2

    10/18

    FWD REV ENA* Description

    1 0 0 Turn on upper left source and lower right sink. (go forward)

    1 0 1 Disable lower right sink. When fed a PWM signal the bridgemodulates the "forward" current through the motor.

    1 1 0 Turn on both lower left sink and lower right sink, shorting the motor.This causes a rotating motor to stop rotating so this mode is called"Braking."

    1 1 1 Disable both lower sinks. When fed a PWM signal the bridgemodulates the "braking" of the motor.

    0 1 0 Turn on the upper right source and lower left sink. (go backward)

    0 1 1 Disable lower left sink. When fed a PWM signal the bridge modulatesthe "reverse" current through the motor.

    0 0 0 Turn off all sources and sinks. "Coast" motor is not engaged at all.

    0 0 1 Turn off all sources and sinks in a different way, same effect though.

    Table 2) Interfacing the H-Bridge (with friendly permission ofMr. Chuck McManis)

    This works because the processor pins become a connection to ground when they areoutputting logic 0. When FWD is 1 and ENA is 0, the lower right sink is getting current fromFWD which it is returning through the pin connected to ENA. At any given time the pin mustbe able to supply enough current to turn on two LEDs and when set to zero sink the currentof two LEDs. With the 470 ohm resistors and a 3.3V processor like the GHI EmbeddedMaster offers this is not a problem. From the data sheet on the opto-isolator, each LED has aforward voltage drop of 1.2V, so (3.3 - 1.2) / 330 is 6.4mA per LED or 12.8mA of load total.The selected GHI pin is specified to be able to drive 20mA. You can further replace the 330ohm resistors with 470 ohm resistors to reduce the current through the LEDs. However the

    LED voltage drop can be as high as 1.4V and the GHI controller operating voltage can be aslow as 3.0V, in that condition with 470 ohm resistors you would only put 3.4mA into eachLED which is below the 5mA specified in the datasheet. The 470 ohm resistor is the betterchoice as it maintains a sufficient broad margin.

    The interface as designed gives you access to all of the interesting combinations of sinksand sources enable, while not allowed for any "illegal" state (see Figure 7 above). Thehuman ear can hear frequencies up to roughly 20 kHz. When using PWM at frequenciesbelow this, the device being driven can often be heard as a buzz. Higher frequencies avoidthis but your cat or dog will probably leave the room, even if you cannot hear the frequency.

    Implementation with the GHI Electronics BoardThe .NET Micro Framework HardwareThe schematic of the microcontroller is integrated on the GHI Embedded Master board. Theblue marked part is the supplement for the GHI Embedded Master TFT version board. Forthe here described example the NON TFT version board was used (Figure 1). The module issoldered onto the development board and placed underneath the display. The TFT versionoffers three more PWM pins.

    http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html
  • 7/31/2019 Motor Pwm2

    11/18

    Figure 13: GHI Embedded Master schematic (courtesy of GHI)

    The Port PinsTwo (5 with the TFT version) PWM pins are exposed with native PWM function support.

    Embedded Master PWM pins are clocked by two separate timers (0 and 1). Thus, PWM lineswith the same clock can have different pulse widths, but the user must be aware thatchanging one clock will affect the other PWM channel with the same clock source on the TFTversion.

    PIN# Name Description16 PWM0.0 PWM 0 ( PWM Timer 0 )17 PWM1.1 PWM 1 ( PWM Timer 1 )35 TFT Version Only PWM1.4 PWM 4 ( PWM Timer 1 )39 TFT Version Only PWM1.3 PWM 3 ( PWM Timer 1 )40 TFT Version Only PWM0.2 PWM 2 ( PWM Timer 0 )

    Table 3) GHI Embedded Master PWM pins (white: Non TFT, all pins on TFT module)

    The user would first initialize the needed PWM channel and then set the desired frequencyand duty cycle which can be set to different values at anytime later. The Duty Cycle value isa percentage of the total period. Valid values are 0% to 100%, inclusive. Frequency can beset to 0 to disable the PWM module. Other values less or equal toPWM.MAX_FREQUENCYare also valid. Currently, the maximum value for the GHI Embedded Master is set to 10MHZ.

    Reference GHIElectronics NamespaceGHIElectronics.Hardware.PWM

    Example// Initialize PWM 1 channel (PWM1.1 pin 17 see table 3 above)PWM pwmChannel1 = new PWM(PWM.PWMChannel.Channel_1);

  • 7/31/2019 Motor Pwm2

    12/18

    // Set Frequency to 50 kHz and duty cycle to 50%pwmChannel1.Set(50000, 50);

    PWM/MISC Header

    Figure 14: The header for PWM (blue: PWM/MISC)

    PWM/MISC HeaderPWM and other miscellaneous pins are available on this header (Figure 14). An LED

    is connected to PWM0 for a quick test of the PWM functionality, too. Its changing theintensity if the motor speed is going higher or lower.Header Pin # Function Pin Connected to H-Bridge1 E13/P3.16/PWM0 (PWM Timer 0) ENA*2 E14/P3.24/PWM1 (PWM Timer 1) -3 E16/P1.19/USB_PWR_EN FWD4 E19/P1.27/USB_OC# REV5 GND -

    Table 4) the pins used for the interface are rendered in red

  • 7/31/2019 Motor Pwm2

    13/18

    Figure 15: Wiring up the H-Bridge

    Figure 16: Board + H-Bridge

    The Code for the PWM Motor Class File// change this - if you are using other hardware#define GHIElectronics

    using System;using System.Threading;

    using Microsoft.SPOT;using Microsoft.SPOT.Input;using Microsoft.SPOT.Hardware;

    //Change this namespaces - if you are using other hardware#if GHIElectronicsusing GHIElectronics.Hardware;using GHIElectronics.System;

    #else// other Namespaces#endif

    namespace SENET.Hardware.Motor{

    classMotor : IDisposable{

    #region speed enums - PWM negative logic for duty cycles// negative logicpublicenumSpeed : int{

    Maximum = 0,Fast = 0,Percent_100 = 0,Percent_95 = 5,Percent_90 = 10,Percent_85 = 15,Percent_80 = 20,Percent_75 = 25,Percent_70 = 30,

  • 7/31/2019 Motor Pwm2

    14/18

    Percent_65 = 35,Percent_60 = 40,Percent_55 = 45,Half = 50,Percent_50 = 50,Percent_45 = 55,Percent_40 = 60,Percent_35 = 65,

    Percent_30 = 70,Percent_25 = 75,Percent_20 = 80,Percent_15 = 85,Percent_10 = 90,Percent_5 = 95,Stopped = 100,None = 100

    }#endregion

    #region motor direction and PWM frequency enumspublicenumDirection : int { None, Left, Right, Break};publicenumFrequency : int {

    None = 0,kHz_20 = 20000,

    kHz_25 = 25000,kHz_30 = 30000,kHz_50 = 50000

    };#endregion

    #region initialization// moving statesprivateDirection direction = Direction.None;

    // motor PWM parameterprivateint duty = (int)Speed.None;privatePWM pwm = null;privateFrequency fequency = Frequency.kHz_50;privatePWM.PWMChannel pwmChannel = PWM.PWMChannel.Channel_0;

    //stearing ports for motor movement into

    //clockwise or counter-clockwise spin directionprivateOutputPort moveLeft;privateOutputPort moveRight;#endregion

    #region constructors for motor PWM////// Initialization of the PWM stuff to stear a DC motor//////PWM Port Channelpublic Motor(PWM.PWMChannel PWMPort){

    // channel usedthis.pwmChannel = PWMPort;

    // preset port pins - change this if another hardware is used

    // false means: pin is not high!this.moveLeft = newOutputPort(EmbeddedMaster.Pins.E16, false);

    // false means: pin is not high!this.moveRight = newOutputPort(EmbeddedMaster.Pins.E19x, false);

    // the motor is current lessthis.duty = (int)Speed.None;

    // set PWM freq. to 50 kHzthis.fequency = Frequency.kHz_50;

    StartMotorPWM();

    System.Threading.Timer timer = new System.Threading.Timer(newTimerCallback(OnTimer),null, 0, 200);

    }

    ////// Initialization of the PWM stuff to stear a DC motor.

  • 7/31/2019 Motor Pwm2

    15/18

    /// Use this ctr if other pins for stearing the moting are wished//////PWM port channel///Port pin for clokwise motion///Port pin for anti-clockwise motionpublic Motor(PWM.PWMChannel PWMPort,

    Cpu.Pin RightPin,Cpu.Pin LeftPin)

    : this(PWMPort){

    // false means: pin is not high! No signal to the pin no movementthis.moveLeft = newOutputPort(LeftPin, false);

    // false means: pin is not high!No signal to the pin no movementthis.moveRight = newOutputPort(RightPin, false);

    }

    ////// Initialization of the PWM stuff to stear a DC motor./// Use this ctr if all possibilities have to be set for/// stearing a motor and it's behaviour//////PWM port channel///Port pin for clokwise motion

    ///Port pin for anti-clokwise motion///PWM frequency - use something above 20 kHz///PWM duty cyclepublic Motor(PWM.PWMChannel PWMPort,

    Cpu.Pin RightPin,Cpu.Pin LeftPin,Motor.Frequency Frequency,int dutyState): this(PWMPort, RightPin, LeftPin)

    {this.duty = dutyState;this.fequency = Frequency;

    }#endregion

    #region private methodsprivatevoid StartMotorPWM()

    {SystemManager.Start(null);

    this.pwm = this.pwm ?? newPWM(pwmChannel);this.pwm.Set((int)this.fequency, this.duty);

    }

    privatevoid StopMotorPWM(){

    this.Dispose();SystemManager.Shutdown();

    }

    ////// direction of motor movement///

    ///direction of movementprivateint Velocity(int Speed){

    if ((Speed >= 0) && (Speed

  • 7/31/2019 Motor Pwm2

    16/18

    caseDirection.Left:this.moveLeft.Write(true);this.moveRight.Write(false);

    break;

    caseDirection.Break:this.moveRight.Write(true);this.moveLeft.Write(true);

    break;

    caseDirection.None:this.moveLeft.Write(false);this.moveRight.Write(false);

    break;

    default:this.moveLeft.Write(false);this.moveRight.Write(false);

    break;}

    }#endregion

    #region motor properties

    ////// get/set the direction of motor movement//////clockwise or anti-clockwisepublicDirection Move{

    get { returnthis.direction; }set { this.direction = value; }

    }

    ////// set/get the motor motion speed//////the duty cycle is equivalent to the motor speedpublicint MovingSpeed{

    get { returnthis.duty; }

    set { Velocity(value); }}#endregion

    #region IDisposable Memberspublicvoid Dispose(){

    // Dispose PWMStopMotorPWM();

    }#endregion

    }}

    The Test ImplementationpublicWindow CreateWindow(){

    // Connect the button handler to all of the buttons.mainWindow.AddHandler(Buttons.ButtonDownEvent,

    newButtonEventHandler(this.OnButtonDown),false);

    // start the PWM testthis.StartMotor();

    return mainWindow;}

    privatevoid StartMotor(){

  • 7/31/2019 Motor Pwm2

    17/18

    this.motor = newMotor(PWM.PWMChannel.Channel_0);this.motor.MovingSpeed = (int)Motor.Speed.None;

    }

    privatevoid OnExit(){

    // do shut down here...this.motor.Dispose();

    }

    privatevoid OnButtonDown(object sender, ButtonEventArgs e){

    // Print the button code to the Visual Studio output window.Debug.Print(e.Button.ToString());

    switch (e.Button){

    caseButton.VK_UP:if (this.motor.MovingSpeed > (int)Motor.Speed.Maximum)

    this.motor.MovingSpeed -= 5;else

    this.motor.MovingSpeed = (int)Motor.Speed.Maximum;break;

    caseButton.VK_DOWN:

    if (this.motor.MovingSpeed < (int)Motor.Speed.Stopped)this.motor.MovingSpeed += 5;else

    this.motor.MovingSpeed = (int)Motor.Speed.Stopped;break;

    caseButton.VK_LEFT:this.motor.Move = Motor.Direction.Left;break;

    caseButton.VK_RIGHT:this.motor.Move = Motor.Direction.Right;break;

    caseButton.VK_MENU:this.motor.Move = Motor.Direction.Break;break;

    caseButton.VK_BACK:this.motor.Move = Motor.Direction.Break;break;

    caseButton.VK_SELECT:this.motor.Move = Motor.Direction.None;break;

    default:this.motor.Move = Motor.Direction.None;break;

    }}

    Whats next?- Motor driver designed with the integrated circuit LM298.- A Power Supply steering the output voltage over PWM.- A poor mans DAC with PWM.

    Revision HistoryRevision Description Date0.5 Initial Release - Internally 2009.23.April0.8 Internal Release 2009.24.April0.9 After Revision 2009.04.Mai1.0 Initial Public Release 2009.10.Mai

    Sources:(1) A Basic Step by Step Guide for .NET Micro Framework Application Development on the iPac 9302 (By Sean Liming &

    John R. Malin - SJJ Embedded Micro Solutions, LLC)

    (2) Embedded Master User Manual; Rev. 2.03 Date: March 23, 2009(3) Embedded Master User Manual; Rev. 2.04 Date: April 29, 2009

    (4) Device solutions.net (http://devicesolutions.net/default.aspx?id=116)

    (5) Expert .NET Micro Framework book by Apress written by Jens Khner (ISBN-13: 978-1-59059-973-0)

    http://devicesolutions.net/default.aspx?id=116http://devicesolutions.net/default.aspx?id=116http://devicesolutions.net/default.aspx?id=116http://devicesolutions.net/default.aspx?id=116
  • 7/31/2019 Motor Pwm2

    18/18

    (6) The really great home page of Mr. McManis (http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html)

    (7) Wikipedia, the free encyclopedia (http://en.wikipedia.org/wiki/H-bridge)

    (8) http://www.discovercircuits.com/H/hbridge.htm

    (9) http://electronicdesign.com/Articles/Index.cfm?AD=1&ArticleID=6199

    (10) http://www.4qdtec.com/bridge.html

    (11) http://bansky.net/blog/2008/07/dc-motor-driver-and-power-supply-board/

    http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.htmlhttp://en.wikipedia.org/wiki/Wikipediahttp://en.wikipedia.org/wiki/Free_contenthttp://en.wikipedia.org/wiki/Encyclopediahttp://en.wikipedia.org/wiki/H-bridgehttp://en.wikipedia.org/wiki/H-bridgehttp://en.wikipedia.org/wiki/H-bridgehttp://www.discovercircuits.com/H/hbridge.htmhttp://www.discovercircuits.com/H/hbridge.htmhttp://electronicdesign.com/Articles/Index.cfm?AD=1&ArticleID=6199http://electronicdesign.com/Articles/Index.cfm?AD=1&ArticleID=6199http://www.4qdtec.com/bridge.htmlhttp://www.4qdtec.com/bridge.htmlhttp://www.4qdtec.com/bridge.htmlhttp://bansky.net/blog/2008/07/dc-motor-driver-and-power-supply-board/http://bansky.net/blog/2008/07/dc-motor-driver-and-power-supply-board/http://bansky.net/blog/2008/07/dc-motor-driver-and-power-supply-board/http://bansky.net/blog/2008/07/dc-motor-driver-and-power-supply-board/http://www.4qdtec.com/bridge.htmlhttp://electronicdesign.com/Articles/Index.cfm?AD=1&ArticleID=6199http://www.discovercircuits.com/H/hbridge.htmhttp://en.wikipedia.org/wiki/H-bridgehttp://en.wikipedia.org/wiki/Encyclopediahttp://en.wikipedia.org/wiki/Free_contenthttp://en.wikipedia.org/wiki/Wikipediahttp://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html