/*
* Application.cpp
*
* Copyright 2021 Akihiro Yamamoto.
* Licensed under the Apache License, Version 2.0
* <https://spdx.org/licenses/Apache-2.0.html>
*
*/#include"main.h"#include<ST7032iLcd.hpp>#include<array>#include<cmath>externI2C_HandleTypeDefhi2c1;externTIM_HandleTypeDefhtim2;staticST7032iLcdi2c_lcd(hi2c1);usingExcitingACBD=uint8_t;constexprconstExcitingACBDExA=0b1000;constexprconstExcitingACBDExC=0b0100;constexprconstExcitingACBDExB=0b0010;constexprconstExcitingACBDExD=0b0001;usingHiACBDLoACBD=uint8_t;staticinlineHiACBDLoACBDfromExcitingACBD(ExcitingACBDacbd){return(acbd&0xf)<<4|(acbd&0xf);}//
staticinlinevoidexcitingCoil(HiACBDLoACBDhiloACBD){uint32_todr=GPIOA->ODR;if((odr&0xff)!=hiloACBD){GPIOA->BSRR=(~hiloACBD&0xff)<<16;// clang-format off
asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");// 10
asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");// 20
// clang-format on
GPIOA->BSRR=hiloACBD&0xff;}}// turn off all transistor
staticinlinevoidturnOffAll(){GPIOA->BSRR=0xff<<16;}// short brake = turn ON all lower side switch.
staticinlinevoidshortBrake(){excitingCoil(0b00001111);}// Low A (PA0)
staticinlinevoidturnOnLowA(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);}staticinlinevoidturnOffLowA(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);}// Low C (PA1)
staticinlinevoidturnOnLowC(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);}staticinlinevoidturnOffLowC(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);}// Low B (PA2)
staticinlinevoidturnOnLowB(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET);}staticinlinevoidturnOffLowB(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET);}// Low D (PA3)
staticinlinevoidturnOnLowD(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);}staticinlinevoidturnOffLowD(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);}// High A (PA4)
staticinlinevoidturnOnHighA(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);}staticinlinevoidturnOffHighA(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);}// High C (PA5)
staticinlinevoidturnOnHighC(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);}staticinlinevoidturnOffHighC(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);}// High B (PA6)
staticinlinevoidturnOnHighB(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET);}staticinlinevoidturnOffHighB(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);}// High D (PA7)
staticinlinevoidturnOnHighD(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET);}staticinlinevoidturnOffHighD(){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET);}enumclassRotation:int8_t{CW=1,CCW=-1};// Wave drive (one phase on)
staticinlineint32_twaveDrive(int32_tsteps,Rotationr){constexprstaticconststd::array<ExcitingACBD,4>pulses{ExA,// A
ExB,// B
ExC,// C
ExD,// D
};uint32_tx=(pulses.size()+(steps&3))&3;excitingCoil(fromExcitingACBD(pulses[x]));returnsteps+static_cast<int32_t>(r);}// Full-step drive (two phases on)
staticinlineint32_tfullStepDrive(int32_tsteps,Rotationr){constexprstaticconststd::array<ExcitingACBD,4>pulses{ExA|ExB,// AB
ExB|ExC,// BC
ExC|ExD,// CD
ExD|ExA,// DA
};uint32_tx=(pulses.size()+(steps&3))&3;excitingCoil(fromExcitingACBD(pulses[x]));returnsteps+static_cast<int32_t>(r);}// Half-step drive
staticinlineint32_thalfStepDrive(int32_tsteps,Rotationr){constexprstaticconststd::array<ExcitingACBD,8>pulses{ExA,// A
ExA|ExB,// AB
ExB,// B
ExB|ExC,// BC
ExC,// C
ExC|ExD,// CD
ExD,// D
ExD|ExA,// DA
};uint32_tx=(pulses.size()+(steps&7))&7;excitingCoil(fromExcitingACBD(pulses[x]));returnsteps+static_cast<int32_t>(r);}extern"C"voidapplication_setup(){HAL_Delay(300);// time wait for LCD prepare
shortBrake();//
i2c_lcd.init();std::stringbuff(50,' ');std::snprintf(buff.data(),buff.size(),u8"ステッピングモーター テスト");i2c_lcd.setDdramAddress(0);i2c_lcd.putString(buff);//
HAL_TIM_Base_Start_IT(&htim2);TIM_OC_InitTypeDefsConfigOC={0};sConfigOC.OCMode=TIM_OCMODE_PWM1;sConfigOC.Pulse=1000;sConfigOC.OCPolarity=TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode=TIM_OCFAST_DISABLE;HAL_TIM_PWM_ConfigChannel(&htim2,&sConfigOC,TIM_CHANNEL_4);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);}staticvolatileint32_tstepCounter=0;staticvolatileRotationrotation=Rotation::CW;constexprstaticconstint32_tRightAngle=400/2;staticvoidshowPosition(){std::stringbuff(50,' ');switch(rotation){caseRotation::CW:std::snprintf(buff.data(),buff.size(),"CW %+5ld pulses",stepCounter);break;caseRotation::CCW:std::snprintf(buff.data(),buff.size(),"CCW %+5ld pulses",stepCounter);break;}i2c_lcd.setDdramAddress(0x40);i2c_lcd.putString(buff);}typedefvoid(*Procedure)();staticvoidprocHomePosition(){i2c_lcd.setDdramAddress(0x40);i2c_lcd.puts(u8" HOME position. ");HAL_Delay(1000);HAL_TIM_Base_Start_IT(&htim2);}staticvoidprocStopPosition(){showPosition();HAL_Delay(1000);HAL_TIM_Base_Start_IT(&htim2);}staticvoidprocReturnPosition(){rotation=(rotation==Rotation::CW)?Rotation::CCW:Rotation::CW;showPosition();HAL_Delay(1000);HAL_TIM_Base_Start_IT(&htim2);}staticProceduregetProcedure(int32_tcounter){switch(std::abs(counter)){case0*RightAngle:// home position
returnprocHomePosition;case1*RightAngle:// 90
returnprocStopPosition;case2*RightAngle:// 180
case3*RightAngle:// 270
case4*RightAngle:// 360
case5*RightAngle:// 450
case6*RightAngle:// 540
case7*RightAngle:// 630
case8*RightAngle:// 720
case9*RightAngle:// 810
returnnullptr;case10*RightAngle:// 900
returnprocReturnPosition;default:returnnullptr;}}extern"C"voidapplication_loop(){if(Procedurep=getProcedure(stepCounter);p!=nullptr){(*p)();}else{showPosition();HAL_Delay(1);}}extern"C"voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim){if(htim->Instance==htim2.Instance){stepCounter=halfStepDrive(stepCounter,rotation);if(getProcedure(stepCounter)!=nullptr){HAL_TIM_Base_Stop_IT(&htim2);}}}
/*
* Application.cpp
*
* Copyright 2021 Akihiro Yamamoto.
* Licensed under the Apache License, Version 2.0
* <https://spdx.org/licenses/Apache-2.0.html>
*
*/#include"main.h"#include<ST7032iLcd.hpp>#include<array>#include<cmath>externI2C_HandleTypeDefhi2c1;externTIM_HandleTypeDefhtim2;staticST7032iLcdi2c_lcd(hi2c1);// H-brigde pin class
template<GPIO_TypeDef*PORT(),uint32_tPIN>classHbridgePin{public:staticGPIO_PinStatestate(){if(((PORT()->ODR)&PIN)==0){returnGPIO_PIN_RESET;}else{returnGPIO_PIN_SET;}}staticvoidturnOn(){HAL_GPIO_WritePin(PORT(),PIN,GPIO_PIN_SET);}staticvoidturnOff(){HAL_GPIO_WritePin(PORT(),PIN,GPIO_PIN_RESET);}};// two H-brigdes port declaration
constexprGPIO_TypeDef*HbHighA_GPIO_Port(){returnHighA_GPIO_Port;}constexprGPIO_TypeDef*HbHighC_GPIO_Port(){returnHighC_GPIO_Port;}constexprGPIO_TypeDef*HbHighB_GPIO_Port(){returnHighB_GPIO_Port;}constexprGPIO_TypeDef*HbHighD_GPIO_Port(){returnHighD_GPIO_Port;}constexprGPIO_TypeDef*HbLowA_GPIO_Port(){returnLowA_GPIO_Port;}constexprGPIO_TypeDef*HbLowC_GPIO_Port(){returnLowC_GPIO_Port;}constexprGPIO_TypeDef*HbLowB_GPIO_Port(){returnLowB_GPIO_Port;}constexprGPIO_TypeDef*HbLowD_GPIO_Port(){returnLowD_GPIO_Port;}// two H-brigdes pins declaration
usingHbPinHighA=HbridgePin<HbHighA_GPIO_Port,HighA_Pin>;usingHbPinHighC=HbridgePin<HbHighC_GPIO_Port,HighC_Pin>;usingHbPinHighB=HbridgePin<HbHighB_GPIO_Port,HighB_Pin>;usingHbPinHighD=HbridgePin<HbHighD_GPIO_Port,HighD_Pin>;usingHbPinLowA=HbridgePin<HbLowA_GPIO_Port,LowA_Pin>;usingHbPinLowC=HbridgePin<HbLowC_GPIO_Port,LowC_Pin>;usingHbPinLowB=HbridgePin<HbLowB_GPIO_Port,LowB_Pin>;usingHbPinLowD=HbridgePin<HbLowD_GPIO_Port,LowD_Pin>;usingExcitingACBD=uint8_t;constexprExcitingACBDExA=0b1000;constexprExcitingACBDExC=0b0100;constexprExcitingACBDExB=0b0010;constexprExcitingACBDExD=0b0001;usingHiACBDLoACBD=uint8_t;staticinlineHiACBDLoACBDfromExcitingACBD(ExcitingACBDacbd){return(acbd&0xf)<<4|(acbd&0xf);}//
staticinlinevoidexcitingCoil(HiACBDLoACBDhiloACBD){{ExcitingACBDhi=(HbPinHighA::state()?ExA:0)|(HbPinHighC::state()?ExC:0)|(HbPinHighB::state()?ExB:0)|(HbPinHighD::state()?ExD:0);ExcitingACBDlo=(HbPinLowA::state()?ExA:0)|(HbPinLowC::state()?ExC:0)|(HbPinLowB::state()?ExB:0)|(HbPinLowD::state()?ExD:0);if(((hi<<4)|lo)==hiloACBD){return;}}// clang-format off
//
if(!(hiloACBD&(ExA<<4))){HbPinHighA::turnOff();}if(!(hiloACBD&(ExC<<4))){HbPinHighC::turnOff();}if(!(hiloACBD&(ExB<<4))){HbPinHighB::turnOff();}if(!(hiloACBD&(ExD<<4))){HbPinHighD::turnOff();}if(!(hiloACBD&ExA)){HbPinLowA::turnOff();}if(!(hiloACBD&ExC)){HbPinLowC::turnOff();}if(!(hiloACBD&ExB)){HbPinLowB::turnOff();}if(!(hiloACBD&ExD)){HbPinLowD::turnOff();}asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");// 10
asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");asm("NOP");// 20
//
if(hiloACBD&(ExA<<4)){HbPinHighA::turnOn();}if(hiloACBD&(ExC<<4)){HbPinHighC::turnOn();}if(hiloACBD&(ExB<<4)){HbPinHighB::turnOn();}if(hiloACBD&(ExD<<4)){HbPinHighD::turnOn();}if(hiloACBD&ExA){HbPinLowA::turnOn();}if(hiloACBD&ExC){HbPinLowC::turnOn();}if(hiloACBD&ExB){HbPinLowB::turnOn();}if(hiloACBD&ExD){HbPinLowD::turnOn();}// clang-format on
}// short brake = turn ON all lower side switch.
staticinlinevoidshortBrake(){excitingCoil(0b00001111);}//
enumclassRotation:int8_t{CW=-1,CCW=1};// Wave drive (one phase on)
staticinlineint32_twaveDrive(int32_tsteps,Rotationr){constexprstaticconststd::array<ExcitingACBD,4>pulses{ExA,// A
ExB,// B
ExC,// C
ExD,// D
};uint32_tx=(pulses.size()+(steps&3))&3;excitingCoil(fromExcitingACBD(pulses[x]));returnsteps+static_cast<int32_t>(r);}// Full-step drive (two phases on)
staticinlineint32_tfullStepDrive(int32_tsteps,Rotationr){constexprstaticconststd::array<ExcitingACBD,4>pulses{ExA|ExB,// AB
ExB|ExC,// BC
ExC|ExD,// CD
ExD|ExA,// DA
};uint32_tx=(pulses.size()+(steps&3))&3;excitingCoil(fromExcitingACBD(pulses[x]));returnsteps+static_cast<int32_t>(r);}// Half-step drive
staticinlineint32_thalfStepDrive(int32_tsteps,Rotationr){constexprstaticconststd::array<ExcitingACBD,8>pulses{ExA,// A
ExA|ExB,// AB
ExB,// B
ExB|ExC,// BC
ExC,// C
ExC|ExD,// CD
ExD,// D
ExD|ExA,// DA
};uint32_tx=(pulses.size()+(steps&7))&7;excitingCoil(fromExcitingACBD(pulses[x]));returnsteps+static_cast<int32_t>(r);}extern"C"voidapplication_setup(){HAL_Delay(300);// time wait for LCD prepare
shortBrake();//
i2c_lcd.init();std::stringbuff(50,' ');std::snprintf(buff.data(),buff.size(),u8"ステッピングモーター テスト");i2c_lcd.setDdramAddress(0);i2c_lcd.putString(buff);//
HAL_TIM_Base_Start_IT(&htim2);TIM_OC_InitTypeDefsConfigOC={0};sConfigOC.OCMode=TIM_OCMODE_PWM1;sConfigOC.Pulse=1000;sConfigOC.OCPolarity=TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode=TIM_OCFAST_DISABLE;HAL_TIM_PWM_ConfigChannel(&htim2,&sConfigOC,TIM_CHANNEL_4);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);}staticvolatileint32_tstepCounter=0;staticvolatileRotationrotation=Rotation::CW;constexprstaticconstint32_tRightAngle=400/2;staticvoidshowPosition(){std::stringbuff(50,' ');int8_tsign=(stepCounter==0)?0:((stepCounter<0)?(-1):1);switch(sign){case0:std::snprintf(buff.data(),buff.size(),u8" HOME position. ");break;casestatic_cast<int8_t>(Rotation::CW):std::snprintf(buff.data(),buff.size(),u8"CW %5ld pulses",std::abs(stepCounter));break;casestatic_cast<int8_t>(Rotation::CCW):std::snprintf(buff.data(),buff.size(),u8"CCW %5ld pulses",std::abs(stepCounter));break;default:break;}i2c_lcd.setDdramAddress(0x40);i2c_lcd.putString(buff);}typedefvoid(*Procedure)();staticvoidprocStopPosition(){showPosition();HAL_Delay(1000);HAL_TIM_Base_Start_IT(&htim2);}staticvoidprocReturnPosition(){rotation=(rotation==Rotation::CW)?Rotation::CCW:Rotation::CW;showPosition();HAL_Delay(1000);HAL_TIM_Base_Start_IT(&htim2);}staticProceduregetProcedure(int32_tcounter){switch(std::abs(counter)){case0*RightAngle:// home position
case1*RightAngle:// 90
returnprocStopPosition;case2*RightAngle:// 180
case3*RightAngle:// 270
case4*RightAngle:// 360
case5*RightAngle:// 450
case6*RightAngle:// 540
case7*RightAngle:// 630
case8*RightAngle:// 720
case9*RightAngle:// 810
returnnullptr;case10*RightAngle:// 900
returnprocReturnPosition;default:returnnullptr;}}extern"C"voidapplication_loop(){if(Procedurep=getProcedure(stepCounter);p!=nullptr){(*p)();}else{showPosition();HAL_Delay(1);}}extern"C"voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim){if(htim->Instance==htim2.Instance){stepCounter=halfStepDrive(stepCounter,rotation);if(getProcedure(stepCounter)!=nullptr){HAL_TIM_Base_Stop_IT(&htim2);}}}
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.
コメント