DLPIO20 デバイスの DS18B20+ センサーからのリアルタイム温度データの読み取りに問題があります。Windows プラットフォームで FTD2XX.DLL .NET ラッパー (バージョン 1.0.14) を使用しています (リンク: http://www.ftdichip.com/Support/SoftwareExamples/CodeExamples/CSharp/FTD2XX_NET_v1.0.14.zip ) 。 .
問題を実証するためのアプリケーションのテストは以下のとおりです。
これが私がリアルタイムで意味するものです。
2.1 ほぼ一定の周囲温度 (20° C としましょう) では、デバッグ モードで一貫した結果を確認するための温度読み取りはほとんどありません (ライン 55 の温度読み取りサイクルの最後のブレーク ポイント)。
2.2.次に、ブレークポイントで、センサーに息を吹き込むか、他の手段を使用して周囲温度より数度加熱します。
2.3. さらに 2 ~ 3 サイクルの温度読み取りを実行します。
センサーが加熱された後の最初の読み取りは、20°C の「古い」温度です。2 回目または 3 回目の読み取りサイクルでのみ、28°C 付近で現実的な結果が得られます。
興味深いことに、テスト アプリケーション プログラム IO20Demo (DLP-IO20 ボードの購入に付属) を使用して、読み取り前に Convert コマンドを発行すると、すぐに 28° C のリアルタイムの結果が得られます。このプログラムとマネージ .NET ラッパー クラスを使用して、Read の前に Convert コマンドも送信しましたが、役に立ちませんでした。大きな違いは、IO20Demo はマネージ ラッパー クラスを使用せず、FTD2XX.lib を直接使用することです。
ここで私が間違っていることを理解するのを手伝ってもらえますか? マネージド .NET ラッパー クラスを使用してリアルタイムの温度データを取得するにはどうすればよいですか?
あなたの助けは大歓迎です!
/// <summary>
/// Program for DLPIO20 device to read temperature data from DS18B20+
/// digital temperature sensor attached to one of its channels.
/// </summary>
class Program
{
static void Main(string[] args)
{
FTDI FtdiWrapper = null;
// DLPIO20 channel where the DS18B20+ sensor is attached
byte sensorChannel = 0x06;
try
{
// create new instance of the FTDI device class
FtdiWrapper = ConnectToFirstFtdiDevice();
if (FtdiWrapper == null || !FtdiWrapper.IsOpen)
{
throw new Exception("Error connection to FTDI device.");
}
// didn't helped at all for 85dC issue
//PurgeRxBuffer(FtdiWrapper);
// helped avoid 85dC issue at first read
ConvertSensorData(FtdiWrapper, sensorChannel);
// send read sensor command
float? degreesC = null;
for (int i = 0; i < 100; i++)
{
// calling Convert just before ReadTemperatureSensor causes
// IO20Demo (using FTD2XX.lib) to return real temperature
// but it doesn't help when using .NET wrapper
ConvertSensorData(FtdiWrapper, sensorChannel);
// other failed attempts to get real time sensor data
// previous value returned:
//PurgeRxBuffer(FtdiWrapper);
// read but only initiate conversion on success
degreesC = ReadTemperatureSensor(FtdiWrapper, sensorChannel);
if (degreesC == null)
{
throw new Exception("Error converting raw data to Celsius");
}
var message = string.Format("Success! {0}° Celsius.", degreesC);
Console.WriteLine(message);
}
Console.WriteLine("Press any key to exit ...");
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.WriteLine("Press any key to exit ...");
Console.ReadKey();
}
finally
{
if (FtdiWrapper != null && FtdiWrapper.IsOpen)
{
FtdiWrapper.Close();
}
}
}
これは、最初の FTDI デバイスへの接続に使用されるコードです
static private FTDI ConnectToFirstFtdiDevice()
{
FTDI FtdiWrapper = new FTDI();
UInt32 ftdiDeviceCount = 0;
FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
// Determine the number of FTDI devices connected to the machine
ftStatus = FtdiWrapper.GetNumberOfDevices(ref ftdiDeviceCount);
// Check status
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception(string.Format("Error after GetNumberOfDevices(), ftStatus: {0}", ftStatus));
if (ftdiDeviceCount == 0)
throw new Exception("No FTDI device found");
// Allocate storage for device info list
var ftdiDeviceList = new FTDI.FT_DEVICE_INFO_NODE[ftdiDeviceCount];
// Populate our device list
ftStatus = FtdiWrapper.GetDeviceList(ftdiDeviceList);
if (ftStatus == FTDI.FT_STATUS.FT_OK)
{
// Open first device in our list by serial number
ftStatus = FtdiWrapper.OpenBySerialNumber(ftdiDeviceList[0].SerialNumber);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception(string.Format("Error opening first device, ftStatus: {0}", ftStatus));
ftStatus = FtdiWrapper.SetBaudRate(9600);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception(string.Format("Error to set Baud rate, ftStatus: {0}", ftStatus));
// Set data characteristics - Data bits, Stop bits, Parity
ftStatus = FtdiWrapper.SetDataCharacteristics(FTDI.FT_DATA_BITS.FT_BITS_8, FTDI.FT_STOP_BITS.FT_STOP_BITS_1, FTDI.FT_PARITY.FT_PARITY_NONE);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception(string.Format("Error to set data characteristics , ftStatus: {0}", ftStatus));
// Set flow control - set RTS/CTS flow control
ftStatus = FtdiWrapper.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11, 0x13);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception(string.Format("Error to set flow control , ftStatus: {0}", ftStatus));
// Set read timeout to 5 seconds, write timeout to infinite
ftStatus = FtdiWrapper.SetTimeouts(5000, 0);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception(string.Format("Error to set timeouts, ftStatus: {0}", ftStatus));
}
return FtdiWrapper;
}
生のセンサーデータを変換する方法
static private void ConvertSensorData(FTDI FtdiWrapper, byte sensorChannel)
{
FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
UInt32 numBytesWritten = 0;
byte[] convertCommand = new byte[] { 0x03, 0x40, sensorChannel };
ftStatus = FtdiWrapper.Write(convertCommand, convertCommand.Length, ref numBytesWritten);
bool isAllBytesWritten = numBytesWritten == convertCommand.Length;
if (ftStatus != FTDI.FT_STATUS.FT_OK && isAllBytesWritten)
throw new Exception(string.Format("Failed to write Convert command to device; Status: {0}, isAllBytesWritten: {1}", ftStatus.ToString(), isAllBytesWritten));
}
センサー温度の読み取り方法
static private float? ReadTemperatureSensor(FTDI FtdiWrapper, byte sensorChannel)
{
float? degreesC = null;
FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
UInt32 numBytesWritten = 0;
byte[] readSensorCommand = new byte[] { 0x03, 0x41, sensorChannel };
ftStatus = FtdiWrapper.Write(readSensorCommand, readSensorCommand.Length, ref numBytesWritten);
bool isAllBytesWritten = numBytesWritten == readSensorCommand.Length;
if (ftStatus != FTDI.FT_STATUS.FT_OK && isAllBytesWritten)
throw new Exception(string.Format("Failed to write readSensorCommand to device; Status: {0}, isAllBytesWritten: {1}", ftStatus.ToString(), isAllBytesWritten));
// Read back response
UInt32 numBytesAvailable = 0;
UInt32 numBytesExpected = 2; // read sensor command expected to return 2 bytes
while (numBytesAvailable == 0)
{
Thread.Sleep(40); // value of 40 taken from DLP IO20 demo solution
ftStatus = FtdiWrapper.GetRxBytesAvailable(ref numBytesAvailable);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception("Failed to get number of bytes available to read; error: " + ftStatus);
} //while (numBytesAvailable < numBytesExpected);
if (numBytesAvailable != numBytesExpected)
throw new Exception("Error: Invalid data in buffer. (1350)");
UInt32 numBytesRead = 0;
byte[] rawData = new byte[numBytesExpected];
ftStatus = FtdiWrapper.Read(rawData, numBytesAvailable, ref numBytesRead);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception("Failed to read data from device after command has been sent; error: " + ftStatus);
//convert raw response data to degrees Celsius
degreesC = ConvertTemperature(rawData);
return degreesC;
}
送信バッファをパージする方法
static private void PurgeRxBuffer(FTDI FtdiWrapper)
{
UInt32 numBytesAvailable = 0;
UInt32 numBytesRead = 0;
FTDI.FT_STATUS ftStatus = FTDI.FT_STATUS.FT_OTHER_ERROR;
byte[] rx = new byte[1001]; //allocate large enough space to read from device
Thread.Sleep(5);
ftStatus = FtdiWrapper.GetRxBytesAvailable(ref numBytesAvailable);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception("Failed to get number of bytes available to read; error: " + ftStatus);
if (numBytesAvailable > 1000)
numBytesAvailable = 1000;
while (numBytesAvailable > 0)
{
//read the data from the buffer
numBytesRead = 0;
ftStatus = FtdiWrapper.Read(rx, numBytesAvailable, ref numBytesRead);
ftStatus = FtdiWrapper.GetRxBytesAvailable(ref numBytesAvailable);
if (ftStatus != FTDI.FT_STATUS.FT_OK)
throw new Exception("Failed to get number of bytes available to read; error: " + ftStatus);
if (numBytesAvailable > 1000)
numBytesAvailable = 1000;
Thread.Sleep(5);
}
}
生データから温度を摂氏に変換する方法
static private float? ConvertTemperature(byte[] rawData)
{
float? tempCelsius = null;
bool isnegative = false;
//check input
if (rawData.Length < 2)
throw new Exception(string.Format("Input parameter rawData for temperature conversion must be 2 bytes, actual length is: {0}", rawData.Length));
int temp = rawData[0] | (rawData[1] << 8);
if ((temp & 0x8000) == 0x8000)//if MSBit is set then negative temperature
{
temp &= 0x07ff;
isnegative = true;
temp = 0x800 - temp;
}
temp &= 0x07ff;
tempCelsius = (float)((float)temp / 16.0);
if (isnegative) tempCelsius *= -1;
return tempCelsius;
}
}