In my last article, we utilized a Raspberry Pi running Windows IoT Core to bi-directionally control a single DC motor with the help of the L293D chip. In this article, we will take things a bit further and have the L293D chip control two motors placed on a chassis to create a Two Wheel Robot.
MaterialsWiring DetailsWiring Diagram L293D with Two Motors
L293D Pin Out Diagram from the Datasheet
- Cobbler 5v to the Breadboard Power Rail #1
- Cobbler GND to the Breadboard Ground Rail #1
- Breadboard Ground Rail #1 to the Opposite Breadboard Ground Rail #2
- L293D Pins 4,5,12,13 to Breadboard Ground Rail
- L293D Pin 16 (VCC1) to Breadboard Power Rail
- Cobbler Pin 21 to L293D Pin 1 (1,2EN)
- Cobbler Pin 20 to L293D Pin 2 (1A)
- Cobbler Pin 16 to L293D Pin 7 (2A)
- Cobbler Pin 24 to L293D Pin 9 (3,4EN)
- Cobbler Pin 25 to L293D Pin 10 (3A)
- Cobbler Pin 12 to L293D Pin 15 (4A)
- Battery Pack Positive (Red wire) to Breadboard Power Rail #2
- Battery Pack Ground (Black wire) to the Breadboard Ground Rail #2
- L293D Pin 8 (VCC2) to Breadboard Power Rail #2
- Motor 1 Wire (red or yellow) to L293D Pin 3 (1Y)
- Motor 1 Wire (black or green) to L293D Pin 6 (2Y)
- Motor 2 Wire (red or yellow) to L293D Pin 11 (3Y)
- Motor 2 Wire (black or green) to L293D Pin 15 (4Y)
Dual Motor Wiring
Assemble the robot chassis. It is possible that you will need to switch wires on the motor once testing starts (remember from the last article, that the motor wires are interchangeable and simply control the direction that the motor is turning). Using the Adafruit kit, here is what my robot looks like (ignore the wheel on the left, I didn’t realize it had fallen off the rim when I took the pictures):
Two Wheel Robot Chassis Assembled
I also used really long wires from my motors mounted on the robot to my breadboard in order to control the robot on the floor (continue to ignore the wheel on the left 😉 ):
Two Wheel Robot on the floor
Two Wheel Robot Control UI
Create a new Universal Windows Application, I’ve named mine PiDCMotorControl. Once the project has been generated, add a reference to Windows IoT Extensions for the UWP. Replace the UI listing of MainPage.xaml with the following:
XAML UI Definition:
<Page
x:Class="PiDCMotorControl.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PiDCMotorControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="200" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock FontSize="30" Grid.Row="1" Grid.ColumnSpan="3">Motor Control</TextBlock>
<Button Name="btnIgnitionOn" Margin="5" Background="Green" Foreground="White" Grid.Row="2"
Click="btnIgnitionOn_Click">Ignition ON</Button>
<Button Name="btnIgnitionOff" Margin="5" Background="Red" Foreground="White" IsEnabled="False"
Grid.Row="2" Grid.Column="1" Click="btnIgnitionOff_Click">Ignition Off</Button>
<Button Name="btnForward" Margin="5" Background="LightBlue" Foreground="DarkBlue" IsEnabled="False"
Grid.Row="3" Click="btnForward_Click">Forward</Button>
<Button Name="btnReverse" Margin="5" Background="Orange" Foreground="OrangeRed" IsEnabled="False"
Grid.Row="3" Grid.Column="1" Click="btnReverse_Click">Reverse</Button>
<Button Name="btnRight" Margin="5" Background="Orchid" Foreground="White" IsEnabled="False"
Grid.Row="4" Grid.Column="0" Click="btnRight_Click">Turn Right</Button>
<Button Name="btnLeft" Margin="5" Background="Goldenrod" Foreground="Green " IsEnabled="False"
Grid.Row="4" Grid.Column="1" Click="btnLeft_Click">Turn Left</Button>
<Button Name="btnStop" Click="btnStop_Click" Background="Salmon" Foreground="Sienna" IsEnabled="True"
Grid.Row="5" Margin="5">Stop</Button>
</Grid>
</Page>
Next, we will implement the communication from the UI to the Raspberry Pi. We will follow the guidance provided in the L293D datasheet:
DC Motor Control table from the Datasheet
Replace the code in MainPage.xaml.cs with the following:
UI Implementation File:
using Windows.Devices.Gpio;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace PiDCMotorControl
{
/// <summary>
/// Basic Bi-Directional Control of a Two Wheel Robot with DC Motors
/// </summary>
public sealed partial class MainPage : Page
{
private int _pinEn1_2 = 21;
private int _pin1A = 20;
private int _pin2A = 16;
private int _pinEn3_4 = 24;
private int _pin3A = 25;
private int _pin4A = 12;
private GpioController _controller;
private GpioPin _motorEnableMotorLeft;
private GpioPin _motorControl1AMotorLeft;
private GpioPin _motorControl2AMotorLeft;
private GpioPin _motorEnableMotorRight;
private GpioPin _motorControl3AMotorRight;
private GpioPin _motorControl4AMotorRight;
public MainPage()
{
this.InitializeComponent();
_controller = GpioController.GetDefault();
_motorEnableMotorLeft = _controller.OpenPin(_pinEn1_2);
_motorControl1AMotorLeft = _controller.OpenPin(_pin1A);
_motorControl2AMotorLeft = _controller.OpenPin(_pin2A);
_motorEnableMotorRight = _controller.OpenPin(_pinEn3_4);
_motorControl3AMotorRight = _controller.OpenPin(_pin3A);
_motorControl4AMotorRight = _controller.OpenPin(_pin4A);
_motorEnableMotorLeft.SetDriveMode(GpioPinDriveMode.Output);
_motorControl1AMotorLeft.SetDriveMode(GpioPinDriveMode.Output);
_motorControl2AMotorLeft.SetDriveMode(GpioPinDriveMode.Output);
_motorEnableMotorRight.SetDriveMode(GpioPinDriveMode.Output);
_motorControl3AMotorRight.SetDriveMode(GpioPinDriveMode.Output);
_motorControl4AMotorRight.SetDriveMode(GpioPinDriveMode.Output);
}
private void _turnOnIgnition()
{
_motorEnableMotorLeft.Write(GpioPinValue.High);
_motorEnableMotorRight.Write(GpioPinValue.High);
}
private void _forwardMotor()
{
_motorControl1AMotorLeft.Write(GpioPinValue.High);
_motorControl2AMotorLeft.Write(GpioPinValue.Low);
_motorControl3AMotorRight.Write(GpioPinValue.High);
_motorControl4AMotorRight.Write(GpioPinValue.Low);
}
private void _reverseMotor()
{
_motorControl1AMotorLeft.Write(GpioPinValue.Low);
_motorControl2AMotorLeft.Write(GpioPinValue.High);
_motorControl3AMotorRight.Write(GpioPinValue.Low);
_motorControl4AMotorRight.Write(GpioPinValue.High);
}
private void _turnRight()
{
//right reverse, left forward
_motorControl1AMotorLeft.Write(GpioPinValue.High);
_motorControl2AMotorLeft.Write(GpioPinValue.Low);
_motorControl3AMotorRight.Write(GpioPinValue.Low);
_motorControl4AMotorRight.Write(GpioPinValue.High);
}
private void _turnLeft()
{
//left reverse, right forward
_motorControl1AMotorLeft.Write(GpioPinValue.Low);
_motorControl2AMotorLeft.Write(GpioPinValue.High);
_motorControl3AMotorRight.Write(GpioPinValue.High);
_motorControl4AMotorRight.Write(GpioPinValue.Low);
}
private void _stopMotor()
{
_motorControl1AMotorLeft.Write(GpioPinValue.Low);
_motorControl2AMotorLeft.Write(GpioPinValue.Low);
_motorControl3AMotorRight.Write(GpioPinValue.Low);
_motorControl4AMotorRight.Write(GpioPinValue.Low);
}
private void _turnOffIgnition()
{
_motorEnableMotorLeft.Write(GpioPinValue.Low);
_motorControl1AMotorLeft.Write(GpioPinValue.Low);
_motorControl2AMotorLeft.Write(GpioPinValue.Low);
_motorEnableMotorRight.Write(GpioPinValue.Low);
_motorControl3AMotorRight.Write(GpioPinValue.Low);
_motorControl4AMotorRight.Write(GpioPinValue.Low);
}
private void btnIgnitionOn_Click(object sender, RoutedEventArgs e)
{
btnIgnitionOn.IsEnabled = false;
btnIgnitionOff.IsEnabled = true;
btnForward.IsEnabled = true;
btnReverse.IsEnabled = true;
btnRight.IsEnabled = true;
btnLeft.IsEnabled = true;
_turnOnIgnition();
}
private void btnIgnitionOff_Click(object sender, RoutedEventArgs e)
{
btnIgnitionOn.IsEnabled = true;
btnIgnitionOff.IsEnabled = false;
btnForward.IsEnabled = false;
btnReverse.IsEnabled = false;
btnRight.IsEnabled = false;
btnLeft.IsEnabled = false;
_turnOffIgnition();
}
private void btnForward_Click(object sender, RoutedEventArgs e)
{
btnForward.IsEnabled = false;
btnReverse.IsEnabled = true;
btnRight.IsEnabled = true;
btnLeft.IsEnabled = true;
_forwardMotor();
}
private void btnReverse_Click(object sender, RoutedEventArgs e)
{
btnReverse.IsEnabled = false;
btnForward.IsEnabled = true;
btnRight.IsEnabled = true;
btnLeft.IsEnabled = true;
_reverseMotor();
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
btnForward.IsEnabled = true;
btnReverse.IsEnabled = true;
btnRight.IsEnabled = true;
btnLeft.IsEnabled = true;
_stopMotor();
}
private void btnRight_Click(object sender, RoutedEventArgs e)
{
btnForward.IsEnabled = true;
btnReverse.IsEnabled = true;
btnRight.IsEnabled = false;
btnLeft.IsEnabled = true;
_turnRight();
}
private void btnLeft_Click(object sender, RoutedEventArgs e)
{
btnForward.IsEnabled = true;
btnReverse.IsEnabled = true;
btnRight.IsEnabled = true;
btnLeft.IsEnabled = false;
_turnLeft();
}
}
}
When you run this application you will be able to have the robot move forward and backward as well as spin clockwise and counter-clockwise. You may need to switch the wires that feed your motors to get them to react properly (this really only has to do with the way they are mounted on the chassis).
http://blog.falafel.com/tag/dc-motors/
Comments