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:

  1. Acesse http://www.windowsondevices.come clique em Downloads para baixar o Windows IoT Core Dashboard;
  2. 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; } } } }

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>