ACS712電流センサー:ArduinoでDCとACの電流を測る
ACS712電流センサーの使い方:5A/20A/30Aの感度、2.5 Vのゼロ点、ArduinoのDC・AC実効値(RMS)のコード、電力の計算、ESP32用の分圧回路とINA219を解説します。
ACS712電流センサーは、回路を流れる電流をホール効果で検出し、Arduinoが読める電圧に変える小さくて安いモジュールです。電流がないときの出力は約2.5 Vで、電流が一方向に流れると上がり、逆方向に流れると下がります。つまり、1本のアナログピンで直流(DC)と交流(AC)の両方の電流を測れます。モーターがどれだけ電流を消費しているかを見たり、電池の放電を追跡したり、機器が動いているかを検出したり、家庭の電化製品がどれだけ電力を使っているかを調べたりするのに使われます。そのうえ、測定する電流の経路はArduino側から電気的に絶縁されています。
このガイドでは、ACS712の内部構造、5A・20A・30Aモデルの違いとどれを選ぶべきか、モジュールを回路と直列につなぐ方法、DC電流を測る最初のArduinoスケッチ、平均化でふらつく値を落ち着かせる方法、AC電流の実効値(RMS)の計算、電力(W)とエネルギー(Wh)の求め方をステップごとに学びます。そのあと、3.3 VのESP32やRaspberry Pi Picoに分圧回路を通してつなぐ方法、商用電源の電圧になぜ細心の注意が必要か、そして小さな電流にはなぜINA219の方が向いているかを見ていきます。

ACS712電流センサーとは?そのしくみ
ACS712はAllegro製の8ピンのチップです。測定する電流は、チップ内部の太い銅の経路を1・2番ピンから3・4番ピンへと流れます。この経路の抵抗はわずか1.2 mΩで、10 Aでも電圧降下は12 mV、発熱は0.12 Wにすぎないので、測定する回路にはほとんど影響しません。この導体を電流が流れると、電流に比例した磁界が生まれます。銅の経路のすぐ上にあるホールセンサーがその磁界を検出し、チップ内部の増幅器が電圧に変えます。基本についてはホール効果センサーのガイドで詳しく読めます。
電流が流れる銅の経路とチップに電源を供給する側の間には電気的なつながりがなく、両者を結んでいるのは磁界だけです。そのため、測定するラインとArduinoは互いに絶縁されています(ガルバニック絶縁)。出力電圧は次の式に従います:Vout = VCC / 2 + 感度 × I。電流がIP+からIP−へ流れると出力は2.5 Vより上がり、逆に流れると下がります。ACS712はレシオメトリックでもあり、ゼロ点と感度の両方が電源電圧に比例して変わります。電源が4.8 Vに下がると、ゼロ点は2.4 Vになり、5Aモデルの感度は185から約178 mV/Aに下がります。
| 項目 | 値 |
|---|---|
| 電源電圧 | 4.5〜5.5 V(標準5 V) |
| 消費電流 | 標準10 mA、最大13 mA |
| 電流ゼロのときの出力 | VCC × 0.5(5 Vのとき2.5 V) |
| 導体の抵抗 | 1.2 mΩ |
| 帯域幅 | 80 kHz(FILTERピンのコンデンサで狭められる) |
| 出力の総合誤差 | 25 °Cで±1.5% |
| 絶縁耐圧 | 2.4 kV RMS(60秒) |
| 出力の負荷 | 4.7 kΩ以上、10 nF以下 |
| 短時間の過電流 | 100 A(単発パルス、100 ms) |
| 動作温度 | −40〜85 °C |
| モジュールの接続 | VCC、OUT、GNDと2極のネジ端子 |
5A・20A・30Aモデル:感度と分解能
ACS712には、外見がまったく同じ3つのバージョンがあります。どれを持っているかは、チップの刻印を読めばわかります。ELC-05Bは±5 A、ELC-20Aは±20 A、ELC-30Aは±30 Aを測ります。感度は、電流1 Aあたり出力が何ミリボルト変わるかを示します。測定範囲が広いほど感度は低くなり、そのおかげで20Aと30Aのモデルでもフルスケールの電流で出力が0.5〜4.5 Vに収まります。下の表には、Unoの10ビットADCの1ステップ(4.88 mV)が各モデルで何ミリアンペアに当たるかも示しています。
| モデル(チップの刻印) | 測定範囲 | 感度 | フルスケールでの出力 | UnoのADC 1ステップ | ノイズ(47 nFフィルタ) |
|---|---|---|---|---|---|
| ACS712ELCTR-05B | ±5 A | 185 mV/A(180〜190) | 1.58〜3.43 V | ≈ 26 mA | 21 mV ≈ 0.11 A(ピークツーピーク) |
| ACS712ELCTR-20A | ±20 A | 100 mV/A(96〜104) | 0.50〜4.50 V | ≈ 49 mA | 11 mV ≈ 0.11 A(ピークツーピーク) |
| ACS712ELCTR-30A | ±30 A | 66 mV/A(63〜69) | 0.52〜4.48 V | ≈ 74 mA | 7 mV ≈ 0.11 A(ピークツーピーク) |
この表から2つの大事な結論が出ます。1つ目に、アンペアで表したノイズは3つのモデルとも約0.1 Aです。2 Aの負荷に30Aモデルを使うと、分解能の3分の2を捨てることになります。ルールは簡単で、測定する最大電流(ACならピーク値)を余裕をもってカバーできるいちばん小さいモデルを選びます。たとえば、最大2〜3 Aを消費する12 VのDCモーターには5Aモデル、1500 Wのヒーターには20Aモデルが合います。2つ目に、ACS712は小さな電流向けに設計されていません。数ミリアンペアのLEDやディープスリープ中のESP32は測れません。その用途には、このガイドの最後で紹介するINA219の方がはるかに優れています。
ACS712の配線:Arduino Uno、ESP32、Pico
ACS712モジュールには2つの側があります。ネジ端子の側は測定する回路のものです。電流は一方の端子から入ってもう一方から出なければならないので、モジュールは電流計と同じように負荷と直列につなぎます。ふつうは電源のプラス線を切り、電源から来る端を端子の片側に、負荷へ向かう端をもう片側につなぎます。3ピンの側はArduinoにつなぎます。ACS712は5 Vでしか動かないので、ESP32やPicoでも5 Vを出すピンからモジュールに電源を供給し、出力は分圧回路を通して読みます。
| ACS712のピン | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 5V(ボードによってはVIN) | VBUS(40番ピン) |
| OUT | A0 | GPIO 34(10k/20kの分圧回路経由) | GP26(10k/20kの分圧回路経由) |
| GND | GND | GND | GND |
| ネジ端子 | 負荷と直列 | 負荷と直列 | 負荷と直列 |
モジュールにはチップのほかに部品がほとんどありません。電源ラインのパスコン(デカップリングコンデンサ)、帯域幅を決めるFILTERピンの小さなコンデンサ、電源LED(D1)とその抵抗(R1)だけです。R1に印刷された102は1 kΩを意味します。こうした表示はSMDコード解読ツールで簡単に読み解けます。ACS712は絶縁されているので、電流だけを測る場合は、測定する回路のマイナスをArduinoのGNDにつなぐ必要はありません。
ステップごとに:ArduinoでDC電流を測る
- モジュールのVCCピンをArduinoの5Vピンに、GNDをGNDに、OUTをA0につなぎます。基板の電源LEDが点灯するはずです。
- 測定したい回路のプラス線を切ります。電源から来る端を端子の片側に、負荷(たとえば12 VのモーターやLEDテープ)へ向かう端をもう片側につなぎます。
- 負荷の電源はオフのままにして、下のスケッチを書き込みます。起動時に、電流が流れていない状態でゼロ点を測ります。
- シリアルモニタを9600ボーで開きます。電流がないとき、値は0.00 A前後にとどまり、揺れても100分の数アンペア程度のはずです。
- 負荷の電源をオンにします。電流がマイナスで表示される場合は、端子の2本の線を入れ替えるか、結果に−1を掛けます。
- コードのSENSITIVITYをモデルに合わせて設定します。5Aなら0.185、20Aなら0.100、30Aなら0.066です。
1// ACS712 ile DC akım ölçme / DC current measurement with ACS712
2const int SENSOR_PIN = A0; // ACS712 OUT pini / ACS712 OUT pin
3const float SENSITIVITY = 0.185; // V/A: 5A=0.185, 20A=0.100, 30A=0.066
4const float ADC_STEP = 5.0 / 1024.0; // bir ADC basamağı (V) / one ADC step (V)
5const int SAMPLES = 200; // ortalama için örnek sayısı / samples to average
6
7float zeroRaw = 512.0; // akım yokken ham değer / raw value at zero current
8
9// SAMPLES kez okuyup ortalamayı döndürür / reads SAMPLES times and returns the average
10float readAverageRaw() {
11 long sum = 0;
12 for (int i = 0; i < SAMPLES; i++) {
13 sum += analogRead(SENSOR_PIN);
14 }
15 return sum / (float)SAMPLES;
16}
17
18void setup() {
19 Serial.begin(9600);
20 delay(500); // sensörün oturmasını bekle / let the sensor settle
21 zeroRaw = readAverageRaw(); // yük KAPALIYKEN sıfır noktası / zero point with the load OFF
22 Serial.print(F("Sifir noktasi / Zero point: "));
23 Serial.print(zeroRaw * ADC_STEP, 3);
24 Serial.println(F(" V"));
25}
26
27void loop() {
28 float raw = readAverageRaw();
29 float current = (raw - zeroRaw) * ADC_STEP / SENSITIVITY; // amper / amps
30
31 Serial.print(F("Akim / Current: "));
32 Serial.print(current, 2);
33 Serial.println(F(" A"));
34 delay(500);
35}このスケッチは1回の読み取りごとにanalogReadの結果を200回平均します。Unoでは1回のanalogReadに約0.11 msかかるので、およそ22 msです。電流はI = (生の値 − ゼロ点) × (5 / 1024) / 感度で求めます。たとえば5Aモデルでゼロ点が512のとき、平均の読み取り値が550なら差は38ステップです。これは38 × 4.88 mV = 185.5 mVに当たるので、電流は185.5 / 185 ≈ 1.00 Aです。2.5 Vと決めつけずに起動時にゼロ点を測るのが大切なのは、チップ自身のオフセットや基板のグラウンドラインのわずかな差でゼロ点が数ステップずれ、その誤差がすべての読み取り値に加わるからです。
ノイズと平均化
ACS712の出力は、電流が一定でも揺れ続けます。1つ目の原因はホールセンサー自身のノイズです。メーカーは上のノイズの値をFILTERピンに47 nFのコンデンサを付けた条件で示しており、これは約2 kHzの帯域幅に当たります。しかし多くのモジュールは、メーカーの回路例と同じくそこに1 nFを使っています。帯域幅は80 kHzに広がり、ノイズは何倍にもなります。2つ目の原因はADCです。5AモデルでもUnoは26 mA刻みで測るので、最後の1ステップは常に上下にちらつきます。ランダムなノイズは、平均するサンプル数の平方根に比例して小さくなります。16サンプルで4分の1、256サンプルで16分の1になります。ほかのフィルタの方法はセンサーデータのフィルタリングのガイドをご覧ください。
- 多サンプル平均:DCでは100〜500サンプルを平均します。サンプルを20 msにわたって取れば、商用電源の50 Hzの干渉も平均の中で打ち消されます(西日本の60 Hzでは1周期が16.7 msなので、100 msにわたって取れば両方で打ち消せます)。
- 指数移動平均:新しい読み取り値をfiltered = filtered + 0.1 × (new − filtered)で古い値に混ぜていきます。メモリをほとんど使わず、ディスプレイに落ち着いた値を表示できます。
- 不感帯:何もつないでいないのに0.03 Aのような値が見えるのが嫌なら、絶対値が0.05 A未満の結果を0として扱います。
- ハードウェアフィルタ:はんだ付けができるなら、FILTERピンのコンデンサに47 nFのコンデンサを並列に加えて、帯域幅を約2 kHzまで下げます。DCや50 Hz(西日本では60 Hz)の商用電源の電流には十分すぎるほどです。
- 磁界から離す:ACS712はホールセンサーです。近くの磁石やスピーカー、大電流が流れる別の電線があると、読み取り値がずれます。
- ゼロ点を測り直す:ゼロ点は温度によって数ミリボルトずれます。長時間動かすプロジェクトでは、負荷がオフのときにゼロ点を測り直してください。

平均化でノイズは消えますが、系統的な誤差は直りません。感度はチップごとに数パーセント異なることがあり、5Aモデルでは180〜190 mV/Aの範囲です。いちばん正確にするには、電流レンジにしたテスターをACS712と同じラインに直列につなぎ、1〜2 Aのような既知の電流を流して2つの値を比べます。テスターが2.00 A、Arduinoが1.94 Aを示したら、補正係数は2.00 / 1.94 = 1.031です。コードのSENSITIVITYをこの数で割れば(0.185 / 1.031 ≈ 0.179)、読み取り値がテスターと一致します。
AC電流を測る:実効値(RMS)の計算
商用電源の電流は向きが変わり続けます。周波数はヨーロッパと世界の大部分で50 Hz、アメリカで60 Hzです(日本では東日本が50 Hz、西日本が60 Hz)。そのため、ACS712の出力は2.5 Vを中心とした正弦波を描き、その平均は電流ゼロに当たります。DC用のスケッチをACの負荷に使うと、0 Aに近い意味のない値になります。ACで大事なのは実効値(RMS)です。これは同じ熱を生むDC電流に等しく、テスターやヒューズ、電化製品のラベルで使われている値です。計算は名前のとおりです。各サンプルからゼロ点を引いて二乗し(Square)、二乗の平均を取り(Mean)、その平方根を取ります(Root)。
測定窓の長さが重要です。窓に整数個の周期が入っていないと、結果が毎回少しずつ変わります。1周期は50 Hzで20 ms、60 Hzで16.7 msです。100 msの窓なら50 Hzでちょうど5周期、60 Hzでちょうど6周期が入るので、どちらの電力網でも正しく動きます。Unoはその間に約900サンプルを取ります。純粋な正弦波ならピーク値は実効値の1.414倍なので、ピーク値を√2で割ることもできます。しかし、スマートフォンの充電器やLED電球、調光器のような負荷はとがった正弦波でない電流を流すので、この近道では正しく測れません。下のスケッチは真の実効値(True RMS)を計算するので、こうした負荷でもずっと正確です。ピーク値はモデルの測定範囲内に収まる必要があります(下の表の電力は230 Vの場合です。日本の商用電源は100V(50/60Hz)です)。
| モデル | ピーク電流の上限 | 最大AC電流(実効値、正弦波) | 230 Vでのおよその電力 |
|---|---|---|---|
| 5A | ±5 A | 3.5 A | ≈ 800 W |
| 20A | ±20 A | 14.1 A | ≈ 3250 W |
| 30A | ±30 A | 21.2 A | ≈ 4900 W |
1// ACS712 ile AC akım (RMS) ve görünür güç / AC current (RMS) and apparent power with ACS712
2const int SENSOR_PIN = A0;
3const float SENSITIVITY = 0.100; // 20A modül: 100 mV/A / 20A module: 100 mV/A
4const float ADC_STEP = 5.0 / 1024.0;
5const unsigned long WINDOW_MS = 100; // 50 Hz'te 5, 60 Hz'te 6 tam periyot / 5 cycles at 50 Hz, 6 at 60 Hz
6const float MAINS_VOLTAGE = 230.0; // şebeke gerilimi (V) / mains voltage (V)
7
8float noiseRms = 0.0; // yük yokken ölçülen gürültü (A) / noise measured with no load (A)
9
10// Pencere boyunca örnek alır, ortalamayı çıkarıp RMS hesaplar / samples over the window, removes the mean, returns RMS
11float readRmsAmps() {
12 long sum = 0;
13 unsigned long sumSq = 0;
14 unsigned int n = 0;
15 unsigned long start = millis();
16 while (millis() - start < WINDOW_MS) {
17 int d = analogRead(SENSOR_PIN) - 512; // 2,5 V'u sıfıra yaklaştır / shift 2.5 V to about zero
18 sum += d;
19 sumSq += (long)d * d;
20 n++;
21 }
22 float mean = sum / (float)n; // sıfır noktası kayması / zero point offset
23 float variance = sumSq / (float)n - mean * mean; // yalnız AC kısım / AC part only
24 if (variance < 0) variance = 0;
25 return sqrt(variance) * ADC_STEP / SENSITIVITY;
26}
27
28void setup() {
29 Serial.begin(9600);
30 delay(500);
31 noiseRms = readRmsAmps(); // ilk ölçüm yük KAPALIYKEN / first reading with the load OFF
32 Serial.print(F("Gurultu / Noise: "));
33 Serial.print(noiseRms, 3);
34 Serial.println(F(" A"));
35}
36
37void loop() {
38 float irms = readRmsAmps();
39 float sq = irms * irms - noiseRms * noiseRms; // gürültüyü karesel çıkar / subtract noise in quadrature
40 irms = (sq > 0) ? sqrt(sq) : 0.0;
41 float apparentPower = MAINS_VOLTAGE * irms; // VA; dirençli yükte ≈ W / VA; ≈ W for resistive loads
42
43 Serial.print(F("Irms: "));
44 Serial.print(irms, 3);
45 Serial.print(F(" A Guc / Power: "));
46 Serial.print(apparentPower, 1);
47 Serial.println(F(" VA"));
48 delay(1000);
49}このスケッチはゼロ点を固定の数として保存しません。窓ごとにサンプルの平均を求めて、それを引きます。数学的には、これは分散の平方根です:RMS² = 二乗の平均 − 平均の二乗。AC電流は整数個の周期で平均するとゼロになるので、求めた平均はちょうどゼロ点の誤差に当たり、ゼロ点が温度でずれても自動的に補正されます。起動時に負荷をオフにして測ったノイズは二乗で差し引きます。ノイズと実際の電流は互いに独立していて、実効値は二乗で足し合わされるからです。この処理がないと、何もつないでいないのに0.1 Aや23 VAといった幽霊のような値が見えます。例を挙げると、1000 Wのアイロンは230 Vで約4.35 Aを流します。ピーク値の6.1 Aは5Aモデルの測定範囲を超えるので、20Aモデルで測ってください。
家庭の電化製品の電流をはるかに安全に測る方法は、SCT-013のような分割型のカレントトランス(CT)を使うことで、電線を切らずに使えます。クランプメーターのようにケーブルを挟み込み、商用電源と金属で接触することはありません。注意点は1つだけで、クランプで挟むのは電圧側(L)か中性線(N)のどちらか1本だけにします。両方を一緒に挟むと、逆向きの電流の磁界が打ち消し合って結果はゼロになります。カレントトランスはACしか測れません。DCにはACS712かINA219が必要です。
電力(W)とエネルギー(Wh)の計算
電流がわかれば、電力は掛け算1つで求まります:P = V × I。12 Vの電池が1.5 Aを消費するモーターに電力を供給しているなら、電力は12 × 1.5 = 18 Wです。オームの法則計算ツールで確かめることもできます。エネルギーは電力に時間を掛けたものです。18 Wのモーターが2時間動けば、36 Whを使います。スケッチは読み取りのたびに電力に経過時間を掛けて足し合わせることでこれを計算します。電圧を測るには、0〜25 V電圧センサーとして売られているモジュールを使えます。30 kΩと7.5 kΩの分圧回路が入っていて、入力電圧を5分の1にします。自分の抵抗値で分圧回路を設計したいなら、分圧計算ツールを使ってください。
1// ACS712 + gerilim sensörü ile güç (W) ve enerji (Wh) / power (W) and energy (Wh) with ACS712 + voltage sensor
2const int CURRENT_PIN = A0; // ACS712 OUT
3const int VOLTAGE_PIN = A1; // 0-25 V gerilim sensörü S pini / 0-25 V voltage sensor S pin
4const float SENSITIVITY = 0.185; // 5A modül / 5A module (V/A)
5const float DIVIDER_RATIO = 5.0; // (30k + 7,5k) / 7,5k = 5 / divider ratio
6const float ADC_STEP = 5.0 / 1024.0;
7const int SAMPLES = 200;
8
9float zeroRaw = 512.0;
10float energyWh = 0.0; // biriken enerji / accumulated energy
11unsigned long lastMs = 0;
12
13float averageRaw(int pin) {
14 long sum = 0;
15 for (int i = 0; i < SAMPLES; i++) sum += analogRead(pin);
16 return sum / (float)SAMPLES;
17}
18
19void setup() {
20 Serial.begin(9600);
21 delay(500);
22 zeroRaw = averageRaw(CURRENT_PIN); // yük kapalıyken sıfır noktası / zero point with the load off
23 lastMs = millis();
24}
25
26void loop() {
27 float current = (averageRaw(CURRENT_PIN) - zeroRaw) * ADC_STEP / SENSITIVITY;
28 float voltage = averageRaw(VOLTAGE_PIN) * ADC_STEP * DIVIDER_RATIO;
29 float power = voltage * current; // P = V x I (W)
30
31 unsigned long now = millis();
32 energyWh += power * (now - lastMs) / 3600000.0; // W x saat = Wh / W x hours = Wh
33 lastMs = now;
34
35 Serial.print(voltage, 2); Serial.print(F(" V "));
36 Serial.print(current, 2); Serial.print(F(" A "));
37 Serial.print(power, 1); Serial.print(F(" W "));
38 Serial.print(energyWh, 3); Serial.println(F(" Wh"));
39 delay(1000);
40}電圧モジュールは測定する回路のプラスとマイナスの間につなぐので、今度は回路のマイナスとArduinoのGNDをつなぐ必要があります。理由は共通GNDのガイドでわかります。電池が何時間もつかを見積もるには、測った平均電流をmAhとWhの計算や電池寿命計算ツールと組み合わせます。AC側では少し事情が違います。Vrms × Irmsは皮相電力で、単位はVAです。有効電力(W)はそれに力率を掛けたものです。電気ケトル、アイロン、白熱電球のような抵抗負荷では力率がほぼ1なので、VA ≈ Wです。モーター、ACアダプター、LED電球では0.5〜0.9になることがあり、有効電力を測るには電圧の波形も同時にサンプリングする必要があります。それにはZMPT101Bのような絶縁型の電圧センサーモジュールを使います。
ESP32でACS712を使う:分圧回路を通して読む
ESP32は3.3 Vで動き、アナログ入力で測れるのは約3.1 Vまでです。ピンに3.6 Vを超える電圧をかけるとボードが壊れることがあります。一方ACS712は5 Vでしか動かず、20Aと30Aのモデルでは出力が4.5 V、過電流時にはほぼ5 Vに達することがあります。そこで、センサーはESP32ボードの5Vピン(ボードによってはVIN)から電源を取り、OUTは分圧回路を通します。10 kΩ + 20 kΩがよい組み合わせです。OUTから10 kΩを通ってESP32のピンへ、その同じ点から20 kΩを通ってGNDへつなぎます。比は20 / 30 = 0.667で、合計30 kΩはACS712の最小負荷4.7 kΩを余裕で満たします。
| ACS712の出力 | 意味 | ESP32のピンでの電圧 |
|---|---|---|
| 0.50 V | 20Aモデルで−20 A | 0.33 V |
| 2.50 V | 電流ゼロ | 1.67 V |
| 4.50 V | 20Aモデルで+20 A | 3.00 V |
| 5.00 V | 過電流で飽和 | 3.33 V |
コードには2つのポイントがあります。1つ目に、ESP32のADCは両端付近で直線的でないので、生の値ではなく、工場でチップに書き込まれたキャリブレーションデータを使うanalogReadMilliVolts()を使います。GPIO 34はADC1にあり、Wi-Fiがオンでも使えます。ADC2のピンはWi-Fiと同時には使えません。2つ目に、Unoのレシオメトリックの便利さはここにはありません。ESP32のADCの基準電圧は固定ですが、ACS712の感度はUSBから来る5 Vによって変わります。対策は簡単な工夫です。電流ゼロのとき出力はVCCの半分に等しいので、起動時に測ったゼロ点を2倍すればセンサーの実際の電源電圧がわかり、それに合わせて感度を補正できます。ゼロ点と測定信号の両方に同じ誤差が含まれるので、この方法は分圧回路の抵抗の誤差も補正します。スケッチは100 msの間サンプリングし、2つの結果をまとめて返します。DCの負荷なら1つ目の数を、商用電源の電化製品なら2つ目の数を見てください。
1// ESP32 + ACS712 (10k/20k gerilim bölücüyle) / ESP32 + ACS712 (with a 10k/20k voltage divider)
2const int SENSOR_PIN = 34; // ADC1_CH6, Wi-Fi açıkken de çalışır / works while Wi-Fi is on
3const float DIVIDER = 20.0 / 30.0; // R2 / (R1 + R2) = 20k / 30k
4const float SENS_AT_5V = 185.0; // mV/A: 5A=185, 20A=100, 30A=66
5const unsigned long WINDOW_MS = 100; // 50 Hz'te 5 tam periyot / 5 full cycles at 50 Hz
6
7float zeroMv = 2500.0; // akım yokken sensör çıkışı (mV) / sensor output at zero current (mV)
8float sensMv = SENS_AT_5V; // düzeltilmiş hassasiyet (mV/A) / corrected sensitivity (mV/A)
9
10// Bölücüden önceki gerilimin ortalaması (mV) / average voltage before the divider (mV)
11float averageMv(int samples) {
12 uint32_t sum = 0;
13 for (int i = 0; i < samples; i++) sum += analogReadMilliVolts(SENSOR_PIN);
14 return sum / (float)samples / DIVIDER;
15}
16
17// Pencere boyunca okur: DC (ortalama) ve AC (RMS) akım / reads over the window: DC (mean) and AC (RMS) current
18void measure(float &dcAmps, float &acAmps) {
19 double sum = 0, sumSq = 0;
20 uint32_t n = 0;
21 uint32_t start = millis();
22 while (millis() - start < WINDOW_MS) {
23 double d = analogReadMilliVolts(SENSOR_PIN) / DIVIDER - zeroMv;
24 sum += d;
25 sumSq += d * d;
26 n++;
27 }
28 double mean = sum / n;
29 double variance = sumSq / n - mean * mean;
30 if (variance < 0) variance = 0;
31 dcAmps = mean / sensMv;
32 acAmps = sqrt(variance) / sensMv;
33}
34
35void setup() {
36 Serial.begin(115200);
37 analogReadResolution(12);
38 delay(500);
39 zeroMv = averageMv(1000); // yük KAPALIYKEN / with the load OFF
40 sensMv = SENS_AT_5V * (2.0 * zeroMv) / 5000.0; // oransal düzeltme: VCC = 2 x sıfır / ratiometric fix: VCC = 2 x zero
41 Serial.printf("Sifir / Zero: %.0f mV Hassasiyet / Sensitivity: %.1f mV/A\n", zeroMv, sensMv);
42}
43
44void loop() {
45 float dc, ac;
46 measure(dc, ac);
47 Serial.printf("DC: %.2f A AC (RMS): %.2f A\n", dc, ac);
48 delay(1000);
49}Raspberry Pi PicoとMicroPythonでACS712を使う
Raspberry Pi Picoも3.3 Vで動くので、配線はESP32と同じです。ACS712のVCCを、PicoがUSBから給電されているときに5 Vを出すVBUS(40番ピン)に、OUTを同じ10k/20kの分圧回路を通してGP26(ADC0、31番ピン)につなぎます。MicroPythonではread_u16()が0〜65535の値を返し、電圧 = 生の値 × 3.3 / 65535です。PicoのADCは12ビットで、分圧回路と合わせると、計算上は5Aモデルで約6.5 mA刻みで測れます。Unoのおよそ4倍細かい刻みです。下のコードは起動時にゼロ点を測り、レシオメトリック補正をかけ、そのあと1秒ごとにDCとACの実効値の電流を表示します。
1from machine import ADC
2import time
3import math
4
5adc = ADC(26) # GP26 = ADC0, fiziksel pin 31 / physical pin 31
6VREF = 3.3 # ADC referansı (V) / ADC reference (V)
7DIVIDER = 20 / 30 # 10k/20k bölücü oranı / 10k/20k divider ratio
8SENS_AT_5V = 0.185 # V/A: 5A=0.185, 20A=0.100, 30A=0.066
9
10
11def read_volts(samples=200):
12 # bölücüden önceki ortalama gerilim / average voltage before the divider
13 total = 0
14 for _ in range(samples):
15 total += adc.read_u16() # 0-65535
16 return total / samples * VREF / 65535 / DIVIDER
17
18
19zero = read_volts(1000) # yük KAPALIYKEN / with the load OFF
20sens = SENS_AT_5V * (2 * zero) / 5.0 # oransal düzeltme / ratiometric correction
21print("Sifir / Zero: {:.3f} V".format(zero))
22
23
24def read_rms(window_ms=100):
25 # 100 ms = 50 Hz'te 5 periyot / 5 cycles at 50 Hz
26 n = 0
27 s = 0.0
28 s2 = 0.0
29 start = time.ticks_ms()
30 while time.ticks_diff(time.ticks_ms(), start) < window_ms:
31 v = adc.read_u16() * VREF / 65535 / DIVIDER - zero
32 s += v
33 s2 += v * v
34 n += 1
35 mean = s / n
36 return math.sqrt(max(s2 / n - mean * mean, 0)) / sens
37
38
39while True:
40 dc = (read_volts() - zero) / sens
41 print("DC: {:.2f} A AC (RMS): {:.2f} A".format(dc, read_rms()))
42 time.sleep(1)ACS712とINA219のどちらを使う?
INA219はTexas Instruments製の電流・電圧監視チップで、I2Cで通信します。ホール効果ではなく、電流が流れる小さなシャント抵抗(モジュールではふつう0.1 Ω)の電圧降下を測ります。よく使われるモジュールは、約0.8 mAの分解能で±3.2 Aまで測り、26 Vまでのバス電圧を自分で読み取り、電力もチップ内で計算します。つまり、1つのI2C接続で電圧、電流、電力がまとめて得られ、ADCや平均化、ゼロ点のキャリブレーションに手間をかける必要がありません。その代わり、測定する回路とArduinoの間の絶縁がなく、AC電流は測れず、26 Vを超える電圧には使えません。
| 項目 | ACS712 | INA219モジュール |
|---|---|---|
| 測定方式 | ホール効果(磁気) | シャント抵抗(0.1 Ω) |
| 電流の範囲 | ±5 / ±20 / ±30 A | ±3.2 A(シャント抵抗による) |
| 分解能 | Unoで26〜74 mA | ≈ 0.8 mA |
| AC電流 | 測れる | 測れない |
| 電圧と電力 | 測れない(別に分圧回路が必要) | 測れる(26 Vまで) |
| 絶縁 | あり | なし |
| インターフェース | アナログ出力 | I2C(アドレス0x40〜0x4F) |
| 電源 | 5 Vのみ | 3〜5.5 V |
| 向いている用途 | モーター、ヒーター、商用電源の電化製品、大電流 | 電池、ソーラーパネル、センサーやボードの消費電流 |
1#include <Wire.h>
2#include <Adafruit_INA219.h>
3
4Adafruit_INA219 ina219; // varsayılan adres 0x40 / default address 0x40
5
6void setup() {
7 Serial.begin(9600);
8 if (!ina219.begin()) {
9 Serial.println(F("INA219 bulunamadi / INA219 not found"));
10 while (true) delay(10);
11 }
12 // ina219.setCalibration_16V_400mA(); // küçük akımda daha ince çözünürlük / finer resolution for small currents
13}
14
15void loop() {
16 float busV = ina219.getBusVoltage_V(); // yük tarafındaki gerilim / voltage on the load side
17 float current_mA = ina219.getCurrent_mA(); // akım (mA) / current (mA)
18 float power_mW = ina219.getPower_mW(); // güç (mW) / power (mW)
19
20 Serial.print(busV, 2); Serial.print(F(" V "));
21 Serial.print(current_mA, 1); Serial.print(F(" mA "));
22 Serial.print(power_mW, 0); Serial.println(F(" mW"));
23 delay(1000);
24}コードには、ライブラリマネージャからAdafruit INA219ライブラリをインストールします。モジュールのSDAとSCLのピンをUnoのA4とA5につなぎます。測定する電流はVIN+から入ってVIN−から負荷へ出ていく必要があり、INA219のGNDは測定する回路と共通にしなければなりません。まとめると、数ミリアンペアから3 AまでのDC電流を電圧と一緒に測るならINA219を、もっと大きな電流やAC電流、絶縁が必要ならACS712を選ぶのが正解です。
ACS712のプロジェクトのアイデア
- モーターの過電流保護:L298Nで駆動するDCモーターが拘束されると、電流が急に上がります。しきい値を超えたらモーターを止めて警報を鳴らします。
- 電池とソーラーパネルのモニター:充電と放電の電流を向きも含めて測り、電圧を掛けてWhを積算し、結果をOLEDディスプレイに表示します。
- スマートプラグ:リレーモジュールでコンセントを切り替え、ACS712で電化製品が本当に動いているかを確かめ、データをMQTTでHome Assistantに送ります。
- 洗濯機の終了通知:電流が設定値より低い状態が数分続いたら、ESP32からTelegramでメッセージを送ります。
- ポンプの空運転アラーム:水がなくなるとポンプの消費電流が下がります。それを検出してポンプを止めます。
- エネルギーロガー:電流と電力を1分に1回SDカードやGoogleスプレッドシートに記録し、1日の消費電力のグラフを描きます。
- 卓上の電力計:Arduinoで電圧計を作るプロジェクトにACS712を加えて、電圧、電流、電力を1つの画面に表示する測定器を作ります。
よくある失敗と対策
| 症状 | 考えられる原因 | 対策 |
|---|---|---|
| 電流がないのに0.1〜0.3 Aと表示される | コードがゼロ点を2.5 Vまたは512と決めつけている | 起動時に負荷をオフにしてゼロ点を測り、小さな不感帯を加える |
| 値が跳び続ける | 1サンプルだけの読み取り、1 nFフィルタの広い帯域幅 | 100〜500サンプルを平均する。必要ならFILTERに47 nFを追加する |
| 電流がマイナスになる | 電流が端子を逆向きに流れている | 線を入れ替えるか、結果に−1を掛ける |
| ACの負荷で0 Aに近い値になる | DC用のコードを使っている。正弦波は平均するとゼロになる | 実効値(RMS)を計算するスケッチを使う |
| 値がいつも数パーセント高い、または低い | モデルの値が間違っている、または感度の個体差 | チップの刻印から0.185、0.100、0.066を選び、テスターでキャリブレーションする |
| 生の値が0か1023のまま動かない | OUTが違うピンにつながっているかVCCにつながっている、電流がモデルの測定範囲を超えている | 配線を確認し、必要なら大きいモデルを使う |
| 電源が落ちる、電線が熱くなる | 端子を電源と並列につないでいる(ショート) | モジュールを負荷と直列につなぐ |
| ESP32で値が安定しない | 分圧回路がない、ADC2のピンを使っている、または生のanalogRead | 10k/20kの分圧回路、GPIO 34、analogReadMilliVoltsを使う |
| 磁石の近くで読み取り値が変わる | ホールセンサーが外部の磁界を拾っている | モジュールを磁石、スピーカー、大電流の電線から離す |
ACS712は電流の測定を学び始めるのにぴったりです。1本のアナログピンでDCとACの電流を測れ、数行のコードで電力とエネルギーも求められます。正しいモデルを選び、ゼロ点を測り、サンプルを平均し、テスターでキャリブレーションすれば、誤差数パーセント以内の信頼できる結果が得られます。アナログの読み取りの基本はADCのガイドでしっかり固められます。BlueGraysアプリには、アナログセンサーの読み取り、LCDディスプレイ付きデジタル電圧計、リレーで商用電源の電球を制御するプロジェクト、ESP32のデータロガーなどがあり、それぞれステップごとの回路図とコードが付いています。
よくある質問
ACS712は何アンペアまで測れますか?どのモデルを選べばいいですか?
ACS712には±5 A、±20 A、±30 Aを測る3つのモデルがあり、感度はそれぞれ185、100、66 mV/Aです。測定する最大電流(ACならピーク値)をカバーできるいちばん小さいモデルを選んでください。小さいモデルほど、同じ電流で出力の振れ幅が大きく、分解能も高くなります。モデルはチップのELC-05B、ELC-20A、ELC-30Aという刻印でわかります。
ACS712は電流がないのになぜ2.5 Vを出力するのですか?
ACS712が両方向の電流を測れるように、出力は電源電圧の半分から始まります。電流が一方向に流れると出力は2.5 Vより上がり、逆方向に流れると下がります。電源がちょうど5 Vでない場合、ゼロ点はVCC / 2にずれるので、起動時に測るのがいちばんよい方法です。
ACS712で商用電源の電流を測れますか?
はい。チップの絶縁耐圧は2.4 kV RMSで、230 Vなら5Aモデルは約800 Wまで、20Aモデルは約3250 Wまでの負荷に向いています(日本の100 Vでは、同じ電流での電力はこの半分以下になります)。ただし、モジュールのネジ端子とはんだ付け部分は商用電源の電圧になるので、配線はプラグを抜いた状態でだけ行い、閉じたケースに入れ、経験がない場合は一人で作業しないでください。より安全なのは、電線を切る必要のないSCT-013のようなクランプ式のカレントトランスです。
ACS712はESP32や3.3 Vで使えますか?
ACS712には4.5〜5.5 Vが必要で、3.3 Vでは正しい結果が出ません。ESP32やRaspberry Pi Picoでは、5V、VIN、VBUSのいずれかのピンからモジュールに電源を供給し、出力を10 kΩ + 20 kΩの分圧回路を通してアナログピンにつなぎます。そうすれば、5 V近い出力でもピンでは3.33 V未満に収まります。
ACS712は電流がないのになぜゼロにならないのですか?
理由は2つあります。コードがゼロ点をちょうど2.5 Vまたは512と決めつけていることと、センサー自身にノイズがあることです。起動時に負荷をオフにしてゼロ点を測り、100〜500サンプルを平均し、0.05 Aのような小さな不感帯を加えてください。ACでは、ノイズを二乗で差し引くと、待機中に表示される幽霊のような電流が消えます。
ACS712とINA219、どちらがよいですか?
用途によります。INA219はI2Cで動き、±3.2 Aまでの範囲で約0.8 mAの分解能で電流、電圧、電力をまとめて得られるので、電池や小さなDC回路にははるかに精密です。ACS712は30 Aまで測れ、AC電流も読め、測定する回路をArduinoから絶縁します。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
LDRで光の強さを測定
部屋の明るさを数値で見てみませんか?光に反応する小さな部品、LDRで周囲の光を測定し、Arduinoが0.5秒ごとにその値をコンピューターの画面に表示します。手で覆うと数値が変わる様子を確認できます。自動で点灯する常夜灯などのプロジェクトへの第一歩です。

ESP32とLDRモジュールで光の強さを読み取る
LDRモジュールの生のADC値と、暗い状態・明るい状態の基準値から計算した相対的な明るさの割合を、シリアルモニタでリアルタイムに確認します。この割合はルクスの測定値ではありません。モジュールの校正の仕組みを学べます。しきい値の決定に使うため、プロジェクト10の前に取り組むのが適しています。

LCDディスプレイ付きデジタル電圧計
自作の測定器で、電池や電源アダプターが出力する電圧を調べます。2つの抵抗で作る分圧回路が、高い電圧をボードで読み取れるレベルまで下げます。Arduinoが元の電圧を計算し、2行のLCDディスプレイにボルト単位で表示します。この回路では約55ボルトまでの直流電圧を測定できます。コンセントの商用電源には絶対に接続しないでください。

ボタンを押している間だけ220V電球を点灯
ボタンを押している間は実際の220ボルトの電球が点灯し、離すとすぐに消灯します。Arduinoの小さな信号では電球を直接点灯できないため、電気で動くスイッチであるリレーを間に入れ、電球の回路を開閉します。ボードで家庭の照明を操作するための第一歩です。家庭用電源を扱う際は十分に注意し、不安がある場合は詳しい人に手伝ってもらってください。

ESP32と可変抵抗でLEDの明るさを制御(アナログ→PWM)
可変抵抗を使ってLEDの明るさをアナログ操作で調整します。ESP32のADCピンで可変抵抗からの0-3.3Vの電圧を読み取り、PWM(パルス幅変調)信号に変換してLEDに出力します。可変抵抗を回すと、LEDが徐々に明るくなったり暗くなったりします。Arduino Core 3.0+ではanalogWrite()を直接使えます。ESP32-S2/S3ではADCの分解能を12ビットに固定します。

I2CでLCDディスプレイを使う
Arduinoにディスプレイを接続し、最初のメッセージを表示します。2行のLCDディスプレイは数本の配線だけで接続できます。まず上の行にあいさつを表示し、次に下の行にもう1つのメッセージを表示します。その後、表示を消去して最初から繰り返します。温度や時刻、スコアを表示するプロジェクトは、すべてこのステップから始まります。

ESP32 I2C LCDディスプレイ(16x2)
このプロジェクトでは、16x2文字のLCDをI2CでESP32に接続して文字を表示します。I2Cならデータ用の2本のピン(SDAとSCL)だけで制御でき、従来のパラレル接続のように6本以上のピンを使わずに済みます。コードでは1行目に固定メッセージ、2行目に毎秒増えるカウンターを表示します。また、起動時にI2Cスキャナーを実行し、ディスプレイのアドレス(通常は0x27または0x3F)をシリアルモニタに表示します。

ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)
ESP32で日時付きの温度・湿度記録システムを作ります!DHT22で1分ごとに温度と湿度を読み取り、DS1307 RTCから取得した日時とともにmicroSDカードへCSV形式で記録します。OLEDには最新の温度を大きな文字で表示し、湿度のパーセント値、日時、総記録数も表示します。SDカードの/temp_log.csvファイルはExcel、Google Sheets、Pythonのpandasで開いて分析できます。温室の監視、家や部屋の温度管理、実験室のデータ収集、食品の保管環境や養蜂箱の監視に適しています。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

