Skip to content

Commit

Permalink
Fixed MTPA, adjusting, documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
rombrew committed Oct 12, 2024
1 parent f1bc5c4 commit d672779
Show file tree
Hide file tree
Showing 27 changed files with 556 additions and 404 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ There are a few videos about PMC on [youtube](https://www.youtube.com/@romblv).
with inline or low-side placement.
- Self-adjustment of all onboard measurements (current and voltage) along
symmetrical channels.
- Dead-Time Compensation (DTC) based on currents polatity (**EXPERIMENTAL**).
- Dead-Time Compensation (DCU) based on currents polatity (**EXPERIMENTAL**).

- Advanced SVPWM scheme provides:
- Reduced switching losses and fully utilised DC link voltage.
Expand Down
18 changes: 10 additions & 8 deletions bench/bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ tlm_plot_grab()
fmt_GP(pm.vsi_IF, 0);
fmt_GP(pm.vsi_UF, 0);

fmt_GP(pm.dtc_uX, "V");
fmt_GP(pm.dtc_uY, "V");
fmt_GP(pm.dcu_DX, "V");
fmt_GP(pm.dcu_DY, "V");

fmt_GP(pm.lu_MODE, 0);
fmk_GP(pm.lu_mq_produce, pm.const_Zp, "Nm");
Expand All @@ -172,8 +172,8 @@ tlm_plot_grab()
sym_GP(atan2(pm.flux_F[1], pm.flux_F[0]) * kDEG, "pm.flux_F", "deg");
fmk_GP(pm.flux_wS, kRPM, "rpm");

fmt_GP(pm.kalman_rsu[0], "A");
fmt_GP(pm.kalman_rsu[1], "A");
fmt_GP(pm.kalman_rsu_D, "A");
fmt_GP(pm.kalman_rsu_Q, "A");
fmt_GP(pm.kalman_bias_Q, "V");
fmk_GP(pm.kalman_lpf_wS, kRPM, "rpm");

Expand All @@ -197,11 +197,14 @@ tlm_plot_grab()
fmt_GP(pm.watt_lpf_Q, "V");

fmt_GP(pm.i_setpoint_current, "A");
fmk_GP(pm.i_setpoint_torque, pm.const_Zp, "Nm");
fmt_GP(pm.i_track_D, "A");
fmt_GP(pm.i_track_Q, "A");
fmt_GP(pm.i_integral_D, "V");
fmt_GP(pm.i_integral_Q, "V");

fmt_GP(pm.mtpa_setpoint_Q, "A");
fmt_GP(pm.mtpa_load_Q, "A");
fmt_GP(pm.mtpa_D, "A");
fmt_GP(pm.weak_D, "A");

Expand Down Expand Up @@ -375,8 +378,8 @@ void bench_script()
tlm_restart();

m.Rs = 7.E-3;
m.Ld = 37.E-6;
m.Lq = 57.E-6;
m.Ld = 35.E-6;
m.Lq = 65.E-6;
m.Udc = 49.;
m.Rdc = 0.1;
m.Zp = 5;
Expand All @@ -392,8 +395,7 @@ void bench_script()

pm.config_LU_ESTIMATE = PM_FLUX_KALMAN;
pm.config_LU_SENSOR = PM_SENSOR_HALL;
pm.config_HFI_WAVETYPE = PM_HFI_SINE;
//pm.config_DTC_VOLTAGE = PM_DISABLED;
pm.config_RELUCTANCE = PM_ENABLED;

pm.watt_wA_maximal = 80.f;
pm.watt_wA_reverse = 80.f;
Expand Down
42 changes: 31 additions & 11 deletions bench/tsfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,20 @@ void ts_self_adjust()
break;
}

usual_Mq = m.Mq[3];
m.Mq[3] = 5.E-1;
if (pm.config_DCU_VOLTAGE == PM_ENABLED) {

pm.fsm_req = PM_STATE_ADJUST_DTC_VOLTAGE;
ts_wait_IDLE();
usual_Mq = m.Mq[3];
m.Mq[3] = 5.E-1;

m.Mq[3] = usual_Mq;
pm.fsm_req = PM_STATE_ADJUST_DCU_VOLTAGE;
ts_wait_IDLE();

printf("const_im_Rz = %.4E (Ohm)\n", pm.const_im_Rz);
printf("dtc_deadband = %.1f (ns)\n", pm.dtc_deadband);
printf("self_DTu = %.4f (V)\n", pm.self_DTu);
m.Mq[3] = usual_Mq;

printf("const_im_Rz = %.4E (Ohm)\n", pm.const_im_Rz);
printf("dcu_deadband = %.1f (ns)\n", pm.dcu_deadband);
printf("self_DTu = %.4f (V)\n", pm.self_DTu);
}
}
while (0);
}
Expand Down Expand Up @@ -197,8 +200,12 @@ void ts_probe_impedance()

void ts_probe_spinup()
{
int backup_LU_DRIVE;
float Kv;

backup_LU_DRIVE = pm.config_LU_DRIVE;
pm.config_LU_DRIVE = PM_DRIVE_SPEED;

do {
pm.fsm_req = PM_STATE_LU_STARTUP;

Expand Down Expand Up @@ -323,14 +330,19 @@ void ts_probe_spinup()
printf("s_gain_D = %.2E\n", pm.s_gain_D);
}
while (0);

pm.config_LU_DRIVE = backup_LU_DRIVE;
}

void ts_adjust_sensor_hall()
{
int backup_LU_SENSOR, N;
int backup_LU_SENSOR, backup_LU_DRIVE, N;

backup_LU_SENSOR = pm.config_LU_SENSOR;
backup_LU_DRIVE = pm.config_LU_DRIVE;

pm.config_LU_SENSOR = PM_SENSOR_NONE;
pm.config_LU_DRIVE = PM_DRIVE_SPEED;

do {
pm.fsm_req = PM_STATE_LU_STARTUP;
Expand Down Expand Up @@ -365,16 +377,20 @@ void ts_adjust_sensor_hall()
while (0);

pm.config_LU_SENSOR = backup_LU_SENSOR;
pm.config_LU_DRIVE = backup_LU_DRIVE;
}

void ts_adjust_sensor_eabi()
{
int backup_LU_SENSOR;
int backup_LU_SENSOR, backup_LU_DRIVE;

double F0g;

backup_LU_SENSOR = pm.config_LU_SENSOR;
backup_LU_DRIVE = pm.config_LU_DRIVE;

pm.config_LU_SENSOR = PM_SENSOR_NONE;
pm.config_LU_DRIVE = PM_DRIVE_SPEED;

do {
pm.fsm_req = PM_STATE_LU_STARTUP;
Expand Down Expand Up @@ -406,6 +422,7 @@ void ts_adjust_sensor_eabi()
while (0);

pm.config_LU_SENSOR = backup_LU_SENSOR;
pm.config_LU_DRIVE = backup_LU_DRIVE;
}

static void
Expand Down Expand Up @@ -781,12 +798,15 @@ void ts_script_test()
m.Rdc = 0.1;
m.Zp = 5;
m.lambda = blm_Kv_lambda(&m, 58.);
m.Jm = 4.E-3;
m.Jm = 15.E-3;

ts_script_default();
ts_script_base();
blm_restart(&m);

//pm.config_DCU_VOLTAGE = PM_DISABLED;
//pm.dcu_tol = 1.f;

ts_script_speed();
blm_restart(&m);

Expand Down
10 changes: 5 additions & 5 deletions doc/CommandLineInterface.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ command.
- You can specify a register number instead of its name to refer the exactly
one register.

Something like that:
Something like that.

(pmc) reg <pattern> <value>
(pmc) reg <ID> <value>
Expand Down Expand Up @@ -76,11 +76,11 @@ link it to another register if you want control another parameter. We provide
many registers in different units of measurement. You are free to choose how to
control current in Amperes or percentage from full scale or something else.

There are telemetry module with 10 link registers. Choose any registers you
need to be captured.
We have telemetry module with 20 links that configured to the most important
registers by default. You can choose any registers you need to be captured.

(pmc) reg tlm.reg_ID0 pm.tvm_A
(pmc) reg tlm.reg_ID1 pm.tvm_B
(pmc) reg tlm.reg_ID0 pm.dbg_flux_rsu
(pmc) reg tlm.reg_ID1 pm.watt_consumed_Ah
(pmc) reg tlm.reg_ID2 ...

Command to grab telemetry into RAM and flush textual dump.
Expand Down
46 changes: 34 additions & 12 deletions doc/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ The aim of our PCB design is to optimize electrical and thermal performance.
We are not trying to cram all the components into a small volume. However, we
sometimes cross the border of quality in favor of PCB size.

Our recent HW revision is `REV5` designed in 8-layer PCB with 35um or 70um
copper foil thickness. To improve heat dissipation it is necessary to mount an
aluminium heatsink at bottom side through thermal interface.
Our recent HW revision is `REV5` designed in 8-layer PCB with 35um copper foil
thickness. To improve heat dissipation it is necessary to mount an aluminium
heatsink at bottom side through isolated thermal interface.

You can also try to use third-party hardware like VESC or its clones. Look into
[Hardware VESC](HardwareVESC.md) document to get an overview of supported
hardware.
third-party hardware.

## Basic wiring

Expand Down Expand Up @@ -53,7 +53,7 @@ erased MCU) then short BOOT pin to +3.3v before the power up.

## Software

There are a few parts of software:
PMC software consist of several main parts.

1. Workbench includes numerical model of VSI with PMSM connected (`bench/...`).
The numerical model enables us to develop control code in fast cycle without
Expand All @@ -66,19 +66,37 @@ There are a few parts of software:
and diagnose PMC in visual way. This frontend communicates with PMC using
the CLI via serial port or USB.

3. Firmware code for onboard MCU (`src/...`). All of control algorithms are
implemented here.
3. Firmware code for onboard MCU (`src/...`). All of PMSM control algorithms
and related functions are implemented here.

You can build the software from sources yourself or get binaries from bundle
[resleases](https://github.com/rombrew/phobia/releases).

## Build

The firmware can be compiled with appropriate [GCC](https://gcc.gnu.org/) or
[Clang](https://clang.llvm.org/) toolchain. For example, let us build the
firmware for the `REV5` hardware.
[Clang](https://clang.llvm.org/) toolchain. Setting up the build toolchain is
beyond the scope of this document.

For example let us build the firmware for our `REV5` hardware.

$ git clone https://github.com/rombrew/phobia.git phobia
$ cd phobia/src
$ make HWREV=PHOBIA_rev5

So using the above commands we have built the firmware. Next there are a few
ways to load the firmware into the MCU:
You can specify cross-compiler prefix `CROSS` and serial device name `TTY`.

$ make HWREV=PHOBIA_rev5 CROSS=armv7m-none-eabi TTY=/dev/rfcomm0

If you modified source code files it may be necessary to regenerate `defs.h`
files by `mkconfig` python script before build.

$ ./mkconfig
$ make HWREV=PHOBIA_rev5

## Load

There are several ways to load the firmware into the MCU.

SWD interface with [GDB](https://www.gnu.org/software/gdb/). We use
[Black Magic Probe](https://1bitsquared.com/products/black-magic-probe). Be
Expand Down Expand Up @@ -117,7 +135,11 @@ embedded bootloader without BOOT pin. Just run the command in the CLI.

(pmc) ap_bootload

Read the following documentation for setting PMC up.
## Basic configuration

We recommend you to do built-in [integrity check](IntegritySelfTest.md) and
self-adjustment the first time you power PMC up. Then read all of documentation
for setting PMC up.

- [Command Line Interface](CommandLineInterface.md)
- [Graphical User Interface](GraphicalUserInterface.md)
Expand Down
37 changes: 17 additions & 20 deletions doc/HardwareDesign.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ PMC internals. Also this page will be useful for understanding.

## Hardware

We have a three-phase Voltage Source Inverter (VSI) which consists of at least
six metal–oxide–semiconductor field-effect transistors (MOSFET). The voltage at
each of the output terminals is measured. Phase current A and B (optionally C)
is measured. The output terminals are connected to the machine.
We have a three-phase Voltage Source Inverter (VSI) which typically consists of
at least six Metal–Oxide–Semiconductor Field-Effect Transistors (MOSFET). The
voltage at each of the output terminals is measured. Phase current A and B
(optionally C) is measured. The output terminals are connected to the machine.

```
(VCC) >---+--------+---------+---------+
Expand Down Expand Up @@ -52,7 +52,7 @@ PWM scheme as shown in the diagram.
Each half-bridge consists of two MOSFETs controlled by a gate drivers with a
specified dead-time `DT`. Depending on the direction of the current flow during
the dead-time the actual voltage on half-bridge may be different. The amount of
uncertainty in the output voltage `DTu` expressed as follows:
uncertainty in the output voltage `DTu` expressed as follows.

```
DT * DC_link_voltage
Expand Down Expand Up @@ -90,13 +90,10 @@ uncertainty in the output voltage `DTu` expressed as follows:
The voltage divider (R1, R2) and filter capacitor (C1) are used to measure the
terminal voltage (uA, uB, uC) and supply voltage (uS). This RC scheme forms an
exponential integrator that allows us to restore the pulse width by measured
voltage. Additional resistor R3 is used to bias the operating point into the
voltage. Additional resistor R3 can be used to bias the zero volatege into the
linear region. You can skip the terminal voltage sensing if you do not need
related features but supply voltage measuring is mandatory.

To get acceptable accuracy you need to make sure that the RC scheme time
constant is comparable to the typical `dT` value. Also make sure that your
capacitors are stable over whole temperature and voltage range.

```
+------< REF
Expand All @@ -114,7 +111,7 @@ capacitors are stable over whole temperature and voltage range.
R2 27K | | -----
|_| -----
| | C1 1nF
| | (C0G)
| |
+--------+
|
---
Expand All @@ -131,13 +128,13 @@ measurement you will need to configure the software appropriately.
```
// Current measurement //
>-----+
| (+) |\ R1 = 0.5 mOhm
| (+) |\ R1 = 0.5 mOhm
+------| \
| | \ +---+
\ | \ / |
R1 / |Amp +--- ADC |
\ | / \ |
| (-) | / +---+
| | \ +---+
\ | \ / |
R1 / |Amp +------- ADC |
\ | / \ |
| (-) | / +---+
+------| /
| |/
|
Expand All @@ -151,8 +148,8 @@ three ADCs. Then the voltages and other signals are sampled depending on
particular sampling scheme selected.

The values obtained are passed to the main IRQ handler to process. The MCU
software calculates a new value of duty cycle and load it to hw timer. This
value will be used at next PWM period.
software calculates a new value of duty cycle and load it to TIM. This value
will be used at next PWM period.

```
// Control loop diagram //
Expand All @@ -165,7 +162,7 @@ value will be used at next PWM period.
---*--*--*-----------------------------+-------------*--*--*--------
| | | | | | |
iA uS uC preload DC | iA uS uC
iB uA u? to hw timer --> TIM iB uA u?
iB uA u? to HW timer --> TIM iB uA u?
iC uB u? iC uB u?
\ / \ ...
pm_feedback() /
Expand All @@ -174,7 +171,7 @@ value will be used at next PWM period.

## Clean zones

We typically need about 5us before current samples to be clean. If MOSFETs
We typically need about 5 us before current samples to be clean. If MOSFETs
switching occur at this time then ADC result is discarded.

```
Expand Down
Loading

0 comments on commit d672779

Please sign in to comment.