STM32F302R8 with Konrad's inverter boards for senior design.

Dependencies:   mbed

Fork of Blue_Board_Ticker by Brad VanderWilp

main.cpp

Committer:
vicyap
Date:
2016-04-15
Revision:
23:cb38086e8695
Parent:
22:72905102b50d

File content as of revision 23:cb38086e8695:

#include "mbed.h"

PwmOut phaseA(PA_8);    //Out1, Green
DigitalOut phaseAEN(PC_10);
PwmOut phaseB(PA_9);    //Out2, Blue
DigitalOut phaseBEN(PC_11);
PwmOut phaseC(PA_10);   //Out3, White
DigitalOut phaseCEN(PC_12);

AnalogIn pot(PB_1);

InterruptIn button(USER_BUTTON);

DigitalOut redLed(PB_2);
DigitalOut led(LED1);
InterruptIn hallA(PA_15);   //H1, Green
InterruptIn hallB(PB_3);    //H2, Blue
InterruptIn hallC(PB_10);   //H3, White

Ticker rpmInterrupt;
Ticker spinTicker;
int revCount = 0;
int rpmPrintFlag = 0;
int currentRPM;

int ADCCountMax = 1000; // tune for responsiveness vs. stability, higher value -> less responsive -> more stable
float ADCSum = 0;
int ADCCount = 0;

float pwmMax = 0.9; // tune for max pwmDuty. higher value -> more power available
float pwmDuty;
int start = 0;
int reverse = 0;

int spinTickerCounter = 0;
int spinTickerPeriod_us = 50; // tune for how often hall sensors are checked
int ticksPerHall = 0;
int prevHallState = 0;

float reverseThreshold = 0.4f; // tune for minimum duty cycle to allow reverse

int pole_pairs = 2; // tune for proper mech rpm calculation

int hallToStateNumber(int h1, int h2, int h3)
{
    return (h1 << 2) + (h2 << 1) + h3;   
}

void init()
{
    phaseA.period_us(50);
    phaseB.period_us(50);
    phaseC.period_us(50);

    phaseA.write(0);
    phaseB.write(0);
    phaseC.write(0);

    phaseAEN = 0;
    phaseBEN = 0;
    phaseCEN = 0;
    
    // init the prevHallState
    int h1 = hallA.read();
    int h2 = hallB.read();
    int h3 = hallC.read();
    prevHallState = hallToStateNumber(h1, h2, h3);
}

void rpmCalc()
{
    currentRPM = revCount * 60; // 60 seconds in 1 minute
    currentRPM /= pole_pairs; // account for elec vs mech rpm
    if (reverse == 1)
    {
        currentRPM = -currentRPM; // indicate a reverse direction   
    }
    revCount = 0;
    rpmPrintFlag = 1;
}

/*
L6320
    High : Enabled and Pulsing
    Low : Enabled not Pulsing
    Null : Disabled
    
Konrad's Board (6 step)
    High : high-side pulsing, low-side off
    Low : high-side off, low-side on
    Null : high-side off, low-side off
    
    high-side are PwmOuts
    low-side are DigitalOuts
*/

//original names: CBA CBA, new names: BAC BAC
void Output_ANull_BLow_CHigh()    //state1, A0 B- C+
{
    phaseA.write(0);
    phaseB.write(0);
    phaseC.write(pwmDuty);
    phaseAEN = 0;
    phaseBEN = 1;
    phaseCEN = 1;
}

void Output_AHigh_BLow_CNull()    //state2, A+ B- C0
{
    phaseA.write(pwmDuty);
    phaseB.write(0);
    phaseC.write(0);
    phaseAEN = 1;
    phaseBEN = 1;
    phaseCEN = 0;
}

void Output_AHigh_BNull_CLow()    //state3, A+ B0 C-
{
    phaseA.write(pwmDuty);
    phaseB.write(0);
    phaseC.write(0);
    phaseAEN = 1;
    phaseBEN = 0;
    phaseCEN = 1;
}

void Output_ANull_BHigh_CLow()    //state4, A0 B+ C-
{
    phaseA.write(0);
    phaseB.write(pwmDuty);
    phaseC.write(0);
    phaseAEN = 0;
    phaseBEN = 1;
    phaseCEN = 1;
}

void Output_ALow_BHigh_CNull()    //state5, A- B+ C0
{
    phaseA.write(0);
    phaseB.write(pwmDuty);
    phaseC.write(0);
    phaseAEN = 1;
    phaseCEN = 0;
    phaseBEN = 1;
}

void Output_ALow_BNull_CHigh()    //state6, A- B0 C+
{
    phaseAEN = 1;
    phaseBEN = 0;
    phaseCEN = 1;
    phaseA.write(0);
    phaseB.write(0);
    phaseC.write(pwmDuty);
}

void toggleRedLed()
{
    redLed = !redLed;
}

void SixStepNext(int h1, int h2, int h3)
{
    // compute next outputs
    if (reverse == 0)
    {
        if(h1 == 0 && h2 == 1 && h3 == 1) { //state1
            Output_AHigh_BLow_CNull();
        } else if(h1 == 0 && h2 == 0 && h3 == 1) { //state2
            Output_AHigh_BNull_CLow();
        } else if(h1 == 1 && h2 == 0 && h3 == 1) { //state3
            Output_ANull_BHigh_CLow();
        } else if(h1 == 1 && h2 == 0 && h3 == 0) { //state4
            Output_ALow_BHigh_CNull();
        } else if(h1 == 1 && h2 == 1 && h3 == 0) { //state5
            Output_ALow_BNull_CHigh();
        } else if (h1 == 0 && h2 == 1 && h3 == 0) { //state6
            Output_ANull_BLow_CHigh();
        }
    }
    else if (reverse == 1) // to go in reverse, shift the mappings by 180 degrees
    {
        if(h1 == 0 && h2 == 1 && h3 == 1) { //state1
            Output_ALow_BHigh_CNull();
        } else if(h1 == 0 && h2 == 0 && h3 == 1) { //state2
            Output_ALow_BNull_CHigh();
        } else if(h1 == 1 && h2 == 0 && h3 == 1) { //state3
            Output_ANull_BLow_CHigh();
        } else if(h1 == 1 && h2 == 0 && h3 == 0) { //state4
            Output_AHigh_BLow_CNull();
        } else if(h1 == 1 && h2 == 1 && h3 == 0) { //state5
            Output_AHigh_BNull_CLow();
        } else if (h1 == 0 && h2 == 1 && h3 == 0) { //state6
            Output_ANull_BHigh_CLow();
        }
    }   
}

void SpinTicker_callback()
{
    int h1 = hallA.read();
    int h2 = hallB.read();
    int h3 = hallC.read();
    //check where we start
    int currentHallState = hallToStateNumber(h1, h2, h3);
    if (currentHallState != prevHallState)
    {
        ticksPerHall = spinTickerCounter;
        spinTickerCounter = 0; // reset the number of ticks per hall sensor change
        if (prevHallState == 1) // arbitrarily choose state 1
        {
            revCount += 1;
        }
    }
    prevHallState = currentHallState;
    spinTickerCounter += 1; // count the number of times spinTicker runs per hall sensor
    
    SixStepNext(h1, h2, h3);
    
    toggleRedLed();
}

void user_button_callback()
{
    if(start == 0) 
    {
        start = 1;
    } 
    else 
    {
        if (pwmDuty < reverseThreshold)
        {
            reverse = reverse ^ 1;
        }
    }
}

float buffered_ADC_read()
{
    if(ADCCount == ADCCountMax) {
        ADCSum = ADCSum - (ADCSum / ADCCountMax);
        ADCSum += pot.read();
        return ADCSum / ADCCountMax;
    }
    else
    {
        ADCSum += pot.read();
        ADCCount++;
        return 0.0; 
    }
}

int main()
{
    //wait until button push to start
    rpmInterrupt.attach(&rpmCalc, 1);
    button.rise(&user_button_callback);
    while(start == 0) {
        led = !led;
        wait(1);
    }
    
    init();

    spinTicker.attach_us(&SpinTicker_callback, spinTickerPeriod_us);
    while(1) {
        led = !led;
        
        pwmDuty = buffered_ADC_read() * pwmMax;
        
        if(rpmPrintFlag == 1) {
            printf("%d rpm; %f duty; reverse: %d; ticksPerHall = %d\r\n", currentRPM, pwmDuty, reverse, ticksPerHall);
            rpmPrintFlag = 0;
        }
    }
}