• AVR Freaks

AnsweredHot!Controlling a bipolar stepper with my PIC16F1825

Page: 12 > Showing page 1 of 2
Author
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
2019/05/21 03:10:33 (permalink)
0

Controlling a bipolar stepper with my PIC16F1825

Dear all,
 
I am trying to programm my first stepper control. The bipolar stepper is driven by a SN754410NE.
 
First I tested my setup (motor and driver) with an Arduino and noted the pattern the Arduino is using to controll the stepper. Then I tried to simpy copying it for my PIC.
 
/*
 * File:   Stepper.c
 * Author: kart
 *
 * Created on 14. Mai 2019, 14:22
 */


#include <xc.h>
#define _XTAL_FREQ 500000  //define clockspeed used for calculating __delay_ms
void delayMS(int max);


void main(void) {
  
    
    ANSELCbits.ANSC0 = 0;
    ANSELCbits.ANSC1 = 0;
    ANSELCbits.ANSC2 = 0;
    ANSELCbits.ANSC3 = 0;
    
    TRISCbits.TRISC0 = 0;   // setze RC0 auf output
    TRISCbits.TRISC1 = 0;   // setze RC1 auf output
    TRISCbits.TRISC2 = 0;   // setze RC2 auf output
    TRISCbits.TRISC3 = 0;   // setze RC3 auf output
    
   
    
    while (1)
    {
        
        LATC=0b00000110;
        //LATCbits.LATC0 = 0;
        //LATCbits.LATC1 = 1;
        //LATCbits.LATC2 = 1;
        //LATCbits.LATC3 = 0;
        delayMS(50);
        LATC=0b00001010;
        //LATCbits.LATC0 = 0;
        //LATCbits.LATC1 = 1;
        //LATCbits.LATC2 = 0;
        //LATCbits.LATC3 = 1;
        delayMS(50);
        LATC=0b00001001;
        //LATCbits.LATC0 = 1;
        //LATCbits.LATC1 = 0;
        //LATCbits.LATC2 = 0;
        //LATCbits.LATC3 = 1;
        delayMS(50);
        LATC=0b00000101;
        //LATCbits.LATC0 = 1;
        //LATCbits.LATC1 = 0;
        //LATCbits.LATC2 = 1;
        //LATCbits.LATC3 = 0;
        delayMS(50);
    
    }
    
    
}
void delayMS(int max){
    do {
      __delay_ms(1);
   } while (--max);
}
// PIC16F1825 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
 
When analyzing the output patterns via skope it seems ok. But when I finally attach the driver and stepper to my pic the stepper is buzzing  but not moving?!
 
Any ideas?
 
thanks
Michael
 
#1
LdB_ECM
Senior Member
  • Total Posts : 125
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/21 08:23:08 (permalink)
+2 (2)
You probably do not have the motor phases right ... there are two coils ... find the pairs with a multimeter.
Place a multimeter probe on one wire and test for continuity on the other 3 wires only 1 will have continuity and that is COIL A. The other two wires are COIL B. 
 
Look at the datsheet http://www.ti.com/lit/ds/symlink/sn754410.pdf  ... diagram 10.2
See how you can see the coils.
 
So one coil pair goes between pins 3 & 6  and the other coil pair goes between pins 11 & 14 it does not matter which of the pairs goes to which pin that just determines motor direction. So now you have the coils connected correctly
 
Now you must apply the sequence correctly to the input it must do this
That represents time across and the 4 port bits down for each step
pin 2   aka 1a ....  1100110011001100110011001
pin 7   aka 2a ....  0011001100110011001100110
pin 10 aka 3a ....  0110011001100110011001100
pin15  aka 4a ....  1001100110011001100110011

So in binary if portC is connected so bit0 = 1a, bit1 = 2a, bit2 = 3a, bit 3 = 4a then the 4 port C sequence is
0b1001, 0b1010, 0b0110, 0b0101

The pattern must match the connections to 1a, 2a,3a,4a if you have portc connected differently you must adjust it.

Now the only thing else is the motor direction may be wrong to what you want. You can reverse the direction by changing the two wires of either coil. It matters not which pair either will cause the motor direction reversal.
#2
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/22 02:58:29 (permalink)
0
Hi,
The 2 coil pairs are wired corretly ... otherwise it wouldn't work with the Arduino either (but I double checked).
I changed the pattern from my original one to the one stated by you but still the stepper is just humming, vibrating but not moving.
#3
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/22 03:09:25 (permalink)
+1 (1)
If you massively increase the delays, can you see if it's just moving back and forth one step, or if it moves more than one step in one direction before returning?
 
 
 

Nearly there...
#4
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/22 03:36:00 (permalink)
0
Hi,
I changed the delay to 500 ms. I checked the shaft with a manication glass but do not see ANY movement (while I feel the tact in the hand holding the motor).
 
The actual wiring is as follows:
 
PIC                   SN
Pin 10 RCO  to    Pin 2    1A
Pin 9   RC1  to    Pin 7    2A
Pin 8   RC2  to    Pin 10  3A
Pin 7   RC3  to    Pin 15  4A
 
regards
Michael
 
#5
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/22 03:54:15 (permalink) ☼ Best Answerby kart 2019/05/22 03:59:02
0
I can guess manication" should be "magnification", but I can't guess what "tact" means.
 

Nearly there...
#6
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/22 04:01:09 (permalink)
0
sorry ;-)
 
magnification is correct, by "tact" I meant clock/beat (500ms cycles)
#7
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/22 04:14:51 (permalink)
0
Hi,
 
I just once again replaced the lines to the SN by 4 LEDs ... and I see that I do not get a perfect pattern. It seams that randomly RC1 goes high and low out of sync which of course disturbs the pattern. I see that a comperator is asigned to this port too. Do I have to disable some service on the PIC to release the port for digital output?
 
regards
Michael
#8
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/27 00:25:13 (permalink)
0
Hi, 
I just checked the output for one coil with a scope ... and the timing of the outputs is totally "floating" ... no single cycle is exactly the same lenght then the other, and some are extremly short?!
 
Any reason, why __delay_ms provides useless values in this case?
 
regards
Michael
#9
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/27 01:40:13 (permalink)
+1 (1)
If you don't have interrupts running at the same time, then __delay_ms() is extremely good.
I suspect you have something else going on, like random hardware resets.
You have the MCLR pin enabled. Do you have it pulled high?
 

Nearly there...
#10
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/27 04:37:28 (permalink)
0
Dear all,
 
1) Floating problem was solved by replacing the microcontroller itself ... seems to be defective.
 
2) Stepper controll still didn't work. As long as no motor was connected to the bridge the stepper control by the pic worked (controlled by oszilloscope), but as soon as the motor was attached (nema 17, 12V 0,5 A) the output signals from the pic broke down.
 
I fixed this problem by adding a 1000uF condensator to support the pic input ... now everything works fine 
 
... but I still do not understand how the motor behind the bridge managed to tear down the microcontroller (the common power source was a high end labor power supply so I would not expect any problems from this end)
 
Any idea what causes this problem?
 
thanks
Michael
#11
LdB_ECM
Senior Member
  • Total Posts : 125
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/27 05:58:55 (permalink)
+2 (2)
It is a switching transient and it tells you in the datasheet to put two minimum size caps in
Section 12.2 Layout Example
 
It doesn't matter how good the power supply the transient needs suppression right at the chip not after several inches of track or wire.  
#12
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/27 06:10:58 (permalink)
0
While everything works fine now to rotate in one direction I can't change the direction of the motor rotation. I change the pattern as follows:
 
for (int i = 0; i < 5;i++){
        LATC=0b00001001;
        delayMS(50);
        LATC=0b00000101;
        delayMS(50);
        LATC=0b00000110;
        delayMS(50);
        LATC=0b00001010;
        delayMS(50);
        }
        delayMS(2000);
       for (int i = 0; i < 5;i++){
        LATC=0b00000110;
        delayMS(50);
        LATC=0b00000101;
        delayMS(50);
        LATC=0b00001001;
        delayMS(50);
        LATC=0b00001010;
        delayMS(50);
        }
 
The motor keeps turining in the same direction ...
#13
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/28 03:07:59 (permalink)
0
Depending on which sequence above is first the motor starts either turning clockwise or counter clockwise ... but as soon as it turns it doesn't change the direction any more when the patterns change. So the pattern seem to be correct in general for controlling the turning direction ... but what do I have to do to change the direction if in motion already? Sending a 0b00000000 in between doesn't help either
#14
LdB_ECM
Senior Member
  • Total Posts : 125
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/28 04:12:59 (permalink)
0
Read post 2 again .. I told you how to do that .. you don't have to change any code
 
Now the only thing else is the motor direction may be wrong to what you want. You can reverse the direction by changing the two wires of either coil. It matters not which pair either will cause the motor direction reversal.

 
No coding required reverse one of the coil pairs and magically it will go the other way.
 
If you mapped out the magnetic fields you world work out why.
#15
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/28 04:21:57 (permalink)
0
Of course I can change the direction by reversing one of the coils ... but that isn't helpfull in a standard environment. In most environments you have to change the direction frequently (plotters, robots, ...) and this has to be done by software. When I drive a stepper via arduino I can change the turning direction per software without any problems ...
 
I can't think of many solutions where a step motor is required to turn in one direction only?!
#16
LdB_ECM
Senior Member
  • Total Posts : 125
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/28 05:08:05 (permalink)
0
Okay from code you are walking one way thru the byte array just walk backwards with a direction flag
In pseudo code it is like this

int8_t dir  = 1;    // 1 = forward, -1 = backward
int8_t stepidx = 0; // step index
uint8_t StepArray[4] = {0b1001, 0b1010, 0b0110, 0b0101};
// step loop  .. dir preset either 1 or -1  and preset number_of_steps
while (number_of_steps > 0)
{
        output port = StepArray[stepidx]; // out put byte
        stepidx += dir;     // move to next table pos
        stepidx &= 0x3;   // make sure index stays 0..3 (might give warning it is signed)
        do delay;             // Do your delay
        number_of_steps--;   // One step done
}

post edited by LdB_ECM - 2019/05/28 08:35:50
#17
kart
Starting Member
  • Total Posts : 49
  • Reward points : 0
  • Joined: 2016/12/01 07:55:28
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/29 03:30:40 (permalink)
0
thanks!
 
I will test it on Friday. Are there some other hardware requirements with repect to steering the bridge with my pic (in addition to the capacitor)? Because basically it should work to send the patterns manually one by one as I did but the direction doesn't change ... the results when starting my code seem unpedictable even when getting a verification ok ater loading down the code.
#18
LdB_ECM
Senior Member
  • Total Posts : 125
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/29 06:04:58 (permalink)
+3 (3)
There are two speed restrictions on a stepper
 
The first is motor speed vs torque on the data sheet called the "pull out rate". That is the maximum pulse rate a motor can run for a given load.
 
There is another called "start characteristic" which is the maximum pulse to load the motor will start stepping at without losing synchronization. Generally the slower the rate the more load it can have. It follows to make a steeper motor run optimally it requires to be ramped up from a slow speed to a fast speed and then slowed again when it wants to reverse direction. The ramp is usually constructed 3 points a 1 property
 
1.) min speed (often called corner speed)
2.) Max speed (often called traverse speed)
3.) Number of steps the motor uses to get from min to max
4.) The shape of the curve between min/max
 
The simplest way to ramp on the pseudocode above is each step the delay is shortened until the delay gets to a minimum matching the maxium speed. Conversely as the motor starts getting to a number of steps from a reversal the delay at each step will be increased until it reaches some max value representing the minimum speed.
 
This is a good point to help you understand and construct the ramp calculation
https://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
 
It is a lost art these days because mostly we add a rotary encoder encoder onto a DC motor and run them directly from the same H-Bridge you have but track the encoder. It is far more common than stepper motors and servos these days simply because of lower cost for the higher power output and speed.
 
#19
LdB_ECM
Senior Member
  • Total Posts : 125
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: Controlling a bipolar stepper with my PIC16F1825 2019/05/29 08:01:47 (permalink)
+1 (1)
I added half stepping and added a rough linear ramp in this code if you want a rough start point
#include <stdint.h>
static int16_t absposX = 0;   // Absolute position to where motor is
// This is the half step sequence made up of 8 phase changes
// Full step takes every second one
//                          9       8        A      2       6       4        5        1
static uint8_t StepArray[8] = { 0b1001, 0b1000,  0b1010, 0b0010, 0b0110, 0b1000, 0b0101,  0b0001 };
static int8_t stepidx = 0;     // current step index

// Move to position target x, starting at minSpeed pulse per second, reaching maxSpeed pulse per second with a ramp of rampSteps
void MoveMotorTo (int16_t targetx, uint16_t minSpeed, uint16_t maxSpeed, uint16_t rampSteps)
{
    int8_t xdir;        // Stepper motor director to move
    uint16_t dx;        // Steps to move as an absolute value
    uint16_t rampdn_pt;    // Point to start ramp down
    uint16_t rampcount;    // Ramp count
    uint16_t deltaspeed;// Speed change over ramplength
    uint16_t curSpeed;  // Current speed
    if (targetx < absposX)                            // Need to move negative
    {
        xdir = -1;                                    // Move negative
        dx = absposX - targetx;                        // Absolute movement requested
    }
    else {
        xdir = 1;                                    // Move positive
        dx = targetx - absposX;                        // Absolute movement requested
    }
    if (dx < (2 * rampSteps))                        // We need (2*rampsteps) to get to full speed and back to slow
    {                                                // If move is shorter than that ramp at exactly half way
        rampdn_pt = dx / 2;                            // Set the ramp down point at exactly half way
        rampcount = dx / 2;                            // Set the ramp up count to stop exactly half way
    }
    else {
        rampdn_pt = dx - rampSteps;                    // Otherwise start ramp down rampSteps from targetX
        rampcount = rampSteps;                        // Ramp up for ramp steps
    }
    deltaspeed = maxSpeed - minSpeed;                // Difference between two speeds
    curSpeed = minSpeed;                            // We start at min speed
    while (absposX != targetx)                        // Repeat until we reach target
    {
        LATC = StepArray[stepidx];                    // Step the motor
        stepidx += xdir;                            // Move the step index
        stepidx &= 0x7;                                // Zero to seven phase changes    
        absposX += xdir;                            // Update absolute position
        delayMS(delayval);                            // Cal for delay
        if (rampcount > 0 && rampdn_pt != 0)        // We have not reached end of ramp up or ramp down point so speed up
        {
            uint32_t temp;                            // 32bit because of multiply
            rampcount--;                            // One ramp up processes done
            temp = (rampSteps - rampcount);            // Transfer how far along ramp we are
            temp *= deltaspeed;                        // Multiply by deltaspeed
            temp /= rampSteps;                        // divid by ramp steps
            curSpeed = (uint16_t)temp;                // Transfer to curSpeed
            curSpeed += minSpeed;                    // Add the minimum speed
        }
        if (rampdn_pt == 0)                            // Opposite to ramp up we are counting down until ramp down time
        {
            uint32_t temp;                            // 32bit because of multiply
            rampcount--;                            // One ramp down processes done
            temp = rampupcount;                        // Transfer how far along ramp we are
            temp *= deltaspeed;                        // Multiply by deltaspeed
            temp /= rampSteps;                        // divid by ramp steps
            curSpeed = (uint16_t)temp;                // Transfer to curSpeed
            curSpeed += minSpeed;                    // Add the minimum speed
        }
        else {                                        // Counting until ramp time
            rampdn_pt--;                            // One step done .. no ramp until zero
            if (rampdn_pt == 0)                        // Check if ramp down started
                rampup_pt = rampSteps;                // Starting ramp down set ramp count
        }
        delayMS(1000 / curSpeed);                    // Set the delay for the speed
    }
}

int main(void)
{
    MoveMotorTo(10000, 50, 300, 200);  // Move to x = 10000  start 50 pps speed up to 300 pps in 200 steps
    MoveMotorTo(0, 50, 300, 200);      // Move back to 0 start 50 pps speed up to 300 pps in 200 steps
    MoveMotorTo(-10000, 50, 300, 200);  // Move to x = -10000 start 50 pps speed up to 300 pps in 200 steps
    MoveMotorTo(0, 50, 300, 200);      // Move back to 0 start 50 pps speed up to 300 pps in 200 steps
}

#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5