Ver imagen.
Este proyecto ya es un reto para muchos, jajajja, aún así se puede intentar.
Aquí tengo un simulador de lavadora, puedes controlar el giro del tambor o motor, velocidad, nivel de agua. Es totalmente funcional.
Hay en este caso aunque si funciona, quiero ignorarlo para el próximo programa, Giro del motor.
La mejora o el próximo programa funciona desde el puerto serie sin usar ningún trackBar.
trackBar_Velocidad_motor funciona los valores como máximo a 100 y mínimo a 0.
trackBar_Nivel_de_agua funciona los valores como máximo a 90 y mínimo a -90.
Los sustitutos del trackBar son datos que llegan desde el puerto serie, algo así como esto, por ejemplo:
Código
50, 80
El ejemplo de arriba indica el número 50, que varía de 0 a 100, la velocidad. El 80 es el caso del 90 a -90 del nivel de agua.
Esos datos si quiero que esté. Puede recibir datos a 9600 baudios y por cada 1000 milisegundos, o lo que es lo mismo, a cada segundo.
El código completo de este programa con trackBar es este.
Código
/* Te explico la formula float fDeltaAngulo = (((nRPM * 360) / (60 * 1000)) * timer.Interval) * ((float)trackBar_Velocidad_motor.Value / (float)trackBar_Velocidad_motor.Maximun) 1. (nRPM * 360) -> Grados por minuto. 2. (60 * 1000) -> Milisegundos por minuto. 3. ((nRPM * 360) / (60 * 1000)) -> Grados por milisegundo. 4. (((nRPM * 360) / (60 * 1000)) * timer.Interval) -> Grados por tick del timer. 5. ((float)trackBar_Velocidad_motor.Value / (float)trackBar_Velocidad_motor.Maximun) -> Porcentaje de la velocidad. 6. (((nRPM * 360) / (60 * 1000)) * timer.Interval) * ((float)trackBar_Velocidad_motor.Value / (float)trackBar_Velocidad_motor.Maximun) -> Calcula los grados por tick del timer aplicando un porcentaje. Según esta formula, si el trackbar esta en 0, grados por tick * 0 = 0 (esta parado), si el trackbar esta al maximo, grados por tick * 1 = grados por tick (el angulo aumenta al máximo). */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Lavadora_05 { public partial class Form1 : Form { // Variables. private Pen lápiz2; private Pen lápiz3; private Pen lápiz4; private float angulo; private SolidBrush agua; private GraphicsPath m_lavadora; private GraphicsPath m_agua; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Text = "Simulador lavadora"; pictureBox1.BackColor = Color.LightGray; lápiz2.StartCap = LineCap.ArrowAnchor; lápiz2.EndCap = LineCap.RoundAnchor; angulo = 0; trackBar_Nivel_de_agua.Value = -90; // Para que empiece sin agua. } // Dibuja y colorea. private void pictureBox1_Paint(object sender, PaintEventArgs e) { e.Graphics.DrawRectangle(lápiz3, 10, 10, pictureBox1.ClientSize.Width - 20, pictureBox1.ClientSize.Height - 20); e.Graphics.DrawEllipse(lápiz4, 10, 10, pictureBox1.ClientSize.Height - 20, pictureBox1.ClientSize.Height - 20); e.Graphics.TranslateTransform(pictureBox1.ClientSize.Width / 2, pictureBox1.ClientSize.Height / 2); e.Graphics.RotateTransform(angulo); e.Graphics.TranslateTransform(-pictureBox1.ClientSize.Width / 2, -pictureBox1.ClientSize.Height / 2); //e.Graphics.DrawLine(lápiz2, 20, pictureBox1.ClientSize.Height / 2, pictureBox1.ClientSize.Width / 2, pictureBox1.ClientSize.Height / 2); e.Graphics.DrawPath(lápiz2, m_lavadora); e.Graphics.ResetTransform(); e.Graphics.FillPath(agua, m_agua); } // Refresca el valor actual. private void trackBar_Giro_del_motor_ValueChanged(object sender, EventArgs e) { angulo = (float)trackBar_Giro_del_motor.Value; pictureBox1.Refresh(); } // Cambia el tamaño del control. private void pictureBox1_Resize(object sender, EventArgs e) { int ancho = pictureBox1.ClientSize.Width; int alto = pictureBox1.ClientSize.Height; m_lavadora.AddEllipse(20, 20, ancho - 40, alto - 40); m_lavadora.CloseFigure(); m_lavadora.AddLine(20, (alto / 2), ancho - 20, (alto / 2)); m_lavadora.CloseFigure(); m_lavadora.AddLine(ancho / 2, 20, ancho / 2, alto - 20); m_lavadora.CloseFigure(); m_agua.AddArc(20, 20, ancho - 40, alto - 40, trackBar_Nivel_de_agua.Value, 180 - 2 * trackBar_Nivel_de_agua.Value); m_agua.CloseFigure(); } private void trackBar_Nivel_de_agua_ValueChanged(object sender, EventArgs e) { m_agua.AddArc(20, 20, pictureBox1.ClientSize.Width - 40, pictureBox1.ClientSize.Height - 40, -trackBar_Nivel_de_agua.Value, 180 - 2 * -trackBar_Nivel_de_agua.Value); m_agua.CloseFigure(); pictureBox1.Refresh(); } private void timer1_Tick(object sender, EventArgs e) { //60 vueltas por minuto float nRPM = 60; float fDeltaAngulo = (((nRPM * 360) / (60 * 1000)) * (float)timer1.Interval) * ((float)trackBar_Velocidad_motor.Value / (float)trackBar_Velocidad_motor.Maximum); float track = (float)trackBar_Velocidad_motor.Value; angulo += fDeltaAngulo; label_angulo.Text = "angulo " + angulo.ToString(); label_fDeltaAngulo.Text = "fDeltaAngulo " + fDeltaAngulo.ToString(); pictureBox1.Refresh(); } private void button_Empezar_Click(object sender, EventArgs e) { timer1.Start(); //timer1.Enabled = true; // También válido. } private void button_parar_Click(object sender, EventArgs e) { timer1.Stop(); //timer1.Enabled = false; // También válido. } } }
El código que he intentado es este pero no funciona ni una parte y está incompleto.
Código
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Lavadora_07 { public partial class Form1 : Form { // Utilizaremos un string-builder como búfer auxiliar. // La trama llegará fragmentada. StringBuilder sb; // Nuestro delegado recibe como argumento el string con la trama. readonly Action<string> NuevaTrama; // Variables. private Pen lápiz2; private Pen lápiz3; private Pen lápiz4; private float angulo; private SolidBrush agua; private GraphicsPath m_lavadora; private GraphicsPath m_agua; // Variables sustituto del trackBar. private int trackBar_Nivel_de_agua = 0; private int trackBar_Velocidad_motor = 0; public Form1() { InitializeComponent(); NuevaTrama = Actualizar; } private void Form1_Load(object sender, EventArgs e) { // Añado los puertos disponible en el PC con SerialPort.GetPortNames() al comboBox_Puerto. try { comboBox_Puerto.DataSource = SerialPort.GetPortNames(); } catch { MessageBox.Show("No encuentra ningún puerto físico ni virtual.", "Aviso:", MessageBoxButtons.OK, MessageBoxIcon.Warning); } // Añado los puertos disponible en el PC con SerialPort.GetPortNames() al comboBox_Puerto. comboBox_Puerto.DataSource = SerialPort.GetPortNames(); // // Añade puertos disponibles físicos y virtuales. serialPort1.PortName = comboBox_Puerto.Text.ToString(); // Dibujo tambor lavadora. pictureBox1.BackColor = Color.LightGray; lápiz2.StartCap = LineCap.ArrowAnchor; lápiz2.EndCap = LineCap.RoundAnchor; angulo = 0; trackBar_Nivel_de_agua = -90; // Para que empiece sin agua. } // Detecta USB o puerto serie virtual cuando lo conecta y desconecta del cable. protected override void WndProc(ref Message USB) { if (USB.Msg == 0x219) { comboBox_Puerto.DataSource = SerialPort.GetPortNames(); } base.WndProc(ref USB); // Detecta si hay cambios en el usb y si los hay los refleja. } // Dibuja y colorea. private void pictureBox1_Paint(object sender, PaintEventArgs e) { e.Graphics.DrawRectangle(lápiz3, 10, 10, pictureBox1.ClientSize.Width - 20, pictureBox1.ClientSize.Height - 20); e.Graphics.DrawEllipse(lápiz4, 10, 10, pictureBox1.ClientSize.Height - 20, pictureBox1.ClientSize.Height - 20); e.Graphics.TranslateTransform(pictureBox1.ClientSize.Width / 2, pictureBox1.ClientSize.Height / 2); e.Graphics.RotateTransform(angulo); e.Graphics.TranslateTransform(-pictureBox1.ClientSize.Width / 2, -pictureBox1.ClientSize.Height / 2); //e.Graphics.DrawLine(lápiz2, 20, pictureBox1.ClientSize.Height / 2, pictureBox1.ClientSize.Width / 2, pictureBox1.ClientSize.Height / 2); e.Graphics.DrawPath(lápiz2, m_lavadora); e.Graphics.ResetTransform(); e.Graphics.FillPath(agua, m_agua); } // Cambia el tamaño del control. private void pictureBox1_Resize(object sender, EventArgs e) { int ancho = pictureBox1.ClientSize.Width; int alto = pictureBox1.ClientSize.Height; m_lavadora.AddEllipse(20, 20, ancho - 40, alto - 40); m_lavadora.CloseFigure(); m_lavadora.AddLine(20, (alto / 2), ancho - 20, (alto / 2)); m_lavadora.CloseFigure(); m_lavadora.AddLine(ancho / 2, 20, ancho / 2, alto - 20); m_lavadora.CloseFigure(); m_agua.AddArc(20, 20, ancho - 40, alto - 40, trackBar_Nivel_de_agua, 180 - 2 * trackBar_Nivel_de_agua); m_agua.CloseFigure(); } // Conectar comunicación con el puerto serie. private void button_Conectar_Click(object sender, EventArgs e) { try { serialPort1.PortName = comboBox_Puerto.Text.ToString(); // Puerto seleccionado previamente. serialPort1.BaudRate = Convert.ToInt32(comboBox_Baudios.Text); // Baudios. serialPort1.Open(); // Abrir puerto. comboBox_Puerto.Enabled = false; comboBox_Baudios.Enabled = false; button_Conectar.Enabled = false; button_Desconectar.Enabled = true; } catch { MessageBox.Show("El puerto no existe.", "Aviso:", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } // Desconectar comunicación con el puerto serie. private void button_Desconectar_Click(object sender, EventArgs e) { try { serialPort1.Close(); // Cerrar puerto. comboBox_Puerto.Enabled = true; comboBox_Baudios.Enabled = true; button_Conectar.Enabled = true; button_Desconectar.Enabled = false; } catch (Exception error) { MessageBox.Show(error.Message, "Aviso:", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } // Al cerrar el formulario, antes cierra el puerto si está abierto. private void Form1_FormClosing(object sender, FormClosingEventArgs e) { try { serialPort1.Close(); // Cerrar puerto. } catch (Exception error) { MessageBox.Show(error.Message, "Aviso:", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } // Recibe datos por el puerto serie. private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { // Caracter/es disponible/s desde la última vez. string recibidos = serialPort1.ReadExisting(); // analizamos cada caracter recibido foreach (char item in recibidos) { switch (item) { // Ignoramos el \u000D case '\r': break; // Aquí detectamos el final de la trama \u000A case '\n': // y la enviamos al control. Invoke(NuevaTrama, sb.ToString()); // Luego limpiamos el búfer. sb.Clear(); break; // Cualquier otro caracter recibido, lo agregamos al búfer. default: sb.Append(item); break; } } } private void Actualizar(string trama) { // Delimitador. Ignoramos las comas. string[] datosArray = trama.Split(','); // Compara si dos datos del array es igual a la cantidad total que en este // caso son 2. Si es igual a 2, entonces ejecuta todo el código dentro del if. if (datosArray.Length == 2) { // Mostrar datos. label_Entrada_analogica_A1.Text = "Entrada Analógica A1: " + datosArray[0]; label_Entrada_analogica_A2.Text = "Entrada Analógica A2: " + datosArray[1]; } } private void trackBar_Nivel_de_agua_ValueChanged(object sender, EventArgs e) { m_agua.AddArc(20, 20, pictureBox1.ClientSize.Width - 40, pictureBox1.ClientSize.Height - 40, -trackBar_Nivel_de_agua, 180 - 2 * -trackBar_Nivel_de_agua); m_agua.CloseFigure(); pictureBox1.Refresh(); } } }
¿Alguna idea de este proyectado tipo reto?
Un cordial saludos camaradas.