Índice:
- Etapa 1: Opsamling Af Data para Vægt Samt Registrering Af UID
- Etapa 2: programa Arduino
- Etapa 3: Node-RED, banco de dados Lagring Af Data I
- Etapa 4: projeto do banco de dados
- Etapa 5: Patelog
- Etapa 6: Ordertable
- Etapa 7: personalizável
- Etapa 8: ajustável
- Etapa 9: Programa C #
Vídeo: EAL-Industri4.0-RFID Dataopsamling Til Database: 10 etapas (com imagens)
2024 Autor: John Day | [email protected]. Última modificação: 2024-01-30 11:39
Dette projekt omhandler opsamling af vægtdata, registrering af identiteter vha. RFID, lagring af data in MySQL database vha. node-RED, samt fremvisning e behandling af de opsamlede data i et C # program in form at Windows Form Application. Vi forestiller os følgende:
Vi har en produktionslinje som produtor leverpostej i 200g foliebakker. Todos os udstyres de alavanca de færdigbagte após afkøling med et RFID tag in plasticlåget / labelen, some indeholder et unikt ID (UID = Unique Identifier, er en 32 bits kode, 8 hexadecimale karakterer) para entydig identifikation 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 maga færdigvægten, bruges UID Tagget dotado pelo knytte hver enkelt Leverpostej til en specifik lagerlokation relativos lageret, hvor der Kun lagres leverpostejer til én specifik kunde. Kunderne er supermarkedskæder:
1. Irma. Avalie på Irmas luksus leverpostej skal holde sig inden para +/- 5%, mínimo 190g e máximo 210g.
2. Brugsen. Veja no Brugsens leverpostej skal holde sig inden para +/- 10%, mínimo 180g e máximo 220g.
3. Aldi. Vægten på Aldis desconto de taxa postej skal holde sig inden para +/- 15%, altså mínimo 170g e máximo 230g.
Der er således følgende sorteringer:
Intervalo 0: fora do intervalo
Faixa 1: mínimo 190g / máximo210g
Faixa 2: mínimo 180g / máximo220g
Faixa 3: mínimo 170g / máximo230g
Etapa 1: Opsamling Af Data para Vægt Samt Registrering Af UID
Até a obtenção de dados para vægt, mesmo registro de tags RFID e anvendt em Arduino MEGA2560 com leitor / gravador RFID-RC522. Da vi ikke har nogen vægt, simulador vi data for vægten med et potmeter tilsluttet en analog indgang på Arduinoen.
Følgende opstilling er anvendt:
1 stk potmeter 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 -> pino 53
SCK -> pin52
MOSI -> pin51
MISO-> pin50
IRQ -> NC
GND -> GND
RST -> pin5
3,3 V -> 3,3 V
De opsamlede data, para hhv. UID e vægten, envia på den serielle port som en komma-separeret tekststreng videre to node-Red som står for den efterfølgende præsentation på et dashboard e lagring in en database.
Etapa 2: programa Arduino
I Arduino programmet inkluderes de to biblioteker SPI.h og MFRC522.h para at kunne bruge RFID læseren. I starten af programmet initialiseres de anvendte variable. Der laves en instans af MFRC522. I Setup blokken initialiseres den serielle forindelse, SPI porten og MFRC522. Desrespeite a leitura após as etiquetas RFID. For ikke e 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 que kan sendes på den serielle port. Hvis nyUID e oldUID er ens, er der tale om mesmo tag UID e 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. Os dados são enviados para você. Som det sidste sættes oldUID = nyUID, således e koden klart to læse et nyt tag RFID.. Den sidste funktion i programmet er den funktion som sammenligner 2 arrays. Retornador de função true hvis array'ne er ens, og false hvis array'ne er forskellige.
#incluir
#include // Este programa verifica os cartões RFID usando a placa de leitura / gravação RDIF-RC522. // UID é lido, um pino analógico é lido. O valor analógico 0-1023 é escalado para 150-250. // UID e valor analógico são enviados como texto separado por vírgulas na porta serial usando 9600, N, 8, 1. // Cuidado foi tomado para enviar cada UID apenas uma vez em uma linha, // um novo UID deve ser presente antes que o mesmo UID possa ser enviado novamente. // Esta função é implementada no código comparando matrizes: oldUID nyUID na função 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); // Cria instância MFRC522.
void setup ()
{Serial.begin (9600); // Inicia uma comunicação serial SPI.begin (); // Inicia o barramento SPI mfrc522. PCD_Init (); // Iniciar MFRC522}
void loop ()
{// Procure por novos cartões if (! Mfrc522. PICC_IsNewCardPresent ()) {return; } // Selecione um dos cartões if (! Mfrc522. PICC_ReadCardSerial ()) {return; } // carregar nyUID com tag UID para (byte i = 0; i <mfrc522.uid.size; i ++) {nyUID = mfrc522.uid.uidByte ; } // if oldUID nyUID if (! array_cmp (oldUID, nyUID)) {// enviar tag UID na porta serial para (byte i = 0; i 1000) {Value = 1000; } Valor = (Valor / 10) + 150; // envia valor analógico em escala Serial.print (Value); // enviar nova linha Serial.println (); // definir oldUID = nyUID para (byte z = 0; z <4; z ++) oldUID [z] = nyUID [z]; } // aguarde 1 seg. delay (1000); }
// compare 2 matrizes …
boolean array_cmp (byte a , byte b ) {bool test = true; // teste cada elemento para ser o mesmo. se apenas um não for, retorna falso para (byte n = 0; n <4; n ++) {if (a [n]! = b [n]) teste = falso; // se o byte não for igual, teste = falso} se (teste == verdadeiro) retornar verdadeiro; senão retorna falso; }
Etapa 3: Node-RED, banco de dados Lagring Af Data I
Følgende flow er lavet i node-RED:
COM4 é uma série de proibições de modtages de dados hvor do painel Arduino. Funktionerne "Split and Get value" e "Split and Get UID" splitter teksstrengen ved kommaet e returnere hhv vægten e UID. Vægten bruges to fremvisning på dashboardet i et linechart and en scale. UID fremvises i et tekstfelt. Funktionen test_sound advarer verbalt med sætningen "Out of range", hvis vægten er abaixo de 170g ou acima de 230g, dvs i range 0.
Dividir e obter valor:
var output = msg.payload.split (',');
temp = {carga útil: (saída [1])}; return temp;
Dividir e obter UID:
var output = msg.payload.split (",");
temp = {carga útil: saída [0]}; return temp;
test_sound:
var number = parseInt (msg.payload);
if (número> 230 || número <170) {newMsg = {carga útil: "Fora do intervalo"}; return newMsg; } else {newMsg = {carga útil: ""}; return newMsg; }
Funktionen Split string "," indsætter et timestamp, UID e vægten in database patedb.patelog.
var output = msg.payload.split (","); // divida msg.payload por vírgula na matriz
UIDTag = saída [0]; // primeira parte na primeira posição [0] ValueTag = output [1]; // segunda parte na segunda posição [1]
var m = {
tópico: "INSERT INTO patedb.patelog (timestamp, UID, weight) VALUES ('" + new Date (). toISOString () + "', '" + UIDTag + "', '" + ValueTag + "');" }; return m;
Patelog er en banco de dados MySQL proíbe alguns outros sat op med følgende parametre:
Host: localhost
Porta: 3306
Usuário: root
Banco de dados: patedb
Etapa 4: projeto do banco de dados
Databasen 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 de i C # programmet benyttede range.
Etapa 5: Patelog
Tabellen patelog indeholder folgende 6 kolonner:
pateID (int) er chave primária og inkrementeres automatisk.
Timestamp, UID & 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 to kolonnerne rangeNr og orderID. rangeNr og orderID tilader NULL værdier, det bruges i C # programmet to detektere de rækker som skal tilskrives værdier for rangeNr og orderID
Etapa 6: Ordertable
ordertable 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. (Tælles af C # programmet)
comentário (tinytext) er en eventuel kommentar til ordren.
customerID (int) er det aktuelle kundenummer på ordren.
Etapa 7: personalizável
customertable indeholder 6 kolonner:
customerID (int) er chave primária og auto inc.
nome, endereço, telefone, e-mail (varchar) med forskellig max længde
rangeNr (int)
Etapa 8: ajustável
rangetable indeholder 3 kolonner:
rangeNr (int) er chave primária og auto inc.
rangeMin (int)
rangeMax (int)
Etapa 9: Programa C #
Når der produceres en ordre leverpostej, er proceduren følgende:
Kundenummer, ordrenummer, ordreantal og en eventuel kommentar indtastes i C # programmet (i praksis overføres det digitalt fra virksomhedens ordresystem. på et transportbånd) Samhørende værdier of UID e den aktuelle vægt sendes serielt to node-RED, so viser of opsamlede data på dashboard 'et. tidspunkt ikke tilskrives mais værdier til rangeNr e orderID vil de ter værdien NULL.
Med et timerinterval undersøger C # programmet patedb.patelogtabellen para 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 de opsamlede data i patelog tabellen fremvises ved at trykke på de forskellige knapper i gruppen Atualizar DataGridview. ordertable kan også vises, og der kan søges ordredata på individueller UID'er eller kundedata på individuelle ordrer.
using System; using System. Collections. Generic; using System. ComponentModel; using System. Data; using System. Drawing; usando System. Linq; using System. Text; using System. Threading. Tasks; using System. Windows. Forms; using MySql. Data. MySqlClient;
namespace show_data_from_database
{classe pública parcial Form1: Formulário {conexão MySqlConnection = new MySqlConnection ("datasource = localhost; username = root; password = ''"); int RowNumber = 0; // Variável para armazenar o valor pateID int RangeNumber = 0; // Variável para armazenar o rangenumber int weight = 0; // Variável para armazenar o peso int OrderNr = 0; // Variável para armazenar OrderNR int QuantProduced = 0; // Variável para armazenar a quantidade produzida int NumberOfRows = 0; // número de linhas com nulos.. bool ProdRunning = false; // Variável que indica se os botões iniciar e parar foram ativados int limits = new int [6]; // inicializar array int CustomerID; // Variável para armazenar customerID public Form1 () {InitializeComponent (); load_table (); // chame load_table}
void load_table ()
{Comando MySqlCommand = new MySqlCommand ("SELECT * FROM patedb.patelog ORDER BY timestamp DESC;", conexão); tente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = command; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; SetRowOrder (); adaptador. Atualizar (dbdataset); } catch (Exceção ex) {MessageBox. Show (ex. Message); }}
private void SetRowOrder ()
{dataGridView1. Columns ["pateID"]. DisplayIndex = 0; // Her kan 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; // Seu kan rækkefølgen af kolonner ændres}
private void GetData_Click (object sender, EventArgs e) // Lê a tabela do banco de dados e pedidos por carimbo de data / hora
{load_table (); }
private void btnRefreshUID_Click (objeto remetente, EventArgs e) //
{string timeStr = "SELECT * FROM patedb.patelog ORDER BY UID;"; Comando MySqlCommand = novo MySqlCommand (timeStr, conexão); tente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = command; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; SetRowOrder (); adaptador. Atualizar (dbdataset); } catch (Exceção ex) {MessageBox. Show (ex. Message); }}
private void btnRefreshValue_Click (objeto remetente, EventArgs e)
{string weightSort = "SELECT * FROM patedb.patelog ORDER BY CAST (weight AS SIGNED INTEGER);"; Comando MySqlCommand = novo MySqlCommand (weightSort, conexão); tente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = command; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; SetRowOrder (); adaptador. Atualizar (dbdataset); } catch (Exceção ex) {MessageBox. Show (ex. Message); }}
private void ChkNullBtn_Click (objeto remetente, EventArgs e)
{if (ProdRunning) {CheckTableForNull (); load_table (); }}
private void CheckTableForNull ()
{// Verificar / definir intervalo de tempo mínimo 100 ms int i; int. ExperimenteParse (textTimer1. Text, out i); if (i <100) {timer1. Stop (); i = 100; timer1. Interval = i; MessageBox. Show ("Valor mínimo i 100 ms"); timer1. Start (); } else {timer1. Interval = i; } textTimer1. Text = timer1. Interval. ToString (); // Verifique se alguma linha com nulo está disponível na tabela, retorna o número de linhas na variável: NumberOfRows string weightStr = ""; string chkNull = "SELECT COUNT (*) FROM patedb.patelog ONDE rangeNR É NULO ORDEM POR pateID LIMIT 1;"; Comando MySqlCommand = novo MySqlCommand (chkNull, conexão); tente {connection. Open (); NumberOfRows = Convert. ToInt32 (command. ExecuteScalar ()); conexão. Fechar (); } catch (Exceção ex) {MessageBox. Show (ex. Message); } finalmente {if (NumberOfRows! = 0) {try {// Seleciona o menor número pateID onde rangeNr é NULL string readID = "SELECIONE pateID FROM patedb.patelog ONDE rangeNR É NULL ORDER BY pateID ASC LIMIT 1;"; MySqlCommand cmdID = novo MySqlCommand (readID, conexão); {connection. Open (); RowNumber = (int) cmdID. ExecuteScalar (); // inteiro !! conexão. Fechar (); } listPateID. Text = RowNumber. ToString (); // lê o número PateID selecionado // Seleciona o peso do rownumber string row = RowNumber. ToString (); string readweight = "SELECIONE o peso FROM patedb.patelog WHERE pateID =" + linha; MySqlCommand cmdweight = novo MySqlCommand (peso de leitura, conexão); {connection. Open (); weightStr = (string) cmdweight. ExecuteScalar (); //Fragmento !! conexão. Fechar (); } peso = int. Parse (weightStr); // converter para int txtWeight. Text = weight. ToString (); // imprime int RangeNumber = 0; if (peso> = limites [0] && peso = limites [2] && peso = limites [4] && peso <= limites [5]) {RangeNumber = 3; }} txtRange. Text = RangeNumber. ToString (); UpdateLog (); } catch (Exceção ex) {MessageBox. Show (ex. Message); } QuantProduced = QuantProduced + 1; }}} private void btnStart_Click (objeto remetente, EventArgs e) {if (ProdRunning == false) {int valtest; tente {CustomerID = int. Parse (txtCustomerNr. Text); // leia o ID do cliente} catch {MessageBox. Show ("Insira os dados de produção e pressione o botão 'iniciar'."); }
string test = "SELECT COUNT (*) FROM patedb.customertable WHERE customerID =" + CustomerID;
MySqlCommand cmdtestcustomer = novo MySqlCommand (teste, conexão); {connection. Open (); valtest = Convert. ToInt32 (cmdtestcustomer. ExecuteScalar ()); // retorna 0 se o cliente não existe conexão. Close (); } if (valtest == 1) // se o cliente existe no banco de dados - inicie a produção {tente {OrderNr = int. Parse (txtOrderNumber. Text); ProdRunning = true; timer1. Start (); textTimer1. Text = timer1. Interval. ToString (); ReadLimits (); } catch (Exception ex) {MessageBox. Show ("Insira os dados de produção e pressione o botão 'iniciar'."); }} else MessageBox. Show ("O cliente não está no banco de dados, tente novamente"); } // ReadLimits (); }
private void ReadLimits ()
{// Lê limites de rangetable, intervalo de 1 a 3 int counter = 0; for (int rangeNr = 1; rangeNr <4; rangeNr ++) {string readmin = "SELECIONE rangeMin FROM patedb.rangetable WHERE rangeNr =" + rangeNr; MySqlCommand cmdmin = novo MySqlCommand (readmin, conexão); {connection. Open (); limites [contador] = (int) cmdmin. ExecuteScalar (); contador = contador + 1; conexão. Fechar (); } // MessageBox. Show (counter. ToString ()); string readmax = "SELECIONE rangeMax FROM patedb.rangetable WHERE rangeNr =" + rangeNr; MySqlCommand cmdmax = novo MySqlCommand (readmax, conexão); {connection. Open (); limites [contador] = (int) cmdmax. ExecuteScalar (); contador = contador + 1; conexão. Fechar (); }} // fim do loop}
private void UpdateLog ()
{// ATUALIZAR rangeNR & orderID string Range = RangeNumber. ToString (); string Order = OrderNr. ToString (); string update = "UPDATE patedb.patelog SET rangeNr =" + Range + ',' + "orderID =" + OrderNr + "WHERE pateID =" + RowNumber; MySqlCommand updatecmd = novo MySqlCommand (atualização, conexão); tente {connection. Open (); updatecmd. ExecuteNonQuery (); conexão. Fechar (); } catch (Exceção ex) {MessageBox. Show (ex. Message); }}
private void btnStop_Click (objeto remetente, EventArgs e)
{if (ProdRunning == true) {timer1. Stop (); ProdRunning = false; UpdateOrderTable (); } else {MessageBox. Show ("Nenhuma produção iniciada ainda. Insira os dados e pressione o botão 'iniciar'"); }}
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 = novo MySqlCommand (inserir, conexão); tente {connection. Open (); insertcmd. ExecuteNonQuery (); conexão. Fechar (); QuantProduced = 0; } catch (Exceção ex) {MessageBox. Show (ex. Message); }}
private void timer1_Tick (objeto remetente, EventArgs e)
{CheckTableForNull (); load_table (); }
private void btnShowOrderTable_Click (objeto remetente, EventArgs e)
{if (ProdRunning == false) {comando MySqlCommand = new MySqlCommand ("SELECT * FROM patedb.ordertable ORDER BY orderID DESC;", conexão); tente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = command; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; adaptador. Atualizar (dbdataset); } catch (Exceção ex) {MessageBox. Show (ex. Message); }} else {MessageBox. Show ("Pressione parar para acessar a tabela de pedidos"); }}
private void btnShowOrderDetails_Click (objeto remetente, 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 ONDE patedb.patelog. UID = '"+ txtShowOrderDetails. Text +"' "); Comando MySqlCommand = novo MySqlCommand (teste, conexão); tente {connection. Open (); Adaptador MySqlDataAdapter = novo MySqlDataAdapter (); adapter. SelectCommand = command; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; adaptador. Atualizar (dbdataset); } catch (Exceção ex) {MessageBox. Show (ex. Message); } conexão. Fechar (); } else {MessageBox. Show ("Pressione parar para ver os detalhes do pedido"); }}
private void btnShowCustomerDetails_Click (objeto remetente, 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 +"' "); Comando MySqlCommand = novo MySqlCommand (teste, conexão); tente {MySqlDataAdapter adapter = new MySqlDataAdapter (); adapter. SelectCommand = command; DataTable dbdataset = new DataTable (); adaptador. Fill (dbdataset); BindingSource bsource = new BindingSource (); bsource. DataSource = dbdataset; dataGridView1. DataSource = bsource; adaptador. Atualizar (dbdataset); } catch (Exceção ex) {MessageBox. Show (ex. Message); }} else {MessageBox. Show ("Pressione parar para obter os detalhes do cliente"); }}}
}
Recomendado:
Howto: Instalando Raspberry PI 4 Headless (VNC) com Rpi-imager e imagens: 7 etapas (com imagens)
Howto: Instalando Raspberry PI 4 Headless (VNC) com Rpi-imager e imagens: Eu pretendo usar este Rapsberry PI em um monte de projetos divertidos em meu blog. Sinta-se à vontade para dar uma olhada. Eu queria voltar a usar meu Raspberry PI, mas não tinha um teclado ou mouse no meu novo local. Já fazia um tempo desde que configurei um Raspberry
Gesture Hawk: robô controlado por gestos manuais usando interface baseada em processamento de imagens: 13 etapas (com imagens)
Gesture Hawk: Robô controlado por gestos manuais usando uma interface baseada em processamento de imagem: Gesture Hawk foi apresentado no TechEvince 4.0 como uma interface homem-máquina baseada em processamento de imagem simples. Sua utilidade reside no fato de que nenhum sensor adicional ou vestível, exceto uma luva, é necessário para controlar o carro robótico que funciona em diferentes
Como desmontar um computador com etapas e imagens fáceis: 13 etapas (com imagens)
Como desmontar um computador com etapas e imagens fáceis: Esta é uma instrução sobre como desmontar um PC. A maioria dos componentes básicos é modular e facilmente removível. No entanto, é importante que você seja organizado sobre isso. Isso ajudará a evitar que você perca peças e também a fazer a remontagem e
EAL-Industry 4.0-Smart Rocket: 8 etapas (com imagens)
EAL-Industry 4.0-Smart Rocket: Este é um projeto escolar, feito em Erhversakademiet Lilleb æ lt na Dinamarca. O projeto é feito em uma classe chamada " Industri 4.0 ". A tarefa é implementar um sistema automático da indústria 4.0 princípios. O sistema deve ser capaz de
Salvando suas imagens para sua tarefa: 4 etapas (com imagens)
Salvando suas imagens para sua tarefa: 1. Abra um novo documento do Google e use esta página para proteger suas imagens.2. Use ctrl (control) e " c " chave para copy.3. Use ctrl (control) e " v " chave para colar