2021年3月18日木曜日

Lazarus IOT

 http://m-and-i.cocolog-nifty.com/freetalk/2017/02/raspberry-pilaz.html 参照

Raspberry piでLazarusを使ってIoT

Raspberry pi/RaspbianでのC#/mono実行環境ではデータ入力と送信のサイクル限界が200ms程度とあまりよろしくありませんでした。Raspbian上のmonoが遅いのか、MCP3208アクセスライブラリが遅いのか原因はよくわかりこれはませんが、何とか処理スピードを上げられないかと、ネイティブコンパイラであるLazarusを使用してみました。
ADコンバータMCP3208用のライブラリは、トランジスタ技術のダウンロードサービスから2014年7月号の「特集 第6章 HDMIテレビにグラフ表示! 8チャネル・ロング・メモリ・データ・ロガー」をダウンロードして、この中のspi_mcp3208.pasを使用させていただきました。
また、MQTTライブラリにはmqtt-free-pascal-masterを使用しています。

尚、そのままではLaspbian上でコンパイルした実行ファイルがMQTTに接続する時点で、Semaphore init failed (possibly too many concurrent threads)エラーが出て停止してしまうため、プロジェクトソースに以下の変更を加えています(Web上で見つけた解決策です)。

1
2
3
4
5
6
7
8
9
10
program publish;
  
{$mode objfpc}{$H+}
  
uses
  {$DEFINE UseCThreads} ←この一行を追加
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}

Lazarusで作成したアプリケーションでは、データ入力と送信のサイクル限界が30msまで上がりました。この性能が出ると、50msサイクル程度までは安定した出力が保証できそうです。8チャンネル分の入力データをいちいちフォーム上に表示させていてこのスピードですから、さすがはネイティブコンパイラといった感じでしょうか。入力データの表示を行わなければ、もっとスピードが上がるかもしれません。

Delphi使いの私としては、Lazarusは言語仕様がDelphi互換でフォームデザインも同じ感覚で行うことが出来るので、使っていてまったく違和感がありません。また、LazarusはWindows上でも使用できるためフォームデザインから基本的なプログラミングまでをWindows上で行ってRaspbian上にプロジェクトをコピーして仕上げることが出来ます。Visual Studio/C#ではWindows上で作成した実行ファイルがRaspbian/mono上でそのまま動くという利点はありますが、GPIO処理などのRaspberry pi依存部分のデバッグは遅くて貧弱なRaspbian上のMonoDevelopで行う必要がありますので、Lazarusの方が優位と行った感じでしょうか。

Rasplaz

Lazarus/Raspbianでの主な処理は以下の通りです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
unit Unit1;
  
{$mode objfpc}{$H+}
  
interface
  
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, Spin, DateUtils, IniFiles, MQTT, spi_mcp3208;
  
// スタート
procedure TForm1.StartBtnClick(Sender: TObject);
var
  URL: string;
  i: integer;
begin
  Topic := PTopic.Text;
  URL := BURL.Text;
  MQTTClient := TMQTTClient.Create(URL, 1883);
  MQTTClient.Connect;
  Sleep(500);
  if MQTTClient.isConnected then
  begin
    IdleTimer1.Interval := Interval.Value;
    IdleTimer1.Enabled:= True;
    StopBtn.Enabled:= True;
    StartBtn.Enabled:= False;
    BURL.Enabled := False;
    PTopic.Enabled:= False;
    for i := 1 to 8 do
      CB[i].Enabled:= False;
    Pdt := 0;
  end else begin
    MQTTClient.ForceDisconnect;
    MQTTClient.Free;
    MessageDlg('MQTT connection was failed.', mtError, [mbOK], 0);
  end;
end;
  
// データ入力・Publish処理
procedure TForm1.IdleTimer1Timer(Sender: TObject);
var
  InData: array[0..7] of single;
  i, tgap: integer;
  tdt: TDateTime;
  pub, tmp: ansistring;
begin
  // 出力フォーマット
  // YYYY/MM/DD h:min:sec.msec, interval, data1, data2, .... ,data8
  // intervalは前回データ取得から今回までの間の時間(msec)
  tdt := Now;
  if Pdt > 0 then
    tgap := MilliSecondsBetween(Pdt, tdt) //前回から今回までの時間をmsecで取得
  else
    tgap := 0;
  Pdt := tdt;
  DateTimeToString(pub, 'yyyy/mm/dd hh:nn:ss.z', tdt);
  tmp := IntToStr(tgap);
  pub := pub + ',' + tmp;
  ADC8.Read(InData);
  for i:= 1 to 8 do
  begin
    if CB[i].Checked then
    begin
      tmp := FloatToStr(InData[i-1]);
      if MonitorStat.Checked then
        DT[i].Text:= tmp;
      pub := pub + ',' + tmp;
    end else
      pub := pub + ',';
    end;
  MQTTClient.Publish(Topic, pub);
end;

2021年3月14日日曜日

Raspberry pi VNCなど・・解像度変更

 

画面の解像度を変更する

raspi-configで解像度を上げることができます。

sudo raspi-config


むかしは、Advanced の項目だった。Raspi OSになってからか(いつの時点か??)、Display--resolusionの項目に含まれるようになったようだ。

2021年3月12日金曜日

動画 mjpeg

 

参照

https://qiita.com/MuAuan/items/b3abd4cff2f39aa1f2d0

MJPG-streamer

参考サイトのとおり、インストールすると動く。
【参考】
・第8回: MJPG-streamerのインストール
・Raspberry Pi でWebカメラ (4) M-JPEG streamerをつかったストリーミング配信
・Raspberry Piでwebカメラの映像を配信する方法(MJPG-streamer編)

枝葉は異なるが、参考サイトは全て同じ手順で実施しているので、以下で動く。
ポイントはどこにインストールしたいかをあらかじめ決めて、Dirを作成しておくことです。

$ cd ~
$ mkdir mjpg-streamer
$ cd mjpg-streamer

その後、以下のコマンドを実行してください。

svn ではなく git clone https://github.com/jacksonliam/mjpg-streamer.git  だな。sourceforgは終了したので、下のsvnでははねられた。2022.6.24


sudo apt-get install cmake libjpeg9-dev
sudo apt-get install gcc g++ も最新のRasPiOSならいらないはず。これは飛ばして次に。
git clone https://github.com/jacksonliam/mjpg-streamer.git 
cd mjpg-streamer-experimental
make
sudo make install
$ sudo apt-get install subversion libjpeg-dev imagemagick
$ svn co https://mjpg-streamer.svn.sourceforge.net/svnroot/mjpg-streamer mjpg-streamer
$ cd mjpg-streamer/mjpg-streamer
$ make
$ sudo install
start_server.sh
#!/bin/sh

PORT="8080" #ポート番号
ID="xxxx" #IDは好きなもの
PW="xxxxxxxx" #パスワード
SIZE="640x480" #画面サイズ
FRAMERATE="20" #フレームレート
export LD_LIBRARY_PATH=/usr/local/lib
./mjpg_streamer \
    -i "input_uvc.so -f $FRAMERATE -r $SIZE -d /dev/video0 -y -n" \
    -o "output_http.so -w /usr/local/www -p $PORT -c $ID:$PW"

$ sh start_server.shを実行すると、RasPiのコンソールは以下のような表示が表れます。

$ sh start_server.sh
MJPG Streamer Version: svn rev: 3:172
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 20
 i: Format............: YUV
 i: JPEG Quality......: 80
 o: www-folder-path...: /usr/local/www/
 o: HTTP TCP port.....: 8080
 o: username:password.: xxxx:xxxxxxxx
 o: commands..........: enabled

そして、ブラウザから
http://xxx.xxx.xxx.xxx:8080
にアクセスし、usernameとpasswordを入力すると以下の画像が表れます。




Ras Pi 4では次のものがエラーなしだった



https://github.com/cncjs/cncjs/wiki/Setup-Guide:-Raspberry-Pi-%7C-MJPEG-Streamer-Install-&-Setup-&-FFMpeg-Recording

MJPEG-Streamer Install & Setup

# Update & Install Tools
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install build-essential git imagemagick libv4l-dev libjpeg-dev cmake -y

# Clone Repo in /tmp
cd /tmp
git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental

# Make
make
sudo make install

# Run
/usr/local/bin/mjpg_streamer -i "input_uvc.so -r 1280x720 -d /dev/video0 -f 30" -o "output_http.so -p 8080 -w /usr/local/share/mjpg-streamer/www"

MJPEG-Streamer Auto Start

Manager Script

nano /home/pi/mjpg-streamer.sh

Add the below code to ( /home/pi/mjpg-streamer.sh )

#!/bin/bash
# chmod +x mjpg-streamer.sh
# Crontab: @reboot /home/pi/mjpg-streamer/mjpg-streamer.sh start
# Crontab: @reboot /home/pi/mjpg-streamer/mjpg-streamer-experimental/mjpg-streamer.sh start

MJPG_STREAMER_BIN="/usr/local/bin/mjpg_streamer"  # "$(dirname $0)/mjpg_streamer"
MJPG_STREAMER_WWW="/usr/local/share/mjpg-streamer/www"
MJPG_STREAMER_LOG_FILE="${0%.*}.log"  # "$(dirname $0)/mjpg-streamer.log"
RUNNING_CHECK_INTERVAL="2" # how often to check to make sure the server is running (in seconds)
HANGING_CHECK_INTERVAL="3" # how often to check to make sure the server is not hanging (in seconds)

VIDEO_DEV="/dev/video0"
FRAME_RATE="5"
QUALITY="80"
RESOLUTION="1280x720"  # 160x120 176x144 320x240 352x288 424x240 432x240 640x360 640x480 800x448 800x600 960x544 1280x720 1920x1080 (QVGA, VGA, SVGA, WXGA)   #  lsusb -s 001:006 -v | egrep "Width|Height" # https://www.textfixer.com/tools/alphabetical-order.php  # v4l2-ctl --list-formats-ext  # Show Supported Video Formates
PORT="8081"
YUV="yes"

################INPUT_OPTIONS="-r ${RESOLUTION} -d ${VIDEO_DEV} -f ${FRAME_RATE} -q ${QUALITY} -pl 60hz"
INPUT_OPTIONS="-r ${RESOLUTION} -d ${VIDEO_DEV} -q ${QUALITY} -pl 60hz --every_frame 2"  # Limit Framerate with  "--every_frame ", ( mjpg_streamer --input "input_uvc.so --help" )


if [ "${YUV}" == "true" ]; then
	INPUT_OPTIONS+=" -y"
fi

OUTPUT_OPTIONS="-p ${PORT} -w ${MJPG_STREAMER_WWW}"

# ==========================================================
function running() {
    if ps aux | grep ${MJPG_STREAMER_BIN} | grep ${VIDEO_DEV} >/dev/null 2>&1; then
        return 0

    else
        return 1

    fi
}

function start() {
    if running; then
        echo "[$VIDEO_DEV] already started"
        return 1
    fi

    export LD_LIBRARY_PATH="$(dirname $MJPG_STREAMER_BIN):."

	echo "Starting: [$VIDEO_DEV] ${MJPG_STREAMER_BIN} -i \"input_uvc.so ${INPUT_OPTIONS}\" -o \"output_http.so ${OUTPUT_OPTIONS}\""
    ${MJPG_STREAMER_BIN} -i "input_uvc.so ${INPUT_OPTIONS}" -o "output_http.so ${OUTPUT_OPTIONS}" >> ${MJPG_STREAMER_LOG_FILE} 2>&1 &

    sleep 1

    if running; then
        if [ "$1" != "nocheck" ]; then
            check_running & > /dev/null 2>&1 # start the running checking task
            check_hanging & > /dev/null 2>&1 # start the hanging checking task
        fi

        echo "[$VIDEO_DEV] started"
        return 0

    else
        echo "[$VIDEO_DEV] failed to start"
        return 1

    fi
}

function stop() {
    if ! running; then
        echo "[$VIDEO_DEV] not running"
        return 1
    fi

    own_pid=$$

    if [ "$1" != "nocheck" ]; then
        # stop the script running check task
        ps aux | grep $0 | grep start | tr -s ' ' | cut -d ' ' -f 2 | grep -v ${own_pid} | xargs -r kill
        sleep 0.5
    fi

    # stop the server
    ps aux | grep ${MJPG_STREAMER_BIN} | grep ${VIDEO_DEV} | tr -s ' ' | cut -d ' ' -f 2 | grep -v ${own_pid} | xargs -r kill

    echo "[$VIDEO_DEV] stopped"
    return 0
}

function check_running() {
    echo "[$VIDEO_DEV] starting running check task" >> ${MJPG_STREAMER_LOG_FILE}

    while true; do
        sleep ${RUNNING_CHECK_INTERVAL}

        if ! running; then
            echo "[$VIDEO_DEV] server stopped, starting" >> ${MJPG_STREAMER_LOG_FILE}
            start nocheck
        fi
    done
}

function check_hanging() {
    echo "[$VIDEO_DEV] starting hanging check task" >> ${MJPG_STREAMER_LOG_FILE}

    while true; do
        sleep ${HANGING_CHECK_INTERVAL}

        # treat the "error grabbing frames" case
        if tail -n2 ${MJPG_STREAMER_LOG_FILE} | grep -i "error grabbing frames" > /dev/null; then
            echo "[$VIDEO_DEV] server is hanging, killing" >> ${MJPG_STREAMER_LOG_FILE}
            stop nocheck
        fi
    done
}

function help() {
    echo "Usage: $0 [start|stop|restart|status]"
    return 0
}

if [ "$1" == "start" ]; then
    start && exit 0 || exit -1

elif [ "$1" == "stop" ]; then
    stop && exit 0 || exit -1

elif [ "$1" == "restart" ]; then
    stop && sleep 1
    start && exit 0 || exit -1

elif [ "$1" == "status" ]; then
    if running; then
        echo "[$VIDEO_DEV] running"
        exit 0

    else
        echo "[$VIDEO_DEV] stopped"
        exit 1

    fi

else
    help

fi

Start on Boot

# Make Executable
chmod +x /home/pi/mjpg-streamer.sh

# Open Cron Job
crontab -e

# Add line
@reboot /home/pi/mjpg-streamer.sh start

FFMpeg Compile, Install, & Setup

http://www.jeffreythompson.org/blog/2014/11/13/installing-ffmpeg-for-raspberry-pi/

# Install FFMpeg from Package Manager
sudo apt-get update  
sudo apt-get install ffmpeg -y

---- OR ------

# COMPILE & INSTALL FFMPEG
# Run as Sudo
sudo -i

# INSTALL H264 SUPPORT
cd /usr/src
git clone https://code.videolan.org/videolan/x264.git
cd x264
./configure --host=arm-unknown-linux-gnueabi --enable-static --disable-opencl
make
sudo make install

# COMPILE & INSTALL FFMPEG (This may take a REALLY long time, so be patient.)
cd /usr/src
git clone https://github.com/FFmpeg/FFmpeg.git
cd FFmpeg
sudo ./configure --arch=armel --target-os=linux --enable-gpl --enable-libx264 --enable-nonfree
make
sudo make install

Recored Stream w/ ffmpeg

# [Varables]
source_stram="http://localhost:8080/?action=stream"
destination_directory="/home/pi/Videos"
destination_file="cncjs-recording_$(date +'%Y%m%d_%H%M%S').mpeg"

# Recored Stream w/ ffmpeg
ffmpeg -f mjpeg -re -i "${source_stream}" -q:v 10 "${destination_directory}/${destination_file}"



2021年3月11日木曜日