View previous topic :: View next topic |
Author |
Message |
Zek_De
Joined: 13 Aug 2016 Posts: 100
|
BLDC control with encoder and encoder zero crossing |
Posted: Fri Oct 25, 2019 1:09 am |
|
|
Hi guys,
I would like to sense commutation sequence using encoder (1024 resolution) for bldc motor and if current state - previous state >= a then motor can move for other sequence but if encoder value change 0-1023 then I can't find the difference. For example if motor position in 10 encoder value and I controlled the motor to move other sequence and new value 1000 now 1000-10 is problem. What is best solution for it, I tried asin(sin(enc_val)) but still doesn't work well ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Oct 25, 2019 3:29 am |
|
|
How are your 'positions' declared. If you are gong to support -ve movements
these need to be declared as _signed_. Signed int16 or signed int32. |
|
|
Zek_De
Joined: 13 Aug 2016 Posts: 100
|
|
Posted: Fri Oct 25, 2019 3:46 am |
|
|
Hi Ttelmah, I didn't understand what you mean exactly. Encoder give uint16 0-1023. I converted these value using asin(sin(enc_val*(360/1024))) to get result in -90 and 90 in this case I can take the difference current value and previous value in angle. For 10 Poles motor (10/2)*6 = 30 commutation equals 1 revolution and 1024/30 = 34.1333 equals one commutation so difference should be 34 between current and previous? But doesn't work? What am I not calculating? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Oct 25, 2019 4:01 am |
|
|
You should not be involving sin or asin anywhere.
Your position is simply a count round a circle. If you want degrees, then
these are just count/2.84. Nothing more needed. However normally a
position will be for multiple revolutions, so you actually need a count of
tens of thousands, and to wrap when you get to the end of a revolution.
So a count of 20000, is 19+ turns. If you need to turn 90 degrees, this
is just 256 counts.
If you start using sin and asin, remember these take an absolute age
several hundred mSec, and these work in radians, not degrees. |
|
|
Zek_De
Joined: 13 Aug 2016 Posts: 100
|
|
Posted: Fri Oct 25, 2019 4:57 am |
|
|
Probably I couldn't tell its right because language. I mean I couldn't move the motor for next commutation. Of course I can read motor position. But if I need to find motor position for commutation in this case I need to get difference next and previous value. In this case I have a problem in that point. When the motor crosses the zero point again and if I get the current encoder value before 0 and for next after the 0 difference will be too high.
For example this doesn't work.
Code: |
encoder = Get_Position(&encConfig);
dir = Get_Position(&encConfig);
result1_i = encoder - tut_u;
if(abs(result1_i) >= 34-5)
{
tut_u = Get_Position(&encConfig);
say=say+1;
if(dir) Set_DutyCycle(cw_table[say],pwm);
if(!dir) Set_DutyCycle(ccw_table[say],pwm);
if(say==5) say = -1;
delay_ms(15);
//do
//{
//test_u = qdec_get_position(&encConfig);
//result_i = test_u - tut_u;
//}while( (abs(result_i) <= (34-5)) );
} |
This is why I tried this one
Code: |
deltaT = (180/PI)*Keep_Enc_Val_Rad();
if((fabs(deltaT - tut) >= thetaMechanicalRad-5))
{
tut = (180/PI)*Keep_Enc_Val_Rad();;
say=say+1;
if(dir) Set_DutyCycle(cw_table[say],pwm);
if(!dir) Set_DutyCycle(ccw_table[say],pwm);
if(say==5) say = -1;
delay_ms(15);
//do
//{
//test = (180/PI)*Keep_Enc_Val_Rad();
//}while( (fabs(test - tut) <= (thetaMechanicalRad-2)) );
}
|
Code: |
double Keep_Enc_Val_Rad(void)
{
double deltaTheta=0;
uint16_t enc=0;
enc = Get_Position(&encConfig);
deltaTheta = (double)enc*ANGLE_RES_RAD;
deltaTheta = asin( sin(deltaTheta));
return deltaTheta;
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 25, 2019 5:10 am |
|
|
I think his entire problem is that he doesn't understand how to handle
wrapping around past 0. He is subtracting the previous value from the
current value and he can't figure out what to do if the result is negative.
Example:
Range = 0 to 1023
Last value = 1000
Current value = 10
So 10 - 1000 = -990 He can't handle this.
One solution is to used signed variables, as Ttelmah says.
Then check if the result is negative. (Example -990).
If so, then add 1024 to it. Example:
-990 + 1024 = 34 This is the desired result. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Fri Oct 25, 2019 5:21 am |
|
|
Agreed.
Also there are going to need to be signed values, otherwise you can't
move backwards... |
|
|
Zek_De
Joined: 13 Aug 2016 Posts: 100
|
|
Posted: Fri Oct 25, 2019 7:02 am |
|
|
Now it works yes It moves ccw for trying but new problem is after a while when motor moving it is getting slow and stop for a moment and again moving. I am thinking about resolution. This is the algorithm.
34 is 1024/30,
And you guys are the king.
Code: |
encoder_u = Get_Position(&encConfig);
encoder_i = (int32_t)encoder_u;
if(1)
{
result_i = tut_i - encoder_i ;
if(result_i < 0) result_i += 1024;
}
if(result_i >= 34)
{
tut_u = Get_Position(&encConfig);
tut_i = (int32_t)tut_u;
say=say+1;
//if(dir) Set_DutyCycle(cw_table[say],pwm);
if(!dir) Set_DutyCycle(ccw_table[say],pwm);
if(say==5) say = -1;
delay_ms(3); // Here
}
|
Last edited by Zek_De on Fri Oct 25, 2019 7:15 am; edited 1 time in total |
|
|
Zek_De
Joined: 13 Aug 2016 Posts: 100
|
|
Posted: Fri Oct 25, 2019 7:14 am |
|
|
Okay it is not about resolution. If I put there delay_ms(3) there is no problem. I have to handle it, but do you have a nice solution ? Of course I can apply. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Fri Oct 25, 2019 7:27 am |
|
|
You need to read and understand (well, try...) the 'electrical characteristics' of the motor AND it's 'drive electronics'. Those must be on the datasheet somewhere.
Also be sure the power supply is overrated by at least 200%. Most (all ?) steppers require a large current, then taper off to effect rotation.
Jay |
|
|
|