Introduction: Previsão De Acidentes Em Maquinário Industrial
Nesse tutorial mostraremos como implementar um sistema para prevenção de acidentes que pode ser aplicado em fábricas e indústrias usando uma DragonBoard 401c e o sensor de temperatura DS20B18.
Essa é uma versão genérica que utiliza somente o sensor de temperatura para fazer a leitura dos dados e informar para o algorítimo. Esse algoritmo irá consultar em um pequeno "banco de dados" e determinar se aquela determinada temperatura, em conjunto a outros fatores(ex.: vazamento de gás e umidade do ar), está inconsistente com o padrão, podendo assim ocasionar acidentes graves.
Step 1: Montagem
Como esta montagem requer algumas ligações utilizamos também uma Breadboard, pois é bastante fácil de utilizar e ajuda nas ligações dos vários componentes. Aconselho em primeiro lugar a montagem do sensor DS18B20, pois a montagem requer alguns cuidados, só depois da montagem do sensor de temperatura conectaremos os jumpers na entrada serial da mezzanine.
Material necessário:
- DragonBoard 401c;
- Protoboard;
- Resistência 4.7Ω;
- Jumpers;
- Sensor de temperatura DS18B20;
Instalação do sensor DS18B20:
Como podem verificar na imagem com montagem completa, conetamos os jumpers na entrada serial da mezzanine, cada pino tem uma função especifica (VCC, GND e dois pinos de informações). Para explicar mais facilmente o funcionamento do sensor usamos um esquema que utiliza o Arduíno UNO para ilustrar a pinagem, nessa imagem você pode ver a maneira correta de fazer a ligação dos jumpers com o sensor na protoboard.
Pinos:
Considerando da esquerda para a direita na porta serial (UARTO).
- 1° Vcc;
- 2° Gnd;
- 3° e 4° pinos de comunicação (nesse caso usaremos somete um);
Step 2: Implementação
Agora com a montagem terminada, conectamos a DragonBoard na rede wireless e carregamos o respectivo código.
Instalando o Windows Core IoT:
- Acesse http://www.windowsondevices.come clique em Downloads para baixar o Windows IoT Core Dashboard;
- Clique em GetWindows 10 IoTCore Dashboard, e clique em executar e depois Instalar;
Iremos utilizar o Visual Studio 2017 (VS2017) Community para desenvolver os aplicativos de Internet das Coisas.
O VS2017 Communityé uma ferramenta de desenvolvimento gratuita da Microsoft:
- É possível criar aplicativos para diversos tipos de dispositivos, como PCs, Tablets, Smartphones e para Internet das Coisas, além de ser possível desenvolver aplicações para a Internet, como Web Sites e Web Services
- É um ambiente de desenvolvimento integrado, permitindo inclusive controlar os recursos de banco de dados SQL Server e instâncias do Microsoft Azure dentro da própria plataforma do VS2017.
- No VS2017 é possível criar aplicações para o Windows 10 IoTCore Para tanto, é necessário instalar o IoTProject Templates, que irá permitir que os projetos sejam compilados e enviados para o dispositivo IoT–este último chamado de Deployment
- Para baixar o IoTProject Templates, acesse: https://visualstudiogallery.msdn.microsoft.com/
- Com a extensão do IoTCore instalada, deverá aparecer a opção Windows IoTCore em New Project o templateBackground Application(IoT), que deveremos utilizar.
Biblioteca do sensor no Windows IoT:
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Devices.SerialCommunication; using Windows.Storage.Streams;namespace DS18B201WireLib { class WireSearchResult { public byte[] id = new byte[8]; public int lastForkPoint = 0; } public class OneWire { private SerialDevice serialPort = null; DataWriter dataWriteObject = null; DataReader dataReaderObject = null;
public void shutdown() { if (serialPort != null) { serialPort.Dispose(); serialPort = null; } }
async Task onewireReset(string deviceId) { try { if (serialPort != null) serialPort.Dispose();
serialPort = await SerialDevice.FromIdAsync(deviceId);
// Configure serial settings serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000); serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 9600; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None;
dataWriteObject = new DataWriter(serialPort.OutputStream); dataWriteObject.WriteByte(0xF0); await dataWriteObject.StoreAsync();
dataReaderObject = new DataReader(serialPort.InputStream); await dataReaderObject.LoadAsync(1); byte resp = dataReaderObject.ReadByte(); if (resp == 0xFF) { System.Diagnostics.Debug.WriteLine("Nothing connected to UART"); return false; } else if (resp == 0xF0) { System.Diagnostics.Debug.WriteLine("No 1-wire devices are present"); return false; } else { System.Diagnostics.Debug.WriteLine("Response: " + resp); serialPort.Dispose(); serialPort = await SerialDevice.FromIdAsync(deviceId);
// Configure serial settings serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000); serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000); serialPort.BaudRate = 115200; serialPort.Parity = SerialParity.None; serialPort.StopBits = SerialStopBitCount.One; serialPort.DataBits = 8; serialPort.Handshake = SerialHandshake.None; dataWriteObject = new DataWriter(serialPort.OutputStream); dataReaderObject = new DataReader(serialPort.InputStream); return true; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Exception: " + ex.Message); return false; } }
public async Task onewireWriteByte(byte b) { for (byte i = 0; i < 8; i++, b = (byte)(b >> 1)) { // Run through the bits in the byte, extracting the // LSB (bit 0) and sending it to the bus await onewireBit((byte)(b & 0x01)); } }
async Task onewireBit(byte b) { var bit = b > 0 ? 0xFF : 0x00; dataWriteObject.WriteByte((byte)bit); await dataWriteObject.StoreAsync(); await dataReaderObject.LoadAsync(1); var data = dataReaderObject.ReadByte(); return (byte)(data & 0xFF); }
async Task onewireReadByte() { byte b = 0; for (byte i = 0; i < 8; i++) { // Build up byte bit by bit, LSB first b = (byte)((b >> 1) + 0x80 * await onewireBit(1)); } System.Diagnostics.Debug.WriteLine("onewireReadByte result: " + b); return b; }
public async Task getTemperature(string deviceId) { double tempCelsius = -200;
if (await onewireReset(deviceId)) { await onewireWriteByte(0xCC); //1-Wire SKIP ROM command (ignore device id) await onewireWriteByte(0x44); //DS18B20 convert T command // (initiate single temperature conversion) // thermal data is stored in 2-byte temperature // register in scratchpad memory
// Wait for at least 750ms for data to be collated await Task.Delay(750);
// Get the data await onewireReset(deviceId); await onewireWriteByte(0xCC); //1-Wire Skip ROM command (ignore device id) await onewireWriteByte(0xBE); //DS18B20 read scratchpad command // DS18B20 will transmit 9 bytes to master (us) // starting with the LSB
byte tempLSB = await onewireReadByte(); //read lsb byte tempMSB = await onewireReadByte(); //read msb
// Reset bus to stop sensor sending unwanted data await onewireReset(deviceId);
Implementação:
using DS18B20_1WireBus.Model;
using DS18B201WireLib; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; using Windows.Devices.Enumeration; using Windows.Devices.SerialCommunication; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation;// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace DS18B20_1WireBus { ///
/// An empty page that can be used on its own or navigated to within a Frame. ///public sealed partial class MainPage : Page { private OneWire onewire; private string deviceId = string.Empty; private DispatcherTimer timer; private bool inprog = false; TemperatureModel tempData;
public MainPage() { this.InitializeComponent(); tempData = new TemperatureModel(); deviceId = string.Empty; this.DataContext = tempData; timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromMilliseconds(1200); timer.Tick += Timer_Tick; onewire = new OneWire(); }
private async void StartBtn_Click(object sender, RoutedEventArgs e) { await GetFirstSerialPort(); if(deviceId != string.Empty) { tempData.StatusText = "Reading from device: " + deviceId; tempData.Started = true; timer.Start(); } }
private async void Timer_Tick(object sender, object e) { if (!inprog) { inprog = true; tempData.Temperature = await onewire.getTemperature(deviceId); inprog = false; } }
private void StopBtn_Click(object sender, RoutedEventArgs e) { timer.Stop(); tempData.Started = false; onewire.shutdown(); }
private async Task GetFirstSerialPort() { try { string aqs = SerialDevice.GetDeviceSelector(); var dis = await DeviceInformation.FindAllAsync(aqs); if(dis.Count > 0) { var deviceInfo = dis.First(); deviceId = deviceInfo.Id; } } catch (Exception ex) { tempData.StatusText = "Unable to get serial device: " + ex.Message; } } } }
Attachments
Step 3: Codificação
O código implmenta o algortimo de KNN em C#.
A classe risco implementa as Fetures que foi extraida dos sensores, no caso a temperatura. O método Distace calcula a distância entre dois pontos e o método Classificar passa como paramentro a lista do banco de dados de treinamento e uma temperatura que chegou do sensor. O método Classificar retorna se exite o risco ou não.
<p>List<risco> riscos = New List<risco>();<br></risco></risco></p><p>Riscos.Add(new Risco("Sim", 80)); Riscos.Add(new Risco("Sim", 120)); Riscos.Add(new Risco("Não", 22)); Riscos.Add(new Risco("Sim", 122)); Riscos.Add(new Risco("Sim", 222)); Riscos.Add(new Risco("Não", 23)); Riscos.Add(new Risco("Não", 21)); Riscos.Add(new Risco("Não", 45));</p><p>double[] temperatura = {0.2}</p><p>Classificar(risco, temperatura );</p><p>console.ReadKey();</p><p>public class Risco { string Existe public double[] Features; public Risco(){} { Public Risco(string existe, double temperatura) { this.existe = existe; Fetures = new double[1]; Fetures[0] = temperatura; } }</p><p>private static string Classificar(list<risco> Riscos, double[] fertures) { double value = 0.0; double mimValue = double.MaxValue; string label = string.Empty; for(int i; i < Riscos.Count; i++) { value = Distace(Riscos[i], fertures); if(value < mimValue) { mimValue = value; label = riscos[i].existe; } return label }</risco></p><p>} publica static double Distace(double a[], double[]b) { double sum =0.0; for(int i=0; i < a.Length; i++) { sum +=Math.Pow(a[i] - b[i],2); } return Math.Sqrt(sum); }</p>