This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Could I use Hall sensor to apply on 28069F ?!

Other Parts Discussed in Thread: MOTORWARE, CONTROLSUITE, LAUNCHXL-F28027F, DRV8301, DRV8312, TMDSCNCD28035

Hi all,

I wanna use Hall sensor to know initial rotor angle drive motor directly for low speed, and then to keep FOC (sensorless) drive PMSM motor further.

May I know how to implement the Hall Sensor for 28069F FOC?! any example code or document to be reference ?!

Thanks in advance !

  • Kuo,

    You could do this. I'm pretty sure someone else on this forum did it themselves and may share.

    It is NOT in our plans to add this to MotorWare.  We actually are close to releasing a VERY nice initial position detection solution for MotorWare that is very robust, very fast, and working very well.  This would allow you to get the initial rotor angle sensorlessly and immediately start up perfect with InstaSPIN-FOC.  This initially works with synchronous motors (even non-salient).  We are working on running this also at very slow speeds before FAST takes over.

    I do have a project written in MotorWare that uses hall sensors completely for pseudo-FOC (FAST not being used).  This has been a common approach in the past in applciations like washing machines....I could potentially copy/paste some of the main HALL functions for you.

    If you can't get an example from another member of the forum, you also could go the route of re-using the hall feedback examples from controlSUITE and mix into MotorWare code or code yourself as a MotorWare driver.  Once you have the angle the MotorWare code easily takes the starting angle you want to use by the function

    extern void EST_setAngle_pu(EST_Handle handle,const _iq angle_pu);

    just before you enable the drive.

     

  • Here are some of the things that we did for the Hall Sensor reading.

    1. New function for HALL_ReadTheta

    _iq HALL_ReadTheta(DRV_Handle handle)
    {
     DRV_Obj *drv_obj = (DRV_Obj *)handle;
     _iq temp;
     uint32_t hall_temp;

     hall_temp = GPIO_A_read_all(drv_obj->gpioHandle);
     gHallStat = (hall_temp >> 24) & 0x0007;

     switch(gHallStat)
     {
      case 0x03:
       temp = _IQ(MATH_PI);  //180deg
       break;
      case 0x02:
       temp = _IQ(-4.*MATH_PI/6.); //-120deg
       break;
      case 0x06:
       temp = _IQ(-2.*MATH_PI/6.); //-60deg
       break;
      case 0x04:
       temp = _IQ(0.);    //0
       break;
      case 0x05:
       temp = _IQ(2.*MATH_PI/6.); //60deg
       break;
      case 0x01:
       temp = _IQ(4.*MATH_PI/6.); //120deg
       break;
      default:
       temp = _IQ(0.);
       break;
     }
     return temp;
    }

     

    2.

     

  • 2. gpio.c add

    unsigned long GPIO_A_read_all(GPIO_Handle gpioHandle)
    {
      GPIO_Obj *gpio = (GPIO_Obj *)gpioHandle;

      return(gpio->GPADAT);
    } // end of GPIO_A_read_all() function


    unsigned long GPIO_B_read_all(GPIO_Handle gpioHandle)
    {
      GPIO_Obj *gpio = (GPIO_Obj *)gpioHandle;

      return(gpio->GPBDAT);
    } // end of GPIO_A_read_all() function

     

    3. gpio.h add

    //! \brief     Reads the general purpose I/O (GPIO) Port A
    //! \param[in] gpioHandle  The general purpose I/O (GPIO) object handle
    //! \return    The general purpose I/O (GPIO) state
    extern unsigned long GPIO_A_read_all(GPIO_Handle gpioHandle);


    //! \brief     Reads the general purpose I/O (GPIO) Port B
    //! \param[in] gpioHandle  The general purpose I/O (GPIO) object handle
    //! \return    The general purpose I/O (GPIO) state
    extern unsigned long GPIO_B_read_all(GPIO_Handle gpioHandle);

     

  • 4. in your proj_lab##.c

    we built ours inside proj_lab12 from InstaSPIN_MOTION

    //updated the CODE_SECTION for flash and new HALL_ReadTheta

    #ifdef FLASH
    #pragma CODE_SECTION(mainISR,"ramfuncs");
    #pragma CODE_SECTION(ST_runPosConv,"ramfuncs");
    #pragma CODE_SECTION(ST_runVelCtl,"ramfuncs");
    #pragma CODE_SECTION(HALL_ReadTheta,"ramfuncs");
    #endif

    //add to definitions:

    OBSERVER_Obj observer_obj;
    OBSERVER_Handle observerHandle;

    float_t gObserver_BW_Hz = 20.;
    _iq gTheta_hall = _IQ(0.);
    _iq gTheta = _IQ(0.);
    _iq gTheta_offset = _IQ(-0.15);
    uint16_t gHallStat = 0;

    //add to initialization in main():

      // initialize the Observer module
      observerHandle = OBSERVER_init(&observer_obj, sizeof(observer_obj));

      // setup the Observer module
      OBSERVER_setup(observerHandle, USER_IQ_FULL_SCALE_FREQ_Hz, USER_MOTOR_RATED_FLUX, USER_IQ_FULL_SCALE_CURRENT_A, USER_MOTOR_NUM_POLE_PAIRS, USER_SYSTEM_INERTIA, USER_SYSTEM_FRICTION, gObserver_BW_Hz, USER_CTRL_PERIOD_sec, 100.0);

     

  • 5. in the mainISR

    //do first

      // read hall
      gTheta_hall = HALL_ReadTheta(drvHandle);

    // then after the CTRL_setup compute the angle
    // setup the controller
      CTRL_setup(ctrlHandle);

      // compute the electrical angle
      gTheta = gTheta_hall + gTheta_offset;
      GLBQ_BOUND_2PI(gTheta);

     if(gMotorVars.CtrlState != CTRL_State_OnLine || gMotorVars.EstState != EST_State_OnLine)
      {
       gTheta = _IQ(0.);
       OBSERVER_setEstLoadTorque(observerHandle, _IQ(0.));
       OBSERVER_setEstElecAngle(observerHandle, _IQ(0.));
      }
      OBSERVER_run(observerHandle, gTheta, CTRL_getIq_in_pu(ctrlHandle));

      if( CTRL_getSpd_int_ref_pu(ctrlHandle) == _IQ(0.))
      {
       OBSERVER_resetValues(observerHandle);
      }

  • 6. in updateGlobalVariables_motor()

     // get the speed....we re-used the QEP variable, but this is from the HALL observer
    gMotorVars.SpeedQEP_krpm = OBSERVER_getSpeedFiltered_krpm(observerHandle);

    // variable to tune the gain of the HALL observer 
    OBSERVER_setEstGain(observerHandle,gObserver_BW_Hz);

  • 7. We re-used the ST_rnPosConv() funtion from SpinTAC suite to instead update using our new HALL OBSERVER

    void ST_runPosConv(ST_Handle sthandle, CTRL_Handle handle) {

     ST_Obj *stObj = (ST_Obj *)sthandle;

        // update the electrical angle
        STPOSCONV_setElecAngle_erev(stObj->posConvHandle, OBSERVER_getEstElecAngle_pu(observerHandle));
        // run the position converter
        STPOSCONV_run(stObj->posConvHandle);
    }

  • 8. we did the same with the existing ST_runVelCtrl() function, now using the OBSERVER module

    void ST_runVelCtl(ST_Handle sthandle, CTRL_Handle handle)
    {

        _iq speedFeedback, iqReference;
        ST_Obj *stObj = (ST_Obj *)sthandle;
        CTRL_Obj *ctrlObj = (CTRL_Obj *)handle;

        // Get the mechanical speed in pu
        //speedFeedback = STPOSCONV_getVelocityFiltered(stObj->posConvHandle);
        speedFeedback = _IQmpyIQX(OBSERVER_getEstSpeedFiltered(observerHandle),15,_IQ(1./USER_IQ_FULL_SCALE_FREQ_Hz/MATH_TWO_PI),24);

     // Run the SpinTAC Controller
     // Note that the library internal ramp generator is used to set the speed reference
        STVELCTL_setVelocityReference(stObj->velCtlHandle, TRAJ_getIntValue(ctrlObj->trajHandle_spd));
     STVELCTL_setAccelerationReference(stObj->velCtlHandle, _IQ(0.0)); // Internal ramp generator does not provide Acceleration Reference
     STVELCTL_setVelocityFeedback(stObj->velCtlHandle, speedFeedback);
     STVELCTL_run(stObj->velCtlHandle);

     // select SpinTAC Velocity Controller
     iqReference = STVELCTL_getTorqueReference(stObj->velCtlHandle);

     // Set the Iq reference that came out of SpinTAC Velocity Control
     CTRL_setIq_ref_pu(ctrlHandle, iqReference);
    }

  • 9. the new Observer modules (attached) should be placed at

    sw\modules\observer\src\32b\

     

     

     

  • 9 continued since you can't attachmore than 1 file!!!!

     

    observer.h
  • 10. in the main.h include ctrlHALL.h (attached) instead of the ctrlQEP.h

     

    ctrlHALL.h
  • 10 continued. and add ctrlHALL.c to the \src directory

     

  • This was tested with DRV8312-69M-KIT using the supplied NEMA17 motor with hall sensors connected so:

      

     

    You can add these to the proj_lab12.js

    expAdd ("gObserver_BW_Hz");
    expAdd ("gTheta_offset",getQValue(24));
    expAdd ("observer_obj");

    as they are the variables you will need access to.

    You need to tune gTheta_offset and gObserver_BW_Hz

    For theta offset you can use the RsRecal to inject Id, and then read the new angle value.

    Bandwidth can be tuned by user according to the required speed control bandwidth.

    The default values (Theta_offset=_IQ(-0.15), gObserver_BW_Hz=20) works well for our hardware/motor combination.

     

  • Is this approach you posted before applicable to InstaSpin FOC enabled chips like the LAUNCHXL-F28027F?

  • absolutely.

    steps 7 and 8 will change as you won't be using the SpinTAC components for trajectory, you'll have to make these generic from the other MotorWare functions, like the TRAJ module.

    It just made it eaiser to drop this into a fully working project that was already using QEP feedback like proj_12.

     

  • Hi Chris,

            Appreciate your elaborate explanation !
    I will do trial run the example code on DRV8301 EVM board, and keep to discuss with you if has any.
    In fact I agree with you that is great motor solution for TI FOC Technology,
    but recently I do the proj4 (Torgue control) trial run, and then found the motor shaft will oscillate slowly if we have not set high Torgue enough. So, do you have any idea to avoid this oscillate behavior ?!
    In addition even we have skipped low Torgue range,
    but I still found the motor shaft always have a bit count-clockwise then do the clockwise run at startup moment.
    do you know how to resolve this IPD behavior to always keep clockwise run since we don't want to get any count-clockwise when we apply a positive IqRef_A at startup ?!

    btw, May I have your E-mail to have further discussion if need ?!

    My E-mail:bradtom911@yahoo.com.tw

    Thanks in advance !

     

  • Brad,

    "I do the proj4 (Torgue control) trial run, and then found the motor shaft will oscillate slowly if we have not set high Torgue enough."

    It sounds like you had no load on the shaft but the IqRef was lower than the cogging torque of the motor. This is very common phenomenon.  In your real application do you expect no load? Do you expect to give such a small torque reference?  Probably not, hence you won't see this condition.

    You can also try turning ForceAngle on/off and noticing the difference. Some applications prefer one over the other, and it isn't always to have ForceAngle enabled.

    Regarding start-up, initially FAST has no idea where the rotor flux angle is located, so it just puts out the angle starting at 0 (you can seed this angle to anything you like, the default is 0).  If you didn't guess right you can't insure that your torque production will be maximized.  Your stator flux angle MAY be orthogonal in the direction you want to move just by chance, but more likely it is in another orientation that is not producing maximum torque, may be producing MINIMUM torque, and may cause initial movement to start in the wrong direction.  You will be in this state until FAST locks onto the rotor flux angle with some amount of rotation (based on the Flux of your machine).

    I have a post on this topic if you search.

    One option is to do nothing, and depending on load enough rotor movement will occur and FAST will enventually lock on and provide torque.

    Another option is ForceAngle. It drives a consistent rotating stator flux until a given switching point where FAST angle estimation is then used.  This still doesn't guarantee you are creating full torque, it just guarantees that it will produce a cleanly rotating stator field in an attempt to get the rotor to move cleanly until FAST can be used for 100% torque production.

    Third option is to do an initial alignment to force the rotor to a known location that will be orthogonal to our stator flux generation.  This can be done by injecting enough +IdRef to get the rotor to move and align. This is also what we do with the RsRecal feature, so using RsRecal at every start-up will also put you in position to start-up under maximum torque generation.

    Fourth is to use a different technique to estimate the rotor flux angle without having to move the rotor to the starting location you want. We call these Initial Position Detection (IPD) algorithms.  We released one of these (a high frequency injection technique) in a controlSUITE example with our eSMO observer and we will soon release multiple IPD solutions for InstaSPIN-FOC / MotorWare / FAST observer.

     

  • Hi Chris expert,

    Firstly appreciate your detail explanation !

    Regarding shaft oscillate issue, indeed we have trial run it without loading, and we also use ForceAngle ON after have enough Torgue to fix this behavior as your suggestion. But that is tricky if we have given some extra-loading then this behavior will be reappeared since the torque is still low at this extra-loading moment. On the other word, we may fine tune the enough torque & enable ForceAngle ON for on-road condition (vehicle application), but suspect this on-road torque condition will be failure when vehicle is driven for off-road (more loading alike at motor startup moment). Anyway I will double confirm with real vehicle loading test to check if this behavior is still present or not.

     In addition, Regarding Startup concern, we fully agree this intrinsic sensorless relation, that is why we need to use Hall sensor to let FOC know the startup angle to avoid any incorrect direction at motor startup moment. Btw, I had done some trial on project 5A (Torque mode & Tunning Id/Iq PI) for your example code of Hall sensor application. May I know if has any need to do modification since your example code applied on project12?! Because when I implement your example code till to step6 (in updateGlobalVariables_motor()), we found some error after compiler as below picture show...

     

    Item1 & item2 showed the USER_SYSTEM_FRICTION and USER_SYSTEM_INERTIA is undefined in user.h. So may I know what value is reasonable for USER_SYSTEM_FRICTION and USER_SYSTEM_INERTIA?! I will define that in user.h

    Item3 showed “#515 a value of type "int" cannot be assigned to an entity of type "OBSERVER_Handle”” How to resolve this error ?!

    In addition, we also found undefine the “gMotorVars.SpeedQEP_krpm “ in Main.h, should I directly define it in main.h of proj5A as _iq SpeedQEP_krpm ?!

    Thanks in advance

    Have a nice day !


  • "USER_SYSTEM_FRICTION and USER_SYSTEM_INERTIA"

    This doesn't matter, as you won't be using the SpinTAC controller anyways. If you wanted to you could go through the project_lab5c+ to find the inertia/friction of your system. The lab guide and the user.h in the motion projects also have some examples if you just want to enter a value.

     

    "“gMotorVars.SpeedQEP_krpm “ in Main.h, should I directly define it in main.h of proj5A as _iq SpeedQEP_krpm ?!"

    I suppose. If I recall, in this project that is the estimated speed from the Hall interporlation.

    ""int" cannot be assigned to an entity of type "OBSERVER_Handle””"

    sorry, I can't comment on that one, don't have time to go look it up.  This project is unsupported, was just trying to offer up some suggestions and ideas, but for Hall based FOC today it is "fend for yourself".

     

    BTW - we don't have any plans to add this to the InstaSPIN-FOC projects today. We may in the future as an example of using Halls for initial start-up or to compare it to our sensorless IPD solutions.  I would like to add this to the InstaSPIN-MOTION velocity projects as I think it's valuable.

     

  • hello Cris
    I can get with my code leggondo 3 senrori lobby a rotor angle of the BLDC motor with a step of 12 ° (5 pole pairs with 3 hall), both in cw and ccw, appilcando believe that the code you entered I I can go to this corner contollore that I find in the project 13b instaspin_motion?

    which do you think is the best project where integrate this code, my application is a clutch actuator and therefore I have to do 4 laps and then stop it and get it back out.


    about motorware there are new for the release of a new version that integrates finally a control position through sensors halll the motor.

    thanks for everything.
  • cris entering your code by making adjustments to my engine, I can not understand what they are

    OBSERVER_Obj observer_obj;
    OBSERVER_Handle observerHandle;

    and where these are defined.

    I have to define me or I forgot to some business?
  • Andrea,

    MotorWare sensored projects are demonstrated with an encoder through InstaSPIN-MOTION.  We don't have examples using Hall sensors.  We have used hall sensors to provide angle information at start-up and very low speed, then we transition to FAST for sensorless torque or velocity control. We have no plans to release any projects for Hall based position control. There just isn't enough demand for such a project.  When position control is required an encoder or resolver is almost always preferred for accuracy.  The InstaSPIN-MOTION software doesn't really care where the mechanical angle comes from - but the accuracy of that angle will of course effect your control system.

  • AS I understand, this HALL_ReadTheta function is for the 1pole pair motor, for the 4 pole pairs BLDC motor, it the HALL_ReadTheta function the same as you proved?
  • Hi Chris,

    I have done all the steps , but my motor is just shaking, not spining,why?
    I am using the DRV 8312EVM, NEMA17 motor。
  • I'm not sure which steps you have followed. The HALL Observer from this thread?
    I would check your work. Especially your phase and hall wiring. We know it works with the DRV8312 EVM with supplied motor.
  • hi chris,
    I have tried the function of hall sensor using in this post, but I foud the motor shake badly when turning, I am using drv8312_69m_kit,nema17 bldc motor, as we know the motor is 4 pole pairs motor, so when read theta from hall seneor(HALL_ReadTheta) , is theprogress all the same when pole pair is diffrent?
    also can anything be done to tune the hall observer?
  • the code posted should work with DRV8312-C2-KIT and the included NEMA17 motor, when phases and hall wires are properly connected.
    Are you using TMDSCNCD28035 or the CNCD28069MISO?
  • Hi,Chris
    I have used the program you posted to spin the motor by using hall sensor successfully with the motor BLY17, but when I change the motor to Maxon 339281(flat BLDC motor, 8 pole piars, 30 watt), the motor spin with little shake. I am sure the wire connection is correct, and I am also able to control the speed by using spintac.
    I did not use the program to identify the motor parameter, so in this situation(not use the FAST software encoder) which parameter would effect the motor spin? also how could I determine the motor parameters reference to the Maxon official data?
  • the current control bandwidth (Kp and Ki of the PI current controllers) is set by the Rs and Ls in user.h
    my first guess is that these are incorrect for your motor.

    I would ID your motor using proj_lab02c and update the user.h you are using for this Hall project.
  • Chris,

    Thank you for your excellent write up!

    I am trying to use this for proj_lab5e with an additional Hall sensor that I am not using for motor control but just to make through SPI for reading out. I need a more robust position at standstill (afraid of going into the IPD_HFI as it development seems to have stopped). This thread seems perfectly what I need.

    I followed all steps, but I get still 3 errors:

    I don't find the definition of the data types DRV_Handle and DRV_Obj (1. and 5. of your explanation).
    It is also not clear where to define DRVhandle of "gTheta_hall = HALL_ReadTheta(drvHandle);" in 5.

    Sorry for my ignorance ;-). Probably my question is plain stupid...
    I am a mechanical engineer learning so much through the Motorware environment and this forum.
    Thank you for all your efforts!

    Best regards,
    Tomas
  • I am using "motorware_1_01_00_18"
  • Dear Tomas,

    At the time (2014) Chris wrote his explanation, DRV_Handle and DRV_Obj is defined for HAL layer.

    If you are using MotorWare 14, 15, 16, 17 and 18, you MUST change to HAL_Handle and HAL_Obj to use his above code.

    Hope to help,
  • proj_lab11e uses HALL sensors for start-up