Test Foro de elhacker.net SMF 2.1

Programación => Programación General => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Meta en 6 Marzo 2021, 17:39 PM

Título: Hacer funcionar simulador lavadora
Publicado por: Meta en 6 Marzo 2021, 17:39 PM
(https://social.msdn.microsoft.com/Forums/getfile/1656951)

Ver imagen (https://social.msdn.microsoft.com/Forums/getfile/1656951).

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 (csharp) [Seleccionar]
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 (csharp) [Seleccionar]
/*
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.

Código (csharp) [Seleccionar]
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.