Firmware for MC33926 evaluation on KL25Z-based EVB. This works with a Graphical User Interface (GUI) available on NXP.com to control a brushed DC motor using FRDM-33926ESEVM or FRDM-33926PNBEVM. The code enables control of the PWM frequency, duty cycle, enable/disable controls, invert, slew rate control, real-time current monitoring, and includes status flag pin monitoring for undervoltage, short circuit and over-temperature events.

Dependencies:   USBDevice mbed

Fork of Brushed_DC_Motor_Control_MC33926 by Travis Alexander

main.cpp

Committer:
nxf42866
Date:
14 months ago
Revision:
3:d7fd752817e1
Parent:
2:d98eb31a4b69

File content as of revision 3:d7fd752817e1:

#include "mbed.h"
#include "USBHID.h"

// We declare a USBHID device.
// HID In/Out Reports are 64 Bytes long
// Vendor ID (VID):     0x15A2
// Product ID (PID):    0x0138
// Serial Number:       0x0001
USBHID hid(64, 64, 0x15A2, 0x0138, 0x0001, true);

// Setup Digital Outputs for the LEDs on the FRDM
//PwmOut red_led(LED1);
//DigitalOut green_led(LED2);
//DigitalOut blue_led(LED3);

//Setup PWM and Digital Outputs from FRDM-KL25Z to FRDM-17510
PwmOut IN1(PTA5); // Pin IN1 input to MC33926 (FRDM PIN Name)
PwmOut IN2(PTC8); // Pin IN2 input to MC33926 (FRDM PIN Name)
DigitalOut EN(PTE0); // Pin EN input to MC33926 (FRDM PIN Name)
DigitalOut DIS1(PTA2); //  Pin D1 input to MC33926 (FRDM PIN Name)
DigitalOut D2B(PTD5); //  Pin D2B input to MC33926 (FRDM PIN Name)
DigitalOut SLEW(PTA13); //  Pin Slew input to MC33926 (FRDM PIN Name)
DigitalOut INV(PTD0); //  Pin INV input to MC33926 (FRDM PIN Name)
DigitalIn SFB(PTB3); // Pin SF_B output from MC33926 to FRDM-KL25Z
AnalogIn CFB(PTB0); // Pin FB output from MC33926 to FRDM-KL25Z
//DigitalOut READY(PTC7); // Pin READY input to Motor Control Board (FRDM PIN Name)

// Variables
int pwm_freq_lo;
int pwm_freq_hi;
int frequencyHz = 500;
int runstop = 0;
int direction = 1;
int braking;    // does not require initialization
int dutycycle = 75;
int newDataFlag = 0;
int status = 0;
uint16_t CurrFB; 
uint16_t CFBArray[101];
uint32_t CFBTotal;
uint16_t CFBAvg;
uint16_t CFBtemp;

// Storage for send and receive data
HID_REPORT send_report;
HID_REPORT recv_report;

bool initflag = true;

// USB COMMANDS
// These are sent from the PC
#define WRITE_LED   0x20
#define WRITE_GEN_EN  0x40
#define WRITE_DUTY_CYCLE  0x50
#define WRITE_PWM_FREQ  0x60
#define WRITE_RUN_STOP  0x70
#define WRITE_DIRECTION  0x71
#define WRITE_BRAKING  0x90
#define WRITE_RESET  0xA0
#define WRITE_D1  0xB1
#define WRITE_EN 0xC1
#define WRITE_D2B 0xD5
#define WRITE_SLEW 0xE5
#define WRITE_INV 0xF5

#define scaleFactor 0.11868

// LOGICAL CONSTANTS
#define OFF             0x00
#define ON              0x01


int main() 
{
    send_report.length = 64;
    recv_report.length = 64;
    
    
    while(1) 
    {
               //try to read a msg
        if(hid.readNB(&recv_report)) 
        {
            switch(recv_report.data[0])     //byte 0 of recv_report.data is command   
            {
//-----------------------------------------------------------------------------------------------------------------
//          COMMAND PARSER
//-----------------------------------------------------------------------------------------------------------------
////////
                case WRITE_LED:
                    break;
////////                    

////////              
                 case  WRITE_DUTY_CYCLE:
                    dutycycle = recv_report.data[1];
                    newDataFlag = 1;
                    break;
////////                
                 case  WRITE_PWM_FREQ:                      //PWM frequency can be larger than 1 byte
                    pwm_freq_lo = recv_report.data[1];      //so we have to re-assemble the number
                    pwm_freq_hi = recv_report.data[2] * 100;
                    frequencyHz = pwm_freq_lo + pwm_freq_hi;
                    newDataFlag = 1;
                    break;
////////                
                case  WRITE_RUN_STOP:
                    newDataFlag = 1;                
                    if(recv_report.data[1] != 0)
                    {
                         runstop = 1;           // outputs on, run motor
                    }
                    else
                    {
                         runstop = 0;           // outputs off, brake motor
                    } 
                    break;                    
 
////////                
                case  WRITE_DIRECTION:
                    newDataFlag = 1;
                     if(recv_report.data[1] == 1)
                    {
                         direction = 1;         // corrected allocation for FWD
                         //direction = 0;
                    }
                    else
                    {
                         direction = 0;         // corrected allocation for REV
                         //direction = 1;
                    }                    
                    break;
////////
                case  WRITE_BRAKING:
                    newDataFlag = 1;                
                    if(recv_report.data[1] != 0)
                    {
                            braking = 1;        // this is HS recirc
                    }
                    else
                    {
                            braking = 0;        // this is LS recirc
                    }
                    break;
////////                   
                case WRITE_D1:
                    newDataFlag = 1;                                
                    if(recv_report.data[1] == 1)
                    {
                        DIS1 = 1;               // logic hi disables the part
                    }
                    else
                    {
                        DIS1 = 0;               // logic lo enables the part
                    }
                    break;                    
////////
                case WRITE_EN:
                    newDataFlag = 1;                
                    if(recv_report.data[1] == 1)
                    {
                       //EN  = 0;
                       EN = 1;                  // logic hi enables the part
                    }
                    else
                    {
                       //EN = 1;
                       EN = 0;                  // logic lo disable the part
                    }
                    break;                    
////////
               case WRITE_D2B:
                    newDataFlag = 1;                                
                    if(recv_report.data[1] == 1)
                    {
                        D2B = 1;                // logic hi enables the part
                    }
                    else
                    {
                        D2B = 0;                // logic lo disables the part
                    }
                    break;       

////////
               case WRITE_SLEW:
                    newDataFlag = 1;                                
                    if(recv_report.data[1] == 1)
                    {
                        SLEW = 1;               // logic hi prompts FAST slew
                    }
                    else
                    {
                        SLEW = 0;               // logic lo prompts SLOW slew
                    }
                    break;       

////////
               case WRITE_INV:
                    newDataFlag = 1;                                
                    if(recv_report.data[1] == 1)
                    {
                        INV = 1;                // logic hi inverts operation
                        //INV = 0;
                    }
                    else
                    {
                        INV = 0;                // logic lo does not invert operation
                        //INV = 1;
                    }
                    break;       

                
////////                
                default:
                    break;
            }// End Switch recv report data[0]

//-----------------------------------------------------------------------------------------------------------------
//      end command parser    
//-----------------------------------------------------------------------------------------------------------------

            status = SFB;    
            send_report.data[0] = status;      // Echo Command
            send_report.data[1] = recv_report.data[1];      // Echo Subcommand 1
            send_report.data[2] = recv_report.data[2];      // Echo Subcommand 2
            send_report.data[3] = 0x00;
            send_report.data[4] = 0x00;
            send_report.data[5] = 0x00;
            send_report.data[6] = (CFBAvg << 8) >> 8;
            send_report.data[7] = CFBAvg >> 8;
              
            //Send the report
            hid.send(&send_report);
        }// End If(hid.readNB(&recv_report))
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//End of USB message handling        
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        CurrFB = CFB.read_u16();
        CFBArray[0] = CurrFB;
        CFBTotal = 0;
        int i = 0;
        for(i=0; i<100; i++)
        {
        CFBTotal = CFBTotal + CFBArray[i];
        }
        CFBAvg =  CFBTotal / 100;
        
        for(i=100; i>=0; i--)
        {
           
           CFBArray[i+1] = CFBArray[i];
        }

        if(newDataFlag != 0)                            //GUI setting changed
        {
            newDataFlag = 0;
            if(runstop != 0)                            //Running 
            {
                if(direction == 0)                      //reverse
                {
                    if(braking == 1)                    //dynamic
                    {
                        IN1.period(1/(float)frequencyHz);    
                        //IN1 = (float)dutycycle/100.0; // REV + HS, inverted d
                        IN1 = 1.0-((float)dutycycle/100.0); // REV + HS
                        IN2 = 1;
                    }
                    else                                //coast
                    {
                        IN1 = 0;
                        IN2.period(1/(float)frequencyHz);  
                        IN2 = (float)dutycycle/100.0;   // REV + LS                                    
                    }
                }
                else                                    //forward
                {
                    if(braking == 1)                    //dynamic    
                    {
                        IN1 = 1;                        
                        IN2.period(1/(float)frequencyHz); 
                        //IN2 = (float)dutycycle/100.0;   // FWD + HS, inverted d
                        IN2 = 1.0-((float)dutycycle/100.0); // FWD + HS
                    }
                    else                                //coast
                    {
                        IN1.period(1/(float)frequencyHz);  
                        IN1 = (float)dutycycle/100.0;                                    
                        IN2 = 0;                        // FWD + LS
                    }
                }                                    
           }
           else                                         //stopped
           {
                if(braking == 1)    // braking, HS recirc
                {
                    IN1.period(1);
                    IN2.period(1);
                    IN1.write(1);
                    IN2.write(1);    
                }
                else                // coasting, LS recirc
                {
                    IN1.period(1);
                    IN2.period(1);                 
                    IN1.write(0);
                    IN2.write(0);  

                }
            }
        }
    }
}