Sunday, November 6, 2016

Unipolar Stepper Motor Control Example with PIC12F1822 Microcontroller



This topic shows how to drive 5V unipolar stepper motor in 3 modes one-phase, two-phase and half step. The microcontroller used in this project is Microchip PIC12F1822 and the motor drive circuit is ULN2003.
Usually the unipolar stepper motor has 5 wires one for motor supply and the other for coils. This motor has 4 coils and they are connected as shown in the figure below:
Unipolar stepper motor coils
Unipolar Stepper Motor Control Example with PIC12F1822  circuit:
All the three control modes have the same circuit schematic as shown below.
Unipolar stepper motor control with PIC12F1822 circuit
Here PIC12F1822 uses its internal oscillator.
The potentiometer connected to AN0 is used to control motor speed and direction of rotation.
Unipolar Stepper Motor Control Example with PIC12F1822 CCS C code:
One Phase On Mode (Full Step mode):
In one phase control mode only one coil is energized at once. This mode produces smooth motion with low power consumption. Control sequence has 4 steps as shown in the table below:
Unipolar stepper motor one phase full step mode sequence
CCS C code:
/* Unipolar stepper Motor control using PIC12F1822 (one-phase full step mode) CCS PIC C code
   http://ccspicc.blogspot.com/
   electronnote@gmail.com
*/

#include <12F1822.h>
#fuses NOMCLR INTRC_IO PLL_SW
#device ADC = 8                                       // Set ADC resolution to 8-bit
#use delay(clock=32000000)
#use fast_io(A)

unsigned int8 i, step_number = 0;
void stepper(int8 step){
  switch(step){
    case 0:
      output_a(0b100000);
    break;
    case 1:
      output_a(0b010000);
    break;
    case 2:
      output_a(0b000100);
    break;
    case 3:
      output_a(0b000010);
    break;
  }
}
void main() {
  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);            // Set internal oscillator to 32MHz (8MHz and PLL)
  output_a(0);
  set_tris_a(1);                                      // Configure RA0 pin as input 
  setup_adc(ADC_CLOCK_DIV_32);                        // Set ADC conversion time to 32Tosc
  setup_adc_ports(sAN0);                              // Configure AN0 pin as analog
  set_adc_channel(0);                                 // Select channel AN0
  while(TRUE){
    output_a(0);
    i = read_adc();                                   // Read from AN0 and store in i
    while(i >= 128){                                  // Move motor in direction 1
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      stepper(step_number);
      delay_ms(257 - i);
      i = read_adc();                                 // Read from AN0 and store in i
    }
    while(i < 128){                                   // Move motor in direction 2
      if(step_number < 1) 
        step_number = 4;
      step_number--;
      stepper(step_number);
      delay_ms(i + 2);
      i = read_adc();                                 // Read from AN0 and store in i
    }
  }
}
Two Phases On Mode (Alternate Full Step mode):
In two-phase mode two coils are energized. This mode produces high torque but its motion is not smooth like the one phase mode. The following table shows this mode sequence:
Unipolar stepper motor two phases full step mode sequence
CCS C code:
/* Unipolar stepper Motor control using PIC12F1822 (two-phase full step mode) CCS PIC C code
   http://ccspicc.blogspot.com/
   electronnote@gmail.com
*/

#include <12F1822.h>
#fuses NOMCLR INTRC_IO PLL_SW
#device ADC = 8                                       // Set ADC resolution to 8-bit
#use delay(clock=32000000)
#use fast_io(A)

unsigned int8 i, step_number = 0;
void stepper(int8 step){
  switch(step){
    case 0:
      output_a(0b100010);
    break;
    case 1:
      output_a(0b110000);
    break;
    case 2:
      output_a(0b010100);
    break;
    case 3:
      output_a(0b000110);
    break;
  }
}
void main() {
  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);            // Set internal oscillator to 32MHz (8MHz and PLL)
  output_a(0);
  set_tris_a(1);                                      // Configure RA0 pin as input 
  setup_adc(ADC_CLOCK_DIV_32);                        // Set ADC conversion time to 32Tosc
  setup_adc_ports(sAN0);                              // Configure AN0 pin as analog
  set_adc_channel(0);                                 // Select channel AN0
  while(TRUE){
    output_a(0);
    i = read_adc();                                   // Read from AN0 and store in i
    while(i >= 128){                                  // Move motor in direction 1
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      stepper(step_number);
      delay_ms(257 - i);
      i = read_adc();                                 // Read from AN0 and store in i
    }
    while(i < 128){                                   // Move motor in direction 2
      if(step_number < 1) 
        step_number = 4;
      step_number--;
      stepper(step_number);
      delay_ms(i + 2);
      i = read_adc();                                 // Read from AN0 and store in i
    }
  }
}
Half Step Mode:
This mode is just mix of the previous two mode sequences. The half step mode increases motor number of steps by 2, for example a stepper motor of 24 steps of 15 degrees each, it becomes using half step mode 28 steps of 7.5 degrees. Mode sequence shown below:
Unipolar stepper motor half step mode sequence
CCS C code:
/* Unipolar stepper Motor control using PIC12F1822 (half step mode) CCS PIC C code
   http://ccspicc.blogspot.com/
   electronnote@gmail.com
*/

#include <12F1822.h>
#fuses NOMCLR INTRC_IO PLL_SW
#device ADC = 8                                       // Set ADC resolution to 8-bit
#use delay(clock=32000000)
#use fast_io(A)

unsigned int8 i, step_number = 0;
void stepper(int8 step){
  switch(step){
    case 0:
      output_a(0b100010);
    break;
    case 1:
      output_a(0b100000);
    break;
    case 2:
      output_a(0b110000);
    break;
    case 3:
      output_a(0b010000);
    break;
    case 4:
      output_a(0b010100);
    break;
    case 5:
      output_a(0b000100);
    break;
    case 6:
      output_a(0b000110);
    break;
    case 7:
      output_a(0b000010);
    break;
  }
}
void main() {
  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);            // Set internal oscillator to 32MHz (8MHz and PLL)
  output_a(0);
  set_tris_a(1);                                      // Configure RA0 pin as input 
  setup_adc(ADC_CLOCK_DIV_32);                        // Set ADC conversion time to 32Tosc
  setup_adc_ports(sAN0);                              // Configure AN0 pin as analog
  set_adc_channel(0);                                 // Select channel AN0
  while(TRUE){
    output_a(0);
    i = read_adc();                                   // Read from AN0 and store in i
    while(i >= 128){                                  // Move motor in direction 1
      step_number++;
      if(step_number > 7) 
        step_number = 0;
      stepper(step_number);
      delay_ms(257 - i);
      i = read_adc();                                 // Read from AN0 and store in i
    }
    while(i < 128){                                   // Move motor in direction 2
      if(step_number < 1) 
        step_number = 8;
      step_number--;
      stepper(step_number);
      delay_ms(i + 2);
      i = read_adc();                                 // Read from AN0 and store in i
    }
  }
}
Example Video:

Saturday, October 22, 2016

Bipolar stepper motor control using PIC12F1822 and L293D


In this blog there are several posts talking about bipolar stepper motor and how to drive it. The bipolar stepper motor has two windings and 4 wires and to drive this windings 2 H-bridge circuits are needed. L293D motor driver chip is a good choice for driving this type of motor because it's low cost and easy to use.
This post shows how to drive a cd-rom bipolar stepper motor using PIC12F1822 microcontroller and L293D.
To understand how this motor works read the following post:
Bipolar stepper motor control with PIC16F877A microcontroller
Bipolar stepper motor control using PIC12F1822 and L293D circuit:
CD-ROM Bipolar stepper motor control using PIC12F1822 and L293D
The two push buttons for moving the motor in direction 1 or direction 2.
PIC12F1822 internal oscillator is used and internal pull-ups are enabled for the 2 inputs.
The stepper motor voltage is 5V which is the same as the L293D chip VS and VSS.
Bipolar stepper motor control using PIC12F1822 and L293D CCS C code:
In this project the speed of the stepper motor is fixed by a variable called speed_delay = 10. If that number changed the speed of the motor will also change, if you increase that number the motor speed will decrease and if you decrease it the speed will increase.
// Bipolar stepper Motor control using PIC12F1822 and L293D CCS PIC C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com
// Use at your own risk

#include <12F1822.h>
#fuses NOMCLR INTRC_IO PLL_SW
#use delay(clock=32000000)
#use fast_io(A)

unsigned int8 step_number = 0, speed_delay = 10;
void stepper(int8 step){
  switch(step){
    case 0:
      output_a(0b010010);
    break;
    case 1:
      output_a(0b010001);
    break;
    case 2:
      output_a(0b100001);
    break;
    case 3:
      output_a(0b100010);
    break;
  }
}
void main() {
  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);            // Set internal oscillator to 32MHz (8MHz and PLL)
  output_a(0);
  set_tris_a(0x0C);                                   // Configure RA2 & RA3 as inputs 
  port_a_pullups(0x0C);                               // Enable internal pull-ups for pins RA2 & RA3
  while(TRUE){
    output_a(0);
    while(!input(PIN_A2)){                            // If RA2 button pressed
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      stepper(step_number);
      delay_ms(speed_delay);
    }
    while(!input(PIN_A3)){                            // If RA3 button pressed
      if(step_number < 1) 
        step_number = 4;
      step_number--;
      stepper(step_number);
      delay_ms(speed_delay);
    }
  }
}
Bipolar stepper motor control using PIC12F1822 and L293D video:
Project hardware video....

Friday, July 22, 2016

Remote Controlled Bipolar Stepper Motor Using PIC16F877A


Each CD-ROM or DVD-ROM drive has a bipolar stepper motor. The bipolar stepper motor has 2 windings which means that this type of motors has 4 wires.
Bipolar stepper motor coils IR
In this blog there are some topics shows how to control the bipolar stepper motor as the following one:
Bipolar stepper motor control with PIC16F877A microcontroller
Now in this topic an IR remote control is used to control the bipolar stepper motor speed and direction of rotation. The remote control used in this project uses NEC protocol and to see how to decode NEC protocol using PIC16F877A microcontroller see the following post:
NEC Protocol IR remote control decoder with PIC16F877A microcontroller
To control the bipolar stepper motor we need two H-bridge circuits and for that L293D motor driver chip is used, this cheap chip can work as a dual H-bridge drivers.
Project circuit schematic is shown below:
IR Remote controlled cd-rom bipolar stepper motor using PIC16F877A and L293D CCS PIC C
Remote controlled stepper motor using PIC16F877A CCS C code:
The IR remote control used in this project is shown below with the used buttons and their codes which are used in the code.
NEC IR remote control codes for stepper motor 
External interrupt is used for reading IR signals.
// Remote controlled bipolar stepper motor using PIC16F877A and L293D CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock = 8000000)
#use fast_io(B)
#use fast_io(D)

unsigned int8 step_number = 0, speed_delay = 2;
unsigned int32 remote_code;
#INT_TIMER1                                  // Timer1 interrupt ISR
void timer1_isr(void){
  remote_code = 0;
  clear_interrupt(INT_TIMER1);
  disable_interrupts(INT_TIMER1);
}
#INT_EXT                                     // External interrupt ISR
void ext_isr(void){
  unsigned int8 count = 0, i;
  unsigned int32 ir_code;
  // Check 9ms pulse (remote control sends logic high)
  while((input(PIN_B0) == 0) && (count < 200)){
    count++;
    delay_us(50);}
  if( (count > 199) || (count < 160))        // NEC protocol?
    return;                          
  count = 0;
  // Check 4.5ms space or repeated code
  while((input(PIN_B0)) && (count < 100)){
    count++;
    delay_us(50);}
  if( (count > 99) || (count < 30))          // NEC protocol?
    return;
  // Check repeated code
  if(count < 60){
    count = 0;
    while((input(PIN_B0) == 0) && (count < 14)){
      count++;
      delay_us(50);}
    if( (count > 13) || (count < 8))         // NEC protocol?
      return;
    if((remote_code == 0x40BF50AF) || (remote_code == 0x40BF906F))
    set_timer1(0);
  }
  // Read message (32 bits)
  for(i = 0; i < 32; i++){
    count = 0;
    while((input(PIN_B0) == 0) && (count < 14)){
      count++;
      delay_us(50);}
    if( (count > 13) || (count < 8))         // NEC protocol?
      return;                          
    count = 0;
    while((input(PIN_B0)) && (count < 40)){
      count++;
      delay_us(50);}
    if( (count > 39) || (count < 8))         // NEC protocol?
      return;                           
    if( count > 20)                          // If space width > 1ms
      bit_set(ir_code, (31 - i));            // Write 1 to bit (31 - i)
    else                                     // If space width < 1ms
      bit_clear(ir_code, (31 - i));          // Write 0 to bit (31 - i)
  }
  if((ir_code == 0x40BF50AF) || (ir_code == 0x40BF906F)){
    set_timer1(0);
    clear_interrupt(INT_TIMER1);
    enable_interrupts(INT_TIMER1);}
  if(ir_code == 0x40BFA05F){
    speed_delay++;
    if(speed_delay > 20) speed_delay = 20;
    return;}
  if(ir_code == 0x40BF609F){
    speed_delay--;
    if(speed_delay < 2) speed_delay = 2;
    return;}
  remote_code = ir_code; 
}
void stepper(int8 step){
  switch(step){
    case 0:
      output_d(0b000000110);
    break;
    case 1:
      output_d(0b00000101);
    break;
    case 2:
      output_d(0b00001001);
    break;
    case 3:
      output_d(0b00001010);
    break;
  }
}
void main(){
  output_b(0);                                // PORTB initial state
  set_tris_b(0xF7);
  port_b_pullups(TRUE);                       // Enable PORTB internal pull-ups
  output_d(0);
  set_tris_d(0);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);   // Timer1 configuration
  enable_interrupts(GLOBAL);                  // Enable global interrupts
  enable_interrupts(INT_EXT_H2L);                 // Enable external interrupt
  while(TRUE){
    while(remote_code == 0);
    while((remote_code == 0x40BF40BF) || (remote_code == 0x40BF50AF)){
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      stepper(step_number);
      delay_ms(speed_delay);
    }
    while((remote_code == 0x40BF807F) || (remote_code == 0x40BF906F)){
      if(step_number < 1) 
        step_number = 4;
      step_number--;
      stepper(step_number);
      delay_ms(speed_delay);
    }
  output_d(0);
  if((remote_code != 0x40BF40BF) && (remote_code != 0x40B807F))
  remote_code = 0;
  }
}

Remote controlled stepper motor using PIC16F877A video:
The following video shows a hardware circuit for this project.

Thursday, July 21, 2016

Unipolar Stepper Motor Control From IR Remote Control Using PIC18F4550


Remote controlled stepper motor using PIC18F4550
Car MP3 remote control controls 5V stepper motor using PIC microcontroller 
This project shows how to control a 5V unipolar stepper motor from IR remote control uses NEC protocol with PIC18F4550 microcontroller. This controller controls the stepper motor speed and direction of rotation.
If you want to see how to drive the unipolar stepper motor using PIC18F4550 microcontroller read the following topic:
Interfacing unipolar stepper motor with PIC18F4550 microcontroller
And if you want to see how to decode IR remote control with NEC protocol see the following topic:
Extended NEC IR remote control decoder with PIC18F4550 microcontroller
To drive the unipolar stepper motor we need ULN2003 (ULN2004) Darlington transistor array or L293D motor driver as described in the previous topic.
The IR remote control used in this project is shown below:
Car MP3 NEC protocol IR remote control
Project circuit schematic is shown below.
Remote controlled unipolar stepper motor using PIC18F4550 and NEC Car MP3 IR remote control circuit 
PIC18F4550 microcontroller internal oscillator is used.
Remote controlled unipolar stepper motor using PIC18F4550 CCS C code:
External interrupt is used to read IR remote control signals.
// Remote controlled stepper motor using PIC18F4550 CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <18F4550.h>
#fuses NOMCLR INTRC_IO
#use delay(clock = 8000000)
#use fast_io(B)
#use fast_io(D)

short Direction;
unsigned int8 step_number = 0, speed_delay = 2;
unsigned int32 remote_code;
#INT_TIMER1                                  // Timer1 interrupt ISR
void timer1_isr(void){
  remote_code = 0;
  clear_interrupt(INT_TIMER1);
  disable_interrupts(INT_TIMER1);
}
#INT_EXT                                     // External interrupt ISR
void ext_isr(void){
  unsigned int8 count = 0, i;
  unsigned int32 ir_code;
  // Check 9ms pulse (remote control sends logic high)
  while((input(PIN_B0) == 0) && (count < 200)){
    count++;
    delay_us(50);}
  if( (count > 199) || (count < 160))        // NEC protocol?
    return;                          
  count = 0;
  // Check 4.5ms space or repeated code
  while((input(PIN_B0)) && (count < 100)){
    count++;
    delay_us(50);}
  if( (count > 99) || (count < 30))          // NEC protocol?
    return;
  // Check repeated code
  if(count < 60){
    count = 0;
    while((input(PIN_B0) == 0) && (count < 14)){
      count++;
      delay_us(50);}
    if( (count > 13) || (count < 8))         // NEC protocol?
      return;
    if((remote_code == 0x40BF50AF) || (remote_code == 0x40BF906F))
    set_timer1(0);
  }
  // Read message (32 bits)
  for(i = 0; i < 32; i++){
    count = 0;
    while((input(PIN_B0) == 0) && (count < 14)){
      count++;
      delay_us(50);}
    if( (count > 13) || (count < 8))         // NEC protocol?
      return;                          
    count = 0;
    while((input(PIN_B0)) && (count < 40)){
      count++;
      delay_us(50);}
    if( (count > 39) || (count < 8))         // NEC protocol?
      return;                           
    if( count > 20)                          // If space width > 1ms
      bit_set(ir_code, (31 - i));            // Write 1 to bit (31 - i)
    else                                     // If space width < 1ms
      bit_clear(ir_code, (31 - i));          // Write 0 to bit (31 - i)
  }
  if((ir_code == 0x40BF50AF) || (ir_code == 0x40BF906F)){
    set_timer1(0);
    clear_interrupt(INT_TIMER1);
    enable_interrupts(INT_TIMER1);}
  if(ir_code == 0x40BFA05F){
    speed_delay++;
    if(speed_delay > 20) speed_delay = 20;
    return;}
  if(ir_code == 0x40BF609F){
    speed_delay--;
    if(speed_delay < 2) speed_delay = 2;
    return;}
  remote_code = ir_code; 
}
void stepper(int8 step){
  if(Direction == 0){
    switch(step){
      case 0:
        output_d(0b00000011);
        break;
      case 1:
        output_d(0b00000110);
        break;
      case 2:
        output_d(0b00001100);
        break;
      case 3:
        output_d(0b00001001);
        break;
    }
  }
  if(Direction == 1){
    switch(step){
      case 0:
        output_d(0b00001001);
        break;
      case 1:
        output_d(0b00001100);
        break;
      case 2:
        output_d(0b00000110);
        break;
      case 3:
        output_d(0b00000011);
        break;
    }
  }
}
void main(){
  setup_oscillator(OSC_8MHZ);                 // Set internal oscillator to 8MHz
  setup_adc_ports(NO_ANALOGS);                // Configure AN pins as digital
  set_tris_b(1);                           // Configure RB0 as digital input pin
  port_b_pullups(TRUE);                       // Enable PORTB internal pull-ups
  output_d(0);                                // PORTD initial state
  set_tris_d(0);                              // Configure PORTD pins as outputs
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);   // Timer1 configuration
  enable_interrupts(GLOBAL);                  // Enable global interrupts
  enable_interrupts(INT_EXT_H2L);                 // Enable external interrupt
  while(TRUE){
    output_d(0);
    while(remote_code == 0x40BF40BF){
      Direction = 0;
      stepper(step_number);
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      delay_ms(speed_delay);
    }
    while(remote_code == 0x40BF807F){
      Direction = 1;
      stepper(step_number);
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      delay_ms(speed_delay);
    }
    while(remote_code == 0x40BF50AF){
      Direction = 0;
      stepper(step_number);
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      delay_ms(speed_delay);
    }
    while(remote_code == 0x40BF906F){
      Direction = 1;
      stepper(step_number);
      step_number++;
      if(step_number > 3) 
        step_number = 0;
      delay_ms(speed_delay);
    }
  }
}

Remote controlled unipolar stepper motor using PIC18F4550 video:

Tuesday, May 24, 2016

Interfacing unipolar stepper motor with PIC18F4550 microcontroller


Unipolar stepper motor drive with PIC18F4550 microcontroller 
Unipolar 5V stepper motor 
After interfacing PIC18F4550 microcontroller with bipolar stepper motor in the following topic:
CD-ROM Bipolar stepper motor drive using PIC18F4550 and CCS PIC C
Now let's see how to drive a unipolar stepper motor using PIC18F4550 and CCS PIC C compiler.
Usually the bipolar stepper motor has 2 colis and therefore it has 4 wires, and the unipolar has 4 coils which are connected as shown in the following figure:
Unipolar stepper motor coils PIC18F4550
The unipolar stepper motor can be controlled in full step mode or half step mode, the usual method is the full step driving mode which gives higher torque. The following table shows driving sequences:
Unipolar stepper motor driving sequence PIC18F4550
Interfacing PIC18F4550 with unipolar stepper motor circuit:
In the circuit there are 2 pushbuttons which are connected to RB0 and RB1 pins, they are used to choose motor rotation direction. PortB internal pull-ups are enabled in the software.
To control the stepper motor speed a potentiometer (10K) is used and it is connected to analog channel 0(AN0).
ULN2003 (or ULN2004) chip is used to energize the stepper motor coils.
The ULN2003(ULN2004) is a Darlington transistor array which contains seven open collector Darlington pairs with common emitters. For stepper motor controller we need 4 transistors form this chip which means 4 inputs and 4 outputs are needed.

Interfacing unipolar stepper motor with PIC18F4550 ULN2003 circuit CCS PIC C
Instead of the ULN2003 chip, another chip can be used which is L293D dual H-bridge circuits as shown in the circuit schematic below.
For the L293D chip VS voltage always +5V and VSS voltage is the same as the motor voltage for example if the motor voltage is 12V, VSS should be connected to +12V power supply.

Interfacing unipolar stepper motor with PIC18F4550 L293D circuit CCS PIC C
PIC18F4550 internal oscillator is used (8MHz) and MCLR pin function is disabled.
Interfacing PIC18F4550 with unipolar stepper motor CCS C code:
A pot connected to AN0 is used to control the speed of the stepper motor. The microcontroller reads the analog data from AN0 and uses the digital value to change the delay between motor driving sequences.

// Interfacing PIC18F4550 with unipolar stepper motor CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <18F4550.h>
#fuses NOMCLR INTRC_IO
#use delay(clock = 8000000)
#use fast_io(B)
#use fast_io(D)

unsigned int8 speed_;
void main()
{
   setup_oscillator(OSC_8MHZ);              // Set internal oscillator to 8MHz
   setup_adc(ADC_CLOCK_DIV_8);              // Set ADC conversion time to 8Tosc
   setup_adc_ports(AN0);                    // Configure RA0(AN0)as analog
   set_adc_channel(0);                      // Select channel 0 input
   port_b_pullups(TRUE);
   output_b(0);
   set_tris_b(3);
   output_d(0);
   set_tris_d(0);
   delay_ms(100);
   while(TRUE)
   {
      output_d(0);
      while( ! input(PIN_B0))
      {
         speed_ = read_adc();
         if(speed_ < 2)
            speed_ = 2;
         output_d(0b00000011);
         delay_ms(speed_);
         output_d(0b00000110);
         delay_ms(speed_);
         output_d(0b00001100);
         delay_ms(speed_);
         output_d(0b00001001);
         delay_ms(speed_);
      }
      while( ! input(PIN_B1))
      {
         speed_ = read_adc();
         if(speed_ < 2)
            speed_ = 2;
         output_d(0b00001001);
         delay_ms(speed_);
         output_d(0b00001100);
         delay_ms(speed_);
         output_d(0b00000110);
         delay_ms(speed_);
         output_d(0b00000011);
         delay_ms(speed_);
      }
   }
}

Interfacing PIC18F4550 with unipolar stepper motor video:
The following video shows project hardware circuit.

Unipolar stepper motor control using PIC16F877A microcontroller


Interfacing unipolar stepper motor with PIC16F877A
This post shows how to control speed and rotation direction of unipolar stepper motor using PIC16F877A microcontroller and CCS PIC C compiler.
Related topic:
Bipolar stepper motor control with PIC16F877A microcontroller
Usually the unipolar stepper motor has 5 wires one for motor supply and the other for coils. This motor has 4 coils and they are connected as shown in the figure below:
Unipolar stepper motor coils control
The unipolar stepper motor can be controlled in full step mode or half step mode, the usual method is the full step driving mode. The following table shows driving sequences:
Unipolar stepper motor control sequence PIC16F877A
Interfacing PIC16F877A with unipolar stepper motor circuit:
In the circuit there are 2 pushbuttons which are connected to RB0 and RB1 pins, they are used to choose motor rotation direction.
To control the stepper motor speed a potentiometer (10K) is used and it is connected to analog channel 0(AN0).

ULN2003 (or ULN2004) chip is used to energize the stepper motor coils.
The ULN2003(ULN2004) is a Darlington transistor array which contains seven open collector Darlington pairs with common emitters. For stepper motor controller we need 4 transistors form this chip which means 4 inputs and 4 outputs are needed.
Interfacing PIC16F877A microcontroller with unipolar stepper motor control circuit using ULN2003 CCS PIC C
Instead of the ULN2003 chip, another chip can be used which is L293D dual H-bridge circuits as shown in the circuit schematic below.
For the L293D chip VS voltage always +5V and VSS voltage is the same as the motor voltage for example if the motor voltage is 12V VSS should be connected to +12V power supply.
Interfacing PIC16F877A microcontroller with unipolar stepper motor control circuit using L293D CCS PIC C
Interfacing PIC16F877A with unipolar stepper motor CCS C code:
A pot connected to AN0 is used to control the speed of the stepper motor. The microcontroller reads the analog data from AN0 and uses the digital value to change the delay between motor driving sequences.
// Interfacing PIC16F877A microcontroller with unipolar stepper motor CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP                       
#use delay(clock = 8000000)
#use fast_io(B)
#use fast_io(D)

unsigned int8 speed_;
void main(){
  output_b(0);
  set_tris_b(0x03);
  port_b_pullups(TRUE);
  output_d(0);
  set_tris_d(0);
  setup_adc(ADC_CLOCK_DIV_32);      // Set ADC conversion time to 32Tosc
  setup_adc_ports(AN0);             // Configure AN0 as analog  
  set_adc_channel(0);               // Select channel 0 input
  delay_ms(100);                    // Wait 100ms
  while(TRUE)
   {
      output_d(0);
      while( ! input(PIN_B0))
      {
         speed_ = read_adc();
         if(speed_ < 2)
            speed_ = 2;
         output_d(0b00000011);
         delay_ms(speed_);
         output_d(0b00000110);
         delay_ms(speed_);
         output_d(0b00001100);
         delay_ms(speed_);
         output_d(0b00001001);
         delay_ms(speed_);
      }
      while( ! input(PIN_B1))
      {
         speed_ = read_adc();
         if(speed_ < 2)
            speed_ = 2;
         output_d(0b00001001);
         delay_ms(speed_);
         output_d(0b00001100);
         delay_ms(speed_);
         output_d(0b00000110);
         delay_ms(speed_);
         output_d(0b00000011);
         delay_ms(speed_);
      }
   }
}

Interfacing PIC16F877A with unipolar stepper motor video:
The following video shows a hardware circuit for this project.

Monday, May 23, 2016

Interfacing PIC16F84A microcontroller with stepper motor


CD-ROM bipolar stepper motor drive with PIC16F84A and CCS PIC C compiler
This topic shows circuit schematic and C code for interfacing PIC16F84A microcontroller with CD-ROM bipolar stepper motor.
Related Topics:
CD-ROM Bipolar stepper motor drive using PIC18F4550 and CCS PIC C
Bipolar stepper motor control with PIC16F877A microcontroller
The following circuit schematic shows the connection between the microcontroller PIC16F84A and the stepper motor where a dual H-bridge circuit which is L293D chip is used between them.
Interfacing PIC16F84A with stepper motor circuit CCS PIC C
The two pushbuttons are used to choose motor rotation direction.
Interfacing PIC16F84A microcontroller with stepper motor CCS PIC C code:
The motor speed is fixed by the code but we can change it by changing the delay between the four phases.
// Interfacing PIC16F84A with CD-ROM bipolar stepper motor CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <16F84A.h>
#fuses HS,NOWDT,PUT,NOPROTECT
#use delay(clock = 8000000)
#use fast_io(A)
#use fast_io(B)

void main()
{
   output_a(0);
   set_tris_a(0);
   port_b_pullups(TRUE);
   output_b(0);
   set_tris_b(3);
   while(TRUE)
   {
      output_a(0);
      while(!input(PIN_B0))
      {
         output_a(0b00000110);
         delay_ms(5);
         output_a(0b00000101);
         delay_ms(5);
         output_a(0b00001001);
         delay_ms(5);
         output_a(0b00001010);
         delay_ms(5);
      }
      while(!input(PIN_B1))
      {
         output_a(0b00000101);
         delay_ms(5);
         output_a(0b00000110);
         delay_ms(5);
         output_a(0b00001010);
         delay_ms(5);
         output_a(0b00001001);
         delay_ms(5);
      }
   }
}

Interfacing PIC16F84A microcontroller with stepper motor video: The following video shows a hardware circuit of this project.

Sunday, May 22, 2016

CD-ROM Bipolar stepper motor drive using PIC18F4550 and CCS PIC C


Stepper motor interfacing with PIC18F4550 microcontroller
Most of cd-rom or dvd-rom drives has a bipolar stepper motor, this motor has two windings and each winding has 2 inputs which means that this type of motor has 4 wires.
CD-ROM bipolar stepper motor windings PIC18F4550 projects
This topic shows circuit schematic and C code for controlling the bipolar stepper motor speed and direction using PIC18F4550 microcontroller.
The stepper motor can be controlled in full step mode or half step mode. The full step mode is a little bit easier than the half step control mode. In this topic the full step control mode is used.
To control the bipolar stepper motor we need two H-bridge circuits and for that L293D motor driver chip is used, this cheap chip can work as a dual H-bridge drivers.
In the full step control mode always both windings are energized according to the following two tables where table1 shows the driving sequence for rotation direction 1:

stepper motor phases drive PIC18F4550 projects
And the following table shows driving sequence for the other rotation direction:
stepper motor phases control PIC18F4550 projects
Interfacing PIC18F4550 with bipolar stepper motor circuit:
The following image shows circuit schematic diagram of this project a potentiometer connected to AN0 channel is used to control the speed as well as the rotation direction of the stepper motor as shown in the video below.

Interfacing PIC18F4550 microcontroller with CD-ROM stepper motor speed direction control L293D CCS PIC C
PIC18F4550 internal oscillator is used (8MHz) and MCLR pin function is disabled.
Interfacing PIC18F4550 with bipolar stepper motor CCS C code:
The following code is the full C code of this project where a potentiometer which is connected to channel AN0 is used to control the rotation direction and the speed of the stepper motor.
The microcontroller reads the analog value from the output of the pot and uses the digital value to control the rotation direction and the speed with ADC resolution of 8 bits.
// Interfacing PIC18F4550 with CD-ROM bipolar stepper motor CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <18F4550.h>
#fuses NOMCLR INTRC_IO
#use delay(clock = 8000000)
#use fast_io(D)

unsigned int8 speed_, value;
void main()
{
   setup_oscillator(OSC_8MHZ);              // Set internal oscillator to 8MHz
   setup_adc(ADC_CLOCK_DIV_8);              // Set ADC conversion time to 8Tosc
   setup_adc_ports(AN0);                    // Configure RA0(AN0)as analog
   set_adc_channel(0);                      // Select channel 0 input
   output_d(0);
   set_tris_d(0);
   delay_ms(100);                           // Wait 100ms
   while(TRUE)
   {
      value = read_adc();
      if(value  < 2)value = 1;
      if(value  < 0x80)
      {
         speed_ = value;
         output_d(0b00000110);
         delay_ms(speed_);
         output_d(0b00000101);
         delay_ms(speed_);
         output_d(0b00001001);
         delay_ms(speed_);
         output_d(0b00001010);
         delay_ms(speed_);
      }
      else if(value  > 0x80)
      {
         speed_ = 256 - value;
         output_d(0b00000101);
         delay_ms(speed_);
         output_d(0b00000110);
         delay_ms(speed_);
         output_d(0b00001010);
         delay_ms(speed_);
         output_d(0b00001001);
         delay_ms(speed_);
      }
   }
}

Interfacing PIC18F4550 with bipolar stepper motor video:
The following video shows the project in hardware circuit.