Tabla de contenido:
- Paso 1: Opsamling Af Data for Vægt Samt Registrering Af UID
- Paso 2: programa Arduino
- Paso 3: Nodo-RED, base de datos Lagring Af Data I
- Paso 4: diseño de la base de datos
- Paso 5: Patelog
- Paso 6: Ordenar
- Paso 7: personalizable
- Paso 8: tabla de rangos
- Paso 9: Programa C #
Video: EAL-Industri4.0-RFID Dataopsamling Til Database: 10 pasos (con imágenes)
2024 Autor: John Day | [email protected]. Última modificación: 2024-01-30 08:44
Dette projekt omhandler opsamling af vægtdata, registrando un identiteter vha. RFID, datos rezagados en base de datos MySQL vha. node-RED, samt fremvisning og behandling af de opsamlede data i et C # program i for en Windows Form Application. Vi forestiller os følgende:
Vi har en produktionslinje som productor leverpostej i 200g foliebakker. Alle færdigbagte leverpostejer udstyres efter afkøling med et RFID tag i plasticlåget / labelen, som indeholder et unikt ID (UID = Unique Identifier, er en 32 bits kode, 8 hexadecimale karakterer) para la identificación entydig af 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, brujas UID tagget en knytte hver enrettifiktej tillo lagresation en knytte hver enrettifiktej lage lagres leverpostejer til én specifik kunde. Kunderne er supermarkedskæder:
1. Irma. Vægten på Irmas luksus leverpostej skal holde sig inden por +/- 5%, altså mínimo 190g og maksimum 210g.
2. Brugsen. Vægten på Brugsens leverpostej skal holde sig inden por +/- 10%, altså mínimo 180g og maksimum 220g.
3. Aldi. Vægten på Aldis discount leverpostej skal holde sig inden por +/- 15%, altså mínimo 170g og maksimum 230g.
Clasificadora Der er således følgende:
Range0: fuera de rango
Rango 1: mínimo 190 g / máximo 210 g
Rango 2: mínimo 180 g / máximo 220 g
Rango 3: mínimo 170 g / máximo 230 g
Paso 1: Opsamling Af Data for Vægt Samt Registrering Af UID
Hasta examinar los datos para vægt, registrar las etiquetas RFID y anvendt en Arduino MEGA2560 med en RFID-RC522 reader / writer. Da vi ikke har nogen vægt, datos de simulerer vi para vægten med et potmeter tilsluttet en analog indgang på Arduinoen.
Følgende opstilling er anvendt:
1 stk potenciómetro 25k lineært. Yder-benene er tilsluttet hhv. GND og + 5V, midterbenet er tilsluttet AN0
RFID-RC522 er tilsluttet Arduino boardets SPI port på følgende måde:
SDA -> pin 53
SCK -> pin52
MOSI -> pin51
MISO-> pin50
IRQ -> NC
GND -> GND
RST -> pin5
3,3 V -> 3,3 V
Datos de opsamlede, para hhv. UID og vægten, sendes på den serielle port som en komma-separeret tekstreng videre til node-Red som står para den efterfølgende presentation på et dashboard og lagring en una base de datos.
Paso 2: programa Arduino
I Arduino programmet inkluderes de to biblioteker SPI.h og MFRC522.h for at kunne bruge RFID læseren. Empiezo con una inicialización del programa de una variable anvendte. Der laves en instans af MFRC522. I Setup blokken initialiseres den serielle forbindelse, SPI porten og MFRC522. Derefter escanea las etiquetas RFID. Para ikke en 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, carga 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 ignora. 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. Data sendes som en komma-separeret tekstreng. Som det sidste sættes oldUID = nyUID, således en koden klart hasta læse et nyt etiqueta RFID.. Den sidste funktion i programmet er den funktion som sammenligner 2 arrays. Funktionen retornerer true hvis array'ne er ens, og false hvis array'ne er forskellige.
#incluir
#include // Este programa escanea tarjetas RFID usando la placa lectora / grabadora RDIF-RC522. // Se lee UID, se lee un pin analógico. El valor analógico 0-1023 se escala a 150-250. // El UID y el valor analógico se envían como texto separado por comas en el puerto serie usando 9600, N, 8, 1. // Se ha tenido cuidado de enviar cada UID solo una vez consecutiva, // se debe enviar un nuevo UID presente antes de que se pueda enviar de nuevo el mismo UID. // Esta función se implementa en el código comparando matrices: oldUID nyUID en la función array_cmp (oldUID , nyUID )
constexpr uint8_t RST_PIN = 5;
constexpr uint8_t SS_PIN = 53; int sensorPin = A0; int Valor = 0; String StringValue = "0000"; byte oldUID [4] = {}; byte nyUID [4] = {};
MFRC522 mfrc522 (SS_PIN, RST_PIN); // Cree una instancia de MFRC522.
configuración vacía ()
{Serial.begin (9600); // Iniciar una comunicación en serie SPI.begin (); // Iniciar bus SPI mfrc522. PCD_Init (); // Iniciar MFRC522}
bucle vacío ()
{// Busque nuevas tarjetas if (! Mfrc522. PICC_IsNewCardPresent ()) {return; } // Seleccione una de las tarjetas if (! Mfrc522. PICC_ReadCardSerial ()) {return; } // cargar nyUID con etiqueta UID para (byte i = 0; i <mfrc522.uid.size; i ++) {nyUID = mfrc522.uid.uidByte ; } // if oldUID nyUID if (! array_cmp (oldUID, nyUID)) {// enviar etiqueta UID en el puerto serie para (byte i = 0; i 1000) {Value = 1000; } Valor = (Valor / 10) + 150; // enviar valor analógico escalado Serial.print (Value); // enviar nueva línea Serial.println (); // establece oldUID = nyUID para (byte z = 0; z <4; z ++) oldUID [z] = nyUID [z]; } // esperar 1 segundo de retraso (1000); }
// comparar 2 matrices…
boolean array_cmp (byte a , byte b ) {bool test = true; // prueba que todos los elementos sean iguales. si solo uno no lo es, devuelve falso para (byte n = 0; n <4; n ++) {if (a [n]! = b [n]) test = false; // si el byte no es igual, prueba = falso} si (prueba == verdadero) devuelve verdadero; si no, devuelve falso; }
Paso 3: Nodo-RED, base de datos Lagring Af Data I
Følgende flow er lavet i node-RED:
COM4 er den serielle forbindelse hvor data modtages fra Arduino boardet. Funktionerne "Split and Get value" og "Split and Get UID" splitter teksstrengen ved kommaet og return 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 "Fuera de rango", hvis vægten er menos de 170 g mayor de 230 g, dvs i rango 0.
Dividir y obtener valor:
var salida = msg.payload.split (',');
temp = {payload: (salida [1])}; temperatura de retorno;
Dividir y obtener UID:
var salida = msg.payload.split (",");
temp = {payload: output [0]}; temperatura de retorno;
prueba_sonido:
var number = parseInt (msg.payload);
if (número> 230 || número <170) {newMsg = {payload: "Fuera de rango"}; return newMsg; } else {newMsg = {payload: ""}; return newMsg; }
Funktionen Split string "," indsætter et timestamp, UID og vægten en la base de datos patedb.patelog.
var salida = msg.payload.split (","); // dividir msg.payload por coma en una matriz
UIDTag = salida [0]; // primera parte en la primera posición [0] ValueTag = salida [1]; // segunda parte en segunda posición [1]
var m = {
tema: "INSERT INTO patedb.patelog (marca de tiempo, UID, peso) VALUES ('" + nueva Fecha (). toISOString () + "', '" + UIDTag + "', '" + ValueTag + "');" }; return m;
patelog er es Base de datos MySQL forbindelse som er sat op med følgende parametre:
Anfitrión: localhost
Puerto: 3306
Usuario: root
Base de datos: patedb
Paso 4: diseño de la base de datos
Base de datos patedb indeholder 4 tabeller
patelog er dataopsamlingstabellen, tilskrives data af node-RED og C # programmet
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 para las gamas benyttede del programa de i C #.
Paso 5: Patelog
Tabellen patelog indeholder folgende 6 kolonner:
pateID (int) er clave primaria og inkrementeres automatisk.
Marca de tiempo, UID y vægt er af typen varchar (med forskellig max længde)
rangeNr er af typen tinyint (beregnes og tilføjes af C # programmet)
orderID er af 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 hasta detektere de rækker som skal tilskrives værdier para rangeNr og orderID
Paso 6: Ordenar
Titular de mesa ordenable 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. (Programa de Tælles af C #)
comment (tinytext) er en eventuel kommentar til ordren.
customerID (int) er det aktuelle kundenummer på ordren.
Paso 7: personalizable
titular de tabla personalizada 6 kolonner:
customerID (int) er clave primaria og auto inc.
nombre, dirección, teléfono, correo electrónico (varchar) med forskellig max længde
rangeNr (int)
Paso 8: tabla de rangos
indeholder rangetable 3 kolonner:
rangeNr (int) er clave primaria og auto inc.
rangeMin (int)
rangeMax (int)
Paso 9: Programa C #
Når der produceres en ordre leverpostej, er Procedureren 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 (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 tabellenv. Da der pårenv. 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å”detener” - 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 de opsamlede data i patelog tabellen fremvises ved y 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.
usando System; usando System. Collections. Generic; using System. ComponentModel; utilizando System. Data; usando System. Drawing; utilizando System. Linq; usando System. Text; usando System. Threading. Tasks; usando System. Windows. Forms; usando MySql. Data. MySqlClient;
espacio de nombres show_data_from_database
{Public Part1 class Form1: Form {MySqlConnection connection = new MySqlConnection ("datasource = localhost; username = root; password = ''"); int RowNumber = 0; // Variable para almacenar el valor pateID int RangeNumber = 0; // Variable para almacenar rangenumber int weight = 0; // Variable para almacenar el peso int OrderNr = 0; // Variable para almacenar OrderNR int QuantProduced = 0; // Variable para almacenar la cantidad producida int NumberOfRows = 0; // número de filas con nulos.. bool ProdRunning = false; // Variable que indica si se han activado los botones de inicio y parada int limits = new int [6]; // inicializa la matriz int CustomerID; // Variable para almacenar customerID public Form1 () {InitializeComponent (); load_table (); // llamar a load_table}
vacío tabla_de_carga ()
{Comando MySqlCommand = new MySqlCommand ("SELECT * FROM patedb.patelog ORDER BY timestamp DESC;", conexión); intente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = comando; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; SetRowOrder (); adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }}
privado vacío SetRowOrder ()
{dataGridView1. Columns ["pateID"]. DisplayIndex = 0; // Su kan rækkefølgen af kolonner ændres dataGridView1. Columns ["marca de tiempo"]. DisplayIndex = 1; // Su kan rækkefølgen af kolonner ændres dataGridView1. Columns ["UID"]. DisplayIndex = 2; // Su kan rækkefølgen af kolonner ændres dataGridView1. Columns ["peso"]. DisplayIndex = 3; // Su kan rækkefølgen af kolonner ændres dataGridView1. Columns ["rangeNr"]. DisplayIndex = 4; // Su kan rækkefølgen af kolonner ændres dataGridView1. Columns ["orderID"]. DisplayIndex = 5; // Su kan rækkefølgen af kolonner ændres}
private void GetData_Click (remitente del objeto, EventArgs e) // Lee la tabla de la base de datos y los pedidos por marca de tiempo
{load_table (); }
private void btnRefreshUID_Click (remitente del objeto, EventArgs e) //
{string timeStr = "SELECT * FROM patedb.patelog ORDER BY UID;"; Comando MySqlCommand = new MySqlCommand (timeStr, conexión); intente {Adaptador MySqlDataAdapter = new MySqlDataAdapter (); adapter. SelectCommand = comando; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; SetRowOrder (); adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }}
private void btnRefreshValue_Click (remitente del objeto, EventArgs e)
{string weightSort = "SELECT * FROM patedb.patelog ORDER BY CAST (weight AS FIRMADO INTEGER);"; Comando MySqlCommand = new MySqlCommand (weightSort, conexión); intente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = comando; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; SetRowOrder (); adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }}
private void ChkNullBtn_Click (remitente del objeto, EventArgs e)
{if (ProdRunning) {CheckTableForNull (); load_table (); }}
checkTableForNull vacío privado ()
{// Verifica / establece el intervalo de tiempo mínimo 100 ms int i; int. TryParse (textTimer1. Text, out i); if (i <100) {temporizador1. Parar (); i = 100; timer1. Interval = i; MessageBox. Show ("Valor mínimo i 100mS"); timer1. Start (); } else {timer1. Interval = i; } textTimer1. Text = timer1. Interval. ToString (); // Verifica si hay filas con nulo disponibles en la tabla, devuelve el número de filas en la variable: NumberOfRows string weightStr = ""; string chkNull = "SELECT COUNT (*) FROM patedb.patelog DONDE rangeNR ES NULL ORDER BY pateID LIMIT 1;"; Comando MySqlCommand = nuevo MySqlCommand (chkNull, conexión); intente {conexión. Open (); NumberOfRows = Convert. ToInt32 (comando. ExecuteScalar ()); conexión. Cerrar (); } catch (Exception ex) {MessageBox. Show (ex. Message); } finalmente {if (NumberOfRows! = 0) {try {// Selecciona el número pateID más bajo donde rangeNr es NULL string readID = "SELECT pateID FROM patedb.patelog DONDE rangeNR ES NULL ORDER BY pateID ASC LIMIT 1;"; MySqlCommand cmdID = nuevo MySqlCommand (readID, conexión); {conexión. Open (); RowNumber = (int) cmdID. ExecuteScalar (); //¡¡entero!! conexión. Cerrar (); } listPateID. Text = RowNumber. ToString (); // leer el número de PateID seleccionado // Selecciona el peso de la cadena de número de fila seleccionada row = RowNumber. ToString (); string readweight = "SELECCIONE el peso de patedb.patelog DONDE pateID =" + fila; MySqlCommand cmdweight = new MySqlCommand (peso de lectura, conexión); {conexión. Open (); weightStr = (cadena) cmdweight. ExecuteScalar (); //Cuerda !! conexión. Cerrar (); } peso = int. Parse (weightStr); // convertir a int txtWeight. Text = weight. ToString (); // imprimir int RangeNumber = 0; if (peso> = límites [0] && peso = límites [2] && peso = límites [4] && peso <= límites [5]) {RangeNumber = 3; }} txtRange. Text = RangeNumber. ToString (); UpdateLog (); } catch (Exception ex) {MessageBox. Show (ex. Message); } QuantProduced = QuantProduced + 1; }}} private void btnStart_Click (remitente del objeto, EventArgs e) {if (ProdRunning == false) {int valtest; intente {CustomerID = int. Parse (txtCustomerNr. Text); // leer ID de cliente} catch {MessageBox. Show ("Ingrese los datos de producción y presione el botón 'iniciar'."); }
string test = "SELECT COUNT (*) FROM patedb.customertable DONDE customerID =" + CustomerID;
MySqlCommand cmdtestcustomer = new MySqlCommand (prueba, conexión); {conexión. Open (); valtest = Convert. ToInt32 (cmdtestcustomer. ExecuteScalar ()); // devuelve 0 si el cliente no existe connection. Close (); } if (valtest == 1) // si el cliente existe en la base de datos - iniciar la producción {try {OrderNr = int. Parse (txtOrderNumber. Text); ProdRunning = verdadero; timer1. Start (); textTimer1. Text = timer1. Interval. ToString (); ReadLimits (); } catch (Exception ex) {MessageBox. Show ("Ingrese los datos de producción y presione el botón 'iniciar'."); }} else MessageBox. Show ("El cliente no está en la base de datos, inténtelo de nuevo"); } // ReadLimits (); }
ReadLimits vacío privado ()
{// Lee los límites de la tabla de rangos, rango 1 a 3 int contador = 0; for (int rangeNr = 1; rangeNr <4; rangeNr ++) {string readmin = "SELECT rangeMin FROM patedb.rangetable DONDE rangeNr =" + rangeNr; MySqlCommand cmdmin = new MySqlCommand (readmin, conexión); {conexión. Open (); límites [contador] = (int) cmdmin. ExecuteScalar (); contador = contador + 1; conexión. Cerrar (); } // MessageBox. Show (counter. ToString ()); string readmax = "SELECT rangeMax FROM patedb.rangetable DONDE rangeNr =" + rangeNr; MySqlCommand cmdmax = new MySqlCommand (readmax, conexión); {conexión. Open (); límites [contador] = (int) cmdmax. ExecuteScalar (); contador = contador + 1; conexión. Cerrar (); }} // fin del ciclo}
UpdateLog vacío privado ()
{// ACTUALIZAR rangeNR & orderID string Range = RangeNumber. ToString (); string Order = OrderNr. ToString (); string update = "ACTUALIZAR patedb.patelog SET rangeNr =" + Range + ',' + "orderID =" + OrderNr + "WHERE pateID =" + RowNumber; MySqlCommand updatecmd = new MySqlCommand (actualización, conexión); intente {conexión. Open (); updatecmd. ExecuteNonQuery (); conexión. Cerrar (); } catch (Exception ex) {MessageBox. Show (ex. Message); }}
private void btnStop_Click (remitente del objeto, EventArgs e)
{if (ProdRunning == true) {timer1. Stop (); ProdRunning = falso; UpdateOrderTable (); } else {MessageBox. Show ("Aún no ha comenzado la producción. Ingrese los datos y presione el botón 'iniciar'"); }}
UpdateOrderTable vacío privado ()
{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 (insertar, conectar); intente {conexión. Open (); insertcmd. ExecuteNonQuery (); conexión. Cerrar (); QuantProduced = 0; } catch (Exception ex) {MessageBox. Show (ex. Message); }}
temporizador de vacío privado1_Tick (remitente de objeto, EventArgs e)
{CheckTableForNull (); load_table (); }
btnShowOrderTable_Click vacío privado (remitente del objeto, EventArgs e)
{if (ProdRunning == false) {MySqlCommand command = new MySqlCommand ("SELECT * FROM patedb.ordertable ORDER BY orderID DESC;", conexión); intente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = comando; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }} else {MessageBox. Show ("Presione detener para ver la tabla de pedidos"); }}
private void btnShowOrderDetails_Click (remitente del objeto, 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 +"' "); Comando MySqlCommand = nuevo MySqlCommand (prueba, conexión); intente {conexión. Open (); Adaptador MySqlDataAdapter = nuevo MySqlDataAdapter (); adapter. SelectCommand = comando; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); } conexión. Cerrar (); } else {MessageBox. Show ("Presione detener para ver los detalles del pedido"); }}
private void btnShowCustomerDetails_Click (remitente del objeto, 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 DONDE patedb.ordertable.orderID = '"+ txtShowCustomerDetails. Text +"' "); Comando MySqlCommand = nuevo MySqlCommand (prueba, conexión); intente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = comando; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; adapter. Update (dbdataset); } catch (Exception ex) {MessageBox. Show (ex. Message); }} else {MessageBox. Show ("Presione detener para ver los detalles del cliente"); }}}
}
Recomendado:
Oficina con pilas. Sistema solar con paneles solares y turbina eólica con conmutación automática Este / Oeste: 11 pasos (con imágenes)
Oficina con pilas. Sistema solar con paneles solares y turbina eólica con conmutación automática de este a oeste: El proyecto: Una oficina de 200 pies cuadrados debe funcionar con baterías. La oficina también debe contener todos los controladores, baterías y componentes necesarios para este sistema. La energía solar y eólica cargará las baterías. Hay un pequeño problema de solo
Cómo: Instalación de Raspberry PI 4 Headless (VNC) con Rpi-imager e imágenes: 7 pasos (con imágenes)
Cómo: Instalar Raspberry PI 4 Headless (VNC) con Rpi-imager e imágenes: planeo usar este Rapsberry PI en un montón de proyectos divertidos en mi blog. No dudes en comprobarlo. Quería volver a usar mi Raspberry PI, pero no tenía un teclado ni un mouse en mi nueva ubicación. Ha pasado un tiempo desde que configuré una Raspberry
Dataopsamling Af Tyverialarm IIOT 4.0: 8 pasos
Dataopsamling Af Tyverialarm IIOT 4.0: Dette projekt i faget IIOT er en videreudvikling af entyverialarm, som jeg har lavet på en Arduino i et tidligere projekt. Der er i dette projekt blevet fokuseret på lagring af de data, jeg får fra min tyverialarm, samt at lave et brugerinterface. D
Cómo desmontar una computadora con sencillos pasos e imágenes: 13 pasos (con imágenes)
Cómo desmontar una computadora con sencillos pasos e imágenes: esta es una instrucción sobre cómo desmontar una PC. La mayoría de los componentes básicos son modulares y se quitan fácilmente. Sin embargo, es importante que se organice al respecto. Esto ayudará a evitar que pierda piezas y también a que el reensamblaje sea más fácil
EAL-Industry 4.0-Smart Rocket: 8 pasos (con imágenes)
EAL-Industry 4.0-Smart Rocket: Este es un proyecto escolar, realizado en Erhversakademiet Lilleb æ lt en Dinamarca.El proyecto se realiza en una clase llamada " Industri 4.0 ".La tarea es implementar un sistema automático de la industria 4.0 principios. El sistema debe poder l