見出し画像

RTL−SDRとGO言語で電波を受信する実験(6):周波数別のパワーをグラフ表示できた(rtl_powerの一部)

今朝は5時半から開発開始です。昨日は4時から開始したので夜調子悪くなってしましました。なので今朝は、明るくなるまで寝ていました。

さて、RTL-SDRを使った実験の続きです。昨日受信した信号をグラフ表示できたので今朝は周波数別のパワーを表示するプログラムを作りました。RTL-SDRのライブラリにあるrtl_powerの一部です。

rtl_power -f 24M:1.7G:1M -g 50 -i 15m -1

のようなコマンドで実行した場合の処理をGO言語に写経しました。
処理としては、

周波数別のパワーを測定

のような感じになります。
チューナーの設定を変えながら取得したデータからパワーを計算すればよいのでFFTとかで周波数分析する必要はありません。わりと簡単にできました。テストプログラムは、

package main

import (
	"log"
	"math"
	"os"
	"time"

	"github.com/samuel/go-rtlsdr/rtl"

	"github.com/go-echarts/go-echarts/v2/charts"
	"github.com/go-echarts/go-echarts/v2/opts"
)

func main() {
	dev, err := rtl.Open(0)
	if err != nil {
		log.Fatalf("rtl.Open Failed to open device err=%v", err)
	}
	defer dev.Close()
	// no direct sample
	// no offset tuning
	// set auto gain
	if err := dev.SetTunerGainMode(false); err != nil {
		log.Fatalf("dev.SetTunerGainMode err=%v", err)
	}
	// no PPM
	// disable biasTee
	if err := dev.SetBiasTee(false); err != nil {
		log.Fatalf("dev.SetBiasTee err=%v", err)
	}
	// reset buffer
	if err := dev.ResetBuffer(); err != nil {
		log.Fatalf("dev.ResetBuffer err=%v", err)
	}
	// set sample rate 1MHz
	if err := dev.SetSampleRate(1_000_000); err != nil {
		log.Fatalf("dev.ResetBuffer err=%v", err)
	}
	st := time.Now()
	xaxis := []int{}
	data := []opts.LineData{}
	for hz := 24; hz < 1676; hz++ {
		// set center freq
		if err := dev.SetCenterFreq(uint(hz * 1e6)); err != nil {
			log.Fatalf("dev.SetCenterFreq err=%v", err)
		}
		// wait 5mSec
		time.Sleep(time.Millisecond * 5)
		// read data
		buf := make([]byte, 16384)
		n, err := dev.Read(buf)
		if err != nil {
			log.Fatalf("dev.Read err=%v", err)
		}
		p := 0
		t := 0
		for i := 0; i < n; i++ {
			s := int(buf[i]) - 127
			t += s
			p += (s * s)
		}
		dc := float64(t) / float64(n)
		e := float64(t)*2.0*dc - dc*dc*float64(n)
		p -= int(math.Round(e))
		dbm := float64(p)
		dbm /= float64(1e6) // 1M
		dbm = 10 * math.Log10(dbm)
		xaxis = append(xaxis, hz)
		data = append(data, opts.LineData{Value: dbm})
	}
	showChart(xaxis, data)
	log.Printf("dur=%v", time.Since(st))
}

func showChart(xaxis []int, data []opts.LineData) {
	line := charts.NewLine()
	line.SetGlobalOptions(
		charts.WithTitleOpts(opts.Title{Title: "Freq MAP by RTL-SDR"}),
		charts.WithToolboxOpts(opts.Toolbox{
			Show:  true,
			Right: "10%",
			Feature: &opts.ToolBoxFeature{
				SaveAsImage: &opts.ToolBoxFeatureSaveAsImage{
					Show:  true,
					Type:  "png",
					Title: "Save to Image",
				},
				DataZoom: &opts.ToolBoxFeatureDataZoom{
					Show: true,
				},
			}},
		),
	)
	line.SetXAxis(xaxis).
		AddSeries("power", data)
	f, _ := os.Create("power.html")
	line.Render(f)
	defer f.Close()
}

のような感じです。
室内アンテナだと、

室内アンテナ

のような感じです。
TVのアンテナ端子につなぐと

TVのアンテナ

地デジと衛星放送の部分がちゃんと高くなっています。
rtl_powerで測定したのと同じ感じです。
ますます、楽しくなってきました。24Mhz以下の電波も測定したくなってきたのでダイレクトサンプリングとGO言語でFFTする方法を調べています。

明日に続く


開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。