1 2 3 Obbiettivo e situazione di partenza Pag. 4 Schema a blocchi Pag. 5 Schema elettrico Pag. 6 Circuito stampato (fronte, retro e modello 3D) Pag. 7 Schema elettrico Arduino UNO Pag. 8 Codice del programma Pag. 9 Codice dell’interfaccia principale Pag.9 Codice del form con il grafico Pag.16 Codice form seleziona porta seriale Pag.19 Schermata dei collaudi su Excel Pag. 21 Elenco componenti Pag. 22 Progettazione schemi elettrici e circuiti Stampati Pag. 23 Progettazione software Pag. 24 Immagini montaggio hardware e sviluppo software Pag. 25 Dettagli Hardware Pag. 26 Codice di Arduino Pag.27 Dettagli del software Pag. 30 Conclusioni Pag. 32 Obiettivi e situazione di partenza Durante quest’anno scolastico l’azienda di Volpiano SPEA ha indetto un progetto dove potevano aderire gli studenti di classi quinte di indirizzi elettronica, informatica e meccanica. Io ho deciso di aderire al progetto ma facendo sia una parte di elettronica e una parte di informatica. La parte elettronica in sintesi La parte elettronica prevede la misura della temperatura con un sensore LM35 e al superamento dei 75 gradi il circuito deve far scattare un relè o un interruttore per togliere l’alimentazione al dispositivo e metterlo così in condizioni di sicurezza, inoltre il dispositivo deve misurare il valore di resistenze, condensatori e regolatori di tensione, e con un sensore identificare il colore dei diodi led. Tutti i valori devono essere inviati tramite una porta seriale RS232. Il tutto è fatto per collaudare degli alimentatori. La parte informatica in sintesi La parte informatica prevede lo sviluppo di un software che acquisisce, tramite seriale RS232, i valori misurati con il dispositivo hardware. I valori devono essere salvati su un database, e deve essere possibile recuperarli cercandoli per data di salvataggio e poterli visualizzare su un documento di Excel o Access. Siccome ho deciso di unire i due progetti ho dovuto trovare un modo per fare una parte di elettronica e una parte di informatica. Per la parte elettronica ho deciso di sviluppare un hardware in grado di misurare la temperatura e di inviarla ad un microprocessore, da quest’ultimo il dato viene inviato alla seriale RS232 e se la temperatura supera i 75 gradi fa scattare un relè. Il relè è collegato ad un diodo led verde che viene spento al superamento dei 75 gradi. Per la parte informatica ho deciso di sviluppare un software in grado di leggere e visualizzare la temperatura acquisita sulla porta seriale, con la possibilità di salvarla in una tabella dentro un database, nella tabella insieme alla temperatura viene salvato anche l’ID della scheda misurata, la data del collaudo e il nome del operatore che ha effettuato il collaudo. I dati salvati possono essere visualizzati su un foglio elettronico di Excel e con la possibilità di poter visualizzare la temperatura acquisita durante il giorno su un grafico. 4 Schema a blocchi Alimentatore Sensore LM35 5V RS232 Arduino Led verde e giallo in base alla temperatura se è < 75°C Relè e led verde di emergenza 5 Database con le misure Computer con programma in C# Schema elettrico 6 Circuito stampato Circuito stampato parte retro, scala 1:1 Circuito stampato parte frontale, scala 1:1 (SENZA RELE) Modello 3D del dispositivo In allegato i datasheet dei componenti. 7 8 Schema elettrico di Arduino UNO Codice del programma Codice dell’interfaccia principale Interfaccia principale del programma using using using using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms; System.Data.SqlClient; System.IO.Ports; System.IO; using /* * 1) * 2) * 3) * * * * * 1) * 2) Excel = Microsoft.Office.Interop.Excel; Creare un database SqlServer Nella finestra ESPLORA SERVER click destro su CONNESSIONE DATI Selezionare Crea nuovo database di Sql Server... Nell'omonima finestra di dialogo inserire: Nome Server: NomeComputer\SqlExpress Nome nuovo database: nome di database non ancora esistente OK Aggiungere una Connessione dati Nella finestra ESPLORA SERVER click destro su CONNESSIONE DATI Selezionare Aggiungi connessione... 9 * 3) Nell'omonima finestra di dialogo inserire: * Nome Server: NomeComputer\SqlExpress * Seleziona o immetti nome di database: cliccare sul menu a discesa * del comboBox e selezionare il nome di uno dei database proposti quindi * cliccare su OK * 4) Modificare il nome del database nella stringa di connessione (all'interno del * metodo Form1_Load() ) * * Creare ed aprire un file Excel in C# * 1) Menu Progetto | Aggiungi riferimento... * 2) Nella scheda .NET scorrere in basso, selezionare * Microsoft.Office.Interop.Excel quindi OK. * 3) Aggiungere using Excel = Microsoft.Office.Interop.Excel * Per cambiare il numero di fogli di lavoro iniziali in * Excel menu File | Opzioni scheda Generale impostare ad 1 * il numero di fogli da includere */ namespace Collaudo_schede_SPEA { public partial class Form1 : Form { bool start = false; double temperatura; SqlConnection cnSQLServer = new SqlConnection("Data Source= .\\SQLEXPRESS;Initial Catalog = schedeCollaudate; Integrated Security = true"); //SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); SqlCommand cmd = null; //cmd per i comandi da passare a sql int[] xval = { 0 }; // matrice contenente il numero di schede funzionanti e guaste double[] yval = { 0}; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { lblTemperatura.Text = "Dispositivo non connesso."; toolTipTemperatura.Active = true; btnChiudiSeriale.Enabled = false; } private void esciToolStripMenuItem_Click(object sender, EventArgs e) { this.Close(); //chiude il programma } private void impostazioniRS232ToolStripMenuItem_Click(object sender, EventArgs e) { if (serialPort1.IsOpen) //verifica se la porta seriale è gia stata aperta MessageBox.Show("Attenzione seriale già in uso! Prima di aprire le impostazioni chiudere la porta.", "Attenzione!", MessageBoxButtons.OK, MessageBoxIcon.Information); else { ImpostaSeriale selezionaSeriale = new ImpostaSeriale(); selezionaSeriale.ShowDialog(this); //apre il form per selezionare la porta seriale if (selezionaSeriale.DialogResult == DialogResult.OK) { try { serialPort1.PortName = selezionaSeriale.CmbBxPorta.SelectedItem.ToString(); //prende il nome della seriale dal form 10 serialPort1.BaudRate = Convert.ToInt32(selezionaSeriale.CmbBxBaudeRate.SelectedItem); //prende il baudrate dal form della seriale serialPort1.Open(); //apro la porta seriale } catch (InvalidOperationException ex) { MessageBox.Show(ex.Message, "Attenzione!!!"); return; } catch (System.IO.IOException ex1) { MessageBox.Show(ex1.Message, "Attenzione!!!"); return; } } } } private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { int leggidato = serialPort1.ReadByte(); //leggo il dato ricevuto da arduino temperatura = ((5.0 * leggidato) / 1024.0) * 100; //ricavo il valore effettivo della temperatura lblTemperatura.Text = string.Format("{0:F2}", temperatura) + " °C"; //mostro su una label il valore della temperatura DateTime data = DateTime.Now; if (start == true) try { string temp = string.Format("{0:F2}", temperatura); //converto in string il valore della temperatura temp = temp.Replace(',', '.'); //metto il punto al posto della virgola nella temperatura string codiceScheda = TxtBxCodiceScheda.Text; //prendo il codice della scheda dalla txtbox string nomeOperatore = TxtBxOperatore.Text; cnSQLServer.Open(); //mi connetto al server this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); //gli do il comando da c da eseguire in sql cmd.CommandText = "INSERT TestSchede ( CodiceScheda, Temperatura, DataTest, Operatore)" + "VALUES('" + codiceScheda + "','" + temp + "','" + data.ToShortDateString() + "','" + nomeOperatore + "')"; this.Text = cmd.ExecuteNonQuery().ToString(); cnSQLServer.Close();//chiudo il server btnChiudiSeriale.Enabled = true; start = false; } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } finally { cnSQLServer.Close(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; } } private void btnChiudiSeriale_Click(object sender, EventArgs e) 11 { serialPort1.Close(); //chiudo la porta seriale btnChiudiSeriale.Enabled = false; lblTemperatura.Text = "Dispositivo non connesso."; } private void btnStartCollaudo_Click(object sender, EventArgs e) { string pathExe = Application.StartupPath; string LeggiVerifica = pathExe + "\\verificatabella.ska"; string temp = string.Format("{0:f2}", temperatura); StreamReader readVerifica = new StreamReader(LeggiVerifica); string ver = readVerifica.ReadLine();//leggo il valore del file readVerifica.Close(); if (ver == "1" && TxtBxOperatore.Text != "" && serialPort1.IsOpen == true && TxtBxCodiceScheda.Text != "") { //verifico se il valore letto nel file prima è = 1 start = true; DateTime data = DateTime.Now; DataGridViewRowCollection row = this.dataGridView1.Rows; row.Add(TxtBxCodiceScheda.Text, temp, data.ToString(), TxtBxOperatore.Text); } else//se il valore letto nel file è zero appare un messaggio di errore MessageBox.Show("Verifica di aver creato una tabella, di aver aperto la porta RS232, "+ "di aver inserito il nome Operatore e di aver inserito il codice della scheda.", "Attenzione!!", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void mnuCreaTab_Click(object sender, EventArgs e) { try { cnSQLServer.Open(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); //con questo comando sotto creo una tabella di nome TestSchede cmd.CommandText = "CREATE TABLE TestSchede(IDTest INT NOT NULL IDENTITY PRIMARY KEY," + "CodiceScheda CHAR(20),Temperatura CHAR(20),DataTest DATE,Operatore CHAR(20))"; cmd.ExecuteNonQuery(); cnSQLServer.Close(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; string pathExe = Application.StartupPath; string scriviTab = pathExe + "\\verificatabella.ska"; StreamWriter nuovaTab = new StreamWriter(scriviTab); nuovaTab.WriteLine("1"); //la prima volta che crea la tabella salva nel file verificatabella il valore 1 nuovaTab.Close(); } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } finally { cnSQLServer.Close(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; } } 12 private void mnuEliminaTab_Click(object sender, EventArgs e) { try { cnSQLServer.Open(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); //con questo comando cancella la tabella TestSchede cmd.CommandText = "DROP TABLE TestSchede"; cmd.ExecuteNonQuery(); cnSQLServer.Close(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; string pathExe = Application.StartupPath; string scriviTab = pathExe + "\\verificatabella.ska"; StreamWriter nuovaTab = new StreamWriter(scriviTab); nuovaTab.WriteLine("0"); //quando cancella la tabella TestSchede scrive nel file verificatabella il valore 0 nuovaTab.Close(); } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } finally { cnSQLServer.Close(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; } } private void monthCalendar1_DateSelected(object sender, DateRangeEventArgs e) { int countRecord = 0; try { Excel._Worksheet workSheet; SqlDataReader reader = null; cnSQLServer.Open(); this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); cmd.CommandText = "SELECT * FROM TestSchede WHERE DataTest = @DataTest"; SqlParameter data = new SqlParameter("@DataTest", SqlDbType.Date); data.Value = e.Start; //prende il valore della data dall'oggetto e cmd.Parameters.Add(data);//salvo la data nel parametro @DataTest reader = cmd.ExecuteReader(); Excel.Application exceApp = new Excel.Application(); //apre excel exceApp.Workbooks.Add(); //salva i valori della tabella nel server su excel workSheet = exceApp.ActiveSheet; exceApp.Range["A1"].Value = "IDTest"; exceApp.Range["B1"].Value = "Codice Scheda"; exceApp.Range["C1"].Value = "Temperatura"; exceApp.Range["D1"].Value = "Data del test"; exceApp.Range["E1"].Value = "Operatore"; for (int i = 2; reader.Read(); i++) { workSheet.Cells[i, "A"] = reader["IDTest"]; workSheet.Cells[i, "B"] = reader["CodiceScheda"]; workSheet.Cells[i, "C"] = reader["Temperatura"]; workSheet.Cells[i, "D"] = reader["DataTest"]; 13 workSheet.Cells[i, "E"] = reader["Operatore"]; countRecord++; } workSheet.Cells[1, "A"].Interior.Color = Color.Aquamarine; workSheet.Cells[1, "B"].Interior.Color = Color.YellowGreen; workSheet.Cells[1, "C"].Interior.Color = Color.Orange; workSheet.Cells[1, "D"].Interior.Color = Color.LightSeaGreen; workSheet.Cells[1, "E"].Interior.Color = Color.LightCoral; // chiude connessione al database cnSQLServer.Close(); // visualizza stato connessione, nome del database e nome istanza di SQL Server this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; // adatta al contenuto la larghezza delle colonne for (int i = 1; i <= 5; i++) exceApp.Columns[i].AutoFit(); // seleziona cella exceApp.ActiveCell.Offset[countRecord + 2, 0].Select(); // rende visibile Excel (invisibile --> false) exceApp.Visible = true; } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } } private void chiudiPortaRS232ToolStripMenuItem_Click(object sender, EventArgs e) { serialPort1.Close(); //chiudo la porta seriale btnChiudiSeriale.Enabled = false; lblTemperatura.Text = "Dispositivo non connesso."; } private void mnuCancellaRecords_Click(object sender, EventArgs e) { try { // apre connessione al database cnSQLServer.Open(); this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); // costruisce stringa contenente comando DELETE per eliminare tutti i records della tabella TestSchede cmd.CommandText = "DELETE TestSchede"; // chiama metodo ExecuteNonQuery() cmd.ExecuteNonQuery(); cnSQLServer.Close(); this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } finally { // chiude connessione al database cnSQLServer.Close(); this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.DataSource; " + cnSQLServer.Database + " 14 } 15 } private void visualizzaGraficoDellaTemperaturaDiOggiToolStripMenuItem_Click(object sender, EventArgs e) { graficoTemperatura temp = new graficoTemperatura(); temp.Show(this); } private void eliminaUnRecordDallaTabellaToolStripMenuItem_Click(object sender, EventArgs e) { eliminaRecord frmRecords = new eliminaRecord(); frmRecords.ShowDialog(this); if (frmRecords.DialogResult == DialogResult.OK) try { // apre connessione al database cnSQLServer.Open(); // visualizza stato connessione, nome del database e nome istanza di SQL Server this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); // costruisce stringa contenente comando DELETE per eliminare tutti i records della tabella TestSchede cmd.CommandText = "DELETE TestSchede WHERE IDTest = @IDTest"; // creazione del parametro SqlParameter riga = new SqlParameter("@IDTest", SqlDbType.Int); // Imposta valore parametro SQL, cioè numero record da eliminare riga.Value = Convert.ToInt32(frmRecords.txtID.Text); // aggiunge al comando SQL precedente il parametro SQL contenente la data selezionata cmd.Parameters.Add(riga); // chiama metodo ExecuteNonQuery() cmd.ExecuteNonQuery(); // chiude connessione al database cnSQLServer.Close(); // visualizza stato connessione, nome del database e nome istanza di SQL Server this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } finally { // chiude connessione al database cnSQLServer.Close(); // visualizza stato connessione, nome del database e nome istanza di SQL Server " this.Text = cnSQLServer.State.ToString() + " " + cnSQLServer.DataSource; } } } } " + cnSQLServer.Database + Codice del form con il grafico Interfaccia di visualizzazione del grafico /* Controllo Chart * 1)Proprietà Dock di chart1 = Fill * 2)Rinominare Series1 come Tensione: * chart1 | Series | Editor insieme Series | Dati | Name * 3)Scelta tipo di grafico: * chart1 | Series | Editor insieme Series | Grafico | ChartType = Line * 4)Modifica colore sfondo area attorno a grafico: * chart1 | BackColor * 5)Modifica colore sfondo grafico: * chart1 | chartAreas | Editor insieme chartArea | Aspetto | BackColor * 6)Aggiunta titoloa grafico: * chart1 | Titles | Editor insieme Title--> click su pulsante AGGIUNGI * Nelle proprietà di Title1 Aspetto | Text --> digitare il titolo desiderato * 7)Modifica aspetto Legenda: * chart1 | Legends | Editor insieme Legend | Aspetto | Font, BackColor, ForeColor, * BorderColor,BorderWidth * 8)Visualizzazione dei valori di tensione in Etichette: * chart1 | Series | Editor insieme Series | Etichetta | IsValueShownAsLabel = true * 9)Modifica aspetto Etichette: * chart1 | Series | Editor insieme Series | Aspetto Etichetta | Font, LabelBackColor, * LabelForeColor, LabelBorderColor,LabelBorderWidth * 10)Visualizzazione degli Indicatori (marker): * chart1 | Series | Editor insieme Series | Indicatore | MarkerStyle | None, Circle, * Square, Triangle, etc. * 11)Modifica aspetto Indicatori (marker): * chart1 | Series | Editor insieme Series | Indicatore | MarkerColor, MarkerSize, * MarkerBorderColor, MarkerBorderWidth * 12)Modifica aspetto linee grafico: * chart1 | Series | Editor insieme Series --> selezionare serie desiderata, quidi * Aspetto | Color, BorderWidth, BorderColor (colore bordo indicatori) * 13)Inserire titoli per gli assi X e Y: 16 * chart1 | chartAreas | Editor insieme chartArea | Assi | Axes | Editor insieme Axis * --> selezionare un asse, quindi Titolo | Title, TitleFont, TitleForeColor, * TitleAlignment, TextOrientation * 14)Fissare origine assi in X=0: * chart1 | chartAreas | Editor insieme chartArea | Assi | Axes | Editor insieme Axis * --> selezionare un asse, quindi Scala | IsMarginVisible = false * 15)Modifica aspetto assi X e Y: * chart1 | chartAreas | Editor insieme chartArea | Assi | Axes | Editor insieme Axis * --> selezionare un asse, quindi Aspetto | LineColor, LineWidth, ArrowStyle * 16)Inserimento cursore asse X: * chart1 | chartAreas | Editor insieme chartArea | Cursore | CursorX | IsUserEnabled = true, * IsUserSelectionEnabled = true * Sono disponibili anche le proprietà LineColor e Interval (fissa l'entità dello spostamento * del cursore, ad es. 0,1) * 17)Adattare intervallo valori asse X al numero di valori a disposizione * chart1 | chartAreas | Editor insieme chartArea | Assi | Axes | Editor insieme Axis * --> selezione asse X, quindi Intervallo | IntervalAutoMode = VariableCount * 18)Abilitare/Disabilitare segni graduazione griglia secondaria: * chart1 | chartAreas | Editor insieme chartArea | Assi | Axes | Editor insieme Axis * --> selezione asse X, quindi Segni di graduazione griglia | minorGrid | Enabled = true * oppure false * Sono disponibili anche le proprietà LineColor e LineWidth * */ using using using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms; System.Data.SqlClient; System.IO; namespace Collaudo_schede_SPEA { public partial class graficoTemperatura : Form { SqlConnection cnSQLServer = new SqlConnection("Data Source= .\\SQLEXPRESS;Initial Catalog = schedeCollaudate; Integrated Security = true"); SqlCommand cmd = null; public graficoTemperatura() { InitializeComponent(); } private void graficoTemperatura_Load(object sender, EventArgs e) { int countRecord = 0; try { cnSQLServer.Open(); SqlDataReader reader = null; this.Text = cnSQLServer.ToString() + " " + cnSQLServer.Database + " " + cnSQLServer.DataSource; cmd = cnSQLServer.CreateCommand(); cmd.CommandText = "SELECT * FROM TestSchede WHERE DataTest = @DataTest"; SqlParameter data = new SqlParameter("@DataTest", SqlDbType.Date); data.Value = DateTime.Now; cmd.Parameters.Add(data); reader = cmd.ExecuteReader(); 17 for (int i = 2; reader.Read(); i++) { chart1.Series["Temperatura"].Points.AddXY(reader["IDTest"], reader["Temperatura"]); countRecord++; } cnSQLServer.Close(); this.Text = DateTime.Now.ToString(); } catch (SqlException ecc) { MessageBox.Show(ecc.Message, "Attenzione!!"); } } private void chart1_DoubleClick(object sender, EventArgs e) { if (chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D == true) chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = false; else chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true; } } } 18 Codice form seleziona porta seriale Interfaccia di selezione della porta seriale, e della velocità di baudRate using using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms; System.IO.Ports; namespace Collaudo_schede_SPEA { public partial class ImpostaSeriale : Form { public ImpostaSeriale() { InitializeComponent(); } public void BtnOk_Click(object sender, EventArgs e) { if (CmbBxBaudeRate.SelectedIndex != 9) { if (MessageBox.Show("Attenzione! Il baudRate del dispositivo di default è 57600, cambiandolo si potrebbero avere dei dati non attendibili. Impostare baudRate a 57600 Si o No?", "Attenzione!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes) CmbBxBaudeRate.SelectedIndex = 9; } } public void ImpostaSeriale_Load(object sender, EventArgs e) { ControlBox = false; //carica i valori del baudrate nel combobox CmbBxBaudeRate.Items.Add(300); CmbBxBaudeRate.Items.Add(1200); CmbBxBaudeRate.Items.Add(2400); CmbBxBaudeRate.Items.Add(4800); CmbBxBaudeRate.Items.Add(9600); CmbBxBaudeRate.Items.Add(14400); CmbBxBaudeRate.Items.Add(19200); CmbBxBaudeRate.Items.Add(28800); CmbBxBaudeRate.Items.Add(38400); CmbBxBaudeRate.Items.Add(57600); CmbBxBaudeRate.Items.Add(115200); //indice dell'elemento da selezionare CmbBxBaudeRate.SelectedIndex = 9; 19 //seleziona l'elemento con l'indice fissato CmbBxBaudeRate.SelectedItem = CmbBxBaudeRate.SelectedIndex; //salva l'elenco delle porte in una matrice string[] porteCom = SerialPort.GetPortNames(); //visualizza elementi della matrice nel combobox foreach (string portaRS232 in porteCom) CmbBxPorta.Items.Add(portaRS232); //verifica presenza nel pc di almeno una porta COM if (CmbBxPorta.Items.Count != 0) { //imposta ultimo indice come quello dell'elemento selezionato di default CmbBxPorta.SelectedIndex = CmbBxPorta.Items.Count - 1; //seleziona elemento con indice fissato CmbBxPorta.SelectedItem = CmbBxPorta.SelectedIndex; } else { //avviso assenza di porte COM MessageBox.Show("Nessuna porta COM rilevata", "Attenzione!", MessageBoxButtons.OK, MessageBoxIcon.Information); this.Close();//chiude form 2 } } } } 20 Schermata dei collaudi su Excel Visualizzazione dei dati su Excel 21 Elenco componenti Componenti Costi su rs-component 2 resistenze da 680 OHM 0,006€ (1 pz in confezione da 5000) 0,006€ (1 pz in confezione da 5000) 0,006€ (1 pz in confezione da 5000) 0,146€ (1 pz in confezione da 10) 0,233€ (1 pz in confezione da 10) 26,11€ 4,41€ 0,178€ (1 pz in confezione da 25) 1 resistenza da 1,5 KOHM 1 resistenza da 12 KOHM 1 connettore da 3 pin 1 connettore da 8 pin 1 scheda Arduino UNO 1 sensore LM35 4 diodi led (1 rosso, 1 giallo e 2 verde) 1 transistor npn BC337 1 integrato LM358N 1 relè 6V DC Guaina termo restringente 1 diodo 1N4007 0,22€ 0,306€ (1 pz in confezione da 25) 6,20€ 3,04€ 0,023€ (1 pz in confezione da 500) 22 Costi su componenti.elettronici.com 0,14€ 0,07€ 0,07€ 0,34€ 0,34€ / 1,45€ (0,36€, 0,13€, 0,44€) 0,07€ 0,32€ 4,14€ 1,57€ 0,08€ Progettazione schemi elettrici e circuiti Stampati Per creare lo schema elettrico del dispositivo e per la progettazione del circuito stampato ho utilizzato il programma KiCad, è un programma open source di software Electronic Design Automation (EDA) per il disegno di schemi elettrici e circuiti stampati. Come programma l’ho trovato semplice da usare, ed è molto affidabile, per essere gratuito come qualità si avvicina a molti programmi che sono attualmente in commercio. All’interno del programma possiamo trovare diversi programmi. Il primo è Eeschema questo serve per la creazione dello schema elettrico, ci sono molti componenti a disposizione dell’utente, e nel caso che non troviamo un componente che ci serve su internet si possono trovare delle librerie con molti altri componenti, oppure si possono creare direttamente componenti all’interno del programma. Un altro programma importante al suo interno è Pcbnew, questo serve per la creazione del circuito stampato, e anche qui c’è la possibilità di aggiungere componenti mancanti con delle librerie. Con Kicad c’è anche la possibilità di passare da schema elettrico direttamente al circuito stampato grazie a vari tools all’interno del programma. 23 Progettazione software Per lo sviluppo del software ho utilizzato il programma Visual Studio 2010 della Microsoft, all’interno del programma si ha la possibilità di usare diversi programmi con diversi linguaggi di programmazione. Il linguaggio che ho usato io è C# molto comodo e facile da usare. Preciso che ho utilizzato la versione ultimate del programma perché con questa versione si ha la possibilità di avere anche SQLserver mente nella versione Express si hanno parecchie limitazioni, inoltre per la visualizzazione esterna dei dati salvati nel database bisogna avere installato una versione di Microsoft Office per usare il pacchetto di Excel. 24 Immagini montaggio hardware e sviluppo software Dispositivo montato su breadboard Parte del codice software 25 Dettagli Hardware Il dispositivo hardware è abbastanza semplice, come sensore per misurare la temperatura ho usato un LM35 che come si può vedere nel suo datasheet è molto sensibile ( varia di 10mV/°C), all’uscita della Vout del sensore ho messo un inseguitore usando un amplificatore operazionale un LM358N. Come microcontrollore ho deciso di usare una scheda Arduino UNO. Quindi la tensione all’uscita dall’inseguitore va ad un pin analogico di Arduino (nel mio caso l’ho messo al pin 5), non ho dovuto inserire un convertitore AC/DC perché su Arduino ce n’è installato già uno. All’interno del microcontrollore la tensione viene inviata tramite RS232, ( anche questo sulla scheda di Arduino è già installato), e il microcontrollore verifica se la tensione supera i 75°C. Ma prima di verificare bisogna fare dei banali calcoli, siccome in ingresso la tensione è stata convertita da analogica a digitale, in entrata si avrà un valore compreso tra 0 e 1024. Per ricavare la temperatura effettiva quindi bisogna usare una formuletta: ∗ = 2 Dove è la nostra incognita (quindi sarà la nostra temperatura effettiva), è la tensione di Arduino quindi 5V, è il nostro dato arrivato dall’AC/DC e infine è il numero di bit massimo in Arduino cioè 10 quindi al denominatore avremo 1024. Supponiamo che il nostro vale 15, facendo tutti i calcoli avremo 0,0732, ora per avere il valore effettivo lo moltiplichiamo per 100 (perché il sensore lavora nell’ordine dei mV), quindi avremo la nostra temperatura di 7,32°C. Ora che sappiamo la temperatura effettiva possiamo verificare se è minore o maggiore di 75°C. Possiamo notare che nel circuito ci sono 4 led, tre servono per indicare la temperatura il verde si accende se la temperatura è inferiore a 30°C, se invece la temperatura è compresa tra 30 e 50 rimangono accesi i led verde e giallo, se la temperatura è compresa tra 50 e 75 rimane acceso solo il giallo ed infine se supera i 75 si accende il led rosso, ma oltre ad accendersi questo led Arduino fa scattare il relè e quindi fa spegnere il quarto led che è attaccato al relè ( ovvero apre il circuito e toglie tensione per proteggerlo dall’alta temperatura). Ai capi della bobina del relè possiamo trovare un diodo rettificatore di protezione per evitare che danneggi Arduino, e possiamo trovare un transistor il BC337, questo transistor serve per amplificare la corrente al relè altrimenti la bobina non si eccita e quindi non farebbe aprire il circuito. Il circuito viene aperto nello stesso momento in cui si accende il led rosso. Come velocità di baudRate ho impostato 57600 è un valore scelto a caso perché funziona anche con 9600 (il minino) e 115200 (il massimo). Nella pagina seguente si può osservare il programma caricato sul microcontrollore, da notare che il metodo accensione serve solamente come “abbellimento” del circuito creando un effetto luminoso con i led. 26 Codice di Arduino const int piedinoTemperatura=5; //Piedino del sensore di temperatura LM35 const int pinGreen = 11; //piedino usato per il led verde const int pinYellow = 12; //piedino usato per il led giallo const int pinRed = 13; //piedino usato per il led rosso float tempEffettiva; int a; int verifica = 0; void setup(){ pinMode(pinGreen,OUTPUT); //imposto il pin 3 in OUTPUT pinMode(pinYellow,OUTPUT); //imposto il pin 5 in OUTPUT pinMode(pinRed,OUTPUT); //imposto il pin 6 in OUTPUT Serial.begin(57600); //imposto la velocità della trasmissione tramite seriale } void loop(){ if(verifica == 0) { //esegue questo if solo quando si accende for(a = 0; a <= 20; a++) accensione(); verifica = 1; } //acquisisco la temperatura dal sensore unsigned int temperatura = analogRead(piedinoTemperatura); delay(20); //ricavo la temperatura effettiva tempEffettiva = (5.0 * temperatura * 100) / 1024; //invio al pc tramite seriale la temperatura Serial.write(temperatura); //accendo il led verde se la temperatura e < 30 27 if(tempEffettiva <= 30) { digitalWrite(pinGreen,HIGH); digitalWrite(pinYellow,LOW); digitalWrite(pinRed,LOW); } //accendo il led verde e giallo se la temperatura e > 30 e < 50 else if(tempEffettiva > 30 && tempEffettiva <= 50) { digitalWrite(pinGreen,HIGH); digitalWrite(pinYellow,HIGH); digitalWrite(pinRed,LOW); } //accendo il led giallo se la temperatura e > 50 e <= 75 else if(tempEffettiva > 50 && tempEffettiva < 75) { digitalWrite(pinGreen,LOW); digitalWrite(pinYellow,HIGH); digitalWrite(pinRed,LOW); } //accendo il led rosso se la temperatura e >= 75 else if(tempEffettiva >= 75) { digitalWrite(pinGreen,LOW); digitalWrite(pinYellow,LOW); digitalWrite(pinRed,HIGH); } } void accensione(){ //metodo usato quando si accende il dispositivo digitalWrite(pinGreen,HIGH); delay(80); digitalWrite(pinGreen,LOW); digitalWrite(pinYellow,HIGH); delay(80); 28 digitalWrite(pinYellow,LOW); digitalWrite(pinRed,HIGH); delay(80); digitalWrite(pinRed,LOW); digitalWrite(pinYellow,HIGH); delay(80); digitalWrite(pinYellow,LOW); } 29 Dettagli del software Ora analizzeremo più in dettaglio anche la parte del software. All’apertura del programma ci troviamo davanti diverse impostazioni ma molto intuitive, come prima cosa siccome la comunicazione tra hardware e software avviene tramite seriale RS232 dobbiamo aprire la porta seriale, in alto ci sono tre diversi menù tra cui troviamo “impostazioni RS232” se clicchiamo sopra vedremo due voci “Attiva Porta RS232” e “Disattiva Porta RS232” come possiamo vedere nella Figura 1, una volta cliccato possiamo vedere che si apre una piccola finestra con due combo box dove poter scegliere la velocità di trasmissione e la porta seriale da utilizzare come in figura 2. Figura 1 Come possiamo notare si possono scegliere diverse velocità di trasmissione ma di default ho messo 57600 perché come avevo descritto prima nell’hardware avevo preimpostato come velocità questo valore qui. Figura 2 Figura 3 Una volta selezionata la porta seriale il programma inizierà ad acquisire valore forniti da Arduino e questi verranno visualizzati in una label. Per poter iniziare a salvare le misure all’interno del database prima dobbiamo creare una tabella al suo interno. Si può notare che il terzo menù si chiama database come mostrato in Figura 3, se ci clicchiamo sopra verranno mostrate 4 opzioni, con la prima opzione andiamo a creare una tabella all’interno del database così ora possiamo salvare i test al suo interno, poi si può un opzione che elimina la tabella dal server, oppure si possono eliminare tutti i dati dalla tabella ma senza eliminarla definitivamente, ed infine si può eliminare anche una sola riga della tabella, necessario se si ha sbagliato a fare una misura. Ora prima di iniziare a salvare le misure bisogna compilare lo spazio vuoto sotto “inserire il nome operatore”, e sotto ancora bisogna inserire il codice della scheda da testare. Una volta inseriti tutti i dati si può cliccare su start e iniziare a salvare i collaudi all’interno del database. Le misure effettuate potranno essere anche visualizzate nella tabella che c’è nell’applicazione come quella in figura 4. Una volta finiti i test si può cliccare sul tasto “Chiudi porta seriale” per disattivare Figura 4 30 la porta seriale e quindi interrompere la trasmissione dei dati. Per poter visualizzare i risultati dei collaudi all’interno di un documento Excel bisogna semplicemente cliccare su un giorno del calendario che c’è nell’applicazione e verranno visualizzati tutti i test svolti nel giorno selezionato, su un foglio Excel. Per esempio se si clicca sul 19 aprile 2013 verranno visualizzati su Excel tutti i test effettuati tale giorno. Infine se si apre il primo menù “File” si possono trovare altre due voci, “Esci” che ovviamente fa uscire dal programma e poi “Visualizza grafico della temperatura di oggi” come mostrato in figura 5, una volta aperta questa opzione verrà visualizzato un grafico con tutte le temperature riportate di quel giorno, se si fa doppio click sul grafico si potrà vederlo in modalità 3D come nella figura 6. Figura 5 Figura 6 Come si può vedere nel grafico nell’asse delle ordinate possiamo trovare la temperatura che arriva fino ad un massimo di 75°C, invece nell’asse delle ascisse troviamo l’IDSchede ovvero le schede testate in giornata dalla prima all’ultima, di conseguenza la temperatura è come se fosse in funzione del tempo. 31 Conclusioni Il progetto alla fine è stato portato a termine, soddisfacendo gli obbiettivi che mi ero prefissato, cioè creare un progetto con parti hardware e parti software, per quanto riguarda l’hardware non ho avuto molti problemi nella realizzazione, grazie anche ad Arduino che è piuttosto semplice da usare e programmare, per quanto riguarda la parte software non è stata una passeggiata siccome parecchie cose non erano nel programma scolastico come l’utilizzo e la gestione dei database, ma grazie all’aiuto dei professori e alle informazioni ricavate su internet sono riuscito a concludere anche la parte del software con risultati secondo me ottimi! 32