在电池上运行我的.NET nanoFramework 8年之久的dotnet展示

936 阅读18分钟

今天,我想向dotnet展示如何在一个简单的电池上运行你自己的.NET应用程序,并持续多年。我将建立一个应用程序,在一个连接到ESP32的BMP280传感器上读取温度和压力。其核心思想是在一个小型太阳能电池板上运行,为一个锂电池充电。我还将介绍两个真实的案例,都是运行.NET nanoFramework,一个在STM32F7处理器上,另一个在TI CC1352R上。

我是Laurent Ellerbach。我是微软的首席软件工程师经理,在商业软件工程团队工作。我和我的团队正在与我们最大的客户进行联合工程,帮助他们进行数字化转型,并专注于Azure。我更专注于制造业,我参与物联网已经有很长时间了。我一直是.NET物联网的贡献者,并很快成为主要贡献者之一,这促使我与.NET团队紧密合作。作为一个从第一天起就喜欢C#的人,我一直在寻找有趣和创新的方法来尽可能地使用它。我很高兴发现了.NET nanoFramework,我正在努力将.NET IoT和.NET nanoFramework连接起来,使C#开发者更容易使用其中一个,并尽可能多地重复使用代码。

MCU、CPU,有什么区别?

微控制器单元(MCU)是一种小型处理器,通常是低功耗、小尺寸的代名词。现代的MCU如STM32F7、ESP32、TI CC1352R是基于ARM Cortex M的,嵌入了几百KB的RAM、小型闪存和几亿赫兹的时钟节奏。在像这些小型处理器上,你可以运行一个非常简单的操作系统,称为实时操作系统(RTOS),如Azure RTOS。这些RTOS提供线程、线程间消息传递和同步、最低限度的网络能力,你必须在上面建立你的应用程序,传统上使用C/C++。为这些MCU存在一个特殊的.NET实现,它被称为.NET nanoFramework

中央处理器(CPU)是一个较大的处理器,在这个类别中,你会发现所有传统的x86、x64,以及其他ARM处理器,如Raspberry Pi中使用的那种处理器。这些是运行Windows、Linux或macOS等 "真正 "操作系统的系列。在这些类型的处理器上,你可以运行.NET 5.0,比如说。

它们之间的主要区别之一是计算能力,它转化为功耗。当然,在芯片成本方面,CPU要比MCU贵得多。典型的MCU成本从几美分到几美元不等。CPU的成本是一个至少10或100的比例因子。

另外,即使你觉得你的基于CPU的机器速度很快,而且你喜欢的操作系统也很快,你可能没有考虑到诸如启动或从睡眠中回来,测量一些东西,通过网络发送这些测量结果,然后回到睡眠模式的情况。这对于基于CPU的机器来说并不容易。在MCU上,进入睡眠状态很容易,而且由于RTOS非常轻,你的应用可以非常、非常迅速地启动和运行。在MCU上,你可以启用一个睡眠模式,将处理器置于一个能耗非常低的状态。想象一下像刺猬这样的动物过冬的情况,也是差不多的。所有的东西都将被置于一个低消耗的模式,每一个非重要的元素都将被完全关闭。消耗将下降到几毫安或几微安(µA)。

在CPU上,这并不完全可能。在现代架构中,你可以调整CPU的频率,也有睡眠模式,但那只是浅睡眠。因此,CPU将始终处于清醒状态,或处于省电模式,它仍将消耗相当多的能量。这就是为什么在所有硬件或所有供应商上,基于CPU,在轻度睡眠一段时间后,系统会进入休眠状态,这基本上是放弃状态和硬盘上的内存,停止CPU。你已经体验过从这两种模式中唤醒的时间,即使你觉得它很快,它仍然需要相当长的时间,至少是多秒。

在MCU的世界里,有可能只是睡眠或进入深度睡眠模式,甚至进一步减少功耗。你可以想知道:什么可以唤醒MCU?这取决于MCU。最常见的情况之一是基于一个定时器。从技术上讲,所有的东西都将被关闭,除了一个小的手表晶体和一个定时器。这些元件只消耗几个微安培,这意味着该装置可以用电池运行这些元件几年或几十年。当达到唤醒时间时,MCU被唤醒,执行启动程序,并开始执行其程序。

还有其他方法可以唤醒它,就像在现实生活中一样!冷水桶或有人摇晃你也是可能的。这个被称为中断。在MCU的世界里,它将意味着一个通用输入/输出(GPIO)引脚上的状态改变。简而言之,有事发生了。你按了一个按钮,或者你触摸了一个屏幕,改变了GPIO的状态。这种模式比前一种模式消耗更多的能量,但是,处理器仍然处于深度睡眠状态,而且,也只消耗了几个微安培。

.NET nanoFramework针对MCU的世界,支持所有支持的架构,如ESP32、STM32、NXP和TI的睡眠机制。这使得场景可以让.NET代码在一个电池上运行多年,我将在后面解释。

在这个物联网世界中,我们最感兴趣的是不时地测量一个元素,通过空气或电缆发送这些数据,并等待下一个时期再次测量。这是物联网世界中最常见的情况。你想尽可能地减少消耗;你想尽可能不频繁地更换电池,而且你仍然希望设备不时地说它是活的。

自己实验:使用太阳能电池板和锂离子电池

要自己实验这种行为,你需要使用一个支持.NET nanoFramework的MCU。在这里,我将只使用一个便宜的和流行的ESP32。我把这个代码部署在一个花园里。它正在连接到我的Wi-Fi,连接到Azure IoT Hub,获得设置,发布其状态,测量温度和压力,将这些数据发布到Azure IoT Hub,然后回去睡觉。完成这一连串的操作只需要几秒钟。代码可在nanoFramework样本的GitHub仓库中找到。其模式如下,根据哪种ESP32,物理引脚的位置可能会改变。

schema

.NET nanoFramework有一个Visual Studio扩展,你必须要安装。你还必须对你的设备进行闪存。然后你就可以像对待任何.NET应用程序那样调试你的C#代码了你也可以连接到Wi-Fi或有线网络。帮助器使你的生活变得简单,你所需要的一切都在nanoFramework NuGet包中。代码的第一部分连接到Wi-Fi,请求或更新一个IP地址。

// As we are using TLS, we need a valid date & time
// We will wait maximum 1 minute to get connected and have a valid date
CancellationTokenSource cs = new(sleepTimeMinutes);
var success = NetworkHelper.ConnectWifiDhcp(Ssid, Password, setDateTime: true, token: cs.Token);
if (!success)
{
    Trace($"Can't connect to wifi: {NetworkHelper.ConnectionError.Error}");
    if (NetworkHelper.ConnectionError.Exception != null)
    {
        Trace($"NetworkHelper.ConnectionError.Exception");
    }

    GoToSleep();
}

通过之前的代码,我们在代码中存储了SSID和密码,你可以说这并不安全。也可以直接把它存储在设备上,只需调用一个助手就可以连接,完全不用在代码中指定它。

代码的第二部分是与Azure IoT的连接。我将不深入讨论细节问题。我们正在使用MQTT连接到Azure IoT,使用对称密钥。

const string DeviceID = "nanoDeepSleep";
const string IotBrokerAddress = "yourIoTHub.azure-devices.net";
const string SasKey = "alongsastoken";
// nanoFramework socket implementation requires a valid root CA to authenticate with.
// This can be supplied to the caller (as it's doing on the code bellow) or the Root CA has to be stored in the certificate store
// Root CA for Azure from here: https://github.com/Azure/azure-iot-sdk-c/blob/master/certs/certs.c
// We are storing this certificate as an application resource
X509Certificate azureRootCACert = new X509Certificate(Resources.GetBytes(Resources.BinaryResources.AzureCAcertificate));

// Creates MQTT Client with default port 8883 using TLS protocol
MqttClient mqttc = new MqttClient(
    IotBrokerAddress,
    8883,
    true,
    azureRootCACert,
    null,
    MqttSslProtocols.TLSv1_2);

// Handler for received messages on the subscribed topics
mqttc.MqttMsgPublishReceived += ClientMqttMsgReceived;
// Handler for publisher
mqttc.MqttMsgPublished += ClientMqttMsgPublished;

// Now connect the device
byte code = mqttc.Connect(
    DeviceID,
    $"{IotBrokerAddress}/{DeviceID}/api-version=2020-09-30",
    GetSharedAccessSignature(null, SasKey, $"{IotBrokerAddress}/devices/{DeviceID}", new TimeSpan(24, 0, 0)),
    false,
    MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE,
    false, "$iothub/twin/GET/?$rid=999",
    "Disconnected",
    false,
    60
    );

//If we are connected, we can move forward
if (mqttc.IsConnected)
{
    mqttc.Subscribe(
        new[] {
            $"devices/{DeviceID}/messages/devicebound/#",
            "$iothub/twin/res/#"
        },
        new[] {
                MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE,
                MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE
        }
    );
    //Rest of the code here
}

你会注意到的第一件事是,.NET nanoFramework提供了连接到任何MQTT代理的所有必要条件,包括Azure IoT Hub。像其他元素一样,MQTT库是通过NuGet包安装的。这个MQTT库是.NET nanoFramework上的M2Mqtt的一个端口。

需要Azure根证书来验证我们所连接的端点的身份。它被存储在代码资源中。.NET nanoFramework也提供了一个应用程序资源的概念。

我们正在为事件注册。在这里,我们将对我们能收到的消息感兴趣,并确认这些消息已被Azure IoT收到。还有更多的事件你可以订阅。这分两步完成,第一步是用MQTT类,第二步是用协议。

为了连接设备本身,需要一个共享访问签名。这个计算是通过类的帮助器进行的,它允许使用HMACSHA256计算来创建。大多数参数都是针对MQTT协议的,并在Azure IoT Hub文档中有所记载。

继续往前走,我们要求为这个设备提供设备双胞胎。双胞胎是一个概念,它正在创建所需的属性和报告的属性。把这看作是设备的期望和报告的配置。由你来定义你想要设置的东西。

我们将请求它们并等待收到它们。像往常一样,我们使用一个带有超时的模式,以确保即使我们没有收到,也不会阻止代码太长时间,我们将继续进行下一步。

mqttc.Publish($"{TwinDesiredPropertiesTopic}?$rid={Guid.NewGuid()}", Encoding.UTF8.GetBytes(""), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);

CancellationTokenSource cstwins = new(10000);
CancellationToken tokentwins = cstwins.Token;
while (!twinReceived && !tokentwins.IsCancellationRequested)
{
    tokentwins.WaitHandle.WaitOne(200, true);
}

由于我们订阅了消息事件,一旦Twin将被发送,事件将被触发,我们将能够处理它。

void ClientMqttMsgReceived(object sender, MqttMsgPublishEventArgs e)
{
        string message = Encoding.UTF8.GetString(e.Message, 0, e.Message.Length);

        if (e.Topic.StartsWith("$iothub/twin/"))
        {           
            if (message.Length > 0)
            {
                // skip if already received in this session
                if (!twinReceived)
                {
                    try
                    {
                        TwinProperties twin = (TwinProperties)JsonConvert.DeserializeObject(message, typeof(TwinProperties));
                        minutesToGoToSleep = twin.desired.TimeToSleep != 0 ? twin.desired.TimeToSleep : minutesToGoToSleep;
                        twinReceived = true;
                    }
                    catch
                    {
                        // We will ignore
                    }
                }
            }           
        }
    }
}

Twin被编码为Json文本消息:

{"desired":{"TimeToSleep":5,"$version":2},"reported":{"Firmware":"nanoFramework","TimeToSleep":2,"$version":94}}

一个Json序列化器和反序列化器可作为.NET nanoFramework的NuGet。我正在使用一个类来反序列化对象。TimeToSleep 属性描述了我要求设备睡眠的分钟数。在这种情况下,5将代表5分钟。这使我能够调整我的代码的行为,而不需要重新部署我的代码。这个机制是Azure IoT Hub提供的一个非常重要的机制。

一旦收到并处理了Twin的详细信息,或者,如果没有,超时将过期,我就重新发布Twin:

mqttc.Publish($"{TwinReportedPropertiesTopic}?$rid={Guid.NewGuid()}", Encoding.UTF8.GetBytes($"{{"Firmware":"nanoFramework","TimeToSleep":{minutesToGoToSleep}}}"), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);

在这种情况下,我不需要等待任何确认,我直接进入下一步。我的下一步是使用一个BMP280传感器来测量温度和大气压力。这个传感器是一个I2C传感器,非常流行便宜,而且很容易找到。

这个传感器已经在.NET物联网中实现,并被移植到.NET nanoFramework。.NET nanoFramework提供了一个基于相同代码库的大型传感器库。因为.NET nanoFramework有一些限制,所以每一个绑定都被分割成了各自的NuGet。这些绑定的代码可以在nanoFramework.IoT.Device资源库中找到。这些代码必须进行转换,以支持.NET nanoFramework的特定项目类型和其他特殊性,如将通用列表或跨度转换为非通用的。由于大小的限制,例如,Enums有一个简化的实现。IsDefinedGetValues ,因为Enum项目的描述被删除以节省MCU中的闪存。

读取传感器的代码如下:

// I2C bus 1 is using GPIO 18 and GPIO 19 on the ESP32
const int busId = 1;
I2cConnectionSettings i2cSettings = new(busId, Bmp280.DefaultI2cAddress);
I2cDevice i2cDevice = I2cDevice.Create(i2cSettings);
var i2CBmp280 = new Bmp280(i2cDevice);
// set higher sampling
i2CBmp280.TemperatureSampling = Sampling.LowPower;
i2CBmp280.PressureSampling = Sampling.UltraHighResolution;

var readResult = i2CBmp280.Read(); 

运行.NET 5.0的树莓派上,使用.NET物联网设备绑定NuGet包,也会是完全相同的代码。

另外,为了使所有支持的绑定简单、一致和直接,我们做了大量的工作和努力。这使得在.NET中开发的解决方案,从代码和支持的角度来看,很容易在CPU和MCU上重复使用。

一旦测量完成,我们可以在Azure IoT上发布结果。:

//Publish telemetry data using AT LEAST ONCE QOS Level
messageID = mqttc.Publish(telemetryTopic, Encoding.UTF8.GetBytes($"{{"Temperature":{readResult.Temperature.DegreesCelsius},"Pressure":{readResult.Pressure.Hectopascals}}}"), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);

// Wait for the message or cancel if waiting for too long
CancellationToken token = new CancellationTokenSource(5000).Token;
while (!messageReceived && !token.IsCancellationRequested)
{
    token.WaitHandle.WaitOne(200, true);
}

GoToSleep();

我们要等一下才能收到发布结果的确认。那是通过我们订阅的一个事件发生的:

void ClientMqttMsgPublished(object sender, MqttMsgPublishedEventArgs e)
{
    if (e.MessageId == messageID)
    {
        messageReceived = true;
    }
}

像往常一样,如果我们在特定的时间窗口内没有收到确认,我们就会继续,无论如何都要睡觉。没有收到确认,并不一定意味着它没有被发布,也不意味着它没有到达。在一个缓慢的网络上,得到确认可能需要一点时间。此外,一些事件可能被跳过。这就是为什么MQTT协议有一个适应这些情况的交付机制的原因,不做赘述。

_GoToSleep_ ,该方法从设置唤醒机制开始。MCU有很多这样的机制。在这里,我们将使用定时器:

void GoToSleep()
{
    Sleep.EnableWakeupByTimer(new TimeSpan(0, 0, minutesToGoToSleep, 0));
    Sleep.StartDeepSleep();
}

请注意,MCU保持睡眠模式的时间(以分钟为单位)是由从Azure IoT Hub收到的Twin属性决定的:

Sleep 类是.NET nanoFramework特有的,是专门为管理每个设备的睡眠模式而设计的。尽管有一个共同的API,但低级别的实现是特定于每个支持的MCU。有些提供比其他更多的功能。API是统一的,如果一种模式,如定时器模式,在所有的MCU上都可用,API将是完全相同的。

通过大约100行的.NET代码和几个小时的努力,你就可以连接到Wi-Fi网络,连接到Azure IoT Hub,获得双胞胎属性,报告它们,测量一个传感器,将测量结果报告给Azure IoT Hub,然后进入深度睡眠模式,降低MCU的功耗!.NET nanoFramework NuGet和现有的代码助手使之变得简单。

代码执行的持续时间

现在让我们看看运行代码时的更多数据。

示例代码使用Microsoft.Extensions.Logging 进行记录。.NET nanoFrameworks遵循.NET 5.0框架中使用的记录模式,并与.NET IoT中的实现兼容。我们将在这里使用它,以便能够追踪代码运行时的情况。

.NET nanoFramework代码可以使用Visual Studio调试器进行调试。因此,当你处于开发阶段时,你当然可以启动一个调试会话,做你在调试任何.NET C#应用程序时所习惯做的事情。现在,当设备进入睡眠状态时,它失去了调试上下文,当它将被唤醒时,你将无法再回到它。

Debug experience

因此,在这个阶段,为了衡量一切的运行情况,可以使用一个外部日志机制。我们将使用一个串行端口,插在机器上。像Putty这样的工具或任何其他的串行读卡器将完美地工作,以捕获数据。

落实这一点的代码如下:

// Use Trace to show messages in serial COM2 as debug won't work when the device will wake up from deep sleep
// Set the GPIO 16 and 17 for the serial port COM2
Configuration.SetPinFunction(16, DeviceFunction.COM2_RX);
Configuration.SetPinFunction(17, DeviceFunction.COM2_TX);
SerialPort serial = new("COM2");
serial.BaudRate = 115200;
logger = new SerialLogger(ref serial, "My logger");
logger.MinLogLevel = LogLevel.Debug;
Trace("Program Started, connecting to WiFi.");

void Trace(string message)
{
    logger?.LogDebug(message);
}

我在代码中到处都放置了丰富的跟踪调用,所以结果是相当冗长的。而这里是我看到的跟踪的一个例子:

Program Started, connecting to WiFi.
Date and time is now 06/09/2021 12:45:33
subscribing to topics
Getting twin properties
Response from publish with message id: 2
Message received on topic: $iothub/twin/res/200/?$rid=be27fc48-85bb-455e-3585-6ff363d09002
and message length: 115
and was in the success queue.
New sleep time to sleep received: 30
Sending twin properties
Message received on topic: $iothub/twin/res/200/?$rid=be27fc48-85bb-455e-3585-6ff363d09002
and message length: 115
and was in the success queue.
Temperature: 22.86265857°C
Pressure: 991.79647718hPa
Message received on topic: $iothub/twin/res/200/?$rid=be27fc48-85bb-455e-3585-6ff363d09002
and message length: 115
and was in the success queue.
Message ID for telemetry: 4
Response from publish with message id: 3
Message received on topic: $iothub/twin/res/204/?$rid=54f8f9a7-d190-48db-ba88-9ed4a47bc50b&$version=263
and message length: 0
and received confirmation for desired properties.
Response from publish with message id: 4
Full operation took: 00:00:07.3871120
Set wakeup by timer for 30 minutes to retry.
Deep sleep now

首先,整个操作只花了7秒多一点的时间,因为在托管代码中没有包括大约1秒的启动时间。第二,这7秒包括获取Azure双胞胎,调整它们,报告它们,测量传感器,报告测量结果和接收确认

第三,你可能很难理解这些痕迹的逻辑。这也是意料之中的事。.NET nanoFramework与多线程一起工作。当事件发生时,比如收到双胞胎或收到确认发布的消息,所有其他线程继续执行。

需要反思的是,从我自己的测量来看,执行时间在3到10秒之间,平均在6秒左右。

总的执行时间可以通过完全删除输出到串行端口的Trace代码来改善。

在Azure方面,使用例如Azure IoT Explorer,你可以检查设备是否正确地发送了遥测数据,以及你是否收到了一切。

Azure Explorer

测量的消耗

我们真正感兴趣的是将MCU置于深度睡眠模式,并测量其消耗量以与正常执行模式进行比较的可能性。

为此,我们必须在电源线上使用一个电流表。我们将测量MCU在运行时和睡眠时的情况。

在启动运行时,我可以看到一个大约250毫安的峰值,很快就下降到140毫安左右。

一旦进入深度睡眠状态,消耗的电流不到2毫安,因为我仍然有一个小的LED连接,应该被移除。规格说明在这种模式下,电流在10至150微安之间。因此,超过了1000倍!

如果你用一个2000毫安的电池,做简单的计算,深度睡眠的消耗为50微安,你将能够在这个电池上停留40000小时,即超过4年半。阅读真实案例方案一节,可以了解到这是一个真实有效的方案。

现在,假设我将一直运行我的代码,连接到WiFi,到Azure IoT,测量,发布数据,我的消耗将始终在平均约140毫安,你可以期望在电池上工作超过14小时而不中断。这将代表超过5,000个周期。

考虑到电池的健康状况良好,并假定温度和其他一些相关因素是恒定的,我将能够每天运行我的测量2次,我仍然能够在同一电池上停留2年半,没有任何问题。

对于我自己的方案,在我的花园里,我将使用一个简单的太阳能电池板,一个锂聚合物充电器和一个锂聚合物电池。它们将被连接到一个ESP32。这个ESP32将有一个BMP280温度和气压传感器连接。我的ESP32位于花园中,仍然在Wi-Fi的范围内,但远离任何主电源插座。我可以慷慨地每小时进行多次测量,即使几天的天气不是特别晴朗,电池也会足够大。

案例研究。油箱液位监测和超载保护

这个案例研究是关于油箱液位监测与超载保护。想象一下,一个2.5万升的油箱,你有兴趣测量油箱内的液位,当液位过高时发出警报。这是OrgPal.IoT在.NET nanoFramework基础上建立的产品之一。他们也有其他使用.NET nanoFramework的现场遥测产品。

他们设计的板子是基于TI CC1352R MCU的,其中包括同一芯片中的无线电。

TI CC1352R TI CC1352R

这块板子在睡眠模式下的功率很低,只有50微安,用两节3.6V的电池可以维持5-8年。

当水箱被填满时,它将检测到任何潜在的溢出,并充当填充保护。它装在一个小盒子里,靠两节3.6V 2400mA电池运行。盒子在水箱上很容易接近。一个控制加注的浮子被移动并在达到特定水平时被触发,然后该装置被唤醒,通过无线电信号传输到1公里以外的主箱,同时运行一个.NET nanoFramework应用程序,它将通过一个继电器控制板关闭多达32条线路的阀门,防止产品过量,从而节省产品并注意环境危害。

第二种情况是现场遥测。使用的板子是基于STM32F7处理器的。它带有嵌入式屏幕、以太网、RS 485(Modbus)、闪存、SD卡、USB、一个GPS、一个卫星通信模块以及更多通过扩展槽的模块。

Board

它是一个自供电的盒子,有一个内置的太阳能电池板,为系统供电,允许离网使用多年,电力使用量低。例如,这些单元被安装在移动坦克上。操作的情况是这样的。

该装置被唤醒,使用超声波、雷达、电磁等产品液位传感器进行读数,获得储罐的体积。然后它打开GPS接收器,获得精确的GPS位置。

最后一步是通过卫星连接向Azure IoT报告所有这些数据。

一旦数据被报告,该装置就会回到睡眠状态。这个周期每4、6、8小时或根据需要重复一次。

工人可以走到设备前,通过按下盒子上的按钮,通过屏幕获得读数。这将唤醒盒子来处理所要求的测量。然后它将回到睡眠状态。在睡眠模式下使用的功率低至200微安。

这里是盒子,有25x13厘米的太阳能电池板。它足够大,可以在需要时以全功率运行该系统,当然也可以在低功耗模式下运行。

Solar panel box

"微软.NET是建立伟大的应用程序的最佳平台之一,而.NET nanoFramework为我们的微控制器和所有硬件提供了同样的好处。.NET nanoFramework和它背后的团队创造了与老大哥.NET框架同样丰富的开发经验。它也是一个开放源码,拥有一个伟大的社区,这让我们感到放心,我们的投资有一个未来,我们不必依赖专有技术、许可等等。

简单地说,.NET nanoFramework简化了我们的开发过程,它具有强大的、易于使用的工具,如Visual Studio,使我们能够在几天到几周内创建解决方案,而不是几个月到几年,而且限制很少。它有内置的安全措施,确保部署的应用程序是安全和受保护的。如果你的企业需要一个可靠的应用程序,具有很好的性能,易于开发,开放源代码,那么.NET nanoFramework是你的应用程序的最佳选择"。

Zan GligorovOrgPal的负责人

OrgPal.IOT是一家位于德克萨斯州休斯顿的技术公司,专注于专业的物联网(IOT)硬件和软件解决方案,通过遥测技术获取现场服务和数据,以便在Azure云或你的私人企业中进行存储、分析和管理。他们提供边缘端点硬件和信息网关基础设施,将你的数据带到你的指尖,在桌面、服务器和移动设备上。

结论

能源消耗是一个全球性问题。作为开发者,我们有责任。我们选择的技术会产生影响,而在物联网中,选择一种尽可能少消耗能源的技术,同时还能实现我们所喜爱的.NET的所有生产力,这一点更加重要。

这就是在MCU上运行.NET代码的现实,具有极低的功耗,即使在需要向Azure发送数据的情况下也是如此。与使用传统技术相比,现在创建这样的设备包括硬件板是几周或短短几个月的事情。

我如何开始使用.NET nanoFramework?

要开始使用.NET nanoFramework,第一步是获得一个支持的设备,如ESP32。这里有一个板子参考社区支持的板子列表。然后,你必须按照一步一步的指南来安装Visual Studio 2019扩展,闪存你的设备,创建你的第一个项目并运行它。

让你自己的C#.NET代码在这些嵌入式设备之一上运行是几分钟的事,而且非常直接。

你需要像BMP280这样的传感器来重现我一直在做的事情。在.NET IoT.NET nanoFramework中有一个非常大的支持。你可以用同样的方式从CPU或MCU上使用它们!

如果需要任何帮助,.NET nanoFramework社区是非常活跃的,并且使用Discord频道。我们非常欢迎对改进.NET nanoFramework的本地C语言、C#语言和文档方面的贡献。主要的.NET nanoFramework页面会给你所有你需要的链接。