M5Stackでバッテリ容量が読み取れない

パルスオキシセンサーでバッテリー容量の表示をしようと思ってコードを追加しましたが、センサーの初期化処理が干渉しているようで値(初期化処理後は-1が帰る)が読み取れません。

void setup()
{
  M5.begin();
  M5.Power.begin();
  Wire.begin();         // Wire init, adding the I2C bus.
  Serial.begin(115200); // to PC via USB
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextSize(4);
  // Initialize sensor
  if (!pox.begin()) {
    M5.Lcd.println("FAILED");
    for(;;);
   } else {
    M5.Lcd.println("SUCCESS");
  }
  int bat_level = M5.Power.getBatteryLevel();
  Serial.println(bat_level);

loop()処理で読み取れないのでsetup()処理中に読み出しを埋め込むと// Initialize sensorの直後の(

pox.begin()

)から後ろでは-1が帰るようです。

なんだろう?

 

admin

 

 

心拍センサーでパルスオキシメーターを作る

心拍センサーというのが市販されていて、それを使うとパルスオキシメーターが作れるので使ってみました。

https://qiita.com/ghibi/items/aa9ae016dbbe9138a505

にやりたいイメージ通りの例があるので、ほぼそのままを使っています。ただしVScodeで使おうとすると関数を先に定義しないと呼び出せないので、入れ替えはしてあります。関数宣言でもいいですが、これはArduino IDEとVScodeの差分です。

また、デフォルトの設定ではうまく測定値が返ってこないので、

  pox.setIRLedCurrent(MAX30100_LED_CURR_4_4MA);
  //Register a callback for the beat detection
  pox.setOnBeatDetectedCallback(onBeatDetected);
pox.setIRLedCurrent(MAX30100_LED_CURR_4_4MA); 行を追加して、IR ledの電流値を調整しています。画面左上のHeart Pulseマークを見ながら指を当てて測定するのですが、測定値の安定には数秒かかります。
P.S. (2023/2/9)
ライブラリのURL追記
admin

Golangのtesting

Go言語にはテスト環境も整備されていますが、ここではベンチマークの例です。testingモジュールのベンチマーク機能を使うことで、わざわざソースコードに性能測定のためのコードの埋め込みが不要になります。ここでは素数計算のコードをターゲットとしてみました。

package adder

import (
	"fmt"
	"runtime"
	"time"
)

func oddCalc() {
	runtime.GOMAXPROCS(8)
	c := 2
	odd := []int{}
	tStart := time.Now()
	for i := 2; i <= 10000*1000; i++ {
		func() {
			flag := true // if odd number, stay "true"
			for j := 2; j*j <= c; j++ {
				if c%j == 0 {
					flag = false
					break
				}
			}
			if flag {
				odd = append(odd, c)
			}
			c++
		}()
	}
	tStop := time.Now()
	fmt.Println(len(odd))

	el := tStop.Sub(tStart)
	fmt.Println(el)
}

同じディレクトリにベンチマーク用の以下のソースコードファイルを用意しておきます。ターゲットと同じファイル中でも構わないと思いますが、ベンチマークを簡単に実行の趣旨からすると外れてます。

package adder

import (
	"testing"
)

func BenchmarkOddCalc(b *testing.B) {
        oddCalc()
	} 

実行結果は以下のとおりです。終了コードの判定もエラーコードも返していないのでpass~~が出力されています。

% go test -bench=. -v
goos: darwin
goarch: arm64
pkg: test
BenchmarkOddCal
664579
1.241648416s
BenchmarkOddCal-8              1        1241672042 ns/op
PASS
ok      test    1.485s

ソースコードに埋め込んだ時間測定とは微妙に値が異なりますが、精度から見れば誤差範囲です。

と言うわけでGoではわざわざ性能測定のためにターゲットのコード中にコードの埋め込みは要らないよという話でした。

 

admin

UTMでUbuntuデスクトップArm版をM1 Macbookに、

昨年夏はイマイチ動きがおかしくてデスクトップのインストールもできなかったのですが、そろそろと機は熟したようなのでインストールしてみた。

この前にVMwareでのインストールも試みたが、BIOSのメニューから進まないから現時点では諦め。

https://dev.to/andrewbaisden/how-to-install-ubuntu-linux-on-apple-silicon-macbooks-1nia

このリンクの通りにやってみただけですが、ちゃんとデスクトップ画面は立ち上がりました。なぜかChromeは依存関係解決できないと言われて、インストールできないのですが。

P.S. (2023/2/3)

VScodeもインストールできず、いまいちな完成度、UTMのせいなのかArm版Ubuntuだからなのか。

P.S. (2023/2/10)

Ubuntuのアップデート後に再度トライしてみたらVScodeインストールできた、ブラウザはChromium、どこまでChromeと互換あるのか?

 

admin

円周率の計算プログラム

円周率の計算はベンチマークで割と使われますが、公開されているプログラムでどの程度の時間で計算できるのか見てみた。

検索してWindowsとLinux版しかリストになかったのでLinuxで動作するTachusPIという円周率計算プログラムで、一千万桁まで計算させてみる、2019年度Intel i7 Macbookでの時間測定、

https://bellard.org/pi/pi2700e9/tpi.html

VMwareでLinux立ち上げてtpi-0.9-linux.tar.gzをダウンロードして、展開すると実行ファイルtpiがあるのでreadmeを参考に実行させてみる、スレッドは4個指定です。

$ ./tpi -T 4 -o pi.txt 10M

Total time (base 10 result) = 3.050 s
Writing result to ‘pi.txt’

https://bellard.org/pi/pi2700e9/tpi.htmlを見てみると、求める円周率の桁が一桁増えると所要時間はおよそ15倍かかっているから、確かにベンチマーク用として良さそうです。

 

admin

 

BlueSound Node 2にネットラジオ局のお気に入り登録

NodeのTuneInで検索できるラジオ局は簡単に追加できますが、URLを入力して追加するのはストリーミングのURLがわからないと追加出来ない。naimとclassical radio stream(どちらも320Kbps品質)はなんとか見つけ出して追加した。Linn Radioが休止状態だから、この4局だけでもなんとか使えそう。

できれば今現在入手困難なRaspberry PI(RPi)を今Volumioで使っているけど、他の用途で使いたいから。RPiの入手性が改善させるのは早くても今年の下半期じゃないかな。

 

admin

Goでのチャネルの空読み

Goでのチャネルは使い方を誤ればpanicになりますが、これはGoの潔いところと思えばいいですが、チャネルの使い方で読み出しだけれども変数には代入しないというのがあります。

具体的には値を使わないのだから、単にダミーのリードですが実際の使い方としては終了待ちとして使うことになるんだろうと思います。

非常にシンプルな空読みの確認用のコードですが、チャネルでバッファーを2個用意して、最初の値は空読みすることで、2個目の値が変数xに代入されていることがわかります。

package main

import  "fmt"

func main() {
	ch := make(chan int, 2)
	defer 	close(ch)
	go func() {
		ch <- 100
		ch <- 200
	}()
	<- ch		// dummy read
	x := <- ch
	fmt.Println(x)
}

<実行結果>
200

 

admin

Goのsliceの型はなんでも良い

Goでは何でも型に定義できるかと思いますが(例外があるかどうかは定かではない)、例えば関数もそのまま型として使用できます。

例えば以下のように、

ここでは”func(float64) float64“を型名として使用して、二つの関数をスライスに格納して、それぞれの関数を無名関数の引数(あえて無名関数でなくても良いですが)としてfor rangeループで実行させています。

package main

import (
	"fmt"
	"math"
)


func main() {
	f1 := func(a float64) float64{
		return a*a
	}
	f2 := func(a float64) float64{
		return math.Pow(a, 3)
	}
	
	fs := []func(float64) float64{f1, f2}		// "[]func(float64) float64" is a type

	for _, fss := range fs{
		func(f func(float64) float64){
			fmt.Println(f(3))
		}(fss)
	}
}

他の言語からすると奇妙な記述方法ではありますが、Goではこのような記法も成立するのだと。

 

admin

 

Bluesound Node 用のMac版アプリ

去年まではMacで立ち上がらないから、iPadでずっと使っていたけど久々にD.LしてみたらMac(M1)でも動くようになっている。選択の余地が広がるのは良いことです。

版数は、

P.S. (2023.1.30)

いまだbuggy感、プレイの停止ができない!もちろんiPad版では問題ないけども。Intel Macでは起動もしない。

 

admin

Goのloopclosure問題、

問題というよりも、タイミングがそうだからそうなるよねという話です。

Goのgoroutineでの話で、以下のソースをVScodeで読み込ませるとopenclosureというwarningが出ます。実行結果も期待される値ではなくて、例えば全部40とかになるのですが、なぜか?

それは無名関数に明示的に引数としてvを与えてる訳ではないので、無名関数の中でvの使われる時点(v*2)のv値が使われるからです。具体的には並行処理を起動しても、すぐに各ルーチンが実行される訳でもなくて実行タイミングには遅延があるだろうから、実はvを使おうとしたタイミングではすでにfor range処理が先行したり、あるいは終了している可能性もあるから。

対応方法はv無名関数に引数として渡すのがスマートなやり方になるでしょう。

https://github.com/mushahiroyuki/lgo/blob/main/example/ch10/ex1005.go

package main

import "fmt"

func main() {
	a := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20} //liststart
	ch := make(chan int, len(a))
	for _, v := range a {
		go func() {
			ch <- v * 2
			fmt.Println(":", v)
		}()
	}
	for i := 0; i < len(a); i++ {
		fmt.Print(<-ch, " ")
	} //listend
	fmt.Println()
}

こうすれば、無名関数が不規則なタイミングでその時点のv値を使用することなく、意図した値を引き渡すことができます。別の対応方法としてはvをシャドーイング(v := vをfor rangeの直後に挿入)しても良さそうですが。いずれにしろ並行処理の実行順序は保証されないので、結果の並びは昇順にはなりません。

		go func(v int) {
			ch <- v * 2
			fmt.Println(":", v)
		}(v)

 

admin