Software application note FOC (old)


Software setup

This chapter describes how the software is structured and how to configure it according to the requirements.

1.1 Program Structure

The Application consists of four layers. The “Hardware Abstraction Layer” (HAL) provides 4 drivers to communicate with the hardware. The “Motion Encoder” (MENC) provides information from the “Quadrature Encoder Interface” (QEI) to estimate the rotor position. The GPIOs capture information from the Hall-effect sensors and indicate the current state of the motor. The ADC driver provides information for the board sensors (input voltage, phase voltage, phase current). The “Motion Pulse-width modulation” (MPWM) serves to configure the PWM for the motor, to activate/deactivate the GDU and to carry out error handling.

The “Motor control layer” (MCL) retrieves information from the HAL and the latest setpoint from the “Application layer” (APPL), process them via a PI current controller and uses the output to construct the “Space vector modulation” (SVM). This modulation is then fed into the MPWM driver, which sends it to the motor. The part that retrieves information from the HAL is the “position and speed estimation” (PSE), the part that calculates the current and SVM modulation is called the “Field-oriented control” (FOC). The FOC also has a state machine, explained below, which is controlled by the APPL.

APPL consists of the main application function that is attached to a timer and it called periodically. This function handles also the error handling of the GDU and calls the APPL state machine, which in running state, calls the Speed Controller and calculates a current setpoint based on a speed setpoint specified by the user.

MATH is a library, providing the mathematical functionality used by all three layers of the application. The figure below shows the relation between all Layers in this example.

Program structure

Figure 1: Program Structure

1.2 Folder Structure

The figure below shows the folder structure of the example. The next section explained how each layer interacts.

Figure 2: Folder Structure

1.2.1 Application Layer [APPL]

The application layer consists of the application main task, the application state machine and a Speed Controller. The main task receives speed feedback from the PSE and speed setpoint from the ADC driver (potentiometer). It then uses the Speed Controller to calculate and sent a latest setpoint to the FOC.

During initialization, a timer interrupt is set for the application main task, so application main task called every 5ms. Depending on the configuration in the MCL/def_par.h file, the current potentiometer value is fetched from ADC, then the router speed is approximated from the Hall-effect sensor. Finally, the APPL state machine is called.

The Speed Controller function serves to calculate a latest setpoint for the FOC based on the speed feedback, that the application receives from the PSE. For this purpose, the Speed Controller uses the PI regulator defined in Math.h.

The application state machine has the following states:

-APP_RUN - there has been a change in the speed error, therefore the Speed Controller should be activated.

-APP_IDLE - there has been no change in the speed error, do nothing.

-APP_ERROR - there has been an error while setting the current setpoint in the FOC, change FOC state to FOC_FAILED and stop the application.

-APP_STOP - the application is not running, reinitialize the Speed Controller and set the current setpoint to the FOC and set state to IDLE or RUN, depending on the speed error.

Figure 3: Application Layer

1.2.2 Hardware Abstraction Layer [HAL]

HAL include the Low-Level implementation, consist of 4 drivers ADCs, MPWM, MENC and GPIOs for position and speed estimation.

ADC: The ADC driver provides information for the board sensors - input voltage, phase voltage, phase current, etc. The channel assignment for netx90Driver board rev3 are described in the following table. The ADC driver initializes the channels at startup and update them in each MWPM_IRQHandler() call.

Unit

Ch0

Ch1

Ch2

Ch3

Ch4

Ch5

Ch6

Ch7

ADC0

SIN240_HC (X901)

ISENA (DRV8323R)

TSENS (INTERNAL)

VREF_ADC (INTERNAL)

-

-

-

-

ADC1

-

ISENB (DRV8323R)

VDDIO/2 (INTERNAL)

VREF_ADC (INTERNAL)

-

-

-

-

ADC2

SIN0_HA (X901)

AIM (X901)

POT (R33)

VSENA (J5)

VSENVM (J1)

-

NTC (R39)

-

ADC3

SIN120_HB (X901)

AI (X901)

ISENC (DRV8323R)

VSENB (J5)

-

VSENC (J5)

-

-

Table 1: MADC Matrix

GPIO: The GPIO provides information for the Hal sensor state, if PAR_USE_HALL_SPEED in par_def.h is set to 1 or 2. Set to 1 for sampling hall states. Set to 2 for interrupts. If set to zero the application will use the Quadrature Encoder(QE).

MENC: The MENC provides information from the Quadrature Encoder (QE). For the QE to be used, PAR_USE_HALL_SPEED in par_def.h has to be set to 0.

MPWM: The MPWM serves to configure the PWM for the motor, enable/disable the DRV832x 6 to 60-V Three-Phase Smart Gate Driver, as well as read relevant error information from it.

1.2.3 MATH Library [MATH]

MATH is a library, providing the mathematical functionality used by all three layers of the application. It provides:

  • The PI controller ,
  • Sin/Cos functionality
  • The space vector modulation Duty Calculation, 
  • The Clarke transformation, used in space vector modulation control of three-phase inverters
  • The inverse Clarke transformation
  • The Park transformation. The Park Transformation converts the time-domain components of a three-phase system in an abc reference frame to direct, quadrature, and zero components in a rotating reference frame
  • The inverse Park transformation

1.2.4 Motor Control Layer [MCL]

The MCL consist of the FOC and PSE modules. PSE is dedicated for getting the feedback from Hall-effect sensor or MENC. The FOC is responsible for the drive control, also FOC voltage and current control.

The FOC state machine called periodically from MPWM interrupt handler and performed current control, voltage control or disabling the GDU based on the latest state. Of course, the state should not be changed directly. The transit state has the task of changing the state, which called from APPL.

The FOC transit state machine is as follows:

  • FOC_IDLE - Disable GDU (Gate Drive Unit)
  • FOC_CURRENT_OFFSET - proceed to the Current Offset State Machine
  • FOC_CURRENT_CONTROL - calculate current via CurrentControl()
  • FOC_VOLTAGE_CONTROL - voltage control for open loop systems (disabled for this example)
  • FOC_PWM_PATTERN - FOC manual PWM pattern. Not used.
  • FOC_FAILED - disable GDU

Figure 4: Motor Control Layer

The state transition of the FOC is invoked by the application. Before the FOC can start its work, the current offsets have to be calculated. To do this, the FOC takes a series of measurements. When the sums of those measurements fall within predefined intervals, the current offsets are established as the average of these measurements. This process is implemented as a state machine and the following diagram describes its functionality:

Figure 5: Current offset state machine

The PSE is responsible for retrieving information from the motor. The “PSE estimate position” function as the name suggests has the task to assess the position, also calculating the speed. For the closed loop, the estimation is based on the Quadrature Encoder (QE) or Hall-effect sensors. The Hall sensor defines the sector within 60 degree intervals and the QE tracks the position based on estimated speed. For comparison, the speed is also calculated based on Hall sensors. If the estimated position does not match with Hall sensor measurement, estimated position is moved towards hall sensor measurement with a low-pass filter. This way QE position is aligned and position is not changed abruptly. 

1.2.5 User Interface

This example make uses of libc library and a simple UART console interface. The UART is routed through the USB via the FTDI-Chip on the board. The “App_TerminalHandler” function in the main loop reads one character via UART in each loop and store it in a buffer. After receiving the “carriage return” or “line feed” character, the receiving command will be checked. If the commands is valid, sends the corresponding command to the motor or receives feedback. The next chapter explains how to adapt the software to your requirements.

1.3 Configuring the parameter in the Software

This chapter shows how easily the parameter could be change, feel free to tweak the parameter to your desire.

1.3.1 Console parameter

The UART default parameter are located in “libc_file_support.c”. In the case of using the UART interface for feature development, the commands can be easily expand by adding new commands in “Term_TerminalCommandHandler” function and “g_tTerminalCommandsDictionary” dictionary in “TerminalHandler.c”.

Figure 6: UART parameter

1.3.2 Enable/Disable the potentiometer

To use the potentiometer, present on the board in this example application, you need to activate the define DEMO_USE_POTENTIOMETER in par_def.h. This will allow you to control the motor speed with the potentiometer, while the motor is running. In the case of disabling, use the “FOC_APPL_setSpeedSetpoint” function to set the desired speed.

1.3.3 Modifying frequency of the main application

In order to modify the of the “FOC_APPL_Main function, changing the period of the timer (eTimerPeriod) in FOC_APPL.c file is not enough. Some of the beneath-mentioned parameters may need to be changed correspondingly. First, change the PAR_APP_FREQ_HZ to the intended frequency in par_def.h file. This will cause the Current Controller and Speed Controller to be called less or more frequently. Depending on the new value of the frequency, you may have to tweak the parameters of the PI controllers to smooth the operation of motor. These parameters are PAR_SPEED_CONTROLLER_KP, PAR_SPEED_CONTROLLER_KI, PAR_CURRENT_CONTROLLER_KP and PAR_CURRENT_CONTROLLER_KI.

Figure 7: Frequency of the main application

List of changes of application parameters:

Parameter
Default Value
Example1 Value
PAR_APP_FREQ_HZ1000U200U
PAR_SPEED_CONTROLLER_KP0.004f0.001f
PAR_SPEED_CONTROLLER_KI0.000001f0.00000025f
PAR_CURRENT_OFFSET_THRESHOLD_DIG48U88U

Table 2: Suggested parameter for changing of main application 

1.3.4 Other parameters

The MCL parameters are defined in MCL/includes/par_def.h. These parameters control various aspects of the motor behavior. According to your application you may have tweak this parameter.

The table below shows some of the important parameter in this example.

<style><!--table {mso-displayed-decimal-separator:"\."; mso-displayed-thousand-separator:"\,";}@page { mso-header-data:""; mso-footer-data:""; margin:0.75in 0.7in 0.75in 0.7in; mso-header-margin:0.3in; mso-footer-margin:0.3in; mso-page-orientation:Portrait; }tr {mso-height-source:auto; mso-ruby-visibility:none;}col {mso-width-source:auto; mso-ruby-visibility:none;}br {mso-data-placement:same-cell;}ruby {ruby-align:left;}.style0 { mso-number-format:General; text-align:general; vertical-align:bottom; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border:none; mso-protection:locked visible; mso-style-name:Normal; mso-style-id:0;}.font0 { color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; }.font1 { color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; }.font2 { color:#000000; font-size:11pt; font-weight:700; font-style:normal; font-family:"Calibri","sans-serif"; }td {mso-style-parent:style0; mso-number-format:General; text-align:general; vertical-align:bottom; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border:none; mso-protection:locked visible; mso-ignore:padding;}.style0 { text-align:general; vertical-align:bottom; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; mso-style-name:"Normal"; }.style1 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style2 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style3 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style4 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style5 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style6 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style7 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style8 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style9 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style10 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style11 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style12 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style13 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.style14 { text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:10pt; font-weight:400; font-style:normal; font-family:"Arial","sans-serif"; mso-protection:locked visible; }.x15 { mso-style-parent:style0; mso-number-format:General; text-align:general; vertical-align:bottom; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x16 { mso-style-parent:style0; mso-number-format:General; text-align:general; vertical-align:bottom; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:700; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x17 { mso-style-parent:style0; mso-number-format:General; text-align:center; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x18 { mso-style-parent:style0; mso-number-format:General; text-align:center; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x19 { mso-style-parent:style0; mso-number-format:"\@"; text-align:center; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x20 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x21 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:700; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x22 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x23 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:#FFFFFF; mso-pattern:auto none; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x24 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:#9DC3E6; mso-pattern:auto none; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x25 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:normal;word-wrap:break-word; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x26 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:#FFD966; mso-pattern:auto none; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x27 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:#9DC3E6; mso-pattern:auto none; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x28 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:nowrap; background:#FFD966; mso-pattern:auto none; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x29 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:normal;word-wrap:break-word; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; mso-protection:locked visible; }.x30 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:normal;word-wrap:break-word; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:700; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x31 { mso-style-parent:style0; mso-number-format:General; text-align:general; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x32 { mso-style-parent:style0; mso-number-format:General; text-align:left; vertical-align:middle; white-space:normal;word-wrap:break-word; background:#9DC3E6; mso-pattern:auto none; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }.x33 { mso-style-parent:style0; mso-number-format:General; text-align:center; vertical-align:middle; white-space:nowrap; background:auto; mso-pattern:auto; color:#000000; font-size:11pt; font-weight:400; font-style:normal; font-family:"Calibri","sans-serif"; border-top:1px solid windowtext; border-right:1px solid windowtext; border-bottom:1px solid windowtext; border-left:1px solid windowtext; mso-diagonal-down:none; mso-diagonal-up:none; mso-protection:locked visible; }--></style><div class="cells-worksheet" data-sheet-number="0" data-sheet-name="Tabelle1"><table border="0" cellpadding="0" cellspacing="0" style="border-collapse:collapse;table-layout:fixed;width:867pt"> <colgroup> <col class="x20" style="mso-width-source:userset;background:none;width:63px"></col> <col class="x20" style="mso-width-source:userset;background:none;width:283px"></col> <col class="x20" style="mso-width-source:userset;background:none;width:92px"></col> <col class="x17" style="mso-width-source:userset;background:none;width:201px"></col> <col class="x20" style="mso-width-source:userset;background:none;width:84px"></col> <col class="x29" style="mso-width-source:userset;background:none;width:433px"></col> </colgroup> <tbody> <tr class="x16" style="mso-height-source:userset;height:14.6pt" id="r0"> <td class="x21" style="height:13.1pt;width:47.25pt">Number</td> <td class="x21" style="width:212.25pt">Parameter name</td> <td class="x21" style="width:69pt">Datentype</td> <td class="x21" style="width:150.75pt">Default value</td> <td class="x21" style="width:63pt">Position</td> <td class="x30" style="width:324.75pt">Description</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r1"> <td class="x22" style="height:13.1pt">1</td> <td class="x23">APP_POT_SPEED_SLOPE</td> <td class="x22">Float</td> <td class="x18">(7000-50)/(4095-200)</td> <td class="x22">par_def.h</td> <td class="x25">Slope of Potentiometer reading vs Speed request</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r2"> <td class="x22" style="height:13.1pt">2</td> <td class="x23">PAR_ADC_MAX_DIG</td> <td class="x22">Unsigned int</td> <td class="x18">4095</td> <td class="x22">par_def.h</td> <td class="x25">Maximum of ADC resulotion, Internal 12bit ADC</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r3"> <td class="x22" style="height:13.1pt">3</td> <td class="x22">PAR_POT_MIN_SPEED_REQ_DIG</td> <td class="x22">Unsigned int</td> <td class="x18">200</td> <td class="x22">par_def.h</td> <td class="x25">Minimum Potentiometer value for speed request</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r4"> <td class="x22" style="height:13.1pt">4</td> <td class="x22">PAR_POT_HYSTERESIS_DIG</td> <td class="x22">Unsigned int</td> <td class="x18">100</td> <td class="x22">par_def.h</td> <td class="x25">Speed request hysteresis value for Pot.</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r5"> <td class="x22" style="height:13.1pt">5</td> <td class="x24">PAR_MIN_SPEED_RPM</td> <td class="x22">Unsigned int</td> <td class="x18">50</td> <td class="x22">par_def.h</td> <td class="x25">Minimum speed request</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r6"> <td class="x22" style="height:13.1pt">6</td> <td class="x23">PAR_STOPPED_SPEED_RPM</td> <td class="x22">Unsigned int</td> <td class="x18">0U</td> <td class="x22">par_def.h</td> <td class="x25">Motor stopped</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r7"> <td class="x22" style="height:13.1pt">7</td> <td class="x24">PAR_MAX_SPEED_RPM</td> <td class="x22">Unsigned int</td> <td class="x18">7000</td> <td class="x22">par_def.h</td> <td class="x25"> Maximum speed request</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r8"> <td class="x22" style="height:13.1pt">8</td> <td class="x22" style="overflow:hidden">PAR_NUMBER_OF_CURRENT_OFFSET_MEAS</td> <td class="x22">Unsigned int</td> <td class="x18">8</td> <td class="x22">par_def.h</td> <td class="x25">Number of measurements to calculate average current offset</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r9"> <td class="x22" style="height:13.1pt">9</td> <td class="x26" style="overflow:hidden">PAR_CURRENT_OFFSET_THRESHOLD_DIG</td> <td class="x22">Unsigned int</td> <td class="x18">88</td> <td class="x22">par_def.h</td> <td class="x25">Number of digits allowed for current offset</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r10"> <td class="x22" style="height:13.1pt">10</td> <td class="x22">PAR_MAX_DUTY_CYCLE_PERCENT</td> <td class="x22">Float</td> <td class="x18"> 96.0</td> <td class="x22">par_def.h</td> <td class="x25">Maximum allowed duty cycle percentage</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r11"> <td class="x22" style="height:13.1pt">11</td> <td class="x22">PAR_ADC_VREF_VOLTS</td> <td class="x22">Float</td> <td class="x19">3.3</td> <td class="x22">par_def.h</td> <td class="x25">Reference voltage for ADC</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r12"> <td class="x22" style="height:13.1pt">12</td> <td class="x22">PAR_SHUNT_RESISTANCE_OHM</td> <td class="x22">Float</td> <td class="x18">0.007</td> <td class="x22">par_def.h</td> <td class="x25">Shunt resistor value</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r13"> <td class="x22" style="height:13.1pt">13</td> <td class="x22">PAR_CURRENT_AMP_GAIN</td> <td class="x22">Float</td> <td class="x18">20.0</td> <td class="x22">par_def.h</td> <td class="x25">Gain value of op-amp.</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r14"> <td class="x22" style="height:13.1pt">14</td> <td class="x22">PAR_DCBUS_VOLTAGE_GAIN</td> <td class="x22">Float</td> <td class="x18">((2.88 + 82.0) / 2.88)</td> <td class="x22">par_def.h</td> <td class="x25"> DC-bus Voltage gain value, calculated from voltage divider</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r15"> <td class="x22" style="height:13.1pt">15</td> <td class="x22" style="overflow:hidden">PAR_DCBUS_VOLTAGE_OFFSET_DIGITS</td> <td class="x22">Unsigned int</td> <td class="x18">10</td> <td class="x22">par_def.h</td> <td class="x25">DC-bus Voltage offset value, experimentally determined</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r16"> <td class="x22" style="height:13.1pt">16</td> <td class="x22">PAR_PHASE_VOLTAGE_GAIN </td> <td class="x22">Float</td> <td class="x18">((4.99 + 82.0) / 4.99)</td> <td class="x22">par_def.h</td> <td class="x25">Phase Voltage gain value, calculated from voltage divider</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r17"> <td class="x22" style="height:13.1pt">17</td> <td class="x22" style="overflow:hidden">PAR_PHASE_VOLTAGE_OFFSET_DIGITS </td> <td class="x22">Unsigned int</td> <td class="x18">0</td> <td class="x22">par_def.h</td> <td class="x25"> Phase Voltage offset value</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r18"> <td class="x22" style="height:13.1pt">18</td> <td class="x22">PAR_CPU_FREQ_HZ </td> <td class="x22">Unsigned int</td> <td class="x18">100000000</td> <td class="x22">par_def.h</td> <td class="x25">CPU frequency in Hz</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r19"> <td class="x22" style="height:13.1pt">19</td> <td class="x22">PAR_PWM_PERIOD</td> <td class="x22">Unsigned int</td> <td class="x18">5000</td> <td class="x22">par_def.h</td> <td class="x25">PWM frequency in Hz ( Initial pwm period)</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r20"> <td class="x22" style="height:13.1pt">20</td> <td class="x22">PAR_APP_FREQ_HZ</td> <td class="x22">Unsigned int</td> <td class="x18">200</td> <td class="x22">par_def.h</td> <td class="x25">Application (Speed Controller) frequency</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r21"> <td class="x22" style="height:13.1pt">21</td> <td class="x24">PAR_QEI_NUMBER_OF_SLOTS</td> <td class="x22">Unsigned int</td> <td class="x18">256</td> <td class="x22">par_def.h</td> <td class="x25">Number of quadrature encoder slots</td> </tr> <tr style="mso-height-source:userset;height:30pt" id="r22"> <td class="x22" style="height:28.5pt">22</td> <td class="x22">PAR_USE_MAF_CAPTURE</td> <td class="x22">Unsigned int</td> <td class="x18">0</td> <td class="x22">par_def.h</td> <td class="x25">Use moving average filter in speed estimation.Details: To enable set value to 1U. Captured position is filtered with a MAF of size 4</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r23"> <td class="x22" style="height:13.1pt">23</td> <td class="x24">PAR_MOTOR_POLE_PAIRS</td> <td class="x22">Unsigned int</td> <td class="x18">3</td> <td class="x22">par_def.h</td> <td class="x25">Motor pole pair number</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r24"> <td class="x22" style="height:13.1pt">24</td> <td class="x24">PAR_MAX_PHASE_CURRENT_AMP</td> <td class="x22">Float</td> <td class="x19">2.5</td> <td class="x22">par_def.h</td> <td class="x25">Maximum allowed phase current</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r25"> <td class="x22" style="height:13.1pt">25</td> <td class="x26">PAR_SPEED_CONTROLLER_KP</td> <td class="x22">Float</td> <td class="x18">0.001</td> <td class="x22">par_def.h</td> <td class="x25">Proportional gain of speed controller</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r26"> <td class="x22" style="height:13.1pt">26</td> <td class="x26">PAR_SPEED_CONTROLLER_KI</td> <td class="x22">Float</td> <td class="x18"> 0.00000025</td> <td class="x22">par_def.h</td> <td class="x25">Integral gain of speed controller</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r27"> <td class="x22" style="height:13.1pt">27</td> <td class="x26">PAR_FIELDWEAK_CONTROLLER_KP</td> <td class="x22">Float</td> <td class="x18"> 0.1</td> <td class="x22">par_def.h</td> <td class="x25">Proportional gain of field-weakening controller</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r28"> <td class="x22" style="height:13.1pt">28</td> <td class="x26">PAR_FIELDWEAK_CONTROLLER_KI</td> <td class="x22">Float</td> <td class="x18">0.005</td> <td class="x22">par_def.h</td> <td class="x25">Integral gain of field-weakening controller</td> </tr> <tr style="mso-height-source:userset;height:45pt" id="r29"> <td class="x22" style="height:43.5pt">29</td> <td class="x26" style="overflow:hidden">PAR_FIELDWEAK_START_VOLTAGE_RATIO</td> <td class="x22">Float</td> <td class="x19">1.08</td> <td class="x22">par_def.h</td> <td class="x25">Threshold voltage vector magnitude to start field-weakening.Details:Value is less than maximum voltage vector magnitude<span style="mso-spacerun:yes;font-family:&quot;Times New Roman&quot;">  </span>to allow a transition region. </td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r30"> <td class="x22" style="height:13.1pt">30</td> <td class="x26">PAR_CURRENT_CONTROLLER_KP</td> <td class="x22">Float</td> <td class="x18">0.01</td> <td class="x22">par_def.h</td> <td class="x25">Proportional gain of current controller</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r31"> <td class="x22" style="height:13.1pt">31</td> <td class="x26">PAR_CURRENT_CONTROLLER_KI</td> <td class="x22">Float</td> <td class="x18">0.0005</td> <td class="x22">par_def.h</td> <td class="x25">Integral gain of current controller</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r32"> <td class="x22" style="height:13.1pt">32</td> <td class="x23">PAR_USE_OPENLOOP</td> <td class="x18">-</td> <td class="x18">0</td> <td class="x22">par_def.h</td> <td class="x25">To enable open-loop for debugging set to 1</td> </tr> <tr style="mso-height-source:userset;height:30pt" id="r33"> <td class="x22" style="height:28.5pt">33</td> <td class="x22">ul_timerPeriod</td> <td class="x22" style="overflow:hidden">Unsigned long</td> <td class="x18">500000</td> <td class="x22" style="overflow:hidden">FOC_APPL.c</td> <td class="x25">Frequency of FOC APPL Main function (determine how often this function is called) </td> </tr> <tr style="mso-height-source:userset;height:29.15pt" id="r34"> <td class="x22" style="height:27.65pt">34</td> <td class="x32">PAR_USE_HALL_SPEED</td> <td class="x33">-</td> <td class="x18">1</td> <td class="x22">par_def.h</td> <td class="x25">Determines which interface is used to calculate the speed. Default is Hall sensor</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r35"> <td class="x22" style="height:13.1pt">35</td> <td class="x22">DEMO_USE_POTENTIOMETER</td> <td class="x18">-</td> <td class="x18">-</td> <td class="x22" style="overflow:hidden">FOC_APPL.c</td> <td class="x25">If defined, program use the Potentiometer existing on the board</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r36"> <td class="x22" style="height:13.1pt">36</td> <td class="x22" style="overflow:hidden">FOC_CURRENT_OFFSET_MEASURE_NUMBER</td> <td class="x31">uint8_t</td> <td class="x18">8</td> <td class="x22">FOC.c</td> <td class="x25">Number of measurements for current offset</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r37"> <td class="x22" style="height:13.1pt">37</td> <td class="x22">FOC_CURRENT_OFFSET_MIN</td> <td class="x31">uint16_t</td> <td class="x18">2048U - 88U</td> <td class="x22">FOC.c</td> <td class="x25">Minimum value for current offset</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r38"> <td class="x22" style="height:13.1pt">38</td> <td class="x22">FOC_CURRENT_OFFSET_MAX</td> <td class="x31">uint16_t</td> <td class="x18">2048U + 88U</td> <td class="x22">FOC.c</td> <td class="x25">Maximum value for current offset</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r39"> <td class="x22" style="height:13.1pt">39</td> <td class="x22">FOC_CURRENT_OFFSET_SUM_MIN</td> <td class="x31">uint32_t</td> <td class="x18">8(2048U - 88U)</td> <td class="x22">FOC.c</td> <td class="x25">Minimum value for sum of current offset</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r40"> <td class="x22" style="height:13.1pt">40</td> <td class="x22">FOC_CURRENT_OFFSET_SUM_MAX</td> <td class="x31">uint32_t</td> <td class="x18">8(2048U + 88U)</td> <td class="x22">FOC.c</td> <td class="x25">Maximum value for sum of current offset</td> </tr> <tr style="mso-height-source:userset;height:29.15pt" id="r41"> <td class="x22" style="height:27.65pt">41</td> <td class="x22">FOC_CURRENT_OFFSET_WAIT</td> <td class="x31">uint16_t</td> <td class="x18">20000</td> <td class="x22">FOC.c</td> <td class="x25">In case of current offset measurement error wait time for next measurement</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r42"> <td class="x22" style="height:13.1pt">42</td> <td class="x22">FOC_SVM_LIMIT</td> <td class="x31">Float</td> <td class="x18">(96/100)/(1.73205080757/2)</td> <td class="x22">FOC.c</td> <td class="x25">Space-Vector-Modulation limit</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r43"> <td class="x22" style="height:13.1pt">43</td> <td class="x22">FOC_PICONTROL_LOWER_LIM</td> <td class="x31">Float</td> <td class="x18" style="overflow:hidden">(-1)(96/100)/(1.73205080757/2)</td> <td class="x22">FOC.c</td> <td class="x25">Current PI-controller lower limit</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r44"> <td class="x22" style="height:13.1pt">44</td> <td class="x22">FOC_PICONTROL_UPPER_LIM</td> <td class="x31">Float</td> <td class="x18">(96/100)/(1.73205080757/2)</td> <td class="x22">FOC.c</td> <td class="x25">Current PI-controller upper limit</td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r45"> <td class="x20" style="height:14.6pt"></td> <td class="x20"></td> <td class="x20"></td> <td class="x17"></td> <td class="x20"></td> <td class="x29"></td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r46"> <td class="x27" style="height:14.6pt"></td> <td class="x20">Motor dependent</td> <td class="x20"></td> <td class="x17"></td> <td class="x20"></td> <td class="x29"></td> </tr> <tr style="mso-height-source:userset;height:14.6pt" id="r47"> <td class="x28" style="height:14.6pt"></td> <td class="x20">Change the behavior of the running motor</td> <td class="x20"></td> <td class="x17"></td> <td class="x20"></td> <td class="x29"></td> </tr> <tr style="display:none"> <td style="width:47.25pt"></td> <td style="width:212.25pt"></td> <td style="width:69pt"></td> <td style="width:150.75pt"></td> <td style="width:63pt"></td> <td style="width:324.75pt"></td> </tr> </tbody></table></div>

Table 3: user parameter

2 Sending commands

After flashing the example to the NXHX90-MC board due to the Getting started netX Studio CDT, establish a UART console connection with the board by selecting the correct COM-Port, baudrate, number of bits, data length and parity that you configured in the last chapter. Then write and send a command.

The available commands are:

  • APP_TERMINAL_HANDLER_COMMAND_MOTOR_START- this command starts the motor at the speed defined by DEMO_MOTOR_START_SPEED. If DEMO_USE_POT is defined, then the motor speed is regulated by the potentiometer.
  • APP_TERMINAL_HANDLER_COMMAND_MOTOR_GET_SPEED - this command retrieves the current speed of the motor in RPM from the PSE and prints it on the standard output. 
  • APP_TERMINAL_HANDLER_COMMAND_MOTOR_STOP - this command stops the motor.

To use this commands just write "motor_start", "motor_stop" or "motor_get_speed" to the console. To executed the command send the commands with “Carriage Return” (CR) or “Line Feed” (LF) at the end. If the DEMO_USE_POTENTIOMETER is activated, after sending “motor_start” command, you can adjust the motor speed bye turning the potentiometer.

Note: Make sure switches 1 and 2 are on, to enable the debugging and UART through the FTDI, and switch 4 is off, to not have the ADCs disabled. On switch S701 (for more Information on Positions of interfaces and operating elements, see the NXHX 90-MC development board).

3 Abbreviations

Abbreviations

Description

FOC

Field Oriented Control

PSE

Position and Speed Estimation

GDU

Gate Drive Unit

HAL

Hardware Abstraction Layer

MCL

Motor Control Layer

APPL

Application Layer

CR

Carriage Return

LF

Line Feed

ADC

Analog to digital converter

MC

Motion Control

QEI

Quadrature Encoder Interface

MENC

Motion Encoder

MPWM

Motion pulse width modulation

GPIO

General purpose input output

ECZ

Event counter zero

SVM

Space vector modulation

4 Attachments

  File Modified

Microsoft Excel Spreadsheet par_def.xlsx

2021-02-26 by Nico Mäding