電源周波数測定アダプタを真似して作ってみた

# はじめに

部屋のコンセントから出ている商用電源（AC100V）の周波数と電圧を測定するアダプタを AVR ATmega328P マイコンで製作しました。
測定値は USB 接続された仮想 COM ポートとして取得することができるため、Windows PC や Raspberry Pi へアダプタを接続することができます。

回路・マイコンプログラムは次のサイトを参考にしています。~~というかアレンジして作ってみた結果、劣化コピーになりました。~~
* ChaN氏 [ELM - 電圧周波数測定アダプタ](http://elm-chan.org/works/lvfm/report_j.html)

ここで紹介する回路は **AC100V を扱っており、感電をすると死亡する恐れがあります。[^license]** 製作する場合は十分に注意してください。

なお、ここで紹介する設計やプログラムなどは、GitHub でも公開しています。

https://github.com/BerandaMegane/Commercial-Power-Measurement-Adapter

[^license]: この記事を書いている私は、第二種電気工事士の免許を持ち、低圧電気取扱業務特別教育を受けています。なお、個人で回路製作する上で免許や特別教育の修了は必要ないとされています。

![P5040030.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/d178f5f0-aaf9-1980-b2c4-08b585213c4b.jpeg)

# ハードウェア
## 回路製作

今回の回路図です。作ってみて変更したほうが良さそうなところは後ほど説明します。

![circuit_ver1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/9a4d2dbb-69e1-25c7-2023-5f8b5b8dc888.png)

補足が必要そうな部品は次のとおりです。

* FUSE 0.1A ヒューズ
  * 家を火災で燃やさないように必要。ないと怖い。
* D1-4
  * ブリッジダイオードでも代用可、耐圧は AC100V のピーク値以上
* D5 ツェナーダイオード
  * ツェナー電圧 10V 程度、許容損失 0.5W 以上（後述）
* D6
  * なくても良い。ツェナー電圧かさ増し用ダイオード（後述）
* R1
  * 回路が短絡しても、0.1A ヒューズが切れるまでは燃えないもの
* C1 1uF/450V
  * 交流のそこそこ大電流が流れるので注意（後述）
* C6 0.01uF
  * ローパスフィルタ用なのでフィルムコンデンサが良い
* U1 三端子レギュレータ
  * 5V 出力品
* U3 TLP2361
  * トーテム出力なフォトカプラ。普通のフォトカプラでも代用可。
* U4 MCP2221A
  * UART-USB 変換 IC。他の変換モジュールなどで代用可。

:::note info
C1 は交流が流れるため、極性ありの電解コンデンサは使用できません。次のように選定します。

* 無極性
* 耐圧電圧が 300V 以上（AC100V 最高値*2）
* 低損失で交流電流が常時流れていても問題ない

例えば、秋月電子で取り扱いのある [メタライズドポリプロピレンフィルムコンデンサー 1μF450V ルビコンMPS](https://akizukidenshi.com/catalog/g/g105988/) が使用できます。
:::

:::note info
D5 は電圧を制限するためのツェナーダイオードで、次のように選定します。

* ツェナー電圧は 10V 程度 
* 許容損失は 0.5W 以上
許容損失 = ツェナー電圧 * 回路電流 = 10V * 25mA = 0.25W 程度
余裕を見越して 0.5W 以上

製作当初は、なんとなく 6.2V のツェナーダイオードに普通のダイオードの下駄を履かせて使っていました。D6はその名残りなので、ツェナー電圧が高いものを使用するときは必要ありません。
また、回路図通り逆方向で使用する必要があります。
:::

### 電源
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/f7e2691f-ad25-c236-a88c-d43db90707bd.png)

測定アダプタの電源は、測定する商用電源から供給してもらうことにしました。別途マイコンへの電源供給が必要なくなることで、設置が簡単になります。測定回路のマイコンおよびフォトカプラの動作には、多めに見て 5V/25mA 必要と見積もりました。

* マイコン（AVR ATmega328P, 20MHz 動作時は 15mA 程度）
* フォトカプラ（5mA 程度）

次のような電源回路の構成となっております。
* リアクタンスドロッパ回路と全波整流回路を用いて AC100V を DC へ変換
* ツェナーダイオードを用いて 10V 程度に電圧を制限
* 三端子レギュレータで 5V へ降圧

### リアクタンスドロッパについて
リアクタンスドロッパについては、[参考サイト](http://elm-chan.org/works/lvfm/report_j.html) に記載の通りではありますが、初心者向けに説明している動画もあります。

* ニコニコ動画 剣菱P
  * [【零電：実践編　No.20】　ＡＣ１００ＶでＬＥＤ点灯（前編）](https://www.nicovideo.jp/watch/sm20615691)
  * [【零電：実践編　No.20】　ＡＣ１００ＶでＬＥＤ点灯（後編）](https://www.nicovideo.jp/watch/sm20621590)

リアクタンスドロッパは、回路に流れる電流をコンデンサ C1 によって電流制限しています。C1 に必要な容量性リアクタンス Xc は、入力電圧を Vin=100 [V]、回路の消費電流を Ic=25 [mA] とすると、
```math
\begin{align}
X_C &= \frac{V_{in}}{I_C} = \frac{100\mathrm{\,[V]}}{25\mathrm{\,[mA]}} = 4000\mathrm{\,[Ω]}\\
\end{align}
```
Xc=4000 [Ω] と求められます。

C1 に必要な容量は、低めな周波数 f=50 [Hz] として計算すると、
```math
\begin{align}
X_C &=\frac{1}{2πfC} \,なので、\\
C &= \frac{1}{2πfX_C} = \frac{1}{2π×50\mathrm{\,[Hz]}×4000\mathrm{\,[Ω]}} = 0.80\mathrm{\,[uF]}
\end{align}
```
C1=0.80 [uF] となります。

このようなアナログ回路を製作する際は、あらかじめ LTSpice などで回路シミュレーションしたほうが確実に製作できます。実際にシミュレーションしてみると、C1=1.0 [uF] 程度必要なことがわかりました。
8V程度のツェナーダイオードを使用すると、3端子レギュレータが 5V へ降圧するときの余裕電圧（ドロップ電圧）が確保できそうです。

:::note info
製作当初は回路の動作電流を低く見積もってしまったため C1=0.47 [uF] としてしまい、電源が不安定になってしまいました。並列にコンデンサを追加することで解決しています。
:::

:::note warn
交流を直流に変換する際、効率の良さから全波交流回路を使用していますが、測定波形が歪んでしまうことから半波整流回路を使うべきでした。参考サイトにもきちんと記載がありますので注意してください。
:::

下の画像は、シミュレーション回路図上の R2 の電圧および電流のグラフです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/9c104b84-5371-74c1-8f47-dbda9c657094.png)


### 測定とインターフェース
測定に使用したマイコンには、Arduino 化されていない普通の AVR ATmega328P を使用し、外付けクリスタルによる 20MHz で動作させています。AC100V を抵抗分圧し、ADCへ入力しています。

:::note info
参考サイトでは分圧抵抗に精度の高いものを使用していますが、今回は気にせず有り合わせの部品で製作しています。
:::

測定データはマイコンから1秒ごとにシリアル通信(UART)で送信されており、絶縁のためのフォトカプラを通して UART-USB 変換モジュール (MCP2221A) へ入力しています。
測定アダプタを PC などに USB 接続することで、仮想 COM ポートとして認識され、測定値を取得することができます。

### 改良したいところ

もう一度製作するとしたら、次のような回路で製作したいと考えています。

* 半波整流回路とし、C1の値を調整する
  * ADC したあとの信号が歪まなくしたい
* 信号回路のC10の値を変更する
  * LPF のカットオフ周波数が低めなので、もっと高めにしてACラインの信号が減衰しないようにしたい
* 信号回路のR6-R9の値を変更する
  * 入力信号振幅を参考サイトと同じにしたい

![circuit_ver2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/f0a66995-b4eb-c3ae-7ed1-fd58f8c7ee30.png)

さらに、わざわざ AC 電源でマイコンの消費電力を賄わなくてもよいのでは？と思っています。
どうせシリアル通信している PC や Raspberry Pi から電力をもらえるのであれば、 MAU103 のような絶縁 DC-DC コンバーターで供給すると良いと思います。

あとは、制御マイコンに AVR を使っていますが、実効電圧値の算出に平方根 (sqrt 関数) の浮動小数点数演算が必要なため、たまに処理が間に合ってないこともあります。

## 基板製作

ユニバーサル基板で製作し、3Dプリンタでつくった筐体に収めています。

![P5040013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/2d7643db-c93d-b3f8-17d3-34f2e5ad2c1f.jpeg)

![P5040025.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/51ac8246-1613-55c4-e2af-4eab075e3b9b.jpeg)

# ソフトウェア

マイコンは AVR (現 Microchip) ATmega328P を、20MHz 外部クリスタルで動作させています。

* ヒューズビット（20MHz 分周なし）
  * LOW:      0xF7
  * HIGH:     0xD1
  * EXTENDED: 0xFF

分圧抵抗で AC100V を減衰したあと、マイコンの ADC1 に信号入力させています。  
約 12kHz で A-D 連続変換し、レシプロカル方式で電源周波数を測定します。また、電圧実効値や電圧波形も測定しています。  
測定値は絶縁フォトカプラを介して UART で PC へ送信します。

ちなみにソフトウェアは C 言語で作った後に Rust に書き直しています。C/Rust プログラムは下で公開しています。

https://github.com/BerandaMegane/Commercial-Power-Measurement-Adapter/tree/main/Program

## A-D変換サンプリング
AD 連続変換モードを利用してサンプリングしています。
サンプリング周波数 f_s は、動作クロック F_CPU, 分周比 ADC_DIV, AD変換必要クロック数 ADC_CLOCK によって、次のように求められます。

サンプリング周波数 f_s = F_CPU / ADC_DIV / ADC_CLOCK  
= 20000000 / 128 / 13 = 約 12 [kHz]

## 電源周波数測定
電源周波数は、交流波形の周期を求めることで計算できます。電源周波数変動は、だいたい 0.1Hz 程度とのことなので、低い周波数の変動を測定する必要があります。

そこで、入力信号の1周期の時間を測定し、周波数に換算するレシプロカル方式で測定しています。  
電源周波数のように低い周波数を測定する場合によく利用され、次のサイトを参考にしました。

https://www.keisoku.co.jp/md/support/useful/u_about-aa/u_counter/

1秒間、サンプリング周波数 f_s [Hz] で電圧を測定し、周期波形の個数 cycles、サンプリングカウント数 count によって、次のように求められます。

入力信号周波数 = cycles / (count / f_s) [Hz]

この方式で周波数測定するときの分解能は、入力信号周波数 f_in, サンプリング周期 f_s, 測定時間 T とすると次のように求められます。

周波数分解能 = f_in / f_s / T [Hz]

本プログラムで用いる f_s = 12 [kHz], T = 1 [s] のとき、次のようになります。

50 [Hz] のとき分解能 = 0.00417 [Hz] (4.17 [mHz])  
60 [Hz] のとき分解能 = 0.00500 [Hz] (5.00 [mHz])

## 電圧測定
電圧値は実効値の定義に従い、入力信号1周期分の瞬時値に対して、2乗 → 総和平均 → 平方根をとることによって求めます。

## シリアル通信
次のデータを送信します。

* csv-1: 1秒周期
  * 周波数・電圧実効値
* csv-2: 60秒周期
  * サンプリングした電圧波形

```:シリアル通信
mode, data1, data2

csv-1,59.979,98.75  # 1秒周期で 周波数・電圧実効値
csv-1,59.979,98.78 
csv-1,59.979,98.80
csv-1,59.984,98.83
csv-2,0,520  # 60秒周期で サンプリング電圧波形値
csv-2,1,536
csv-2,2,549
csv-2,3,563
csv-2,4,578
csv-2,5,593
csv-2,6,605
csv-2,7,617
... ...
```

# 最後に
作ろうと思ったきっかけは、2021年2月13日の地震による電力網への影響を指摘したツイートです。
商用電源の周波数を測定している狭い界隈があることを知り、私も参加してみたくなりました。
TomonoTokyo氏 [Twitter - 揺れより先に電源周波数が変動したぞ](https://x.com/TomonoTokyo/status/1360593240936751108)