Servo Motor

In this blog, I will be talking about what a servo motor is and how it operates.

A servo motor is an actuator that allows for high degree control of angles between 0 and 90 degree’s (depending on the “range” of the specific motor it could be greater), this is a level of control is achieved due to its design which can be explained in great detail the following video.

A servo motor as shown in the picture below is controlled by a length of a pulse generated from a microcontroller. 

PWM (Pulse Width Modulation) as I have mentioned in my previous blog can be used in many applications. In this scenario, we will be using PWM to control the angle of a servo motor. The minimum pulses being 0 and highest normally being 2 ms. In some servo motors the upper limit and angle will be greater than 180 degrees and 2 ms.

For my mini-project, I intend to make a simple bodyguard robot that has two arms and moves around on wheels. Since two arms are required I decided to use 2 servo motors per arm in a pan and tilt configuration.

with a bit of googling, I stumped upon this.

lynxmotion-pan-and-tilt-kit-aluminium2_2
CLICK ME!

So I decided to buy 2 sets of these arms and a dual bracket to hold them together to act as the torso of the robot. Using two the PWM channels on the DSPIC30F4011, the ADC, and a potentiometer. I used a code to see the limitations of the motors angles.
When the kit arrived, construction began.
img_3404

servomotordouble

// Written by Kevin Tighe
// Based on the code written by Ted Burke
//@batchloaf.wordpress.com or @roboted.wordpress.com
// Last updated 11/12/2016
//

#include <xc.h>
#include 			<libpic30.h>
#include <stdio.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, i.e. 30 MIPS
_FWDT(WDT_OFF); // Watchdog timer off
_FBORPOR(MCLR_DIS); // Disable reset pin

//definitions
#define Second 30000000 // 1 second

// Function prototypes
unsigned int read_analog_channel(int n);

int main()
{
int voltage = 0;
int voltage2 = 0;
// Make all port D pins outputs
TRISD = 0;

// Configure AN0-AN8 as analog inputs
ADCON3bits.ADCS = 15; // Tad = 266ns, conversion time is 12*Tad
ADCON1bits.ADON = 1; // Turn ADC ON

// Configure PWM for free running mode
//
// PWM period = Tcy * prescale * PTPER = 0.33ns * 64 * PTPER
// PWM pulse width = (Tcy/2) * prescale * PDCx
//
PWMCON1 = 0x00FF; // Enable all PWM pairs in complementary mode
PTCONbits.PTCKPS = 3; // prescale=1:64 (0=1:1, 1=1:4, 2=1:16, 3=1:64)
_PEN2H = 1; // Enable PWM1H pin
_PEN2L = 1; // Enable PWM1L pin
PTPER = 9375; // 20ms PWM period (15-bit period value)
PDC1 = 1406;
PDC2 = 1406; // 1.5ms pulse width on PWM channel 1
PDC3 = 1406;
PTCONbits.PTEN = 1; // Enable PWM time base

// Setup UART
U1BRG = 48; // 38400 baud @ 30 MIPS
U1MODEbits.UARTEN = 1; // Enable UART

// fast flsh to signal reset
int n;
for(n=0;n<10;n++) //Small tester code to see if LED / Circuit is working
{
_LATD1 = 1;
__delay32(1500000);
_LATD1 = 0;
__delay32(1500000);
}

while(1)
{
// Read analog voltage from AN0 (pin 2)
// The number returned (between 0 and 1023)
// represents a voltage in the range 0-5V.
voltage = read_analog_channel(0);
voltage2 = read_analog_channel(1);

// If the voltage is greater than 2.5V
// turn on the LED on RD0 (pin 23),
// otherwise turn it off.
if (voltage < 512) _LATD0 = 0;
else _LATD0 = 1;

// Display the voltage reading on screen
printf("\nVoltage = %d\n\n\n", voltage);
printf("\nVoltage2 = %d\n", voltage2);

// Calculate and update the servo angle
// based on potentiometer voltage on AN0.
// In this case we want voltage values
// between 0 and 1023 to be mapped onto
// PDC1 values between 600 and 1800.
PDC2 = 500 + (2000-500)*(voltage/1023.0);
PDC3 = 425 + (1500-450)*(voltage2/1023.0);
// 100ms delay
__delay32(Second/10);
}

return 0;
}
// This function reads a single sample from the specified
// analog input. It should take less than 5us when the
// microcontroller is running at 30 MIPS.
// The dsPIC30F4011 has a 10-bit ADC, so the value
// returned is between 0 and 1023 inclusive.
unsigned int read_analog_channel(int channel)
{
ADCHS = channel; // Select the requested channel
ADCON1bits.SAMP = 1; // Start sampling
__delay32(30); // 1us delay @ 30 MIPS
ADCON1bits.SAMP = 0; // Start Converting
while (!ADCON1bits.DONE); // Should take 12 * Tad = 3.2us
return ADCBUF0;
}

Here's a small video of the progression that was made.

Advertisements

DC MOTOR 2.o (PWM Control)

In this blog post I will cover the operation of a DC motor with PWM control.

PWM stands for “Pulse Width Modulation” and is a very handy tool in electronics and robotics. It can be used to dim an LED (by adjusting the average voltage [also known as the duty cycle, I’ll place some equations about how that relates]) it can also be used to control the angle of a servo motor depending on the “Time” of the pulses being produced by the micro-controller.
dadc74b4230

Now back to the DC motor and its control, based on my last blog we saw we can control motor in three different states [Forward, Backwards, and no where (if I ever edit the code I’ll add the stop position in that code)]. Now we are going to add a control method of accelerating the motor between different speeds. We will send a PWM signal in different duty cycles from the DSPIC30F4011 to the SN754410NE driver chip.

As the SN754410NE datasheet states it has a “1, 2EN and 3, 4EN” on pins 1 and 9. figura_1 These pins will be used to input the PWM signal from the  DSpic. In this scenario 25% duty cycle means 1/4th of the full speed, 50% duty cycle means 1/2 the full speed, 75% means 3/4 the full speed, and 100% duty cycle means full speed. So by having the motor move in a certain direction added with a PWM duty cycle we will have a motor moving in one direction at any given speed.

 

singledconoff

Here is the code used for the video sample below.


//
// DC Motor control example for dsPIC30F4011
// Written by Kevin Tighe
// Based on the code written by Ted Burke
// Last updated 28-10-2016
//

//important stuff
#include <xc.h>
#include 				<libpic30.h>
#include <stdio.h>
//More important stuff
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Clock speed = 7.5MHz x 16, i.e. 30 MIPS
_FWDT(WDT_OFF); // Watchdog timer off
_FBORPOR(MCLR_DIS); // Disable reset pin

//definitions

#define Second 30000000

int main(void)

{
// Make All D pins digital outputs
TRISD = 0b0000;

// Configure PWM
// PWM period = PTPER * prescale * Tcy = 9470 * 64 * 33.33ns = 20ms
_PMOD1 = 0; // PWM channel 3 mode: 0 for complementary, 1 for independent
_PEN1H = 1; // PWM1H pin enable: 1 to enable, 0 to disable
_PTCKPS = 3; // PWM prescaler setting: 0=1:1, 1=1:4, 2=1:16, 3=1:64
PTPER = 9470; // Set PWM time base period to 20ms (15-bit value)
PDC1 = 0; // 0% duty cycle on channel 1 (16-bit value)
_PTEN = 1; // Enable PWM time base to start generating pulses

// Control motor
while(1)
{
// Forward for 4 seconds @ 10% Power
PDC1 = 0.1 * 2 * PTPER;     // 10% duty cycle
LATD = 0b0011;                    // Forward & LED ON
__delay32(Second * 4);

//Forward for 4 seconds @ 25% Power
PDC1 = 0.25 * 2 * PTPER;      // 25% duty Cycle

LATD = 0b0011;                       // Forward & LED ON
__delay32(Second * 4);

//Backward for 4 seconds @ 50% Power
PDC1 = 0.50 * 2 * PTPER;     // 50% duty Cycle

LATD = 0b0100;                      // Backword & LED OFF
__delay32(Second * 4);

//Forward for 4 seconds @ 75% Power
PDC1 = 0.75 * 2 * PTPER;        // 75% duty cycle

LATD = 0b0011;                          // Forward & LED ON
__delay32(Second* 4);

//Forward for 4 seconds @ 25% Power
PDC1 = 1 * 2 * PTPER; // 100% duty cycle

LATD = 0b0
__delay32(Second* 4);

// Stop for 2 seconds
LATD = 0b0010;
PDC1 = 0 * 2 * PTPER; // 25% duty cycle
__delay32(Second * 2);
}
}

As some of you may have noticed I did use a 20 Volt power supply in the video, the main reason for this was at 6 volts I could not get the level of current to drive the motor at higher speeds, its also fun to watch things move fast. Any ways the motor did not move very well with low duty cycles at 6 Volts so I thought 20 Volts was a great idea (since the maximum voltage the driver chip is only 32 Volts DC), another great aspect of higher torque is you can hear the motor changing speeds very well.

ON A SEPARATE NOTE:

I did a quick experiment with 30 volts (since the bench supply unit I had with me at the time could only go up to 30 Volts max), unfortunately I did not record but the motor moving at those speeds… Then my capacitor blew as you can see below it was not a bad explosion, should of used bigger capacitors.

if your wondering which one blew, look at the right one.
img_3515-1img_3517-1
img_3516-1

DC Motor

A DC motor is a type of electrical machine that uses Direct Current to rotate the shaft either clock wise or anti clock wise depending on the polarity applied to the motor.

dc-motor
A simple DC motor

The basic principal of operation for a DC motor is when current flows through the armature the electric field of the armature experiences a torque from the magnetic field caused by the rotor thus causes the armature to turn depending on the direction on which the current is flowing through the armature.

Since we know the current is proportional to the magnetic flux and torque, we can use this aspect of the motor ton control the speed of the motor, however the DSPIC30F4011 cannot supply enough current to even make the motors turn slightly, so a “driver chip” is needed, to produce the current levels to make the motor spin.  SN754410NE quad half H-bridge IC will be used.

The SN75441one job is basically take in a logic instruction (ON or OFF) into its input pins from the DSPIC and produce that same logic instruction on its output pins with greater current levels than to that which the DSPIC can produce to help create the desired torque for the DC motor.

First lets start with ON and OFF control of the DC motor to create some simple forwards and backward motion. This Circuit diagram was created with “fritzing“.

SingleDCOnOFF.png

//
// Single Motor On Off Control example for dsPIC30F4011
// Written by Kevin Tighe
// Based on the code written from Ted Burke
// @batchloaf.wordpress.com or @roboted.wordpress.com
//

//definitions
#define Second 30000000          // 1 second

//important stuff
#include &lt;xc.h&gt;
#include &lt;libpic30.h&gt;
#include &lt;stdio.h&gt;

//more important stuff
_FOSC(CSW_FSCM_OFF &amp; FRC_PLL16); // Clock speed = 7.5MHz x 16, i.e. 30 MIPS
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

int main(void)
{
// Make RD0 and RD2 digital outputs
TRISD = 0b1010;
_TRISE0 = 0;                     // make RE a D/IO
// Control motor
while(1)
     {
        // Forward for 4 seconds
        LATD = 0b0001;          // forwards
        _LATE0 = 1;
        __delay32(Second * 4);

        // Backwaard for 4 seconds
        LATD = 0b0100;         // backwards
        _LATE0 = 0;
        __delay32(Second * 4);

      }
}

 

Here is a sample of the motor in operation, I realized after watching the video that I should have added a stop. Enjoy the video!