Code:
/*
* Project name:
Demo for MkE Stepper card
* Copyright:
(c) Acetronics
* Revision History:
0.0
* Status: Operationnal
* Description:
Demonstrate Stepper Commands.
Maximum frequency limited by the 40µs dead time to ~ 2.5 rpm / s @ 400 steps/rev ...
max clock Frequ is limited to 1100 x MS0 x MS1 Hz ...
Add 2 volts to supply for 3967 internal drop ...
* Test configuration:
MCU: Pic 16F877A
Dev.Board: EasyPic5
Oscillator: 8 Mhz
Ext. Modules: Stepper card on PortC
LCD 2x16 on PortB - Legacy Wiring
SW: MkC Pro 4.15
* NOTES:
Command Connexions:
PortA.0 : Accel rate - Analog
PortA.1 : Decel rate - Analog
PortA.2 : Unlock Motor
Porta.3 : DO NOT USE
Porta.4 : Emergency Stop @ Maximum rate
Porta.5 : Stop @ PortA.1 deceleration rate
Porta.6 : Increase Speed
PortA.7 : Decrease Speed
Pullups on PortA.2 to PortA.7
PortD.5 : Invert Rotation
Pullup on PortD.5
BUTTONS : GND when Pushed
Display connexions:
PortB : STD 2x16 LCD Connexions
Stepper card Connexions:
PortC.0 : Enable
PortC.1 : Step
PortC.2 : Reset
PortC.3 : Sleep
PortC.4 : MS1
PortC.5 : MS2
PORTC.6 : Dir
PortC.7 : Free
// Display :
First line displays Motor Status
Second line displays 1) Speed in % , 2) Acceleration Rate , 3) Deceleration Rate.
ENJOY ...
*/
# include "built_in.h"
// Port Aliases
# define Accel rate PortA.B0
# define Decel rate PortA.B1
# define Run PortA.B2
// # define Free PortA.B3 // A/D reserved
# define Emergency_B PortA.B4
# define Stop PortA.B5
# define Increase PortB.B6
# define Decrease PortB.B7
# define Enable PortC.B0
# define Step PortC.B1
# define Reset PortC.B2
# define Sleeep PortC.B3
# define MS1 PortC.B4
# define MS2 PortC.B5
# define Dir PORTC.B6
# define Alive PortC.B7
// # define Enable PortD.B0
// # define Step PortD.B1
# define Locked PortD.B2
// # define Sleeep PortD.B3
// # define MS1 PortD.B4
# define Reverse PortD.B5
# define Accen PortD.B6
# define Decen PortD.B7
// Variables
# define LoSpeedLimit 500 // (6µs) // Deadband 40µs !!!
# define HiSpeedLimit 20000
# define Debounce 20
// Lcd pinout settings *********************************************************
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D4 at RB0_bit;
// Pin direction ***************************************************************
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D7_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB0_bit;
// Types ***********************************************************************
bit oldstate, lock, Emergency, Rev ;
unsigned int Acc, Dec, Speedo, OldSpeed ,Speed , Speeds;
char text[7];
// Messages ********************************************************************
const char txt0[] = " "; // Blank Line
const char txt1[] = "mikroElektronika";
const char txt2[] = "EasyPIC5";
const char txt3[] = "Stepper Demo";
const char txt4[] = "Dir :"; // First Row
const char txt5[] = "Forward";
const char txt6[] = "Reverse";
const char txt7[] = "Speed :"; // Second Row
const char txt8[] = "Acc :";
const char txt9[] = "Dec :";
const char txt10[] = "Emerg. Brake lock"; // Third Row
const char txt11[] = "Locked";
const char txt12[] = "Decelerating ";
const char txt13[] = "Accelerating";
const char txt14[] = "Stopped";
const char txt15[] = "Waiting Start";
const char txt16[] = "Steady running";
const char txt17[] = "Auto Decelerate";
const char txt18[] = "Auto Accelerate";
const char txt19[] = "Invert Rotation";
//******************************************************************************
//******************************************************************************
void interrupt()
{
if ( PIR1.B0 == 1) // Timer Period ended
{
Step = ! Step; // Toggle Output
Speedo = 65550 - Speed ; // 15 units for interrupt
TMR1H = Hi(Speedo);
TMR1L = Lo(Speedo);
PIR1.B0 = 0; // Reset Flag
}
}
//******************************************************************************
void Text_To_LCD (unsigned Row, unsigned Col, const unsigned char *m) // Write ROM Messages to LCD
{
unsigned i = 0;
Lcd_Out(Row, Col,"");
while(m[i] != 0)
{
Lcd_Chr_Cp(m[i]);
i++;
}
}
//******************************************************************************
void Showstatus() // Show Motor Status
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt14 );
delay_ms(500);
}
//******************************************************************************
void Showspeed() // Show actual parameters
{
Lcd_Cmd(_LCD_RETURN_HOME );
if ( Emergency == 1 )
{
Text_to_LCD(1,1,txt0);
Text_To_LCD(1,1,txt10);
}
{
if (speed == HiSpeedLimit)
{
Speeds = 0;
}
else
{
Speeds = LoSpeedLimit*100/Speed;
}
WordtoStr(Speeds, text);
Lcd_Out(2,1,text);
WordtoStr(Acc, text);
Lcd_Out(2,6,text);
WordtoStr(Dec, text);
Lcd_Out(2,11,text);
}
delay_ms(500);
}
//******************************************************************************
void Read_Accel() // Read Acceleration rate
{
Acc = ADC_Read(0);
if (Acc == 0)Acc = 1 ; // Floor value = 1
Dec = ADC_Read(1);
if (Dec == 0)Dec = 1 ; // Floor value = 1
}
//******************************************************************************
void Decell() // Deceleration routine
{
if( Speed <= (HiSpeedLimit - Dec)) // Care for Underspeed
{
Speed += Dec ;
delay_ms(10);
Showspeed();
}
else // Motor will stop ...
{
T1CON.B0 = 0 ; // Stop TMR1 if motor Stopped
Step = 0; // Low Step Output
Speed = HiSpeedLimit;
ShowSpeed();
Showstatus();
}
}
//******************************************************************************
void Accell() // Acceleration routine
{
if( Acc < (Speed - LoSpeedLimit))
{
Speed -= Acc ;
}
else
{
Speed = LoSpeedLimit ; // Respect Speed Limit
}
delay_ms(10);
ShowSpeed();
}
//******************************************************************************
//******************************************************************************
void main()
{
// Registers Setup: ************************************************************
/*ANSEL = 0; // Configure AN pins as digital I/O
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;*/
CMCON = 7; // Comparators OFF
CVRCON = 0b00000000; // Vref OFF
ADCON0 = 0b1100001; // Adc Config 10 Bits ch 0,1,2 Analog.
ADCON1 = 0b1100100;
T1CON = 0b00010000; // Config Timer 1 : prescaler 1/2, Osc off, - off
CCP1CON = 0; // "CCPM" Config ( Disable all )
CCP2CON = 0;
// Interrupts *****************************************************************
INTCON = 0b11000000; // GIE and PIE Enabled
PIE1 = 0b00000001; // CCP1 int Enabled
PIR1 = 0;
PIE2 = 0;
PIR2 = 0;
// Config Ports ***************************************************************
PORTA = 0b11111111; // Input Control + pots
PORTB = 0b11000000; // LCD Display
PORTC = 0b00000000; // Stepper module control
PORTD = 0b00100000; // Led status display
PORTE = 0b00000000;
TRISA = 0b11111111;
TRISB = 0b11000000;
TRISC = 0b00000000;
TRISD = 0b01100000;
TRISE = 0b00000000; // PortD Digital I/O
// Variables Setup *************************************************************
OldState = 0;
Lock = 0; // Start in Locked Status
Emergency = 0;
Speed = HiSpeedLimit; // Reset to min Speed
OldSpeed = HiSpeedLimit;
Rev = 0; // Forward
T1CON.B0 = 0; // TMR1 Stopped
TMR1H = 0; // Reset TMR1
TMR1L = 0;
delay_ms(500); // LCD Power up delay
// LCD Initialization **********************************************************
LCD_Init();
Lcd_Cmd(_LCD_CLEAR); // Clear Lcd display:
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor OFF
Text_to_LCD ( 1,1,txt11 ); // Show Starting Status
// Output Setup ***************************************************************
Enable = 0; // PortC.B0
Step = 0; // PortC.B1
Reset = 1; // PortC.B2
Sleeep = 1; // PortC.B3
MS1 = 0; // PortC.B4
MS2 = 0; // PortC.B5
Dir = 0; // PORTC.B6
while(1)
{
/*Alive = 1 ; // Show it's alive
delay_ms(300);
Alive = 0;
delay_ms(300);*/
// Read_Inputs();
//******************************************************************************
//******************************************************************************
//void Read_Inputs() // Check Commands
// {
// Lock check***********************************************************
if ( Lock == 1 ) // if Unlocked
{
// 1) Check Emergency Stop *******************************************
if (Button(&PORTA, 4, Debounce, 0)) // Check Emergency Stop demand - Stops motor
{
oldstate = 1; // Update flag
Emergency = 1;
Dec = 1023; // Full Brake ( 64 Steps @ 10 ms)
while ( Speed < HiSpeedLimit )
{
Decell();
}
T1CON.B0 = 0; // TMR1 Stopped
Step = 0; // Low Step Signal
Lock = 0; // Lock Motor
Locked = 0; // Show locked
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt10 ); // Lcd_Out(1,1,"Emerg. Brake Lock");
Text_to_LCD ( 2,1,txt0 );
while (oldstate && Button(&PORTA, 4, Debounce, 0)){} // Loop until button released
oldstate = 0; // Button released - Update flag - Restart authorized
goto bailout;
}
// 2) Check for Direction when stopped ********************************
if ( Speed == HiSpeedLimit )
{
while (Button(&PORTD, 5, Debounce, 0)) // Check for Reverse Demand
{
oldstate = 1;
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt19 ); // Show " Invert Rotation
delay_ms(500);
}
if (oldstate && Button(&PORTD, 5, Debounce, 1)) // Reverse Button Released
{
T1CON.B0 = 0; // TMR1 Stopped to be sure
Step = 0; // Low Step Output
Alive = 1;
Rev = ~ Rev; // invert rotation
Dir = ~ Dir;
Text_to_LCD ( 1,1,txt0 );
if ( Dir == 0 )
{
Text_to_LCD ( 1,1,txt5 ); // Lcd_Out(1,1,"Forward");
}
else
{
Text_to_LCD ( 1,1,txt6 ); // Lcd_Out(1,1,"Reverse");
}
}
delay_ms(500);
oldstate = 0;
Alive = 0;
}
// Now we can do something else
// 2) Check for Increase Speed IF Unlocked*****************************
if (Speed >= LoSpeedLimit)
{
PortD.B0 = 1; // show accel / Decel enabled
while (Button(&PORTB, 6, Debounce, 0)) // Check Increase demand - Increases motor until released
{
oldstate = 1; // Update flag
if ( Speed == HiSpeedLimit) // If motor stopped
{
T1CON.B0 = 1; // Restart TMR1 @ Slow Speed;
PortD.B6 = 1; // Show Accel Led
}
Read_Accel(); // Read Accel Value
//Acc = Acc << 6; // Scale to 16 Bits
if( Speed > LoSpeedLimit )
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt13 ); // Lcd_Out(1,1,"Accelerating");
Accell();
}
else
{
Text_to_LCD ( 1,1,txt16 ); // Lcd_Out(1,1,"Steady running");
}
delay_ms(200);
}
if (oldstate && Button(&PORTB, 6, Debounce, 1)) // Accel Released
{
oldstate = 0; // Update flag
PortD.B6 = 0; // Clear Accel Led
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt16 ); // Lcd_Out(1,1,"Steady running");
delay_ms(200);
}
}
// Decrease Speed Only if motor running !!!
if ( Speed < HiSpeedLimit )
{
// 3) Check for Slow Stop demand *******************************
if (Button(&PORTA, 5, Debounce, 0)) // Check Stop demand - Stops motor slowly
{
oldstate = 1; // Update flag
Read_Accel(); // Read Brake Value
//Dec = Dec << 6; // Scale to 16 Bits
while( Speed < HiSpeedLimit )
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt17 ); // Lcd_Out(2,1,"Auto Decelerate");
Decell();
delay_ms(200);
}
T1CON.B0 = 0; // TMR1 Stopped
Step = 0; // Low Step Output
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt14 ); // Lcd_Out(1,1,"Stopped ");
// Lock = 0; // Lock Motor once stopped - not compulsory
}
if (oldstate && Button(&PORTA, 5, Debounce, 1)) // Stop Released
{
oldstate = 0; // Update flag
}
// Check for Direction *******************************************
while (Button(&PORTD, 5, Debounce, 0)) // Check for Reverse Demand
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt19 ); // Show " Invert Rotation
delay_ms(500);
oldstate = 1;
}
if (oldstate && Button(&PORTD, 5, Debounce, 1)) // Reverse Button Released
{
OldState = 0;
OldSpeed = Speed; // memorize current Speed
Read_Accel();
while( Speed < HiSpeedLimit ) // Decelerate to stop
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt17 ); // Lcd_Out(1,1,"Auto Decelerate");
Decell();
delay_ms(200);
}
T1CON.B0 = 0; // TMR1 Stopped
Step = 0; // Low Step Output
delay_ms(500);
Rev = ~ Rev; // invert rotation
Dir = ~ Dir;
Text_to_LCD ( 1,1,txt0 );
if ( Dir == 0 )
{
Text_to_LCD ( 1,1,txt5 ); // Lcd_Out(1,1,"Forward");
}
else
{
Text_to_LCD ( 1,1,txt6 ); // Lcd_Out(1,1,"Reverse");
}
delay_ms(500);
// Locked = 1; // Show Motor Unlocked
T1CON.B0 = 1;
Read_Accel();
while( Speed > OldSpeed ) // Accelerate to OldSpeed
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt18 ); // Lcd_Out(1,1,"Auto Accelerate");
Accell();
delay_ms(200);
}
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt16 ); // Lcd_Out(1,1,"Steady running");
}
// 4) Check for Decrease Speed *********************************
while (Button(&PORTB, 7, Debounce, 0)) // Check Slow demand - Slows motor until released
{
oldstate = 1; // Update flag
Read_Accel(); // Read Brake Value
//Dec = Dec << 6; // Scale to 16 Bits
if( Speed < HiSpeedLimit ) // is Motor Running ???
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt12 ); // Lcd_Out(1,1,"Decelerating");
Decell();
delay_ms(200);
PortD.B7 = 1;
}
else // NO Motor Stopped
{
T1CON.B0 = 0; // TMR1 Stopped
Step = 0; // Low Step Output
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt14 ); // Lcd_Out(1,1,"Stopped");
}
}
if (oldstate && Button(&PORTB, 7, Debounce, 1)) // Stop Released
{
oldstate = 0; // Update flag
if ( Speed != HiSpeedLimit) // IF motor Stopped
{
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt16 ); // Lcd_Out(1,1,"Steady running");
}
delay_ms(200);
PortD.B7 = 0;
}
}
}
bailout:
// If Motor Locked ... Check for Start !!! ****************************
if (Lock == 0) // if locked
{
if (Button(&PORTA, 2, Debounce, 0)) // Check for Start Demand
{
Oldstate = 1;
}
if (oldstate && Button(&PORTA, 2, Debounce, 1)) // Start Button Released - Motor unlocked
{
T1CON.B0 = 0; // TMR1 Stopped
Speed = HiSpeedLimit; // Slow Speed
Emergency = 0; // Disengage Emergency
Text_to_LCD ( 1,1,txt0 );
Text_to_LCD ( 1,1,txt15 ); // Lcd_Out(1,1,"Waiting Start");
Lock = 1; // Unlock Motor
Locked = 1; // Show Motor Unlocked
delay_ms(500); // Min Delay to read
oldstate = 0; // Update flag
}
}
} // Process inputs
// }
}
I do agree it's not PicBasicPro
Bookmarks