Pythonを用いた三相交流(uvw)のαβ・dq軸変換

## はじめに
本記事は三相交流モータを駆動させる際に必要となる三相交流(uvw)→αβ・dq軸変換をPythonを用いて行う事を目的としている。
数学的な厳密性は置いておいて、実際の波形がどうなっているのかを分かりやすく見る事を目的としている。
パワーエレクトロニクス分野であり、Cが主であるからなのか、配列計算が行い易いPythonを用いた記事があまり見つからなかったため、この記事を書くことにした。
matplotlibでグラフが分かりやすくなっているので、グラフ的なイメージはCよりもこちらの方が分かりやすいと思う。
なお、今回のコードでは、三相交流波形とαβ波形、dq波形を表示した。
また、three_phase_currents_variable_amplitude.csvとして、csvファイルに出力している為、ここからデータ分析等を行う際に活用できる。

## 環境
開発環境:VSCode
言語:Python
使用ライブラリ:numpy pandas matplotlib

## コードの注意点
今回、各種定数は最初に示してある。
また、三相交流の振幅に関しては、t=1.0で1から0.5に変化させている。

## コード
```python:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# パラメータ設定
f = 10  # 周波数 (Hz)
T = 1 / f  # 周期 (s)
beta = 0  # 位相オフセット
t = np.linspace(0, 2, 2000)  # 時間軸 (2秒間、分解能を高く設定)

# 振幅Aを時間に応じて設定
A = np.where(t <= 1, 1.0, 0.5)

# 三相電流の計算
theta = 2 * np.pi * f * t
I_u = -A * np.sin(theta + beta)
I_v = -A * np.sin(theta - 2 * np.pi / 3 + beta)
I_w = -A * np.sin(theta + 2 * np.pi / 3 + beta)

# αβ軸への変換
I_alpha = I_u
I_beta = (1 / np.sqrt(3)) * (I_v - I_w)

# dq軸への変換
I_d = I_alpha * np.cos(theta) + I_beta * np.sin(theta)
I_q = -I_alpha * np.sin(theta) + I_beta * np.cos(theta)

# データをDataFrameにまとめる
data = {
    "time(s)": t,
    "A": A,
    "I_u": I_u,
    "I_v": I_v,
    "I_w": I_w,
    "I_alpha": I_alpha,
    "I_beta": I_beta,
    "I_d": I_d,
    "I_q": I_q,
}
df = pd.DataFrame(data)

# CSVファイルに出力
csv_filename = "three_phase_currents_variable_amplitude.csv"
df.to_csv(csv_filename, index=False)
print(f"データを {csv_filename} に保存しました。")

# グラフの描画 (オプション)
plt.figure(figsize=(10, 6))
plt.plot(t, I_u, label='$I_u$', color='blue')
plt.plot(t, I_v, label='$I_v$', color='red')
plt.plot(t, I_w, label='$I_w$', color='black')
plt.xlabel('Time (s)')
plt.ylabel('Current')
plt.title('Three-Phase Currents with Variable Amplitude')
plt.legend()
plt.grid()
plt.show()

plt.figure(figsize=(10, 6))
plt.plot(t, I_alpha, label='$I_\\alpha$', color='green')
plt.plot(t, I_beta, label='$I_\\beta$', color='purple')
plt.xlabel('Time (s)')
plt.ylabel('Current')
plt.title('Alpha-Beta Currents with Variable Amplitude')
plt.legend()
plt.grid()
plt.show()

plt.figure(figsize=(10, 6))
plt.plot(t, I_d, label='$I_d$', color='orange')
plt.plot(t, I_q, label='$I_q$', color='cyan')
plt.xlabel('Time (s)')
plt.ylabel('Current')
plt.title('dq-Axis Currents with Variable Amplitude')
plt.legend()
plt.grid()
plt.show()
```

## 実行結果
実行結果を三相交流、αβ変換、dq軸変換の順で表す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3792738/91d230fb-6088-0ab1-8b35-a90ca90f0086.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3792738/194e56d0-2501-b915-9215-9a361a9c335a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3792738/db04f1f0-e83e-f07f-b5d5-1557f7b6df68.png)

## 数学的な解説

まず、三相交流の解説から行う。
三相交流とは、交流3信号を使い、2π(360度)分を使用できる手法だ。
三相は一般的にu相、v相、w相と呼ばれ、以下の式で表される。
なお、これから角度は全て弧度法(rad)で表す。

```math
\displaylines{
I_u=Asin(θ)\\
I_v=Asin(θ+\frac{2π}{3})\\
I_w=Asin(θ-\frac{2π}{3})\\
}
```

この式に書かれているように、v相はu相よりも2π/3(rad)、つまり120度前にあり、w相はu相よりも2π/3(rad)、つまり120度後ろにある事が分かる。よって、u、v、w全てで360度を表せている事が分かる。
次に、αβ変換について記述する。
uvwからαβへの変換は、以下の行列式で行われる。
```math
\begin{pmatrix}
I_α \\
I_β 
\end{pmatrix}
=\sqrt{\frac{2}{3}}\
\begin{pmatrix}
1 & {-\frac{1}{2}} & {-\frac{1}{2}}\\
0 & {\frac{\sqrt{3}}{2}} & {-\frac{\sqrt{3}}{2}}
\end{pmatrix}
\begin{pmatrix}
I_u \\
I_v \\
I_w
\end{pmatrix}
```

なお、この式を計算すると、コードの計算式と違う事に気づく。
この原因として、コードの式は実際の制御に用いる場合や最終的にdq軸変換する際に使われる。一方、上記の行列式はエネルギーの正規化を目的とした場合のため、実用されているのはコードの計算式で使われている。

最後に、dq軸変換を扱う。
同様に行列式を書くと、
```math
\begin{pmatrix}
I_d \\
I_q 
\end{pmatrix}
=
\begin{pmatrix}
cos(θ) & sin(θ)\\
-cos(θ) & sin(θ)
\end{pmatrix}
\begin{pmatrix}
I_α \\
I_β
\end{pmatrix}
```
なお、この際のθは2πftで表される。

## 終わりに
今回は三相→αβ・dq軸変換をpythonを用いてグラフ化してみた。
コードを書く過程で実用されている変換式とエネルギー正規化の際の変換式との違いなど、復習になる点が多くあった。
パワーエレクトロニクス分野のQitta記事はあまりないので、これからも書いていこうと思う。