HUB75 LEDにプレゼンターの名前表示

Apache + PHP配下で動いているプレゼン管理アプリにHUB75 LEDアレイつないでプレゼンターの名前を表示するようにした

全体の構成は以下の図の通りで、発表管理アプリは他人が作ったものなのでソースコードの公開は無し、発表者リストのトップの名前をHUB75 LEDに表示するようにしてみた

<発表管理画面>

このトップにあるゲスト20を@以下はjsで削除(最大全角4文字、半角8文字までの表示制限)してgolangサーバーにfetch、golangサーバーにはjs用の口を作って、CORS対応にしています

jsで発表者の並べ替え対応しているので、並べ替えが発生するとeventListenerを起動してgolangサーバーにfetchするようになってます

https://github.com/chateight/golang/tree/master/image

golangサーバー側のソースはこんな感じ、

 

jsで追加部分のコードを抜き出すとこんな処理、ブラウザのjsキャッシュが残っていて結構ハマりました

// notify top presenter name
//
function notifyTopPresenter() {
  const firstItem = document.querySelector("#presentersList .list-item");
  if (firstItem) {
    const name = firstItem.querySelector(".presenter-name")?.textContent || "";
    const event = new CustomEvent("topPresenterChanged", {
      detail: { name: name.trim() },
    });
    document.dispatchEvent(event);
  }
}

// listener for topPresenterChanged event
//
document.addEventListener("topPresenterChanged", function (e) {
  let name = e.detail.name || "";
  name = name.trim().replace(/^["“”'‘’]+|["“”'‘’]+$/g, "");
  name = name.split("@")[0];

  const formData = new FormData();
  formData.append("text", name);
  console.log("先頭の発表者:", name);
  fetch("http://rasp-b.local:8000/uploadText_js", {
    method: "POST",
    //headers: { "Content-Type": "application/json" },
    body: formData
  })
  .then(res => res.text())
  .then(msg => console.log("サーバー応答:", msg))
  .catch(err => console.error("通信エラー:", err));
});

しばらく運用して改良点は反映の予定

 

admin

geminiのAPI経由の使用可能モデル変更されてるね

https://isehara-3lv.sakura.ne.jp/blog/2025/04/28/ラズパイ5のchatbot機能を統合/

4月にラズパイ5で作ったchatbot久々に動かそうとしたら動かない、より正確にはDifyからのレスポンスが返らない(回答が空か短すぎると言われる)、さらに調べるとgeminiへのqueryがエラーになっている

5月あたりにgoogleの対応が変わっていて、古いモデル名は使えなくなっているらしい、以下のFlash 001用のようなモデルは終了で末尾がlatestのモデルを選択したら動いた

変更後、

確認はcurlで、

curl -X POST 'http://localhost/v1/chat-messages' \
--header 'Authorization: Bearer app-***** your api key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "inputs": {},
    "query": "What are the specs of the iPhone 13 Pro Max?",
    "response_mode": "streaming",
    "conversation_id": "",
    "user": "abc-123",
    "files": [
      {
        "type": "image",
        "transfer_method": "remote_url",
        "url": "https://cloud.dify.ai/logo/logo-site.png"
      }
    ]
}'

但し、最近無償版は混雑しているようで、割と頻繁にbusyで帰ってくるから、使いたいなら有償にしなさいよと言ってるようだ、それならばローカルLLMの選択もありだよね

 

admin

sesame関連の電池の仕様と寿命のまとめ

sesameデバイスの種類が増えてきたので、電池の仕様のまとめ

sesameの電池型格
————————-

・セサミ5:CR123A

・セサミタッチ:CR2

・リモコン:CR2450*(1~3個)

・オープンセンサー:CR1632

セサミ5とセサミタッチはそこそこ大容量電池、消費電力多そうだし(一年ぐらいで見とくのが良さそう)、リモコン(電池3個で3年)はそこそこで、オープンセンサーはおそらくライフ中(10年有効とか)に電池交換の機会はなさそうだ

 

admin

この機能に、フロントエンド(アナログ信号の前処理)追加、

https://isehara-3lv.sakura.ne.jp/blog/2025/07/02/オシロスコープのスイープとトリガ条件を追加/

① AC入力のマイナス側も扱えるように、GNDレベルをVss/2 = 1.65 V付近にする、ゲインはフルスケール考慮して-6db

② 次の処理でゲイン6db(プラス方向にしか振れないパルス用)と0db(AC信号用)の選択をデジタルポテンショメーター使ってできるようにした(ただし、i2cバスで値を書き込んでもレスポンスまともだけだけど結果は無視された状態、つまり電源投入状態のwiperが中点状態のまま)、目的はADCの前にダイナミックレンジを確保したかったから

後の処理ではオシロスコープとするには、ADCから読み取った値が反転しているから元に戻す処理必要だけど、コードには未反映

https://github.com/chateight/dsp

回路図とi2cのタイムチャートをアップロードしてあります

 

admin

 

 

 

sesame(smart lock)のアップデート

一ヶ月半使って、不自由に感じたところをアップデート、痒いとこに手が届く製品はちゃんと標準で用意されてます

    1. ドアを開放したままにしたい時でもセサミのタイマーで自動ロックされてしまう
    -> オープンセンサーでセサミタイマーロックは無効にしてオープンセンサーのタイマを使う、ただしセサミタイマーロック無効にするとドア解錠した後にドアを開かないと、オープンセンサにもトリガ条件入らないから、再度自動でロックされない問題あり
    2. いちいちアンロックでセサミのノブを回すのが面倒
    -> リモコンオープナー(クローズ機能付き)を使う

おそらくこの運用でしばらくは問題ないと思う、あとはドアアンロックで顔認証使うとかだけど、それは今のセサミタッチが壊れた時かな

P.S. リモコンオープナーの電池残量不安定(一週間経過後に60%とかになっていて、尚且つその値は不安定で90%以上に回復してる時もある)、sesameに問い合わせると改善検討中との回答、CR2450を3個使いにした方が安定そうだから電池追加で手配した、元々が電池3個入るようになっているのもそのための考慮のように思う

 

admin

オシロスコープのスイープとトリガ条件を追加

概ねどんなオシロスコープにもある表示モードは、

・トリガーモード

・フリーランモード

・ワンショットモード

昨日までの実装はトリガーモードだけだったので、フリーランモードを追加した

該当部分のロジックは、以下のコード、

要はおよそ4ms(2μs*2*1000)の間にトリガー要件が発生しないと、そこからADCのデータ取得して表示しています

ワンショットモードは、トリガーモードで一度条件発生したら以降のトリガーは無効にするだけだろうから包含されていて設定だけの問題

この機能を追加するだけで、普通のオシロスコープらしくなります

ADCの入力開放でフリーラン状態の写真、入力開放だと概ね0.8Vぐらいに見えるようです、何らかの入力保護回路は入っているんだろうけども

 

admin

スペアナにオシロスコープ機能を追加

周波数軸のスペアナに対して時間軸のオシロスコープ機能の実装、最終的には物理スイッチで機能切り替えだろうけど、今はソースコードに埋め込んだ変数で機能切り替え

ソースコードは以下になるけれども、スペアナコードをかなり流用

① ADCのサンプリングコード中に立ち上がりのエッジ検出ロジックを入れ込み(ほぼ方形波前提の検出ロジックになってます)

② LCDの表示バッファーは二面持たせて、変化分だけ描画はスペアナと同じだけどライン描画からドット描画だから相対的に高速のはず

以下は現状のコード

https://github.com/chateight/dsp

スペアナに入力しているおよそ2.3KHzの方形波を表示させたところ

・サンプル周期2μs(およそ500KHz)

・表示時間長はおよそ500μs(256フレーム*2μs)

 

admin

 

表示含めて基本のロジックは組み込み(ラズピコスペアナ)

いくつか当初の思惑と違ったところ、

1. 結局ADCデータ読み取りのDMA処理終わった後の割り込みが2回目以降は発生しない、デバッガで止めながらだと発生するからタイミング問題だろ受けで原因突き止めできない

2.  ADCのクロックデバイドはDMAモード以外でも有効化できない

従って、現状のロジックは、CPUが介在しておよそ500KHzで動くADCのデータを2μsごとに読み取って蓄積

以降の処理はDMA使った時と大差なし

3. LCDの表示処理は初回描画だけは画面全面書き込みになるけど、2回目以降は差分処理だけにして高速化、ただしフレーム周期は今の所およそ12ms*10 =120 ms にしている

4. 初回のLCD(全面書き込み)は500ms程度掛かっているから、FFTデータは一度表示用にコピーして、次のFFT処理で壊されないように別保存している、今は表示周期をおよそ120msぐらいにしているけども、2回目以降は変更部分のみの書き換えだから高速

この画像はおよそ2KHz(ちょっと下)の方形波をPWMから入力して9次の高調波まで表示されている状態

コード全体は、以下のリンクから

https://github.com/chateight/dsp

もちろん用途によるけど、ラズパイシリーズではラズピコが値段考えると一番使い出があるように思う

 

admin

pico-sdk使用してLCD表示(SPIバス)

LCDの動作確認のためにArduino IDEで動作確認(受入試験みたいなもので以下のリンク)しましたが、Cのライブラリ使わないとスペアナ計算と結合できないのでpico-sdk使ってやってみます

https://isehara-3lv.sakura.ne.jp/blog/2025/06/20/ラズピコでspiバス経由でlcd表示させる/

ライブラリは使い方がシンプルなので構造が単純な以下を使います

https://github.com/Imel23/lcd-st7789-library

ライブラリを使う時には、ハードワイヤリングの設定をソース上で行うこととSPIの動作モードを指定しないと動作しなかった(以下変更部分のコード)、それ以外には画面ローテーションの指定もしています、この記事の最後の方に記載

SPI clockは62.5MHzのままだと動作に不安があるので20MHzまで落としてます、どうせ62.5MHzでも最初の電源オンのチラつき(データが初期状態では不定だから)はあるから、バックライト信号の制御がいずれ必要

// Pin definitions for the LCD connection
//#define BL_PIN 13 // Backlight pin
#define DC_PIN 20   // Data/Command pin
#define RST_PIN 21  // Reset pin
#define MOSI_PIN 19 // SPI MOSI pin
#define SCK_PIN 18  // SPI Clock pin
#define CS_PIN 17   // Chip Select pin

// SPI configuration
#define SPI_PORT spi0
#define SPI_BAUDRATE 2000000  // 62.5 MHz SPI clock

// Function prototypes for internal use
static void lcd_write_command(uint8_t cmd);
static void lcd_write_data(uint8_t data);
static void lcd_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);

// Initialize the LCD
void lcd_init() {
    // Initialize SPI
    spi_init(SPI_PORT, SPI_BAUDRATE);
    spi_set_format(SPI_PORT, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);     // to add this line

ライブラリ用にcmakeファイルに設定を追加して、現状の中身は、

# Generated Cmake Pico project file

cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)

# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work ==
if(WIN32)
    set(USERHOME $ENV{USERPROFILE})
else()
    set(USERHOME $ENV{HOME})
endif()
set(sdkVersion 2.1.1)
set(toolchainVersion 14_2_Rel1)
set(picotoolVersion 2.1.1)
#set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
#if (EXISTS ${picoVscode})
#    include(${picoVscode})
#endif()
# ====================================================================================
set(PICO_BOARD pico2_w CACHE STRING "Board type")

set(PICO_SDK_PATH "$ENV{HOME}/pi/pico/pico-sdk")
#set(PICO_SDK_PATH "/Users/usamiryuuichi/pi/pico/pico-sdk")


# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)

project(dsp C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()

# Create a library for the LCD driver
add_library(lcd_driver STATIC
    lcd_st7789_library.c
    font_5x7.c
)

add_library(CMSISDSP STATIC IMPORTED GLOBAL)
set_target_properties(CMSISDSP PROPERTIES IMPORTED_LOCATION
  $ENV{HOME}/pi/pico/CMSISDSP/build/bin_dsp/libCMSISDSP.a)

#target_link_libraries(dsp CMSISDSP ...)

# Add executable. Default name is the project name, version 0.1

add_executable(dsp dsp.c )

pico_set_program_name(dsp "dsp")
pico_set_program_version(dsp "0.1")

# Modify the below lines to enable/disable output over UART/USB
pico_enable_stdio_uart(dsp 0)
pico_enable_stdio_usb(dsp 1)

# Add the standard library to the build
target_link_libraries(dsp
        pico_stdlib
        pico_multicore
        hardware_adc
        hardware_dma
        hardware_pio
        hardware_pwm
        hardware_spi
        CMSISDSP
        lcd_driver
        hardware_timer 
        pico_multicore
)

target_link_libraries(lcd_driver
    pico_stdlib
    hardware_spi
)

# Add the standard include files to the build
target_include_directories(dsp PRIVATE
        ${CMAKE_CURRENT_LIST_DIR}
        $ENV{HOME}/pi/pico/CMSISDSP/CMSIS-DSP/Include
        $ENV{HOME}/pi/pico/CMSISDSP/CMSIS_6/CMSIS/Core/Include
        ${PICO_SDK_PATH}/src/rp2
)

target_include_directories(lcd_driver PRIVATE
    ${CMAKE_CURRENT_LIST_DIR}
    ${PICO_SDK_PATH}/src/common
    ${PICO_SDK_PATH}/src/rp2
)

pico_add_extra_outputs(dsp)

ディレクトリ構成は、

スペアナのコードに追加したのは、動作確認のためだけですが、

// core1 will be used for LCD display control
#include "pico/stdlib.h"
#include "lcd_st7789_library.h"
#include "hardware/spi.h"

void core1_main()
{
    // Initialize the LCD
    lcd_init();

    // Fill the screen
    lcd_fill_color(create_color(255, 255, 255));

    // Draw a rectangle
    lcd_draw_rect(10, 10, 100, 50, create_color(0, 0, 255));

    // Draw some text
    lcd_draw_text(20, 20, "Hello, World!", create_color(255, 0, 0), create_color(255, 255, 255), 1); // char color, bg color, font size

    while (1)
    {

    }
}

実行結果は、

ローテーション指定はライブラリ中のここで、関数もあるようですが関数で後から指定すると表示が二重になった

    lcd_write_command(0x36);  // Memory Data Access Control
    lcd_write_data(0xA0);     // display rotation

 

admin

ラズピコでspiバス経由でLCD表示させる

スペアナプロジェクト用ですが、2インチのLCD(240*320 dots)を購入、SDカードのアクセスもできるようになってますが

https://learn.adafruit.com/2-0-inch-320-x-240-color-ips-tft-display/pinouts

動作確認はArduino IDE使って、ライブラリは、

をインストします

接続は以下のソースコードの通りですが、電源はピコの3.3V出力から取ろうとすると過電流(おそらくピコの電源電圧低下して動作不能状態になってる)でUF2ファイルのダウンロードできないので、USB電源であるVBUSから取らないと機能しなかった

電源電圧とバックライト制御信号(PWM)をまとめてVBUSに接続しています、従ってバックライトの輝度はmax状態ということ、GNDは一本なのでピコ – LCD間の接続は全部で8本です

<テスト用コード>

#include <adafruit_gfx.h>
#include <adafruit_st7789.h>
#include <spi.h>

// ピン定義(PicoのGPIO番号)
#define TFT_CS    17  // pin 22
#define TFT_RST   21  // pin 27
#define TFT_DC    20  // pin 26
#define TFT_SCK   18  // pin 24
#define TFT_MOSI  19  // pin 25

SPISettings settings(2000000, MSBFIRST, SPI_MODE3);
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI, TFT_CS, TFT_DC, TFT_RST);

void setup() {
  tft.init(240, 320, SPI_MODE3);
  delay(100);

  tft.fillScreen(ST77XX_WHITE);   // 背景を白に設定
  tft.setRotation(1);             // 画面を90度回転
  tft.setCursor(20, 100);         // 文字の表示位置を設定
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(3);             // 文字サイズを設定
  tft.print("Hello Pico");       // 文字の表示
}

void loop() {
  delay(1000);
}

ST7789は制御回路にフレームメモリを持っているので、ラズピコからのリフレッシュ動作は不要なので使いやすいと思う、まあラズピコでリフレッシュさせたら負荷も大変だろうから、こういう制御チップがあるということだろう

 

admin