# 0x02. Implementation

## Operation Parameters

Commutation Frequency: 20kHz

Encoder Update Frequency: 10kHz

Position Loop Update Frequency: 2kHz

Current Loop Update Frequency: 20kHz

Current Controller Bandwidth: 1kHz

Encoder Filter Bandwidth: 1kHz

## 1. Clock Setting

We use a 160 MHz system clock. This can be achieved by the following PLL setting

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-9f2a7ea86a46c53831d6244f835f04391378c6f3%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## 2. Pinout

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-7d0214adc9e5945856a90cc22e71eb7721c59f24%2Fimage.png?alt=media" alt=""><figcaption><p>B-ESC Pinout</p></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-6aa01aff2b4246f5123d4a29f8e9681e8e11028f%2Fimage.png?alt=media" alt=""><figcaption><p>DRV8350RS Pinout</p></figcaption></figure>

## 3. TIM Settings

We use TIM1 to generate PWM signals for the gate driver and the trigger to ADC for current sampling.

We use TIM2 as a system timer for position loop scheduling.

We use TIM4 as a time tracking timer for the magnetic encoder, or input capture control when using the ABI incremental encoder.

### 3.1 TIM1 Settings

<div align="center" data-full-width="false"><figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-442bb6a9538bcccf132a45a018efbc12ba79603a%2Fimage.png?alt=media" alt="" width="406"><figcaption></figcaption></figure></div>

We configure Channel 1-3 to be the PWM output for the gate driver. CHx will drive the high-side of the bridge, while CHxN will drive the low-side.

Channel 4 is used to generate the trigger signal to ADC to start sample the current. Another possible way to do this is to use the timer update event. However, using the Channel 4 PWM enables control over the exact current sample point along the PWM cycle.

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-a8adba0c46967eb9747e2c699042d6e03f918793%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

#### 3.1.1 TIM1 Counter Settings and TRGO Parameters

**Prescaler**

is set to 0, which results in a clock value of 160 MHz / (**0** + 1) = **160 MHz**.

**Counter Mode**

is set to center-aligned mode, to generate a **center-aligned PWM signal**. Mode 1-3 does not matter here, as we are not using output compare functionality.

**Dithering**

is kept at the default value.

**Counter Period (ARR)**

is set to 3999, which results in a PWM frequency of 160 MHz / (**3999**+1) / 2 = **20 kHz**

#### Internal Clock Division

is kept at the default value.

#### Repetition Counter

is set to 1 to generate an update interrupt every two counter updates. Because we are setting this before the timer is started, the update interrupt will be generated on counter underflow.

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-d3ecc4a343d86957e5eb8d0c4729f42e8a8d6045%2Fimage.png?alt=media" alt=""><figcaption><p>RM0440 Page 1099</p></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-1a9a34f22a875d0bdb331e8230616e947fbeda73%2Fimage.png?alt=media" alt=""><figcaption><p>RM0440 Page 1099</p></figcaption></figure>

We use this to trigger the current loop calculation on the appropriate frequency and time, where the ADC just finished sampling the phase currents on the previous counter overflow.

**ARR reload preload**

is kept at the default value.

**Master / Slave Mode**

is kept at the default value.

**TRGO**

is set to OC4REF, where

```c
OC4REF = OC4_pulse_value > counter_value;
```

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-5527d5401218f3b3d94ec7b24bf02ae342535c9a%2Fimage.png?alt=media" alt=""><figcaption><p>RM0440 User Manual Page 1122</p></figcaption></figure>

**TRGO2**

is kept at the default value.

#### 3.1.2 TIM1 Break and Dead Time Management - Output Configuration

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-a90573408ec9a9b0400d12f750138d05290540b1%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Dead Time**

is set to 128, which

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-7281be17b6b55ab465b7907ba75f6e5a5531f598%2Fimage.png?alt=media" alt=""><figcaption><p>RM0440 User Manual Page 1205</p></figcaption></figure>

#### 3.1.3 TIM1 PWM Generation Channel 1-3 and 1-3N

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-5ce581e8798bf1624077b4c76486563ecfdf3a86%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Mode**

is set to PWM mode 1

#### 3.1.4 TIM1 PWM Generation Channel 4

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-fc65816c04e25d2c16e264741ec178776b2b9974%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Mode**

is set to PWM mode 1

TIM2

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-9d0e079fe1487e9ab6c57e3273f71df1b094cc5e%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-1dcc327a04fa442211b6a65808a2ffb203bb0f4c%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

TIM3

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-c60eac0d869c6868043f9d9fb63254c108505a95%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-c436d40fbd93bac59523f8826350b4d00f8003da%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## 4. Analog Settings

OpAmpX Settings

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-02cc7835ec436c5d386ac8f26f6d20cb58dd8f99%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-9287fe5835448e191aee3c27249f937d080235f3%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

OpAmp 2 and 3 are with same settings.

ADC 1

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-0476e36b0fd81bc886863924fb738e7d85497bb0%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-2427a8f78b2823212361aff02d85515bdfdc6c2b%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Overrun Behavior**

is set to overrun data overwritten

**External Trigger Source**

is set to Timer 1 Trigger event

**External Trigger Conversion Edge**

is set to on the rising edge, which means we will start the ADC sample right before the timer counter overflow, and thus the sample point will span across the counter overflow, which then gives us the maximum sample time.

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-6346bce383fb9a09638c68107a685a0353f61038%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

Because we need to sample multiple data at the same trigger edge for one ADC, we use the injected conversion feature of the ADC. It will sample the configured channel at trigger edge at the same time, and then convert the reading sequentially in the order of the rank number of the channels. Finally, it will store the converted data inside the ADC injected data register, which means we do not need to use interrupt or DMA to read it out before converting next channel. The data will always be available until the next sample cycle starts.

ADC2

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-3a01b9e98cedab74ba54de9377ecd3e53acac9a4%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-4558e2ccc7ce17accb914a3a0cc5d06a18cca446%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-048f5021a342eec73b30c2f4dab99427fca158cc%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## 6. CAN

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-b869f1436640b6e6072e0183c4d41377ed702f1e%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## 7. UART

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-2bfb0916078cf20956a9a56289e4b2e7e6fccee3%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

NVIC

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2Fgit-blob-e40d7c00fd37781f515efa63c597665455feaa07%2Fimage.png?alt=media" alt=""><figcaption><p>B-ESC</p></figcaption></figure>

SPI Settings

<figure><img src="https://1287130752-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvVJ0h2a4qMIhB1I8GdV8%2Fuploads%2F38uv0FSwaSqCRpyuaeno%2Fimage.png?alt=media&#x26;token=2a857106-28f6-488b-a0f4-af1384d60c40" alt=""><figcaption></figcaption></figure>

Future Iteration:

add protection on each motor controller board/
