How to configure three-phase PWM output for motor control

Hello,

I want to use a brushless DC Motor with S7 and three-phase PWM output motor control. Does anybody have an example Code on how to configure the Driver in e2Studio.

I enable "GPT_Output_Phase_Switching" in Pin Configuration and added in my thread "Timer Driver on r_gpt", but in the properties I must input a channel. I think the Driver is not correct.

Can anybody help?

Regards

  • Mario,

    Currently the SSP Timer Driver does not support OPS mode, so you have to write the code yourself at the register level.

    However, still use the Synergy Configuration tool in E2Studio to create a Timer on GPT0.  

    You need this as the PWM source to driver the OPS.

    Enable the GPT0 interrupt and specify a callback function.  Don't worry about any other settings as you will overwrite these.

    Enable the I/O pins for OPS output in the pin config.

    In your application, try the code below.

    I'll be honest, I don't understand Brush-less DC motor control, so I have no idea if the waveforms being generated are correct.

    If you understand this technology then I'm sure you be able to modify the code to achieve what is required.

    I hope this helps.

    BR, Richard

    /* HAL-only entry function */

    #include "hal_data.h"

    #define PWM_PERIOD_VALUE    0xFFFFL

    #define PWN_DUTY_0A         PWM_PERIOD_VALUE / 4

    void hal_entry(void)

    {

       /* TODO: add your own code here */

       g_timer0.p_api->open( g_timer0.p_ctrl, g_timer0.p_cfg );

       /* Direct register access to some GPT registers is required.

        * A lot of these registers are write protected, so enable access to registers

        */

       R_GPTA0->GTWP = 0x0000A500;

       /*

        * Refer to S7G2 Hardware Users manual for set up flow -

        * 23.3.11.8 GPT_OPS Start Operation Setting Flow

        * Figure 23.85 Example setting for of GPT_OPS start operation

        * for more information

        */

       /* Specify a PWM mode for GPT0 */

       R_GPTA0->GTCR_b.MD = 4; /* Triangle-wave PWM mode 1 (16-bit transfer at trough) (single buffer or double buffer possible) */

       /* Set the Buffer mode for updating Period and Duty registers */

       R_GPTA0->GTBER_b.CCRA = 1;  /* Single buffer operation (GTCCRA ↔ GTCCRC) */

       R_GPTA0->GTBER_b.PR = 0;    /* No buffer operation */

       R_GPTA0->GTIOR = 0;

       R_GPTA0->GTIOR_b.GTIOA = 0x03; /* Set initial output low  - Retain output at cycle end - Toggle output at GTCCRA/GTCCRB compare match */

       /* GPT0 PWM Output enable / disbale */

       R_GPTA0->GTIOR_b.OAE = 1;    /* << If you want to see the GPT0A PWM output, then set this to 1.  Otherwise leave it at 0

       /* Set the PWM Duty and Period of GPT0 PWM */

       R_GPTA0->GTPR = PWM_PERIOD_VALUE;

       R_GPTA0->GTCCRC = PWN_DUTY_0A;

       /* Allow software starting of GPT0 */

       R_GPTA0->GTSSR_b.CSTRT = 1;

       /* Start GPT0 */

       R_GPTA0->GTSTR = 0x00000001;

       /* Set up the OPSCR */

       R_GPT_OPS->OPSCR_b.FB = 1;  /* For demo purposes, input phase from the software settings, not external hardware pins */

       /* Set the phase alignment */

       R_GPT_OPS->OPSCR_b.ALIGN = 1;

       /* Set the phase relationship */

       R_GPT_OPS->OPSCR_b.P = 1;

       R_GPT_OPS->OPSCR_b.N = 1;

       R_GPT_OPS->OPSCR_b.INV = 0;

       /* Enable OPS output */

       R_GPT_OPS->OPSCR_b.EN = 1;

       while(1)

       {

           /* Do nothing */

           /* The values of UF, VF, WF will be modified by the GPT ISR */

       }

    }

    void cb_timer0(timer_callback_args_t * p_args)

    {

       static uint8_t sequence = 0;

       switch( sequence )

       {

           case 0:

           {

               R_GPT_OPS->OPSCR_b.UF = 1;

               R_GPT_OPS->OPSCR_b.VF = 0;

               R_GPT_OPS->OPSCR_b.WF = 1;

               sequence = 1;

               break;

           }

           case 1:

           {

               R_GPT_OPS->OPSCR_b.UF = 1;

               R_GPT_OPS->OPSCR_b.VF = 0;

               R_GPT_OPS->OPSCR_b.WF = 0;

               sequence = 2;

               break;

           }

           case 2:

           {

               R_GPT_OPS->OPSCR_b.UF = 1;

               R_GPT_OPS->OPSCR_b.VF = 1;

               R_GPT_OPS->OPSCR_b.WF = 0;

               sequence = 3;

               break;

           }

           case 3:

           {

               R_GPT_OPS->OPSCR_b.UF = 0;

               R_GPT_OPS->OPSCR_b.VF = 1;

               R_GPT_OPS->OPSCR_b.WF = 0;

               sequence = 4;

               break;

           }

           case 4:

           {

               R_GPT_OPS->OPSCR_b.UF = 0;

               R_GPT_OPS->OPSCR_b.VF = 1;

               R_GPT_OPS->OPSCR_b.WF = 1;

               sequence = 5;

               break;

           }

           case 5:

           {

               R_GPT_OPS->OPSCR_b.UF = 0;

               R_GPT_OPS->OPSCR_b.VF = 0;

               R_GPT_OPS->OPSCR_b.WF = 1;

               sequence = 0;

               break;

           }

           default:

               break;

       }

    }

    Here is the output I see.

    Trace 7 is the GPT0 PWM waveform

    Trace 0 - 6 are the OPS U,V,W waveforms

  • In reply to Richard:

    Hello Richard,

    GREAT! This was very helpful und exacty what I'm looking for, thank you very much.

  • In reply to Richard:

    Hello Richard,

    GREAT! This was very helpful und exacty what I'm looking for, thank you very much.

  • In reply to Richard:

    Hello Richard,

    GREAT! This was very helpful und exacty what I'm looking for, thank you very much.

  • Hello,

    I'm a beginner in the use of S7G2 and e2studio. For information, i'm using e2studio v5.3.0.023, SSP version 1.3.0 and toolchain version 4.9.3.20150529. It is a test project to generate the same waveforms to control a brushless three-phased motor that those in the figure 23.82 of the datasheet of the S7G2, the following one :

    I configured the GPT_OPS in pins configuration on e2studio as followed :

    In Threads part of e2studio, I added a Timer Driver on r_gpt to use the GPT_OPS with the following properties :

    And finally, I put the code provided by Richard, that I really thank for his help, changing the registers settings only like the figure 23.82 specify : so I set up the OPSCR.ALIGN = 0, OPSCR.EN = 1, OPSCR.P = 0, OPSCR.N=0, OPSCR.INV = 0, OPSCR.RV = 0.

    But when I did ran it on the SK-S7G2 and I put an oscilloscope on the correct pins (P413 and P412) to see the PWMs, I saw nothing on the oscilloscope just a line on 0. 

    I don't know if the problem comes from the code or my bad configuration in the pins or the timer, could anybody help me, please?

    I thank you in advance for your answers

    Best Regards,

    Frederic

  • In reply to fenderguitars:

    Hi Frederic,

    As far as I see, you don't have to set any other registers than actually set in Richard's code. What I suggest is to check the configuration of the timer driver added in the configurator (in HAL/Common). Please check the callback is set to cb_timer0. You should see the addresses next to cb_timer0 code if it's used by the timer.

    Regards,
    adboc
  • In reply to adboc:

    Hi adboc,

    I thank you for your answer, I have configured the callback of the timer driver with cb_timer0 as you can see on the following screenshot of my configuration of the timer driver :

    For the code, I just changed the values of some registers like OPSCR.ALIGN, OPSCR.EN, OPSCR.P, OPSCR.N, OPSCR.INV and OPSCR.RV to have the same waveforms than the figure 23.82 of the datasheet of the S7G2.

    Where I can find the adresses next to cb_timer0 code that you're talking about? Indeed, I don't have any adresses in my code apart the R_GPTA0->GTWP = 0x0000A500; at the beginning of the code.

    Because in the code of Richard, there were no adresses near the cb_timer0 code.

    I thank you in advance for your help.

    Regards,

    Frédéric

  • In reply to fenderguitars:

    Hi Frédéric,

    Sorry, I forgot to mention that these addresses are visible when you debug the application. I see that the configuration settings of the timer driver are correctly set. Could you verify the callback is periodically fired (e.g. by setting a breakpoint)?

    Regards,
    adboc