简体   繁体   中英

Scanning Addresses on Windows 10 IOT on Raspberry Pi 3 takes 30 Seconds

Scanning Addresses in I2C

I've been trying to scan addresses 1-128 on the ports of Raspberry Pi 3 that exist when using I2C. Note that we have 1 GB RAM, and our software always maxes it out especially during this process (actually, it is about 900K, really).

The Platform

Our Operating System: Windows 10 Iot Core Build 17744. Atlas Scientific has sensors for pH, CO2, Temperature, Conductivity and Oxidation/reduction potential (ORP). https://www.atlas-scientific.com/product_pages/circuits/ezo_orp.html Let's assume we are using the Whitebox' Labs Tentacle 3 (we are) to host 3 circuits and sensors and their associated sensors. https://www.atlas-scientific.com/product_pages/components/tentacle-t3.html

Iterating through 1-128 takes 35 seconds, which is impermissible . Also, Python on Raspian doesn't take as long. (I'm going to validate that right now).

What We've Tried

1)I noticed the scanning loop was in a static class. I thought "using" would ensure that garbage collection would clear the situation. It didn't.

1a) I rewrote it without "using", but Dispose. Same result;

2) Next I tried the IOT Lightning DMAP driver. https://docs.microsoft.com/en-us/windows/iot-core/develop-your-app/lightningproviders This had no effect on the time either.

Help Me Obi-Wan Kenobi, you're my only hope I've cross posted this to the Windows 10 IOT Support Board. Is it time to try C++?

Note

I've just tried this, but it doesn't seem to work either GetDeviceSelector()..

https://www.hackster.io/porrey/discover-i2c-devices-on-the-raspberry-pi-84bc8b

Code

There are two versions of FindDevicesAsync (one with and one without 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;
    //}


    }
}

This result in so much time due to the exception throw then the address "SlaveAddressNotAcknowledged", the time cost depends on the number of the addresses you scan.

To solve this issue you can use WritePartial instead of Write. WritePartial can't result in an exception thrown but report the status code in the return result: I2cTransferResult, I2cTransferStatus . So save the time. Iterating through 1-105 takes about 1.2 seconds.

You can try the following code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM