在I2C中扫描地址 [英] Scanning Addresses in I2C
问题描述
我一直在尝试扫描地址1-128使用I2C时存在的Raspberry Pi 3端口。请注意,我们有1 GB RAM,我们的软件总是最大化它,特别是在这个过程中(实际上,它大约是900K)。
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).
我们的操作系统:Windows 10 物联网核心构建17744.Atlas Scientific具有pH值传感器,CO2,温度,电导率和氧化/还原电位(ORP)。假设我们使用Whitebox'Labs
触手3(我们)来托管3个电路和传感器及其相关传感器。
Our Operating System: Windows 10 IOT Core Build 17744. Atlas Scientific has sensors for pH, CO2, Temperature, Conductivity and Oxidation/reduction potential (ORP). Let's assume we are using the Whitebox' Labs Tentacle 3 (we are) to host 3 circuits and sensors and their associated sensors.
迭代1-128需要35秒,这是 不允许的。 另外,
Raspian上的Python不需要那么长时间。(我现在要验证它。)
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).
1)我注意到扫描循环是在一个静态类中。我认为"使用"会确保垃圾收集能够清除这种情况。它没有。
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)我在没有"使用"的情况下重写了它,但是Dispose。相同的结果;
1a) I rewrote it without "using", but Dispose. Same result;
2)接下来,我尝试了IOT Lightning DMAP驱动程序。 这对时间没有影响。
2) Next, I tried the IOT Lightning DMAP driver. This had no effect on the time either.
帮助我Obi-Wan Kenobi,你是我唯一的希望我已经将它交叉发布到StackOverflow。是时候尝试使用C ++了吗?
Help Me Obi-Wan Kenobi, you're my only hope I've cross-posted this to StackOverflow. Is it time to try C++?
有两个版本的FindDevicesAsync(一个有一个没有Lightning DMAP)
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;
//}
}
}
推荐答案
Hello Jon Steiner,
Hello Jon Steiner,
由于异常抛出然后地址"SlaveAddressNotAcknowledged"导致这么多时间,时间成本取决于您扫描的地址数。
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.
要解决此问题,您可以使用WritePartial而不是Write。 WritePartial不会导致抛出异常,但会在返回结果中报告状态代码:I2cTransferResult, I2cTransferStatus 。
所以节省时间。迭代1-105大约需要1.2秒。
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());
如果有帮助,请告诉我。
Please let me know if it helps.
祝你好运,
Rita
这篇关于在I2C中扫描地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!