I had some issues with the code on the Pic Processor and I would like to post that information for the sake of someone else who might want more background on a design close to this one.
Here is the link: https://forum.microchip.com/s/topic/a5CV40000002DZ3MAM/t398142
The software I used was used to operate another and simpler motor, but not a stepper. I added the Stepper Motor Code to it, most of it with MP6022 names for the routines. I include the main.c file here simply so you can see what I am attempting or how I am testing the MP6022. The important part is setup and operation of the MP6022. I did not write this code for you to look at, so ask me if you have questions about what part I think it doing what with; it is probably difficult to follow without some study. I think writing a “1” to the Ctrl.step bit should make the motor advance.
At the first occurrence of “for(int i = 0; i < 200; i++) {” is where I have the motor setup as in the application node and am sending STEP commands - expecting the motor to operate.
Here is main.c
/*
- File: main.c
- Author: tmiller
*/
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include “user.h”
#include “system.h”
#include “MP6602.h”
volatile unsigned int pulseCount;
volatile unsigned int Timer0Int;
char lastStep;
unsigned int nFault = 0;
extern unsigned int SPIRead, ReadSDI;
unsigned int MP6602RegisterValues[8];
int main(int argc, char** argv) {
static unsigned char Answer1, Answer2;
unsigned long int i;
int avgIntPerRev; // Calibrated value of interrupts in Capacitance range.
int totalintLimit;
double tuning;
double oldtuning;
int numberOfSteps;
int oldNumberOfSteps;
unsigned char direction;
unsigned int oldPulseCount;
unsigned int stepCount;
unsigned int savPulseCount;
unsigned int firstPulseCount = 0;
char buf[10], sbuf[5];
unsigned int OffTimeChanged = 0;
unsigned int StepModeChanged = 0;
unsigned int EnableChanged = 0;
unsigned int BlankingTimeChanged = 0;
unsigned int SteppingCurrentLimitChanged = 0;
unsigned int StepIndexChanged = 0;
unsigned int Faultschanged = 0;
unsigned int STEPChanged = 0;
PMD0bits.NVMMD = 1; // Disable NVM Module
PMD1bits.NCOMD = 1; // Disable NCO
PMD1bits.TMR6MD = 1; // Disable TMR6
PMD1bits.TMR5MD = 1; // Disable TMR5
PMD1bits.TMR4MD = 1; // Disable TMR4
PMD1bits.TMR3MD = 1; // Disable TMR3
PMD2bits.DACMD = 1; // Disable DAC
PMD3bits.CWG1MD = 1; // Disable CWG
PMD3bits.CWG2MD = 1; // Disable CWG
PMD3bits.PWM6MD = 1; // Disable PWM
PMD3bits.CCP4MD = 1; // Disable Capture and Compare
PMD3bits.CCP3MD = 1;
PMD3bits.CCP2MD = 1;
PMD3bits.CCP1MD = 1;
PMD4bits.UART1MD = 1; // Disable UART1
PMD4bits.MSSP2MD = 1; // Disable MSSP
PMD5bits.CLC1MD = 1; // Disable Configure Logic Cell
PMD5bits.CLC2MD = 1; // Disable CLC2
PMD5bits.CLC3MD = 1; // Disable CLC3
PMD5bits.CLC4MD = 1; // Disable CLC4
PMD5bits.DSMMD = 1; // Disable DSM
// MP6602 FAULT Pin Configuration
// The nFAULT pin reports fault conditions and
// is driven low when a fault condition occurs.
// If the fault condition is released, the nFAULT
// pin is pulled high by an external pull up resistor.
// So long as the pin is high there is no fault condition 1=NoFault
// It reflects the bit setting in the FAULT register
LATCbits.LATC5 = 0; // Clear the Latch of the FAULT pin
ANSELCbits.ANSC5 = 0; // Digital port
ODCONCbits.ODCC5 = 1; // Open Drain (Sink Current Only) Disabled
TRISCbits.TRISC5 = 1; // Fault pin of MP6022
WPUCbits.WPUC5 = 1; // The MP6602 nFault Pin is pulled high by this resistor
// Port Control
// 18345 Output LED
ANSELAbits.ANSA5 = 0; // Digital pin
INLVLAbits.INLVLA5 = 0; // TTL Input Level for Input / Its an Output Pin
LATAbits.LATA5 = 0; // Nothing out yet
ODCONAbits.ODCA5 = 0; // Open Drain on (Sink Current Only) OFF/ its output
SLRCONAbits.SLRA5 = 1; // Slew Rate Control on - to make it easier on the processor
TRISAbits.TRISA5 = 0; // Port is Output
WPUAbits.WPUA5 = 0; // Weak Pull Up Resistor not used.
LATAbits.LATA5 = 1;
// Enable Pin MP6602
ANSELCbits.ANSC1= 0; // Digital Pin
INLVLCbits.INLVLC1 =0; //TTL Input -its an output
ODCONCbits.ODCC1 = 1; // Not Open Drain (Sinks and Sources current)
SLRCONCbits.SLRC1 = 1; // Slew Rate Control On
TRISCbits.TRISC1 = 0; // Output to enable/disable (Pin,not register)
WPUCbits.WPUC1 = 0; // No pull up (i is internal pull down)
LATCbits.LATC1 = 0; // MP6602 Not Enabled through this pin
// Step Pin MP6602
ANSELCbits.ANSC2 = 0; // Digital Pin
INLVLCbits.INLVLC2 =0; //TTL Input -its an output
ODCONCbits.ODCC2 = 1; // Not Open Drain (Sinks and Sources current)
SLRCONCbits.SLRC2 = 1; // Slew Rate Control On
TRISCbits.TRISC2 = 0; // Output to STEP (Pin,not register)
WPUCbits.WPUC2 = 0; // No pull up (i is internal pull down)
LATCbits.LATC2 = 0; // MP6602 Not Enabled through this pin
// DIR (direction) Pin MP6602
ANSELCbits.ANSC4= 0; // Digital Pin
INLVLCbits.INLVLC4 =0; //TTL Input -its an output
ODCONCbits.ODCC4 = 1; // Not Open Drain (Sinks and Sources current)
SLRCONCbits.SLRC4 = 1; // Slew Rate Control On
TRISCbits.TRISC4 = 0; // Output to DIR (Pin,not register)
WPUCbits.WPUC4 = 0; // No pull up (i is internal pull down)
LATCbits.LATC4 = 0; // MP6602 Not Enabled through this pin
INTCONbits.GIE = 1; // Enable all interrupts that are enabled.
INTCONbits.PEIE = 1;
CLKRCONbits.CLKREN = 0; // Reference clock disabled.
#ifdef USE_IOC
PIE1 = 1; // Enable timer 2 interrupt
INTCONbits.GIE = 1; // Enable all interrupts that are enabled.
INTCONbits.INTE = 0;
// Stepper Motor Setup
RB6PPS = 0b11000; // RC6 port at pin 11 is assigned as SCK1
SSP1CLKPPS = 0b01110; // SCLK1 is at RB6
RB5PPS = 0b11001; // RB5 port at pin 12 is assigned as SDO1
SSP1DATPPS = 0b1100; // Peripheral SSP1SDI is at RB4
SSP1SSPPS = 0b10110; // SS1 is at RC6 pin 8
LATBbits.LATB4 = LATBbits.LATB5 = LATBbits.LATB6 = LATCbits.LATC6 = 0;
ANSELBbits.ANSB4 = ANSELBbits.ANSB5 = ANSELBbits.ANSB6 = ANSELCbits.ANSC6 = 0; // Digital pins
WPUBbits.WPUB4 = WPUBbits.WPUB5 = WPUBbits.WPUB6 = WPUCbits.WPUC6 = 1; // Weak Pull ups
ODCONBbits.ODCB4 = 1; // Open drain (sink current only)
SLRCONBbits.SLRB4 = 1; // Slew Rate enabled (slows it down)
INLVLBbits.INLVLB4 = 1; // ST input (lower voltage for high)
TRISBbits.TRISB4 = 1; // SDI (TRIS=1) RB4/13
TRISBbits.TRISB5 = 0; // SDO (TRIS=0) RB5/12
TRISBbits.TRISB6 = 0; // SCLK (TRIS=0) RB6/11
TRISCbits.TRISC6 = 0; // ~SS (TRIS=1) RC6/8
// SP1BRG = 0x13; // 400kHz
// SPI Interrupts
PIR1bits.SSP1IF = 0; // Clear Read/Write Status interrupt Flag
PIR1bits.BCL1IF = 0; // Clear Bit Collision on SPI1 interrupt Flag
PIE1bits.SSP1IE = 1; // Read or write complete on SPI1
PIE1bits.BCL1IE = 1; // Bit Collision on SPI1
// PMD4bits.MSSP1MD = 0; // Enable MSSP module to set ports
SSP1ADD = 0x13; // 400kHz
SSP1CON1bits.SSPM = 0b1010; // SPI Master Mode, clock = FOSC/4 = 32MHz/64 = 500kHz
SSP1CON1bits.CKP = 1; // Clock idle (Clock Polarity) state is high so MP6620 Data shifts on the rising edge of SCLK
SSP1STATbits.CKE = 0; // Transmit occurs on transition from active to idle clock state.
SSP1STATbits.SMP = 0; // Input data sampled at end of data output time.
SSP1CON1bits.SSPEN = 1; // ENable SPI
LATCbits.LATC7 = 0;
LATCbits.LATC1 = 0;
LATBbits.LATB7 = 0;
LATCbits.LATC2 = 0;
LATCbits.LATC4 = 0;
ANSELCbits.ANSC7 = 0; // Reset Pin digital
ANSELCbits.ANSC1 = 0; // Enable Pin digital
ANSELBbits.ANSB7 = 0; // Sleep Pin digital
ANSELCbits.ANSC2 = 0; // STEP Pin digital
ANSELCbits.ANSC4 = 0; // DIR Pin digital
TRISCbits.TRISC7 = 0; // Reset Pin output
TRISCbits.TRISC1 = 0; // Enable Pin output
TRISBbits.TRISB7 = 0; // Sleep Pin Output
TRISCbits.TRISC2 = 0; // STEP pin Output
TRISCbits.TRISC4 = 0; // DIR Pin Output
// Leave enable pin dis-enabled (C1)
// Leave out of sleep (B7)
// Leave STEP not stepping (C2)
// Leave DIR the same (low/C4)
// Reset MP6602 - drive pin 7 reset low
WPUCbits.WPUC7 = 1; // Enable weak pull up on Reset Pin
LATCbits.LATC7 = 1; // Pull up Reset to end RESET (C7)
LATBbits.LATB7 = 0; // Sleep mode inactive
LATCbits.LATC1 = 0; // Enable through register, not pin
__delay_ms(1);
static unsigned int CtrlValue;
static unsigned int RegisterValue;
//
// First one does not work well.
CtrlValue = ReadMP6602(0x00);
FAULTRegValue = ReadMP6602(0x0E); // Read the Fault register because VCCUV is holding the device in RESET mode
FillFAULTRegStruct(FAULTRegValue); // Fill in the structure
FAULTReg.VCCUV = 1; // Write a 1 to VCCUV to clear Reset mode
FAULTRegValue = MakeFAULTRegDataInteger(); // Make the integer to write to the FAULT register
WriteMP6602(0x0E,FAULTRegValue); // Write to the FAULT Register
FAULTRegValue = ReadMP6602(0x0E); // Read it back to verify
// Read All The Initial Register Values
CtrlRegValue = MP6602RegisterValues[0] = ReadMP6602(0x00);
Ctrl2RegValue = MP6602RegisterValues[1] = ReadMP6602(0x02);
ISETRegValue = MP6602RegisterValues[2] = ReadMP6602(0x04);
StallRegValue = MP6602RegisterValues[3] = ReadMP6602(0x06);
BEMFRegValue = MP6602RegisterValues[4] = ReadMP6602(0x08);
TSTPRegValue = MP6602RegisterValues[5] = ReadMP6602(0x0A);
OCPRegValue = MP6602RegisterValues[6] = ReadMP6602(0x0C);
FAULTRegValue = MP6602RegisterValues[7] = ReadMP6602(0x0E);
// Read Control Register 1 and fill in the CtrlReg Structure
// It includes the hold time, the off time, the step mode/increment,
// the direction, step, and enable commands.
ISETRegValue = ReadMP6602(0x04); // Read the ISET Register
FillISETRegStruct(ISETRegValue); // Fill in the stored Structure copy
ISETReg.PeakCurrentStepping.IS = 0x0b; // Set Step Current at 1.5 Amperes
ISETRegValue = MakeISETRegDataInteger(); // Make the new Data Value word.
WriteMP6602(0x04,ISETRegValue); // Configure the MP6602
ISETRegValue = ReadMP6602(0x04); // Read the ISET Register to confirm
CtrlRegValue = ReadMP6602(0x00); // Read Ctrl Register to change off time
FillCtrlRegStruct(CtrlRegValue); // Fill in processor memory copy
CtrlReg.OffTime.OT = 0b111; // Modify (fixed) Off Time (between steps)
CtrlRegValue = MakeCtrlRegDataInteger(); // Make the register transmit value
WriteMP6602(0x00,CtrlRegValue); // Write to the Motor Controller (MP6602)
CtrlRegValue = ReadMP6602(0x00); // Read back Ctrl to confirm
Ctrl2RegValue = ReadMP6602(0x02); // Read Ctrl2 Register to change blanking time
FillCtrlRegStruct(Ctrl2RegValue);
Ctrl2Reg.BlankingTime.BT = 0b111;
Ctrl2RegValue = MakeCtrl2RegDataInteger();
WriteMP6602(0x02,Ctrl2RegValue);
Ctrl2RegValue = ReadMP6602(0x02); // Read Back Ctrl2 to verify
CtrlRegValue = ReadMP6602(0x00); // Read Ctrl Register to change Step Mode
FillCtrlRegStruct(CtrlRegValue);
CtrlReg.StepModeTime.MS = 0b101;
CtrlRegValue = MakeCtrlRegDataInteger();
WriteMP6602(0x00,CtrlRegValue);
CtrlRegValue = ReadMP6602(0x00); // Read Ctrl Register to verify
TSTPRegValue = ReadMP6602(0x0A); // Read TSTP Register to start step counter at 0
FillCtrlRegStruct(TSTPRegValue);
TSTPReg.StepIndex.STP = 0;
TSTPRegValue = MakeTSTPRegDataInteger();
WriteMP6602(0x0A,TSTPRegValue);
TSTPRegValue = ReadMP6602(0x0A); // Read TSTP Register to verify
CtrlRegValue = ReadMP6602(0x00); // Read Ctrl Register to set enable bit
FillCtrlRegStruct(CtrlRegValue);
CtrlReg.EN = 1;
CtrlRegValue = MakeCtrlRegDataInteger();
WriteMP6602(0x00,CtrlRegValue);
CtrlRegValue = ReadMP6602(0x00); // Read Ctrl Register to set enable bit
FillCtrlRegStruct(CtrlRegValue);
CtrlReg.STEP = 1;
CtrlRegValue = MakeCtrlRegDataInteger();
unsigned int changed = checkRegisterValues(CtrlRegValue,Ctrl2RegValue,ISETRegValue,StallRegValue,BEMFRegValue,TSTPRegValue,OCPRegValue,FAULTRegValue);
if(changed & 0b10000000)
if (!((CtrlRegValue&0b000000000010) & 0b000000000010))
NOP(); // Step Changed
if(changed & 0b00010000)
NOP(); // Stall changed
if(changed & 0b00001000)
NOP(); // BEMF changed
for(int i = 0; i < 200; i++) {
WriteMP6602(0x00,CtrlRegValue);
CtrlRegValue = ReadMP6602(0x00); // Read Ctrl Register to set enable bit
FillCtrlRegStruct(CtrlRegValue);
TSTPRegValue = ReadMP6602(0x0A);
CtrlReg.STEP = 1;
CtrlRegValue = MakeCtrlRegDataInteger();
TSTPRegValue = ReadMP6602(0x0A); // Read TSTP Register to start step counter at 0
FillCtrlRegStruct(TSTPRegValue);
__delay_ms(1000);
}
TSTPRegValue = ReadMP6602(0x0A);
FillTSTPRegStruct(TSTPRegValue);
for (int i = 0; i< 200; i++) {
TSTPReg.StepIndex.STP = 0;
TSTPRegValue = MakeCtrlRegDataInteger();
WriteMP6602(0x0A,TSTPRegValue);
TSTPReg.StepIndex.STP = 0x20;
TSTPRegValue = MakeCtrlRegDataInteger();
WriteMP6602(0x0A,TSTPRegValue);
}
changed = checkRegisterValues(CtrlRegValue,Ctrl2RegValue,ISETRegValue,StallRegValue,BEMFRegValue,TSTPRegValue,OCPRegValue,FAULTRegValue);
if(changed & 0b10000000)
if (!((CtrlRegValue&0b000000000010) & 0b000000000010))
NOP(); // Step Changed
if(changed & 0b00010000)
NOP(); // Stall changed
if(changed & 0b00001000)
NOP(); // BEMF changed
for(int i = 0; i < 10; i++) {
PORTCbits.RC2 = 1; // Step
}
// Change the stored copy
// while(1) {
// Alter the memory copy of the first Control register to step
// CtrlReg.STEP = 1;
// Make the data integer to write to the MP6602
// CtrlRegValue = MakeCtrlRegDataInteger(); // Fill in the bitwise Ctrl Register Value
// Write the new contents with the step bit set (should step the motor)
// CtrlValue = WriteMP6602(0x00,CtrlRegValue); // Write the new value
// Read ALL the Registers and fill in the associcated structures.
while(!(OffTimeChanged || StepModeChanged || EnableChanged ||
BlankingTimeChanged || SteppingCurrentLimitChanged ||
StepIndexChanged || Faultschanged)) {
CtrlRegValue = ReadMP6602(0x00);
FillCtrlRegStruct(CtrlRegValue);
if(CtrlReg.OffTime.OT != 0b111)
OffTimeChanged = 1;
if(CtrlReg.StepModeTime.MS != 5)
StepModeChanged = 1;
if(CtrlReg.EN != 1)
EnableChanged = 1;
Ctrl2RegValue = ReadMP6602(0x02);
FillCtrl2RegStruct(Ctrl2RegValue);
if(Ctrl2Reg.BlankingTime.BT != 0b111)
BlankingTimeChanged = 1;
ISETRegValue = ReadMP6602(0x04);
FillISETRegStruct(ISETRegValue);
if(ISETReg.PeakCurrentStepping.IS != 0x0B)
SteppingCurrentLimitChanged = 1;
StallRegValue = ReadMP6602(0x06);
FillStallRegStruct(StallRegValue);
BEMFRegValue = ReadMP6602(0x08);
FillBEMFRegStruct(BEMFRegValue);
TSTPRegValue = ReadMP6602(0x0A);
FillTSTPRegStruct(TSTPRegValue);
if(TSTPReg.StepIndex.STP != 0)
StepIndexChanged = 1;
OCPRegValue = ReadMP6602(0x0C);
FillOCPRegStruct(OCPRegValue);
FAULTRegValue = ReadMP6602(0x0E);
FillFAULTRegStruct(FAULTRegValue);
if(FAULTRegValue != 0)
Faultschanged = 1;
__delay_ms(2000);
};
// // Record the change to the 1st Control Structure (so I can see what changed)
// FillCtrlRegStruct(CtrlRegValue);
// // Read the Step Table register to see if it increments
// TSTPRegValue = ReadMP6602(0x0A); // Read the Step Register
// // Record the state of the step table to the memory structure
// FillTSTPRegStruct(TSTPRegValue); // fill in the most recent data.
// }
CtrlRegValue = ReadMP6602(0x00); // Read the new value from the MP6602
CtrlRegValue = MakeCtrlRegDataInteger();
while(1) {
// CtrlValue = WriteMP6602(0x0,CtrlValue);
NOP();
// CtrlRegValue = ReadMP6602(0x00);
}
CtrlValue = WriteMP6602(0x0,CtrlRegValue);
CtrlRegValue = ReadMP6602(0x00);
CtrlValue = WriteMP6602(0x0,CtrlRegValue);
CtrlRegValue = ReadMP6602(0x00);
CtrlValue = WriteMP6602(0x0,CtrlRegValue);
// ISETReg.ISETRegValue = ReadMP6022(0x40);
// StallReg.StallRegValue = ReadMP6022(0x60);
// BEMFReg.BEMFRegValue = ReadMP6022(0x80);
// TSTPReg.TSTPRegValue = ReadMP6022(0xA0);
// OCPReg.OCPRegValue = ReadMP6022(0xC0);
// FAULTReg.FAULTRegValue = ReadMP6022(0xE0);
SPIRead = 0; // Do not read on interrupt
LATCbits.LATC6 = 1; // Slave not selected
RegisterValue = ReadMP6602(0x0);
RegisterValue = RegisterValue ^ 0x038; // Exclusive or will zero all these bits out
RegisterValue = RegisterValue | 0x028; // Set the step size in 3 bits (1/32)
RegisterValue = WriteMP6602(0x0, RegisterValue); // 1/32 step size
RegisterValue = WriteMP6602(0x0,0x100); // Off Time (default 40us)
RegisterValue = WriteMP6602(0x2,0x004); // Blanking time (default 2us)
RegisterValue = WriteMP6602(0x4,0x280); // Hold Mode steeping 1.5A
RegisterValue = WriteMP6602(0x0,0x200); // Time until Automatic Hold Time stops (15.6ms)