I2C温度センサーで室温計測

もう一回だけ 続最終回

C++ Builder CEで作ったGUIなアプリケーションが作成できるのを確認してほんとの最終回としますね。一つ前のコマンドラインプログラムをベースにVCLなアプリケーションを作ります。ま、手順を間違えなければ動くはずですね。前の記事は、


適当

でした。ここで作ったインポートライブラリを使います。32bit版と64bit版の両方使います。また、実行時にはlibmpsse.dllが必要ですが、32bit版も64bit版も同名で同じディレクトリには置けませんから、混同しないように注意が必要です。さて、起動してスタートボタンを押すと、

で、ストップボタン押すと、

となります、Memo1の空白部分で右クリックすると、上のようなメニューが出ますから、必要に応じて行を選択して、コピーするなりが可能です。ただコンソールに流れるより柔軟に扱えますよね。さて、まずは、Unit1.hから、

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TMemo *Memo1;
	TButton *Stop;
	TButton *Start;
	void __fastcall StopClick(TObject *Sender);
	void __fastcall StartClick(TObject *Sender);
	void __fastcall FormDestroy(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Unit1.cppは、

#include <vcl.h>
#pragma hdrstop
#include "ftd2xx.h"
#include "libMPSSE_i2c.h"

#define ADT7410_ADDRESS 0x48  // 7ビットI2Cアドレス (libmpsse内部で自動シフトされます)

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

bool looping = true;
	FT_HANDLE ftHandle;
	FT_STATUS status;
		DWORD bytesTransferred;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{

	ChannelConfig channelConf;
    //uint32_t channels;
    DWORD channels;
	uint8_t buffer[4];


	Memo1->Lines->Clear();

    // 1. libmpsse の初期化
    Init_libMPSSE();

    status = I2C_GetNumChannels(&channels);
    if (status != FT_OK || channels == 0) {
        ShowMessage("エラー: 利用可能なFTDIデバイスが見つかりません。\n");
		//return -1;
    }

    // 2. 最初のチャンネル(0)を開く
    status = I2C_OpenChannel(0, &ftHandle);
    if (status != FT_OK) {
        ShowMessage("エラー: チャンネルを開けませんでした。\n");
		//return -1;
    }

    // 3. I2C通信速度などの設定 (400kHzに設定)
    channelConf.ClockRate = I2C_CLOCK_STANDARD_MODE; // もしくは 400000 (FAST_MODE)
    channelConf.LatencyTimer = 255;
    channelConf.Options = 0x03;
    status = I2C_InitChannel(ftHandle, &channelConf);
    if (status != FT_OK) {
        ShowMessage("エラー: チャンネル初期化失敗。\n");
        I2C_CloseChannel(ftHandle);
		//return -1;
    }

    // 4. ADT7410 を 16ビット分解能モードに設定する (レジスタ 0x03 に 0x80 を書き込み)
    buffer[0] = 0x03; // 設定レジスタアドレス
    buffer[1] = 0x80; // 16bit mode bit (Bit7 = 1)
    status = I2C_DeviceWrite(ftHandle, ADT7410_ADDRESS, 2, buffer, &bytesTransferred,
                             I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);
    if (status != FT_OK) {
        ShowMessage("警告: 16bitモードへの設定に失敗しました。デフォルトの13bitで動作します。\n");
    }


}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopClick(TObject *Sender)
{
	looping = false;

}
//---------------------------------------------------------------------------
void __fastcall TForm1::StartClick(TObject *Sender)
{
	looping = true;
	uint8_t buffer[4];
	Memo1->Lines->Add("ADT7410 から温度データの読み込みを開始します...\n");

	while (looping ) {
		// 5. ポインタレジスタを 0x00 (温度データ) に指定する
		buffer[0] = 0x00;
		I2C_DeviceWrite(ftHandle, ADT7410_ADDRESS, 1, buffer, &bytesTransferred,
						 I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);

		// 6. 温度データ (2バイト) を読み出す
		// ※libmpsseのI2C_DeviceReadは内部で「スタート -> リード -> ストップ」の一連を処理
		status = I2C_DeviceRead(ftHandle, ADT7410_ADDRESS, 2, buffer, &bytesTransferred,
								I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT);

		if (status == FT_OK && bytesTransferred == 2) {
			// 上位・下位バイトを16ビット値に結合
			int16_t raw_temp = (int16_t)((buffer[0] << 8) | buffer[1]);
			double temperature = 0.0;

			// 16ビット分解能の場合の計算方法
			// 最上位ビット(MSB)は符号ビット、1 LSB = 0.0078度
			temperature = (double)raw_temp / 128.0;

			/*
			int16_t raw_temp = (int16_t)((buffer[0] << 8) | buffer[1]);
			double temperature = 0.0;
			// ※もし13ビットモード(デフォルト)のままで読み出す場合の計算方法はこちら
			raw_temp = raw_temp >> 3; // 下位3ビットはフラグ等のためシフト
			if (raw_temp & 0x1000) {  // 13ビットの符号判定
				raw_temp -= 8192;
			}
			temperature = (double)raw_temp * 0.0625;
			*/


			//ShowMessage("現在の温度: %.4f ℃\n" + FloatToStr(temperature));

			Memo1->Lines->Add("現在の温度: " + FloatToStr(temperature) + "°C");
			Application->ProcessMessages();

		} else {
			ShowMessage("データ読み込みエラー\n");
		}

        #ifdef _WIN32
		Sleep(1000); // 1秒待機
		#else
		sleep(1);
		#endif
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   // 7. クローズ処理
    I2C_CloseChannel(ftHandle);
    Cleanup_libMPSSE();
	//return 0;
}
//---------------------------------------------------------------------------
Memo1->Lines->Add("現在の温度: " + FloatToStr(temperature) + "°C");
Application->ProcessMessages();

上記のようにしないと、ストップボタン拾えません。32bit版と64bit版両対応のプロジェクトなので、プロジェクト関係は、

上図は64bit Debug版の場合です。あー、別の温湿度センサーsht41のことも書くかなあ?とりあえずADT7410は一旦おしまいにします。

コメント