中華AD8307のテストをしてみましたが、これはうまくいけばモジュールとして使えるようにピンヘッダを立てて作りました。
テストした感じでは使えそうなので、まずパワー計として動かしてみることにしました。
といっても、MCUのADCで読んで計算するだけです。
ただ、AD8307 そのままだと入力範囲が -76dBm〜+16dBm と、普段使うには電力範囲が小さいほうに寄りすぎているため、25dB のアッテネータを前段に挿入し、-51dBm〜+41dBm の範囲としました。
耐電力の大きなアッテネータは面倒なので、1/2W 抵抗を使い、定格1W程度、極めて短時間なら10W程度というイメージです。
使用感
実際10W入力すると3秒ぐらいでかなり発熱するのでこわいです。5W ぐらいまでなら〜5秒耐えられそうです。
確度
アッテネータの絶対的な誤差は簡単な校正で消せます (インターセプトが移動してるだけなので) 。AD8307 自体のログとの一致性は±1dB。
ただ、入力周波数によって出力電圧が結構変わりますので、確度を求めるなら周波数カウンタ機能をつけて、周波数も変数にして校正したほうが良さそうです。
例えば10MHzと500MHzだと、出力電圧にほぼ固定で10dB分の差があります (1ケタ!!)。一応、この差は周波数に応じてほぼ固定なので、入力周波数がわかっていれば簡単に補正はできます。
↓ はデータシート記載のものと、実測のもの
今回は周波数を測ってない以上、全域での絶対的な確度はあまり期待できません。
計測できた電力値が実際より大きい分にはあまり問題ではありませんが、実際よりも小さい値が表示されると、これを信じて他の機器につないだときに過大入力になることがあり、よくありません。安全策としては上限周波数で校正をかけることでしょう。
用途
明確な出力が不明な信号源の場合、直接スペアナに繋ぐまえに、一旦チェックする用として使いたい気持ちです。瞬間的になら10W入力できますし、これなら壊れても痛くありません。
コード
#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "interval.hpp"
static const float SLOPE = 26.367;
static const float INTERCEPT = -63.51879243;
LiquidCrystal_I2C lcd(0x27, 16, 2);
String formatWatts(const float watts) {
if (watts < 1e-3) {
return String(watts * 1e6) + "uW";
} else
if (watts < 1e-1) {
return String(watts * 1e3) + "mW";
} else {
return String(watts) + "W ";
}
}
void setup() {
Serial.begin(115200);
Serial.println("init...");
Wire.begin();
lcd.begin();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Hello, World");
lcd.setCursor(0, 1);
lcd.print("TEST");
}
void loop() {
// interval<1000>::run([]{
// Serial.println("1000ms");
// });
uint16_t adc_raw = analogRead(0);
Serial.print("ADC Got = "); Serial.println(adc_raw);
float adc = static_cast<float>(adc_raw) / 1024 * 5;
Serial.print("ADC Voltage = "); Serial.println(adc * 1000);
float dBm = (adc * 1000 / SLOPE) + INTERCEPT;
Serial.print("dBm = "); Serial.println(round(dBm));
float watts = pow(10, dBm / 10) / 1000;
Serial.print("W = "); Serial.println(watts);
Serial.print("mW = "); Serial.println(watts * 1000);
lcd.setCursor(0, 1);
lcd.print(round(dBm));
lcd.print("dBm");
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(formatWatts(watts));
lcd.print(" ");
delay(500);
}