CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

BLDC control with encoder and encoder zero crossing

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

BLDC control with encoder and encoder zero crossing
PostPosted: Fri Oct 25, 2019 1:09 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 3:29 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 3:46 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 4:01 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 4:57 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 5:10 am     Reply with quote

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: 19539

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 5:21 am     Reply with quote

Agreed.
Also there are going to need to be signed values, otherwise you can't
move backwards... Smile
Zek_De



Joined: 13 Aug 2016
Posts: 100

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 7:02 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 7:14 am     Reply with quote

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: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Oct 25, 2019 7:27 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group