In the STM8 motor library written by ST, BLDC can be driven in a non-inductive manner. The STM8 chip has only one AD converter, and it is an 8-bit machine.to oppose in the library
Potential acquisition, comparison and processing, but also the bus voltage, bus current, heat sink temperature, potentiometer and other analog signals to collect, calculate and process.
This priority handling is very important. However, ST writes programs well, at least I think so. It puts different tasks into accurate time periods for collection and processing.
First post its core AD collection and processing, and then analyze it.
#ifdef SENSORLESS
@near @interrupt @svlreg void ADC2_IRQHandler (void)
{
if (ADC_State == ADC_SYNC)
{
// Syncronous sampling
u16 data;
u8 delay;
u16 bemf_threshold;
// Reset bit
bComHanderEnable = 0;
//clear interrupt flag
ADC2->CSR &= (u8)(~BIT7);
//left align – read DRH first
data = ADC2->DRH;
data <<= 2;
data |= (ADC2->DRL & 0x03);
switch( ADC_Sync_State )
{
case ADC_BEMF_INIT:
ADC2->CSR = (u8)((Current_BEMF_Channel|BIT5));
BEMF_Sample_Debounce = 0;
Zero_Sample_Count = 0;
ADC_Sync_State = ADC_BEMF_SAMPLE;
SetSamplingPoint_BEMF();
break;
case ADC_BEMF_SAMPLE:
//detect zero crossing
if( Current_BEMF == BEMF_FALLING )
{
if( Z_Detection_Type == Z_DETECT_PWM_OFF )
{
bemf_threshold = BEMF_FALLING_THRESHOLD;
}
else
{
bemf_threshold = hNeutralPoint;
}
if (Ramp_Step > FORCED_STATUP_STEPS)
{
if( data < bemf_threshold )
{
Zero_Sample_Count++;
BEMF_Sample_Debounce++;
if( BEMF_Sample_Debounce >= BEMF_SAMPLE_COUNT )
{
hTim3Th -= hTim3Cnt;
GetStepTime();
SpeedMeasurement();
bComHanderEnable = 1;
BEMF_Sample_Debounce = 0;
}
}
else
{
BEMF_Sample_Debounce = 0;
}
}
}
else
{
if( Z_Detection_Type == Z_DETECT_PWM_OFF )
{
bemf_threshold = BEMF_RISING_THRESHOLD;
}
else
{
bemf_threshold = hNeutralPoint;
}
if (Ramp_Step > FORCED_STATUP_STEPS)
{
if( data > bemf_threshold )
{
Zero_Sample_Count++;
BEMF_Sample_Debounce++;
if( BEMF_Sample_Debounce >= BEMF_SAMPLE_COUNT )
{
hTim3Th -= hTim3Cnt;
GetStepTime();
SpeedMeasurement();
bComHanderEnable = 1;
BEMF_Sample_Debounce = 0;
}
}
else
{
BEMF_Sample_Debounce = 0;
}
}
}
break;
case ADC_CURRENT_INIT:
ADC2->CSR = (ADC_CURRENT_CHANNEL|BIT5);
ADC_Sync_State = ADC_CURRENT_SAMPLE;
SetSamplingPoint_Current();
break;
default:
case ADC_AVCURRENT_INIT:
ADC2->CSR = (ADC_AVCURRENT_CHANNEL|BIT5);
ADC_Sync_State = ADC_AVCURRENT_CHANNEL;// ADC_USER_SYNC_SAMPLE;
SetSamplingPoint_AVCURRENT();
break;
case ADC_CURRENT_SAMPLE:
ADC_Buffer[ ADC_CURRENT_INDEX ] = data;
break;
case ADC_AVCURRENT_SAMPLE:
ADC_Buffer[ ADC_AVCURRENT_INDEX] = data;
break;
}
// Store the current channel selected
bCSR_Tmp = ADC2->CSR;
// Set the Async sampling channel
switch (ADC_Async_State)
{
default:
case ADC_BUS_INIT:
ADC2->CSR = (ADC_BUS_CHANNEL|BIT5);
ADC_Async_State = ADC_BUS_SAMPLE;
break;
case ADC_TEMP_INIT:
ADC2->CSR = (ADC_TEMP_CHANNEL|BIT5);
ADC_Async_State = ADC_TEMP_SAMPLE;
break;
case ADC_USER_ASYNC_INIT:
ADC2->CSR = (ADC_USER_ASYNC_CHANNEL|BIT5);
ADC_Async_State = ADC_USER_ASYNC_SAMPLE;
break;
}
// Disable ext. trigger
ADC2->CR2 &= (u8)(~BIT6);
//Start ADC sample
ADC2->CR1 |= BIT0;
ADC_State = ADC_ASYNC;
if (bComHanderEnable == 1)
{
ComHandler();
}
}
else
{
// Syncronous sampling
u16 data;
data = ADC2->DRH;
data <<= 2;
data |= (ADC2->DRL & 0x03);
//clear interrupt flag
ADC2->CSR &= (u8)(~BIT7);
// Restore the sync ADC channel
ADC2->CSR = bCSR_Tmp;
// Enable ext. trigger
ADC2->CR2 |= BIT6;
// Manage async sampling
switch (ADC_Async_State)
{
default:
case ADC_BUS_SAMPLE:
ADC_Buffer[ ADC_BUS_INDEX ] = data;
ADC_Async_State = ADC_TEMP_INIT;
break;
case ADC_TEMP_SAMPLE:
ADC_Buffer[ ADC_TEMP_INDEX ] = data;
ADC_Async_State = ADC_USER_ASYNC_INIT;
break;
case ADC_USER_ASYNC_SAMPLE:
ADC_Buffer[ ADC_USER_ASYNC_INDEX ] = data;
ADC_Async_State = ADC_BUS_INIT;
break;
}
ADC_State = ADC_SYNC;
}
}
#endif
I changed the above code a little bit, that is, one more average current is collected.
There are two types of AD acquisition, one is synchronous and the other is asynchronous. There are three acquisition channels in synchronous and three acquisition channels in asynchronous. The channels in synchronization are back EMF channel, instantaneous current, and average current. Channels in asynchronous acquisition are bus voltage, temperature value, and potentiometer.
Asynchronous acquisition occurs after synchronization is complete. Synchronous acquisition is triggered by channel 4 of TIM1.
Therefore, 2 channels of analog signals are collected in each PWM cycle. The channel of asynchronous acquisition has nothing to do with the ON and OFF states of PWM, so it is arranged in asynchronous acquisition. The back EMF in synchronous acquisition needs to be acquired at a fixed time of PWM, either ON or OFF, see the zero-crossing comparison scheme of BEMF. The instantaneous current is generally collected at the time of TON. Because ST had PWM special moment to do one channel of user, so I added the average current to this channel. In fact, the average current acquisition can also be placed asynchronously. It doesn’t matter, the function implementation is no problem.
In addition, the back EMF channel in the asynchronous acquisition is always set to the channel of the floating phase. Moreover, the collection of back EMF is between D and Z, that is, the asynchronous collection between the end of demagnetization and the zero-crossing point is back-EMF, and the collection of instantaneous current is between Z and C, that is, between zero-crossing and commutation The asynchronous acquisitions performed are all instantaneous instantaneous currents. So the user’s channel (average current) is between commutation and demagnetization.
ST’s non-inductive scheme, the starting scheme feels that it can only be used for industrial motors, such as a motor with a 4K speed under 4 pole pairs, so the starting parameters do not need to be changed. However, if it is changed to a Model aircraft motor, no matter how much the startup PWM is changed, it will always fail to start successfully. It may be that I still found a clever door, or I may not have set the right parameters. For high-speed motors, such a non-inductive start may be reliable only by the boosting method. The routine I wrote in the early days, no matter what motor, uses the boosting method, no matter what motor, it can start normally, but the current during the starting process (about 1S) goes from large to small, and at least runs normally to the minimum current value .