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:
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.
/*
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
.Size = new Size
(300,
300); pictureBox1.BackColor = Color.LightGray;
lápiz2
= new Pen
(Color
.DarkGray,
10); lápiz2.StartCap = LineCap.ArrowAnchor;
lápiz2.EndCap = LineCap.RoundAnchor;
lápiz3
= new Pen
(Color
.Black,
5); lápiz4
= new Pen
(Color
.Gray,
10);
angulo = 0;
agua
= new SolidBrush
(Color
.FromArgb(200,
0,
155,
219)); // Transparencia del agua 200. 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
= new GraphicsPath
();
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
= new GraphicsPath
();
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
= new GraphicsPath
();
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.
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();
sb
= new StringBuilder
(); 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();
serialPort1
.DataReceived += new SerialDataReceivedEventHandler
(serialPort1_DataReceived
);
// Dibujo tambor lavadora.
pictureBox1
.Size = new Size
(300,
300); pictureBox1.BackColor = Color.LightGray;
lápiz2
= new Pen
(Color
.DarkGray,
10); lápiz2.StartCap = LineCap.ArrowAnchor;
lápiz2.EndCap = LineCap.RoundAnchor;
lápiz3
= new Pen
(Color
.Black,
5); lápiz4
= new Pen
(Color
.Gray,
10);
angulo = 0;
agua
= new SolidBrush
(Color
.FromArgb(200,
0,
155,
219)); // Transparencia del agua 200. 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
= new GraphicsPath
();
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
= new GraphicsPath
();
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
= new GraphicsPath
();
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.