Taula de continguts:

EAL-Industri4.0-RFID Dataopsamling Til Database: 10 passos (amb imatges)
EAL-Industri4.0-RFID Dataopsamling Til Database: 10 passos (amb imatges)

Vídeo: EAL-Industri4.0-RFID Dataopsamling Til Database: 10 passos (amb imatges)

Vídeo: EAL-Industri4.0-RFID Dataopsamling Til Database: 10 passos (amb imatges)
Vídeo: Technology Stacks - Computer Science for Business Leaders 2016 2024, Desembre
Anonim
EAL-Industri4.0-RFID Dataopsamling Til Database
EAL-Industri4.0-RFID Dataopsamling Til Database

Dette projekt omhandler opsamling af vægtdata, registring by identiteter vha. RFID, restant a les dades i a la base de dades MySQL. node-RED, us permetrà gestionar les dades opsamlede i el programa C # i form a Windows Form Application. Vi forestiller os følgende:

Es produeix un producte productiu amb un pal de producció de 200 g. Tots els registres de publicació poden utilitzar-se amb etiquetes RFID i etiquetes, un indeholder i unikt ID (UID = Unique Identifier, en 32 bits kode, 8 hexadecimale karakterer) for entydig identification by hver enkelt bakke leverpostej. Da færdigvægten af hver enkelt bakke leverpostej kan svinge (afhængig af råvarer, fordampning i ovn mm), og da kunderne hver har et specifikt krav færdigvægten, bruges UID tagget til at knytte hver enkelt leverpostej til in specifik lagerlokation på lager leverpostejer til én specifik kunde. Kunderne er supermarkedskæder:

1. Irma. Vægten på Irmas luksus leverpostej skal holde sig inden for +/- 5%, altså minimum 190g og maksimum 210g.

2. Brugsen. Vægten på Brugsens leverpostej skal holde sig inden for +/- 10%, altså minimum 180g og maksimum 220g.

3. Aldi. Vægten på Aldis discount leverpostej skal holde sig inden for +/- 15%, altså minimum 170g og maksimum 230g.

Der er således følgende sorteringer:

Range0: fora del rang

Rang 1: mínim 190 g / màxim 210 g

Rang 2: mínim 180 g / màxim 220 g

Rang 3: mínim 170 g / màxim 230 g

Pas 1: analitzar dades af per registrar el registre Sam UID Af UID

Esborranyar dades af per registrar el registre UID Af Aft
Esborranyar dades af per registrar el registre UID Af Aft

Feu servir dades de dades per registrar-les i etiquetes RFID amb Arduino MEGA2560 i lector / escriptor RFID-RC522. Da vi ikke har nogen vægt, simulerer vi data for vægten med et potmeter tilsluttet in analog indgang på Arduinoen.

Fjlgende opstilling er anvendt:

1 stk potmeter 25k lineært. Yder-benene er tilsluttet hhv. GND og + 5V, midterbenet er tilsluttet AN0

RFID-RC522 és un port SPI per a taulers Arduino:

SDA -> pin 53

SCK -> pin52

MOSI -> pin51

MISO-> pin50

IRQ -> NC

GND -> GND

RST -> pin5

3,3V -> 3,3V

Dades opsamlede, per a hhv. UID og vægten, sendes på den serielle port som in komma-separeret tekststreng videre til node-Red som står for den efterfølgende præsentation på et dashboard og lagring i en database.

Pas 2: programa Arduino

El programa Arduino inclou programes de biblioteques SPI.h og MFRC522.h for at kunne bruge RFID læseren. Vaig iniciar un programa inicialitzat amb una variable variable. Der laves en instans af MFRC522. I Setup blokken initialiseres in serielle forbindelse, SPI porten og MFRC522. Posteriorment, escaneja les etiquetes RFID. For ikke at sende det samme UID afsted flere gange efter hinanden, er der lavet en stump kode som tjekker for dette. Når der er scannet et UID tag, loades arary nyUID med det netop læste UID. Hvis array nyUID er forskellig fra oldUID er der tale om et nyt UID som kan sendes på den serielle port. Hvis nyUID og oldUID er ens, er der tale om samme UID tag og UID'et skal ignoreres. Hvis der er tale om et nyt UID, sendes UID'et på den serielle port sammen med en læst værdi fra den serielle port. Den analoge værdi skaleres til området 150-250. Les dades s’envien en format de text separador. Som det sidste sættes oldUID = nyUID, således at koden klart til at læse et nyt tag RFID.. Den sidste funktion i programmet er den funktion som sammenligner 2 arrays. Funktionen returnerer true hvis array'ne er ens, og false hvis array'ne er forskellige.

#incloure

#include // Aquest programa escaneja les targetes RFID mitjançant la placa lector / escriptor RDIF-RC522. // Es llegeix UID, es llegeix un pin analògic. El valor analògic 0-1023 s’amplia a 150-250. // El valor analògic i UID s’envia com a text separat per comes al port sèrie mitjançant 9600, N, 8, 1. // S’ha tingut cura d’enviar cada UID només una vegada seguida, // s’ha d’haver un nou UID present abans que es pugui tornar a enviar el mateix UID. // Aquesta funció s’implementa al codi comparant matrius: oldUID nyUID a la funció array_cmp (oldUID , nyUID )

constexpr uint8_t RST_PIN = 5;

constexpr uint8_t SS_PIN = 53; int sensorPin = A0; valor int = 0; String StringValue = "0000"; byte oldUID [4] = {}; byte nyUID [4] = {};

MFRC522 mfrc522 (SS_PIN, RST_PIN); // Creeu una instància MFRC522.

configuració nul·la ()

{Serial.begin (9600); // Inicieu una comunicació serial SPI.begin (); // Inicieu el bus SPI mfrc522. PCD_Init (); // Inicieu MFRC522}

bucle buit ()

{// Cerqueu targetes noves si (! Mfrc522. PICC_IsNewCardPresent ()) {return; } // Seleccioneu una de les cartes si (! Mfrc522. PICC_ReadCardSerial ()) {return; } // carrega nyUID amb etiqueta UID per (byte i = 0; i <mfrc522.uid.size; i ++) {nyUID = mfrc522.uid.uidByte ; } // if oldUID nyUID if (! array_cmp (oldUID, nyUID)) {// enviar etiqueta UID al port sèrie per (byte i = 0; i 1000) {Valor = 1000; } Valor = (Valor / 10) + 150; // enviar valor analògic a escala Serial.print (Valor); // enviar nova línia Serial.println (); // set oldUID = nyUID per a (byte z = 0; z <4; z ++) oldUID [z] = nyUID [z]; } // espera 1 s de retard (1000); }

// compara 2 matrius …

array_cmp booleà (byte a , byte b ) {bool test = true; // proveu que cada element sigui el mateix. si només no ho és, torneu false per (byte n = 0; n <4; n ++) {if (a [n]! = b [n]) test = false; // si el byte no és igual, test = false} if (test == true) retorna true; en cas contrari, torneu a fals; }

Pas 3: Node-RED, base de dades Lagring Af Data I

Node-RED, base de dades Lagring Af Data I
Node-RED, base de dades Lagring Af Data I
Node-RED, base de dades Lagring Af Data I
Node-RED, base de dades Lagring Af Data I

El flux de lavabo i node-RED:

COM4 és una sèrie de modificacions de dades prohibides entre el tauler Arduino. Funktionerne "Split and Get value" og "Split and Get UID" splitter teksstrengen ved kommaet og returnere hhv vægten og UID. Vægten bruges til fremvisning på dashboardet i et linechart og en scale. UID fremvises i et tekstfelt. Funktionen test_sound advarer verbalt med sætningen "Out of range", hvis vægten er under 170g eller over 230g, dvs i range 0.

Dividiu i obteniu valor:

var sortida = msg.payload.split (',');

temp = {càrrega útil: (sortida [1])}; temperatura de retorn;

Dividiu i obteniu UID:

var output = msg.payload.split (",");

temp = {càrrega útil: sortida [0]}; temperatura de retorn;

so_prova:

var number = parseInt (msg.payload);

if (número> 230 || número <170) {newMsg = {càrrega útil: "Fora del rang"}; torna newMsg; } else {newMsg = {càrrega útil: ""}; torna newMsg; }

Funktionen Split string "," indsætter and timestamp, UID og vægten i in database patedb.patelog.

var output = msg.payload.split (","); // divideix msg.payload per comes en matriu

UIDTag = sortida [0]; // primera part a la primera posició [0] ValueTag = sortida [1]; // segona part en segona posició [1]

var m = {

tema: "INSERT INTO patedb.patelog (timestamp, UID, weight) VALUES ('" + New date (). toISOString () + "', '" + UIDTag + "', '" + ValueTag + "');" }; tornar m;

patelog er a MySQL database forbindelse som er sat op følgende parametre:

Amfitrió: localhost

Port: 3306

Usuari: root

Base de dades: patedb

Pas 4: disseny de bases de dades

Disseny de bases de dades
Disseny de bases de dades

Databasen patedb indeholder 4 tauler

registre de dades patrons de registre, dades de programació de nodes-RED i programari C #

ordertable er en tabel som indeholder data om de genemførte ordrer, tilskrives data af C # programmet

customertable er et kunderegister

rangetable er en tabel som indeholder grænseværdierne for de i C # programmet benyttede range.

Pas 5: Patelog

Patelog
Patelog

Tabellen patelog indeholder folgende 6 kolonner:

pateID (int) er key key og inkrementeres automatisk.

Timestamp, UID & vægt er af typen varchar (med forskellig max længde)

rangeNr er typen tinyint (beregnes og tilføjes af C # programmet)

orderID er typen int (orderID tilføjes af C # programmet)

Node-RED tilføjer ikke værdier til kolonnerne rangeNr og orderID. rangeNr og orderID tillader NULL værdier, det bruges i C # programmet til to detektere de rækker som skal tilskrives værdier for rangeNr og orderID

Pas 6: ordenable

Ordenable
Ordenable

ordinador indeholder 5 kolonner:

orderID (int) er det aktuelle ordrenummer

orderQuant (mediumint) er ordens pålydende antal

quantProduced (mediumint) er antal der rent faktisk er produceret på ordren. (Descripció del programa C #)

comment (tinytext) er en eventuel kommentar til ordren.

customerID (int) er det aktuelle kundenummer på ordren.

Pas 7: personalitzable

Personalitzable
Personalitzable

personalitzable indeholder 6 kolonner:

customerID (int) és la clau principal og auto inc.

nom, adreça, telèfon, correu electrònic (varchar) med forskellig max længde

rangeNr (int)

Pas 8: Rangetable

Rangetable
Rangetable

rangetable indeholder 3 kolonner:

rangeNr (int) er clau principal og auto inc.

rangeMin (int)

rangeMax (int)

Pas 9: programa C #

Programa C #
Programa C #

Når der produceres en ordre leverpostej, er procedureuren følgende:

Kundenummer, ordrenummer, ordreantal og en eventuel kommentar indtastes i C # programmet (i praksis overføres det digitalt fra virksomhedens ordresystem. Produktionen startes nu ved tryk på 'start'- knappen. Når en leverpostej er færdigproduceret og låget er monteret, vteren på et transportbånd) Samhørende værdier af UID og den aktuelle vægt sendes serielt til node-RED, som viser de opsamlede data på dashboard 'et. Samtidig skrives timestamp, UID og vægt i en ny række i patedb.patelog tabellvæ Da der. tidspunkt ikke tilskrives værdier til rangeNr og orderID vil de have værdien NULL.

Med et timerinterval undersøger C # programmet patedb.patelogtabellen for nye tilkomne rækker med NULL værdier i rangeNr kolonnen. Når der er detekteret en række med NULL værdi, beregnes rangeNr og det tilføjes sammen med det aktuelle orderID. Når en ordre er produceret, afsluttes ordren ved tryk på”stop” - knappen. Når ordren afsluttes, tilføjes en række til patedb.ordertable med de aktuelle ordredata. Når en ordre er afsluttet, kan kan of opsamlede data i patelog tabellen fremvises ved at trykke på de forskellige knapper i gruppen Update DataGridview. ordertable kan også vises, og der kan søges ordredata på individueller UID'er eller kundedata på individuelle ordrer.

utilitzant System; utilitzant System. Collections. Generic; utilitzant System. ComponentModel; utilitzant System. Data; utilitzant System. Drawing; utilitzant System. Linq; utilitzant System. Text; utilitzant System. Threading. Tasks; utilitzant System. Windows. Forms; utilitzant MySql. Data. MySqlClient;

espai de noms show_data_from_database

{public partial class Form1: Form {MySqlConnection connection = new MySqlConnection ("datasource = localhost; username = root; password = ''"); int RowNumber = 0; // Variable per emmagatzemar el valor pateID int RangeNumber = 0; // Variable per emmagatzemar el nombre de rang int weight = 0; // Variable per emmagatzemar el pes int OrderNr = 0; // Variable per emmagatzemar OrderNR int QuantProduced = 0; // Variable per emmagatzemar la quantitat produïda int NumberOfRows = 0; // nombre de files amb nuls.. bool ProdRunning = false; // Variable que indica si els botons d'inici i parada s'han activat int limits = new int [6]; // inicialitza la matriu int CustomerID; // Variable per emmagatzemar formulari públic ID client () {InitializeComponent (); load_table (); // trucar a load_table}

void load_table ()

{Comanda MySqlCommand = new MySqlCommand ("SELECT * FROM patedb.patelog ORDRE BY timestamp DESC;", connection); proveu {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = ordre; DataTable dbdataset = new DataTable (); adapter. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = font; SetRowOrder (); adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }}

private void SetRowOrder ()

{dataGridView1. Columns ["pateID"]. DisplayIndex = 0; // Her can rækkefølgen af kolonner ændres dataGridView1. Columns ["timestamp"]. DisplayIndex = 1; // Her kan rækkefølgen af kolonner ændres dataGridView1. Columns ["UID"]. DisplayIndex = 2; // Her kan rækkefølgen af kolonner ændres dataGridView1. Columns ["weight"]. DisplayIndex = 3; // Her kan rækkefølgen af kolonner ændres dataGridView1. Columns ["rangeNr"]. DisplayIndex = 4; // Her kan rækkefølgen af kolonner ændres dataGridView1. Columns ["orderID"]. DisplayIndex = 5; // Her kan rækkefølgen af kolonner ændres}

private void GetData_Click (remitent d'objectes, EventArgs e) // Llegeix la taula de bases de dades i les ordres per marca de temps

{load_table (); }

private void btnRefreshUID_Click (remitent d'objectes, EventArgs e) //

{string timeStr = "SELECT * FROM patedb.patelog ORDRE PER UID;"; Ordre MySqlCommand = new MySqlCommand (timeStr, connexió); proveu {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = ordre; DataTable dbdataset = new DataTable (); adapter. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = font; SetRowOrder (); adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }}

private void btnRefreshValue_Click (remitent d'objectes, EventArgs e)

{string weightSort = "SELECT * FROM patedb.patelog ORDRE PER CAST (pes COM INTEGRE SIGNAT);"; Ordre MySqlCommand = new MySqlCommand (weightSort, connexió); proveu {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = ordre; DataTable dbdataset = new DataTable (); adapter. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = font; SetRowOrder (); adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }}

private void ChkNullBtn_Click (remitent d'objectes, EventArgs e)

{if (ProdRunning) {CheckTableForNull (); load_table (); }}

private void CheckTableForNull ()

{// Comproveu / configureu l'interval de temps mínim 100 ms int i; int. TryParse (textTimer1. Text, out i); if (i <100) {timer1. Stop (); i = 100; timer1. Interval = i; MessageBox. Show ("Valor mínim i 100 mS"); temporitzador 1. Start (); } else {timer1. Interval = i; } textTimer1. Text = timer1. Interval. ToString (); // Comproveu si hi ha cap fila amb nuls disponibles a la taula, retorna el nombre de files de la variable: NumberOfRows string weightStr = ""; string chkNull = "SELECT COUNT (*) FROM patedb.patelog WHERE rangeNR IS NULL ORDER BY PateID LIMIT 1;"; Ordre MySqlCommand = new MySqlCommand (chkNull, connexió); prova {connection. Open (); NumberOfRows = Convert. ToInt32 (command. ExecuteScalar ()); connection. Close (); } catch (Exception ex) {MessageBox. Show (ex. Message); } finalment {if (NumberOfRows! = 0) {try {// Selecciona el número de identificador de pate més baix on rangeNr és NULL string readID = "SELECCIONA pateID DE patedb.patelog WHERE rangeNR IS NULL ORDER BY pateID ASC LIMIT 1;"; MySqlCommand cmdID = nou MySqlCommand (readID, connexió); {connection. Open (); RowNumber = (int) cmdID. ExecuteScalar (); //enter!! connection. Close (); } listPateID. Text = RowNumber. ToString (); // llegeix el número PateID seleccionat // Selecciona el pes de la cadena de números de fila seleccionada fila = RowNumber. ToString (); string readweight = "SELECCIONA el pes DE patedb.patelog WHERE pateID =" + fila; MySqlCommand cmdweight = new MySqlCommand (readweight, connexió); {connection. Open (); weightStr = (string) cmdweight. ExecuteScalar (); // Corda !! connection. Close (); } pes = int. Parse (weightStr); // convertir a int txtWeight. Text = weight. ToString (); // print int RangeNumber = 0; if (pes> = límits [0] && pes = límits [2] && pes = límits [4] && pes <= límits [5]) {RangeNumber = 3; }} txtRange. Text = RangeNumber. ToString (); UpdateLog (); } catch (Exception ex) {MessageBox. Show (ex. Message); } QuantProduced = QuantProduced + 1; }}} private void btnStart_Click (remitent d'objectes, EventArgs e) {if (ProdRunning == false) {int valtest; proveu {CustomerID = int. Parse (txtCustomerNr. Text); // readID client} catch {MessageBox. Show ("Introduïu les dades de producció i premeu el botó" Inici "."); }

string test = "SELECT COUNT (*) FROM patedb.customertable WHERE customerID =" + CustomerID;

MySqlCommand cmdtestcustomer = new MySqlCommand (prova, connexió); {connection. Open (); valtest = Convert. ToInt32 (cmdtestcustomer. ExecuteScalar ()); // retorna 0 si el client no existeix connexió. Tancar (); } if (valtest == 1) // si el client existeix a la base de dades: comenceu la producció {proveu {OrderNr = int. Parse (txtOrderNumber. Text); ProdRunning = cert; temporitzador 1. Start (); textTimer1. Text = timer1. Interval. ToString (); ReadLimits (); } catch (Exception ex) {MessageBox. Show ("Introduïu dades de producció i premeu el botó" Inici "."); }} else MessageBox. Show ("El client no està a la base de dades, torneu-ho a provar"); } // ReadLimits (); }

private void ReadLimits ()

{// Llegeix els límits de la taula de rang, interval 1 a 3 int comptador = 0; for (int rangeNr = 1; rangeNr <4; rangeNr ++) {string readmin = "SELECT rangeMin FROM patedb.rangetable WHERE rangeNr =" + rangeNr; MySqlCommand cmdmin = new MySqlCommand (readmin, connexió); {connection. Open (); limits [comptador] = (int) cmdmin. ExecuteScalar (); comptador = comptador + 1; connection. Close (); } // MessageBox. Show (counter. ToString ()); string readmax = "SELECT rangeMax FROM patedb.rangetable WHERE rangeNr =" + rangeNr; MySqlCommand cmdmax = new MySqlCommand (readmax, connexió); {connection. Open (); limits [comptador] = (int) cmdmax. ExecuteScalar (); comptador = comptador + 1; connection. Close (); }} // final per bucle}

private void UpdateLog ()

{// UPDATE rangeNR & orderID string Range = RangeNumber. ToString (); cadena Order = OrderNr. ToString (); string update = "UPDATE patedb.patelog SET rangeNr =" + Range + ',' + "orderID =" + OrderNr + "WHERE pateID =" + RowNumber; MySqlCommand updatecmd = new MySqlCommand (actualització, connexió); prova {connection. Open (); updatecmd. ExecuteNonQuery (); connection. Close (); } catch (Exception ex) {MessageBox. Show (ex. Message); }}

private void btnStop_Click (remitent d'objectes, EventArgs e)

{if (ProdRunning == true) {timer1. Stop (); ProdRunning = fals; UpdateOrderTable (); } else {MessageBox. Show ("Encara no s'ha iniciat cap producció. Introduïu dades i premeu el botó" Inici "); }}

private void UpdateOrderTable ()

{string insert = "INSERT INTO patedb.ordertable (orderID, orderQuant, quantProduced, comment, customerID) VALUES ('" + this.txtOrderNumber. Text + "', '" + this.txtOrderQuant. Text + "', '" + QuantProduced. ToString () + "','" + this.txtComment. Text + "','" + this.txtCustomerNr. Text + "');"; MySqlCommand insertcmd = new MySqlCommand (insert, connection); prova {connection. Open (); insertcmd. ExecuteNonQuery (); connection. Close (); QuantProduced = 0; } catch (Exception ex) {MessageBox. Show (ex. Message); }}

private void timer1_Tick (remitent d'objectes, EventArgs e)

{CheckTableForNull (); load_table (); }

private void btnShowOrderTable_Click (remitent d'objectes, EventArgs e)

{if (ProdRunning == false) {MySqlCommand command = new MySqlCommand ("SELECT * FROM patedb.ordertable ORDER BY orderID DESC;", connection); proveu {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = ordre; DataTable dbdataset = new DataTable (); adapter. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = font; adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }} else {MessageBox. Show ("Premeu stop per canviar la comanda"); }}

private void btnShowOrderDetails_Click (remitent d'objectes, EventArgs e)

{if (ProdRunning == false) {string test = ("SELECT patedb.ordertable.orderID, orderQuant, quantProduced, comment, customerID FROM patedb.ordertable INNER JOIN patedb.patelog ON patedb.patelog.orderID = patedb.ordertable.orderID WHERE patedb.patelog. UID = '"+ txtShowOrderDetails. Text +"' "); Ordre MySqlCommand = new MySqlCommand (prova, connexió); prova {connection. Open (); MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = ordre; DataTable dbdataset = new DataTable (); adapter. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = font; adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); } connection. Close (); } else {MessageBox. Show ("Premeu Stop per veure els detalls de la comanda"); }}

private void btnShowCustomerDetails_Click (remitent d'objectes, EventArgs e)

{if (ProdRunning == false) {string test = ("SELECT patedb.customertable.customerID, name, address, phone, email, rangeNr FROM patedb.customertable INNER JOIN patedb.ordertable ON patedb.ordertable.customerID = patedb.customertable. customerID WHERE patedb.ordertable.orderID = '"+ txtShowCustomerDetails. Text +"' "); Ordre MySqlCommand = new MySqlCommand (prova, connexió); proveu {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = ordre; DataTable dbdataset = new DataTable (); adapter. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = font; adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }} else {MessageBox. Show ("Premeu stop per veure les dades del client"); }}}

}

Recomanat: