« Raspberry piでC#を使ってIoT | トップページ | Raspberry piでLazarus1.7+FPC3.0 »

2017.02.16

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上で見つけた解決策です)。

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での主な処理は以下の通りです。

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;

|

« Raspberry piでC#を使ってIoT | トップページ | Raspberry piでLazarus1.7+FPC3.0 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: Raspberry piでLazarusを使ってIoT:

« Raspberry piでC#を使ってIoT | トップページ | Raspberry piでLazarus1.7+FPC3.0 »