在 Windows 10 上扫描地址 Raspberry Pi 3 上的 IOT 需要 30 秒
Scanning Addresses on Windows 10 IOT on Raspberry Pi 3 takes 30 Seconds
I2C 扫描地址
我一直在尝试扫描使用 I2C 时存在的 Raspberry Pi3 端口上的地址 1-128。请注意,我们有 1 GB RAM,并且我们的软件总是将其最大化,尤其是在此过程中(实际上,它大约是 900K,真的)。
平台
我们的操作系统:Windows 10 Iot Core Build 17744。
Atlas Scientific 具有用于 pH、CO2、温度、电导率和 Oxidation/reduction 电位 (ORP) 的传感器。
https://www.atlas-scientific.com/product_pages/circuits/ezo_orp.html
假设我们正在使用 Whitebox 的 Labs Tentacle 3(我们是)来托管 3 个电路和传感器及其相关传感器。
https://www.atlas-scientific.com/product_pages/components/tentacle-t3.html
遍历 1-128 需要 35 秒,这是 不允许的。 此外,Python 在 Raspian 上不允许花尽可能长的时间。 (我现在要验证这一点)。
我们的尝试
1)我注意到扫描循环处于静态 class。我认为 "using" 会确保垃圾收集会清除这种情况。它没有。
1a) 我在没有 "using" 的情况下重写了它,但是 Dispose。结果相同;
2) 接下来我尝试了 IOT Lightning DMAP 驱动程序。
https://docs.microsoft.com/en-us/windows/iot-core/develop-your-app/lightningproviders
这对时间也没有影响。
欧比旺克诺比帮帮我,你是我唯一的希望
我已将其交叉发布到 Windows 10 IOT 支持委员会。
是时候尝试 C++ 了吗?
备注
我刚刚试过了,但是好像也不管用
GetDeviceSelector()..
https://www.hackster.io/porrey/discover-i2c-devices-on-the-raspberry-pi-84bc8b
代码
FindDevicesAsync 有两个版本(一个有 Lightning DMAP,一个没有)
using IOT_Sensors;
using MetroLog;
using SQLite.Net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.I2c;
using Windows.Devices;
using Microsoft.IoT.Lightning.Providers;
using Windows.UI.Xaml;
namespace atlas_iot
{
public class SensorFinder
{
public async static Task<IEnumerable<byte>> StaticExample()
{
SensorFinder sf = new SensorFinder();
return await sf.FindDevicesAsync();
}
//the process for searching for sensors could not be garbage collected in a static class
// we are going to return a static List of addresses (bytes). ModuleStore.I2CsystemInit() will give them type
public async Task<IEnumerable<byte>> FindDevicesAsync() //speed this up please!
{
if (LightningProvider.IsLightningEnabled)
{
// Set Lightning as the default provider
LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
}
IList<byte> addresses = new List<byte>();
I2cController controller = await I2cController.GetDefaultAsync();
// const int minimumAddress = 97;
const int minimumAddress =10;
// The Min and Max may need to be adjusted depending on what ID #'s you haveon the EZO circuit.
//const int maximumAddress = 104;
const int maximumAddress = 105;
//const int maximumAddress = 103;
for (byte address = minimumAddress; address <= maximumAddress; address++)
{
// Debug.WriteLine("checking address " + address);
var settings = new I2cConnectionSettings(address)
{
BusSpeed = I2cBusSpeed.FastMode,
SharingMode = I2cSharingMode.Shared
};
I2cDevice device = controller.GetDevice(settings);
if (device != null)
{
try
{
byte[] writeBuffer = new byte[1] { 0 };
device.Write(writeBuffer);
addresses.Add(address);
Debug.WriteLine("Added Address: " + address);
}
catch (FileNotFoundException ex)
{
//Do Nothing
}
catch (Exception ex)
{
Debug.WriteLine("Address {0} not found ", address);
string msg = ex.Message;
//swallow exception
}
}
else
{
Debug.WriteLine("device DOES equal null!", address);
//Do Nothing
}
device.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
}
//byte address2 = 105;
//addresses.Add(address2);
//addresses.Add(maximumAddress + 1); //Adding an extra for Config Button
return addresses;
}
//Maybe use a Hashtable or dictionary instead?ny
//public async Task<IEnumerable<byte>> FindDevicesAsync() //speed this up please!
//{
// IList<byte> addresses = new List<byte>();
// I2cController controller = await I2cController.GetDefaultAsync();
// // const int minimumAddress = 97;
// const int minimumAddress = 1;
// // The Min and Max may need to be adjusted depending on what ID #'s you haveon the EZO circuit.
// //const int maximumAddress = 104;
// const int maximumAddress = 105;
// //const int maximumAddress = 103;
// for (byte address = minimumAddress; address <= maximumAddress; address++)
// {
// // Debug.WriteLine("checking address " + address);
// var settings = new I2cConnectionSettings(address)
// {
// BusSpeed = I2cBusSpeed.FastMode,
// SharingMode = I2cSharingMode.Shared
// };
// using (I2cDevice device = controller.GetDevice(settings))
// {
// if (device != null)
// {
// try
// {
// byte[] writeBuffer = new byte[1] { 0 };
// device.Write(writeBuffer);
// addresses.Add(address);
// Debug.WriteLine("Added Address: " + address);
// }
// catch (FileNotFoundException ex)
// {
// // //This is the WatchDog Feature
// // //If it misses NumberOfTriesBeforeRestart sensors in a row, it can restart the i2c detection ring.
// // //This number is configurable in NumberOfTriesBeforeRestart
// // if (failures == NumberOfTriesBeforeRestart)
// // { //You Can Reboot Here
// // //Reoot Code
// // //CoreApplication.RequestRestartAsync();
// // }
// // else
// // {
// // //Or You Can Shut Down
// // // CoreApplication.Exit();
// // }
// // failures++;
// // string MyEx = ex.Message;
// // //we decided that if 3 or more sensors in a row are caught (fail to be detected), Then
// // //the polling process restarts.
// }
// catch (Exception ex)
// {
// Debug.WriteLine("Address {0} not found ", address);
// string msg = ex.Message;
// //swallow exception
// }
// }
// //else if ((device == null) && (address == 105))
// //{
// // byte[] writeBuffer = new byte[1] { 0 };
// // device.Write(writeBuffer);
// // addresses.Add(address);
// //}
// else
// {
// Debug.WriteLine("device DOES equal null!", address);
// //restart by re-opening the MainPage.xaml file
// // Navigate to a page function like a page
// }
// }
// }
// //byte address2 = 105;
// //addresses.Add(address2);
// //addresses.Add(maximumAddress + 1); //Adding an extra for Config Button
// return addresses;
//}
}
}
由于抛出异常然后地址"SlaveAddressNotAcknowledged",这导致花费了很多时间,时间成本取决于您扫描的地址数量。
要解决此问题,您可以使用 WritePartial 而不是 Write。 WritePartial 不能导致抛出异常,而是在 return 结果中报告状态码:I2cTransferResult,I2cTransferStatus。所以节省时间。遍历 1-105 大约需要 1.2 秒。
您可以试试下面的代码:
const int minimumAddress = 1;
const int maximumAddress = 105;
var stopWatch = new Stopwatch();
stopWatch.Start();
for (byte address = minimumAddress; address <= maximumAddress; address++)
{
// Debug.WriteLine("checking address " + address);
var settings = new I2cConnectionSettings(address)
{
BusSpeed = I2cBusSpeed.FastMode,
SharingMode = I2cSharingMode.Shared
};
using (I2cDevice device = controller.GetDevice(settings))
{
if (device != null)
{
try
{
byte[] writeBuffer = new byte[1] { 0 };
var result = device.WritePartial(writeBuffer);
if (result.Status == I2cTransferStatus.SlaveAddressNotAcknowledged)
continue;
addresses.Add(address);
Debug.WriteLine("Added Address: " + address);
}
catch (Exception ex)
{
}
}
else
{
Debug.WriteLine("device DOES equal null!", address);
}
}
}
stopWatch.Start();
System.Diagnostics.Debug.WriteLine(stopWatch.ElapsedMilliseconds.ToString());
I2C 扫描地址
我一直在尝试扫描使用 I2C 时存在的 Raspberry Pi3 端口上的地址 1-128。请注意,我们有 1 GB RAM,并且我们的软件总是将其最大化,尤其是在此过程中(实际上,它大约是 900K,真的)。
平台
我们的操作系统:Windows 10 Iot Core Build 17744。 Atlas Scientific 具有用于 pH、CO2、温度、电导率和 Oxidation/reduction 电位 (ORP) 的传感器。 https://www.atlas-scientific.com/product_pages/circuits/ezo_orp.html 假设我们正在使用 Whitebox 的 Labs Tentacle 3(我们是)来托管 3 个电路和传感器及其相关传感器。 https://www.atlas-scientific.com/product_pages/components/tentacle-t3.html
遍历 1-128 需要 35 秒,这是 不允许的。 此外,Python 在 Raspian 上不允许花尽可能长的时间。 (我现在要验证这一点)。
我们的尝试
1)我注意到扫描循环处于静态 class。我认为 "using" 会确保垃圾收集会清除这种情况。它没有。
1a) 我在没有 "using" 的情况下重写了它,但是 Dispose。结果相同;
2) 接下来我尝试了 IOT Lightning DMAP 驱动程序。 https://docs.microsoft.com/en-us/windows/iot-core/develop-your-app/lightningproviders 这对时间也没有影响。
欧比旺克诺比帮帮我,你是我唯一的希望 我已将其交叉发布到 Windows 10 IOT 支持委员会。 是时候尝试 C++ 了吗?
备注
我刚刚试过了,但是好像也不管用 GetDeviceSelector()..
https://www.hackster.io/porrey/discover-i2c-devices-on-the-raspberry-pi-84bc8b
代码
FindDevicesAsync 有两个版本(一个有 Lightning DMAP,一个没有)
using IOT_Sensors;
using MetroLog;
using SQLite.Net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.I2c;
using Windows.Devices;
using Microsoft.IoT.Lightning.Providers;
using Windows.UI.Xaml;
namespace atlas_iot
{
public class SensorFinder
{
public async static Task<IEnumerable<byte>> StaticExample()
{
SensorFinder sf = new SensorFinder();
return await sf.FindDevicesAsync();
}
//the process for searching for sensors could not be garbage collected in a static class
// we are going to return a static List of addresses (bytes). ModuleStore.I2CsystemInit() will give them type
public async Task<IEnumerable<byte>> FindDevicesAsync() //speed this up please!
{
if (LightningProvider.IsLightningEnabled)
{
// Set Lightning as the default provider
LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
}
IList<byte> addresses = new List<byte>();
I2cController controller = await I2cController.GetDefaultAsync();
// const int minimumAddress = 97;
const int minimumAddress =10;
// The Min and Max may need to be adjusted depending on what ID #'s you haveon the EZO circuit.
//const int maximumAddress = 104;
const int maximumAddress = 105;
//const int maximumAddress = 103;
for (byte address = minimumAddress; address <= maximumAddress; address++)
{
// Debug.WriteLine("checking address " + address);
var settings = new I2cConnectionSettings(address)
{
BusSpeed = I2cBusSpeed.FastMode,
SharingMode = I2cSharingMode.Shared
};
I2cDevice device = controller.GetDevice(settings);
if (device != null)
{
try
{
byte[] writeBuffer = new byte[1] { 0 };
device.Write(writeBuffer);
addresses.Add(address);
Debug.WriteLine("Added Address: " + address);
}
catch (FileNotFoundException ex)
{
//Do Nothing
}
catch (Exception ex)
{
Debug.WriteLine("Address {0} not found ", address);
string msg = ex.Message;
//swallow exception
}
}
else
{
Debug.WriteLine("device DOES equal null!", address);
//Do Nothing
}
device.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
}
//byte address2 = 105;
//addresses.Add(address2);
//addresses.Add(maximumAddress + 1); //Adding an extra for Config Button
return addresses;
}
//Maybe use a Hashtable or dictionary instead?ny
//public async Task<IEnumerable<byte>> FindDevicesAsync() //speed this up please!
//{
// IList<byte> addresses = new List<byte>();
// I2cController controller = await I2cController.GetDefaultAsync();
// // const int minimumAddress = 97;
// const int minimumAddress = 1;
// // The Min and Max may need to be adjusted depending on what ID #'s you haveon the EZO circuit.
// //const int maximumAddress = 104;
// const int maximumAddress = 105;
// //const int maximumAddress = 103;
// for (byte address = minimumAddress; address <= maximumAddress; address++)
// {
// // Debug.WriteLine("checking address " + address);
// var settings = new I2cConnectionSettings(address)
// {
// BusSpeed = I2cBusSpeed.FastMode,
// SharingMode = I2cSharingMode.Shared
// };
// using (I2cDevice device = controller.GetDevice(settings))
// {
// if (device != null)
// {
// try
// {
// byte[] writeBuffer = new byte[1] { 0 };
// device.Write(writeBuffer);
// addresses.Add(address);
// Debug.WriteLine("Added Address: " + address);
// }
// catch (FileNotFoundException ex)
// {
// // //This is the WatchDog Feature
// // //If it misses NumberOfTriesBeforeRestart sensors in a row, it can restart the i2c detection ring.
// // //This number is configurable in NumberOfTriesBeforeRestart
// // if (failures == NumberOfTriesBeforeRestart)
// // { //You Can Reboot Here
// // //Reoot Code
// // //CoreApplication.RequestRestartAsync();
// // }
// // else
// // {
// // //Or You Can Shut Down
// // // CoreApplication.Exit();
// // }
// // failures++;
// // string MyEx = ex.Message;
// // //we decided that if 3 or more sensors in a row are caught (fail to be detected), Then
// // //the polling process restarts.
// }
// catch (Exception ex)
// {
// Debug.WriteLine("Address {0} not found ", address);
// string msg = ex.Message;
// //swallow exception
// }
// }
// //else if ((device == null) && (address == 105))
// //{
// // byte[] writeBuffer = new byte[1] { 0 };
// // device.Write(writeBuffer);
// // addresses.Add(address);
// //}
// else
// {
// Debug.WriteLine("device DOES equal null!", address);
// //restart by re-opening the MainPage.xaml file
// // Navigate to a page function like a page
// }
// }
// }
// //byte address2 = 105;
// //addresses.Add(address2);
// //addresses.Add(maximumAddress + 1); //Adding an extra for Config Button
// return addresses;
//}
}
}
由于抛出异常然后地址"SlaveAddressNotAcknowledged",这导致花费了很多时间,时间成本取决于您扫描的地址数量。
要解决此问题,您可以使用 WritePartial 而不是 Write。 WritePartial 不能导致抛出异常,而是在 return 结果中报告状态码:I2cTransferResult,I2cTransferStatus。所以节省时间。遍历 1-105 大约需要 1.2 秒。
您可以试试下面的代码:
const int minimumAddress = 1;
const int maximumAddress = 105;
var stopWatch = new Stopwatch();
stopWatch.Start();
for (byte address = minimumAddress; address <= maximumAddress; address++)
{
// Debug.WriteLine("checking address " + address);
var settings = new I2cConnectionSettings(address)
{
BusSpeed = I2cBusSpeed.FastMode,
SharingMode = I2cSharingMode.Shared
};
using (I2cDevice device = controller.GetDevice(settings))
{
if (device != null)
{
try
{
byte[] writeBuffer = new byte[1] { 0 };
var result = device.WritePartial(writeBuffer);
if (result.Status == I2cTransferStatus.SlaveAddressNotAcknowledged)
continue;
addresses.Add(address);
Debug.WriteLine("Added Address: " + address);
}
catch (Exception ex)
{
}
}
else
{
Debug.WriteLine("device DOES equal null!", address);
}
}
}
stopWatch.Start();
System.Diagnostics.Debug.WriteLine(stopWatch.ElapsedMilliseconds.ToString());