2026年10月23日金曜日

draft@http-kaluma

--------------以下は最初は動くがだんだんremote errorとなる。。。。----------------  

kill -9 $(lsof -t -i:3000)でいちいちportを閉じるのが重要だった

//$ mkdir thermo-server

// $ cd thermo-server

//$ npm init -y

//$ npm install express ip --save

--------------node app.js------------------------

const express = require('express');
const ip = require('ip');

const app = express();
const addr = ip.address();
const port = 3000;

let temperature = '0.0';
let humidity = '0';

// ========================================
// データ受信エンドポイント
// ========================================
app.get('/update', (req, res) => {
  if (req.query.t) temperature = req.query.t;
  if (req.query.h) humidity = req.query.h;

  console.log(`[受信] 温度: ${temperature} °C / 湿度: ${humidity} %`);

  // 【対策】明示的に Connection: close ヘッダーを付与して接続を即時切断する
  res.setHeader('Connection', 'close');
  
  // 文字列を返してレスポンスを完了する
  res.status(200).send('OK');
});

// ========================================
// 画面表示用エンドポイント
// ========================================
app.get('/', (req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('Connection', 'close'); // こちらも念のため追加
  res.send(`
<html>
  <head>
    <meta charset="utf-8">
    <title>Pico W センサーデータ</title>
  </head>
  <body>
   <h1>温度: ${temperature} °C</h1>
   <h1>湿度: ${humidity} %</h1>
  </body>
</html>
  `);
});

// ========================================
// サーバー起動
// ========================================
app.listen(port, () => {
  console.log(`Server running at http://${addr}:${port}`);
});
----------------kaluma shell------------------------
const { DHT } = require('dht');
const { WiFi } = require('wifi');
const http = require('http');

// ========================================
// Wi-Fi設定
// ========================================
const WIFI_SSID = 'Pikara2-91d8e4';
const WIFI_PASSWORD = '090e219cbdbf5';

// ========================================
// HTTPサーバー設定
// ========================================
const SERVER_ADDRESS = '192.168.0.11';
const SERVER_PORT = 3000;

// ========================================
// DHT11設定:GP15
// ========================================
const dht = new DHT(15, DHT.DHT11);
const wifi = new WiFi();

// ========================================
// 状態管理
// ========================================
let sending = false;
let timerStarted = false;
let requestTimer = null;

// ========================================
// リクエスト終了処理
// ========================================
function finishRequest(reason) {
    if (!sending) {
        return;
    }

    sending = false;

    if (requestTimer !== null) {
        clearTimeout(requestTimer);
        requestTimer = null;
    }

    console.log('Request finished: ' + reason);
}

// ========================================
// センサー読み取り・HTTP送信
// ========================================
function sendSensorData() {
    if (sending) {
        console.log('Previous request is running. Skip.');
        return;
    }

    sending = true;

    try {
        // DHT11読み取り
        dht.read();

        const temp = dht.temperature;
        const hum = dht.humidity;
        //const temp = 23;
        //const hum = 56;

        console.log('--------------------------');
        console.log('Temperature: ' + temp + ' C');
        console.log('Humidity: ' + hum + ' %');

        // センサー値の検査
        if (
            !Number.isFinite(temp) ||
            !Number.isFinite(hum) ||
            temp < 0 ||
            temp > 50 ||
            hum < 0 ||
            hum > 100
        ) {
            console.log('Invalid DHT11 reading. Skip sending.');
            finishRequest('invalid sensor data');
            return;
        }

        const temperature = temp.toFixed(1);
        const humidity = hum.toFixed(0);

        const path =
            '/update?t=' +
            encodeURIComponent(temperature) +
            '&h=' +
            encodeURIComponent(humidity);

        console.log(
            'Request: http://' +
            SERVER_ADDRESS + ':' +
            SERVER_PORT + path
        );

        // endイベントが来ない場合の保護タイマー
        requestTimer = setTimeout(function () {
            console.log('HTTP response timeout');
            finishRequest('timeout');
        }, 5000);

        // HTTP GET
        const req = http.get({
            host: SERVER_ADDRESS,
            port: SERVER_PORT,
            path: path,
            headers: {
                'Connection': 'close' // 【対策】サーバー側に即時切断を促す
            }
        }, function (res) {
            console.log('HTTP response received');
            console.log('HTTP status: ' + res.statusCode);

            // 【対策】ストリームを明示的に流し、内部バッファの詰まりを防ぐ
            res.resume(); 

            // レスポンス本文の受信
            res.on('data', function (chunk) {
                console.log('Response data: ' + chunk.toString());
            });

            // レスポンスの正常終了
            res.on('end', function () {
                console.log('HTTP response end');
                finishRequest('response end');
            });

            // レスポンスエラー
            res.on('error', function (err) {
                console.log('HTTP response error: ' + err);
                finishRequest('response error');
            });
        });

        // リクエストエラー
        req.on('error', function (err) {
            console.log('HTTP request error: ' + err);
            finishRequest('request error');
        });

        // リクエスト送信
        req.end();

        console.log('req.end() called');

    } catch (err) {
        console.log('Sensor/HTTP error: ' + err);
        finishRequest('exception');
    }
}

// ========================================
// メイン処理
// ========================================
function main() {
    console.log('Pico W DHT11 HTTP Client');
    console.log('KalumaJS v1.2.1');
    console.log('Connecting to Wi-Fi...');

    wifi.connect({
        ssid: WIFI_SSID,
        password: WIFI_PASSWORD
    }, function (err) {
        if (err) {
            console.log('Wi-Fi connection failed');
            console.log(err);
            return;
        }

        console.log('Wi-Fi connected');

        if (timerStarted) {
            return;
        }

        timerStarted = true;

        // 初回送信
        sendSensorData();

        // 10秒ごとに送信
        setInterval(function () {
            sendSensorData();
        }, 10000);
    });
}

// ========================================
// プログラム開始
// ========================================
main();

2026年10月19日月曜日

tinygo on pico with sht35(sh3xシリーズ)

// go get tinygo.org/x/drivers

// tinygo flash -target pico . after set boot mode at pico

package main

import (

"fmt"

"machine"

"time"

"tinygo.org/x/drivers/sht3x"

)


func main() {

// シリアル通信(USB)の準備を待つためのディレイ

time.Sleep(2 * time.Second)

fmt.Println("--- SHT3x 温湿度センサー 開始 ---")


// 1. I2Cの初期化 (Picoの標準ピン GPIO4/GPIO5 を使用)

err := machine.I2C0.Configure(machine.I2CConfig{

Frequency: machine.TWI_FREQ_400KHZ, // 400kHz

SDA:       machine.GP4,             // Pin 6

SCL:       machine.GP5,             // Pin 7

})

if err != nil {

println("I2Cの初期化に失敗しました:", err.Error())

return

}


// 2. SHT3x ドライバーの初期化

// ※ アドレスはモジュールによって 0x44 (デフォルト) または 0x45 です。

// ※ 動かない場合は sht3x.AddressB (0x45) に変更してみてください。

sensor := sht3x.New(machine.I2C0)

sensor.Address = sht3x.AddressA // 0x44


// 3. 2秒ごとにデータを読み取って表示するループ

for {

// センサーから温度と湿度を読み取る

//(内部でSHT3xのコマンド送信、データ取得、CRCチェックが行われます)

temp, humi, err := sensor.ReadTemperatureHumidity()

if err != nil {

fmt.Println("データの読み取りに失敗しました:", err.Error())

} else {

// tinygoのドライバーは、温度を「ミリ度(1/1000℃)」、湿度を「1/100 %」で返します

// 例: 25000ミリ度 = 25.00℃

tCelsius := float64(temp) / 1000.0

hPercent := float64(humi) / 100.0

// シリアルモニターに出力

fmt.Printf("温度: %.2f °C | 湿度: %.2f %%\n", tCelsius, hPercent)

}

time.Sleep(2 * time.Second)

}

}

2026年10月12日月曜日

MMBasic ファイル操作(picocom最終版)

picocom -b 115200 --omap delbs -s "sz --xmodem" /dev/ttyACM0 で転送可能となる 

ctl-a,ctl-xで終了

https://qiita.com/ksakabe/items/2ecfcfd346ef7f857b34 も参考になる

mmbasic picocomでpcからpicoへmmbasicを贈りたいPicoMite (MMBasic) 

を実行中のRaspberry Pi PicoへPCからファイルを転送するには、Pico側のXMODEM RECEIVEコマンドと、picocom のXMODEM送信機能(Ctrl-A 続いて Ctrl-S) を組み合わせて使用します。あらかじめホストPC側に lrzsz(sxコマンド)をインストール。

1.転送の手順PicoMite側で受信待機picocomでPicoに接続します。MMBasicのプロンプトで次のように入力してEnterキーを押します。

XMODEM RECEIVE 

コードは注意してご使用ください。(※画面が止まった/待機状態になったようになります)

picocomからファイルを送信キーボードの

Ctrl-A を押し、続けて Ctrl-Sを押します。画面下部に送信する、そのPCディレクトリのファイルのパス(ファイル名)を尋ねられるので、PC側のファイル名を入力してEnterキーを押すと転送が始まります。

cf 保存されたファイルの一覧を見る

(FILES)SDカードや内蔵フラッシュドライブに保存されているファイル名の一覧を表示します。basic FILES

2. ファイルの中身を画面に表示する

(TYPE)転送されたプログラムの内容が正しいか、テキストとして画面に表示して確認します。basic TYPE "try.bas"

3. プログラムをメモリに読み込んで実行する 

(LOAD RUN)ファイルをメモリにロードして実行します。basic LOAD "try.bas" RUN

4.プログラムをメモリからセーブしてマイコンでfilesできるようにする

(SAVE) basic SAVE "filename.bas"

5.プログラムをその場で編集・確認する

(EDIT)PicoMite内蔵のフルスクリーンエディタでファイルを開きます。basic EDIT "try.bas"

F1 キー(またはCtrl+Q)を押すとメニューが出るので、保存して終了、または保存せずに終了を選べます。

6.メモリ上のプログラムを消去するにはbasic new,

フラッシュ上のプログラムを消去するにはbasic kill  "filename.bas"

----------------------------------------------------------------------------



mmbasic pcのファイルをraspicoとやりとりしたい!!

 sudo picocom -b 115200 --omap delbs /dev/ttyACM0と,もう一つxterminalを立ち上げる

1. MMBasic 側で受信待機にする

MMBasic のプロンプトで以下のいずれかを実行します(保存先に応じて選んでください)。
  • プログラムメモリ(RAM)に直接読み込む場合:
    basic
    XMODEM RECEIVE
    
    コードは注意してご使用ください。
  • SDカードやフラッシュ内のファイルとして保存する場合:
    basic
    XMODEM RECEIVE "foo.bas"
    
    コードは注意してご使用ください。
2. Linux(PC)側から XMODEM で送信する
使用しているシリアル通信環境に合わせて、sx コマンドを使ってファイルを送信します。 [1, 2]
GNU screen を使用している場合:
シリアルセッション中に Ctrl+A を押した後、:exec !! sx foo.bas と入力するか、一度端末をバックグラウンドにして以下のようにリダイレクトします。 [1]
bash
sx foo.bas < /dev/ttyACM0 > /dev/ttyACM0
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
まずエディタからもどってRAM内容をsave "foo.bas"とする
成功しているかfilesで確認する
1. MMBasic(マイコン)側で送信コマンドを実行する
MMBasicのプロンプトで、送信したいファイル名を指定して XMODEM SEND(または省略形の XMODEM S)を実行します。 [1, 2]
  • SDカードやフラッシュ内のファイルを送信する場合:
    basic
    XMODEM SEND "foo.bas"
    
    コードは注意してご使用ください。
  • 現在メモリ(RAM)にあるプログラムをそのまま送信する場合:
    basic
    XMODEM SEND
    
    コードは注意してご使用ください。
コマンドを実行すると、マイコンはPC側からの受信開始合図(NAK文字など)を待つ状態(待機状態)になります。 [1, 2]
2. PC(Linux)側で XMODEM 受信を実行する
マイコンが待機状態になったら、60秒以内にPC側で受信コマンドを実行してください。Linuxでは rx コマンド(XMODEM受信ツール)を使用します。 [1]
一般的なシリアルポート(例: /dev/ttyACM0)で直接やり取りする場合:
端末(ターミナル)を開き、以下のコマンドを実行してファイルを受け取ります。
bash
rx foo.bas < /dev/ttyACM0 > /dev/ttyACM0
コードは注意してご使用ください。