STM32F302R8 with Konrad's inverter boards for senior design.
Fork of Blue_Board_Ticker by
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; } } }