資料介紹
描述
Azure 支持的 AI Freezer Monitor 是基于制造商硬件的 IoT 監(jiān)視器,它使用機(jī)器學(xué)習(xí) (ML) 來提供潛在設(shè)備故障的早期警告。本指南涵蓋了構(gòu)建設(shè)備、收集訓(xùn)練數(shù)據(jù)、設(shè)置電子郵件警報(bào)、訓(xùn)練自定義自動編碼器機(jī)器學(xué)習(xí)模型以及將模型部署到 ESP32 開發(fā)板。
該項(xiàng)目旨在為低溫科學(xué)冷凍機(jī)(-60 C)提供功能,目標(biāo)是減少災(zāi)難性故障和保持備用冷凍機(jī)全時(shí)運(yùn)行的需要。但是,請注意,該項(xiàng)目主要用于演示和教育目的,尚未經(jīng)過廣泛的測試。
這個(gè)項(xiàng)目大約需要一個(gè)小時(shí)才能完全完成。
Azure 設(shè)置
下面有關(guān)于此示例的成本和架構(gòu)的詳細(xì)信息,但如果您只想讓它立即運(yùn)行,這里是開始的步驟。
部署資源
1. 登錄您的 Azure 帳戶
2. 單擊上面的Deploy to Azure鏈接,為該項(xiàng)目預(yù)配所有資源
作為替代方案,您可以使用Azure 門戶中的部署自定義模板服務(wù)部署模板,并在編輯器中選擇構(gòu)建您自己的模板并從該存儲庫上傳azuredeploy.json文件。
3.為項(xiàng)目新建資源組
4.為您的資源選擇一個(gè)區(qū)域,選擇一個(gè)靠近您以獲得最佳性能的區(qū)域
注意:某些資源并非在所有地區(qū)都可用
5. 為所有資源提供唯一名稱
注意:某些資源需要全局唯一名稱
設(shè)置 Azure 函數(shù)
1. 部署完成后,使用左側(cè)導(dǎo)航打開新功能應(yīng)用程序
2.從左側(cè)導(dǎo)航中選擇功能
3.選擇左上角的添加
4. 在窗口中選擇以下選項(xiàng):
開發(fā)環(huán)境:在門戶中開發(fā)
模板:定時(shí)器觸發(fā)器
新功能:dataSaver
您可以保留任何其他設(shè)置
5. 創(chuàng)建函數(shù)后,從左側(cè)導(dǎo)航中選擇Code + Test
6. 在run.csx中,將所有現(xiàn)有代碼替換為:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#r "Newtonsoft.Json"
using System;
using Newtonsoft.Json;
public static void Run(string myIoTHubMessage, ICollector outputTable, ILogger log)
{
log.LogInformation($"C# IoT Hub trigger function processed a message: {myIoTHubMessage}");
dynamic input = JsonConvert.DeserializeObject(myIoTHubMessage);
Guid guid = Guid.NewGuid();
log.LogInformation($"Message guid: {guid}");
outputTable.Add(
new outTable() {
PartitionKey = "test",
RowKey = guid.ToString(),
deviceId = input.deviceId.ToString(),
temperature = input.Temperature}
);
}
public class outTable
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public string deviceId { get; set; }
public float temperature {get; set;}
}
導(dǎo)航到function.json并將所有現(xiàn)有代碼替換為:
{
"bindings": [
{
"type": "eventHubTrigger",
"name": "myIoTHubMessage",
"direction": "in",
"eventHubName": "samples-workitems",
"connection": "ai-freezer-hub_events_IOTHUB",
"consumerGroup": "$Default"
},
{
"name": "outputTable",
"direction": "out",
"type": "table",
"tableName": "tempTable",
"connection": "AzureWebJobsStorage"
}
]
}
8. 使用以下選項(xiàng)對異常檢測器功能重復(fù)這些步驟:
開發(fā)環(huán)境:在門戶中開發(fā)
模板:IoT 中心(事件中心)
新功能:異常檢測器
您可以保留任何其他設(shè)置
運(yùn)行.csx:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#r "Microsoft.WindowsAzure.Storage"
#r "Newtonsoft.Json"
#r "System.Text.Json"
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Table;
using System.Threading.Tasks;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
public static readonly string emailAlertUrl = Environment.GetEnvironmentVariable("EMAIL_ALERT_URL");
public static readonly HttpClient client1 = new HttpClient();
// Anomaly detection API secrets
public static readonly string subscriptionKey = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_KEY");
public static readonly string endpoint = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_ENDPOINT");
const string latestPointDetectionUrl = "/anomalydetector/v1.0/timeseries/last/detect";
public const string batchDetectionUrl = "/anomalydetector/v1.0/timeseries/entire/detect";
public static DateTimeOffset targetTime;
public static async Task Run(TimerInfo myTimer, CloudTable inputTable, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
// Get traget time from when to start reading the data
targetTime = DateTime.UtcNow;
targetTime = targetTime.AddHours(-6);
log.LogInformation($"Target start time is: {targetTime}");
TableQuery rangeQuery = new TableQuery().Where(
TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThan, targetTime));
// Execute the query and loop through the results
List data = new List();
foreach (DataPoint entity in
await inputTable.ExecuteQuerySegmentedAsync(rangeQuery, null))
{
data.Add(new DataPoint() {Timestamp = entity.Timestamp, temperature = entity.temperature});
}
// Sort data by Timestamp
data.Sort((dp1, dp2) => DateTimeOffset.Compare(dp1.Timestamp, dp2.Timestamp));
List formatedData = new List();
data.ForEach( delegate(DataPoint point)
{
formatedData.Add(new FormatedData() { timestamp = point.Timestamp.ToString("yyyy-MM-ddTHH:mm:00Z"), value = point.temperature});
});
var options = new JsonSerializerOptions
{
IgnoreNullValues = true,
// PropertyNamingPolicy = new LowerCaseNamingPolicy()
};
List jsonFormat = new List();
jsonFormat.Add(new JsonFormat() {series = formatedData, granularity = "minutely", customInterval = 1, period = 90, sensitivity = 85});
string dataToSend = JsonSerializer.Serialize(jsonFormat, options);
// Call anomaly detection API
var anomalies = detectAnomaliesBatch(dataToSend, log);
if (anomalies != null){
var json = JsonSerializer.Serialize(anomalies);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client1.PostAsync(emailAlertUrl, content);
log.LogInformation(response.ToString());
}
}
static async Task Request(string apiAddress, string endpoint, string subscriptionKey, string requestData)
{
using (HttpClient client = new HttpClient { BaseAddress = new Uri(apiAddress) })
{
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
var res = await client.PostAsync(endpoint, content);
return await res.Content.ReadAsStringAsync();
}
}
static string detectAnomaliesBatch(string requestData, ILogger log)
{
log.LogInformation("Detecting anomalies as a batch");
requestData = requestData.TrimEnd(']').TrimStart('[');
//construct the request
var result = Request(
endpoint,
batchDetectionUrl,
subscriptionKey,
requestData).Result;
//deserialize the JSON object, and display it
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
System.Console.WriteLine(jsonObj);
string foundAnomalies = "Anomalies detected in the following data positions: ";
if (jsonObj["code"] != null)
{
System.Console.WriteLine($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
log.LogInformation($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
}
else
{
// log.LogInformation(result);
//Find and display the positions of anomalies in the data set
bool[] anomalies = jsonObj["isAnomaly"].ToObject<bool[]>();
System.Console.WriteLine("\nAnomalies detected in the following data positions:");
log.LogInformation("\nAnomalies detected in the following data positions:");
for (var i = 0; i < anomalies.Length; i++)
{
if (anomalies[i])
{
System.Console.Write(i + ", ");
log.LogInformation(i + ", ");
foundAnomalies += i;
foundAnomalies += ", ";
}
}
if (anomalies.Any(item => item == true))
{
return foundAnomalies;
}
}
return null;
}
public class FormatedData
{
public string timestamp { get; set; }
public string value { get; set; }
}
public class DataPoint : TableEntity
{
[JsonPropertyName("value")]
public string temperature { get; set;}
public string timestamp { get; set; }
}
public class JsonFormat
{
public List series { get; set; }
public string granularity { get; set; }
public int customInterval { get; set; }
public int period { get; set; }
// public float maxAnomalyRatio { get; set; }
public int sensitivity { get; set; }
}
public class LowerCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name) =>
name.ToLower();
}
函數(shù).json:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#r "Microsoft.WindowsAzure.Storage"
#r "Newtonsoft.Json"
#r "System.Text.Json"
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Table;
using System.Threading.Tasks;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
public static readonly string emailAlertUrl = Environment.GetEnvironmentVariable("EMAIL_ALERT_URL");
public static readonly HttpClient client1 = new HttpClient();
// Anomaly detection API secrets
public static readonly string subscriptionKey = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_KEY");
public static readonly string endpoint = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_ENDPOINT");
const string latestPointDetectionUrl = "/anomalydetector/v1.0/timeseries/last/detect";
public const string batchDetectionUrl = "/anomalydetector/v1.0/timeseries/entire/detect";
public static DateTimeOffset targetTime;
public static async Task Run(TimerInfo myTimer, CloudTable inputTable, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
// Get traget time from when to start reading the data
targetTime = DateTime.UtcNow;
targetTime = targetTime.AddHours(-6);
log.LogInformation($"Target start time is: {targetTime}");
TableQuery rangeQuery = new TableQuery().Where(
TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThan, targetTime));
// Execute the query and loop through the results
List data = new List();
foreach (DataPoint entity in
await inputTable.ExecuteQuerySegmentedAsync(rangeQuery, null))
{
data.Add(new DataPoint() {Timestamp = entity.Timestamp, temperature = entity.temperature});
}
// Sort data by Timestamp
data.Sort((dp1, dp2) => DateTimeOffset.Compare(dp1.Timestamp, dp2.Timestamp));
List formatedData = new List();
data.ForEach( delegate(DataPoint point)
{
formatedData.Add(new FormatedData() { timestamp = point.Timestamp.ToString("yyyy-MM-ddTHH:mm:00Z"), value = point.temperature});
});
var options = new JsonSerializerOptions
{
IgnoreNullValues = true,
// PropertyNamingPolicy = new LowerCaseNamingPolicy()
};
List jsonFormat = new List();
jsonFormat.Add(new JsonFormat() {series = formatedData, granularity = "minutely", customInterval = 1, period = 90, sensitivity = 85});
string dataToSend = JsonSerializer.Serialize(jsonFormat, options);
// Call anomaly detection API
var anomalies = detectAnomaliesBatch(dataToSend, log);
if (anomalies != null){
var json = JsonSerializer.Serialize(anomalies);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client1.PostAsync(emailAlertUrl, content);
log.LogInformation(response.ToString());
}
}
static async Task Request(string apiAddress, string endpoint, string subscriptionKey, string requestData)
{
using (HttpClient client = new HttpClient { BaseAddress = new Uri(apiAddress) })
{
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
var res = await client.PostAsync(endpoint, content);
return await res.Content.ReadAsStringAsync();
}
}
static string detectAnomaliesBatch(string requestData, ILogger log)
{
log.LogInformation("Detecting anomalies as a batch");
requestData = requestData.TrimEnd(']').TrimStart('[');
//construct the request
var result = Request(
endpoint,
batchDetectionUrl,
subscriptionKey,
requestData).Result;
//deserialize the JSON object, and display it
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
System.Console.WriteLine(jsonObj);
string foundAnomalies = "Anomalies detected in the following data positions: ";
if (jsonObj["code"] != null)
{
System.Console.WriteLine($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
log.LogInformation($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
}
else
{
// log.LogInformation(result);
//Find and display the positions of anomalies in the data set
bool[] anomalies = jsonObj["isAnomaly"].ToObject<bool[]>();
System.Console.WriteLine("\nAnomalies detected in the following data positions:");
log.LogInformation("\nAnomalies detected in the following data positions:");
for (var i = 0; i < anomalies.Length; i++)
{
if (anomalies[i])
{
System.Console.Write(i + ", ");
log.LogInformation(i + ", ");
foundAnomalies += i;
foundAnomalies += ", ";
}
}
if (anomalies.Any(item => item == true))
{
return foundAnomalies;
}
}
return null;
}
public class FormatedData
{
public string timestamp { get; set; }
public string value { get; set; }
}
public class DataPoint : TableEntity
{
[JsonPropertyName("value")]
public string temperature { get; set;}
public string timestamp { get; set; }
}
public class JsonFormat
{
public List series { get; set; }
public string granularity { get; set; }
public int customInterval { get; set; }
public int period { get; set; }
// public float maxAnomalyRatio { get; set; }
public int sensitivity { get; set; }
}
public class LowerCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name) =>
name.ToLower();
}
配置邏輯應(yīng)用
1. 部署完成后,使用左側(cè)導(dǎo)航打開新創(chuàng)建的 Logic App
2.從左側(cè)導(dǎo)航中選擇邏輯應(yīng)用程序設(shè)計(jì)器
3.選擇+新步驟
4. 搜索您要使用的電子郵件客戶端(Office 365 Outlook、Gmail 和 Outlook.com)
5. 選擇發(fā)送電子郵件操作
注意:這將根據(jù)您使用的電子郵件客戶端而有所不同
6. 使用您的電子郵件帳戶登錄
7. 自定義您的消息,此電子郵件將在任何時(shí)候檢測到異常時(shí)發(fā)送。
設(shè)置物聯(lián)網(wǎng)設(shè)備
1. 接下來,您需要獲取設(shè)備的連接字符串,導(dǎo)航到您之前創(chuàng)建的 IoT 中心
2.在左側(cè)導(dǎo)航中選擇物聯(lián)網(wǎng)設(shè)備
3.在頁面左上角選擇+新建
4.給設(shè)備一個(gè)ID
5. 按屏幕底部的保存
6.選擇您創(chuàng)建的設(shè)備
7. 復(fù)制您將在下一節(jié)中使用的主連接字符串
設(shè)備構(gòu)建
1. 將螺絲端子焊接到 MCP9600 的頂部。
2. 將引腳焊接到 MCP9600 的底部。
提示:將引腳放在面包板上,以便在焊接時(shí)將它們固定到位。
3. 將 ESP32 和熱電偶放大器插入面包板。
4. 按照下面的接線圖,使用跳線將熱電偶放大器連接到 ESP32。
5. 將熱電偶連接到 MCP9600 上的螺絲端子
下圖使用通用 ESP32 開發(fā)板,即將推出帶有 Adafruit Huzzah32 的新圖片!
設(shè)備代碼
1. 如果您還沒有,請將此 repo 克隆到您的計(jì)算機(jī)
2.用VS Code打開AiFreezer文件夾
3.在這個(gè)文件夾中新建一個(gè)文件,命名為config.h
4. 將以下代碼粘貼到config.h
const char* ssid = "" ;
const char* password = "" ;
static const char* connectionString = "" ;
5. 填寫您的網(wǎng)絡(luò)憑據(jù)
6. 從 IoT 中心粘貼連接字符串
7. 按照本 [指南] 的第一部分將 ESP32 擴(kuò)展添加到 Arduino IDE。
8. 使用 Arduino 的庫管理器安裝下面列出的庫。如果您在 [此處]之前使用過庫管理器,這是一個(gè)有用的指南。
9. Adafruit MCP9600
注意:如果系統(tǒng)提示您為這些庫安裝其他依賴項(xiàng),請選擇全部安裝
10. 在 VS Code 中打開 FreezerTempAlert.ino,打開命令面板(CTL+SHIFT+P)并輸入Arduino:Change Board Type然后搜索Adafruit ESP32 Feather
11.接下來選擇活動串口,打開命令面板并輸入Arduino:選擇串口
12. 最后將您的代碼上傳到您的羽毛板,打開命令面板并輸入Arduino:
- 使用Azure MT3620和Azure IoT Central的風(fēng)車監(jiān)視器
- 洗衣機(jī)監(jiān)視器MEGR 3171開源
- 4至14芯電池組監(jiān)視器的模擬前端芯片OZ9355 63次下載
- 多電池監(jiān)視器LTC6811-1/LTC6811-2數(shù)據(jù)手冊 47次下載
- 溫度監(jiān)視器
- 高壓電池監(jiān)視器
- 使用單片機(jī)實(shí)現(xiàn)實(shí)用熱水器監(jiān)視器源程序免費(fèi)下載 13次下載
- 如何使用MCP39F511功率監(jiān)視器演示板來評估MCP39F511器件的概述
- MPLAB REAL ICE在線仿真器功率監(jiān)視器的介紹和使用指南詳細(xì)概述
- MPLAB REAL ICE在線仿真器功率監(jiān)視器使用說明書中文概述
- 雙向電流功率監(jiān)視器 8次下載
- 冷凍機(jī)系統(tǒng)的組成及冷凍干燥機(jī)的原理介紹 5次下載
- 基于單片機(jī)的靜脈輸液監(jiān)視器工程實(shí)現(xiàn)
- DINAMAP血壓監(jiān)視器原理分析與故障維修
- 冷凍機(jī)油庫防雷及防靜電圖
- 典型電池監(jiān)視器電路圖分享 604次閱讀
- 簡單的電池監(jiān)視器電路圖 557次閱讀
- 如何創(chuàng)建自定義監(jiān)視器? 516次閱讀
- 光纖應(yīng)用中的監(jiān)視器校準(zhǔn) 880次閱讀
- 如何通過Raspberry Pi設(shè)置CE電流監(jiān)視器 2120次閱讀
- ISL28022數(shù)字功率監(jiān)視器評估套件及相關(guān)基礎(chǔ)知識 2966次閱讀
- Cypress懷孕監(jiān)視器CY8C38系列的性能特性及應(yīng)用方案 2354次閱讀
- KUKA C4如何使用診斷監(jiān)視器? 3595次閱讀
- 具監(jiān)視器的800mA單電阻器堅(jiān)固型線性穩(wěn)壓器LT3089 1123次閱讀
- 單片機(jī)PIC16的外設(shè)--故障保護(hù)時(shí)鐘監(jiān)視器解析 1944次閱讀
- 揭秘液晶顯示器和液晶監(jiān)視器的七大不同點(diǎn) 2091次閱讀
- 鋰離子電池和穩(wěn)壓器監(jiān)視器電路圖 1767次閱讀
- 基于LTC2991系統(tǒng)監(jiān)視器的相對濕度測量 1934次閱讀
- 液晶監(jiān)視器的選購與保養(yǎng) 1022次閱讀
- 120Hz+全高清LCD監(jiān)視器新技術(shù)應(yīng)用解析 1335次閱讀
下載排行
本周
- 1ADI高性能電源管理解決方案
- 2.43 MB | 445次下載 | 免費(fèi)
- 2免費(fèi)開源CC3D飛控資料(電路圖&PCB源文件、BOM、
- 5.67 MB | 133次下載 | 1 積分
- 3基于STM32單片機(jī)智能手環(huán)心率計(jì)步器體溫顯示設(shè)計(jì)
- 0.10 MB | 120次下載 | 免費(fèi)
- 4如何正確測試電源的紋波
- 0.36 MB | 3次下載 | 免費(fèi)
- 5550W充電機(jī)原理圖
- 0.13 MB | 2次下載 | 6 積分
- 6USB的PD快充協(xié)議電壓誘騙控制器FS312A中文手冊
- 1.51 MB | 2次下載 | 免費(fèi)
- 7USB Type_C PD快充協(xié)議智能觸發(fā)芯片F(xiàn)S8025B應(yīng)用手冊
- 1.48 MB | 1次下載 | 免費(fèi)
- 8基于三相二電平PFC和隔離DC-DC轉(zhuǎn)換器的11kW雙向電池充電器
- 618.10 KB | 1次下載 | 免費(fèi)
本月
- 1ADI高性能電源管理解決方案
- 2.43 MB | 445次下載 | 免費(fèi)
- 2免費(fèi)開源CC3D飛控資料(電路圖&PCB源文件、BOM、
- 5.67 MB | 133次下載 | 1 積分
- 3基于STM32單片機(jī)智能手環(huán)心率計(jì)步器體溫顯示設(shè)計(jì)
- 0.10 MB | 120次下載 | 免費(fèi)
- 4使用單片機(jī)實(shí)現(xiàn)七人表決器的程序和仿真資料免費(fèi)下載
- 2.96 MB | 44次下載 | 免費(fèi)
- 53314A函數(shù)發(fā)生器維修手冊
- 16.30 MB | 31次下載 | 免費(fèi)
- 6美的電磁爐維修手冊大全
- 1.56 MB | 22次下載 | 5 積分
- 7使用TL431設(shè)計(jì)電源
- 0.67 MB | 8次下載 | 免費(fèi)
- 8感應(yīng)筆電路圖
- 0.06 MB | 8次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935119次下載 | 10 積分
- 2開源硬件-PMP21529.1-4 開關(guān)降壓/升壓雙向直流/直流轉(zhuǎn)換器 PCB layout 設(shè)計(jì)
- 1.48MB | 420062次下載 | 10 積分
- 3Altium DXP2002下載入口
- 未知 | 233084次下載 | 10 積分
- 4電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191367次下載 | 10 積分
- 5十天學(xué)會AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183335次下載 | 10 積分
- 6labview8.5下載
- 未知 | 81581次下載 | 10 積分
- 7Keil工具M(jìn)DK-Arm免費(fèi)下載
- 0.02 MB | 73807次下載 | 10 積分
- 8LabVIEW 8.6下載
- 未知 | 65987次下載 | 10 積分
評論
查看更多