在 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());