Puerto serie C++. Mejorar el programa.

Iniciado por Meta, 16 Marzo 2017, 22:21 PM

0 Miembros y 2 Visitantes están viendo este tema.

Meta

¿Y cómo se resuelve est e problema?

¿Enviando algo a Arduino que no sea 1 o el 2? ;)

Así no me va, jajajaja. Mejor que C++ controle la situación y estoy que arde de no lograrlo.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

MAFUS

Cambia todo el while(true) por:
Código (c++) [Seleccionar]
Sleep(500);
int n = Puerto->ReadData(lectura, 49);
if (n > 0) {
    lectura[n + 1] = '\0';
    cout << "Recibido: " << lectura << endl;
    cout << "-------------------" << endl;
}

ivancea96

Cita de: ivancea96 en 23 Marzo 2017, 23:54 PM
En primer lugar, yo separaría estoa  una función:

Código (cpp) [Seleccionar]
while (true) {
int n = Puerto->ReadData(lectura, 49);
if (n > 0) {
lectura[n + 1] = '\0';
break;
}
Sleep(1);
}

Una función que espere a que el Arduino envíe datos, y los retorne.

Lo de esperar datos solo lo vas a hacer si pulsan 1 o 2, así que llamas a esa función en cada case. Es cierto que los 2 case son idénticos salvo por la constante que envías. Podrías poner algo como:
Código (cpp) [Seleccionar]
const char *luz[2] = {"Luz_ON", "Luz_OFF"};

switch(opc){
    case 1:
    case 2:
        cout << "Enviando: " << luz[opc-1] << endl;
        Puerto->WriteData(luz[opc-1], strlen(luz[opc-1]));
        cout << "Respuesta: " << obtenerRespuestaArduino() << endl;
        break;

    default:
        // ...
}


De ese modo, solo esperará entrada del Arduino cuando sea necesario hacerlo. Al terminar el switch, puedes poner, si quieres, para leer datos del Arduino (sin esperar indefinidamente, eso sí, para que vuelva al inicio del bucle while y siga preguntando)

El problema es eso, el cómo está estructurado el código. Lo dicho: si tienes más experiencia en C#, puedes tratar de hacerlo ahí primero.

Ya ahí te respondiera el cómo solucionarlo -.-'

Meta

Por fiiiiiiiiiiiiiiiiiiiiiiiiiiiinnnnnnnnnnnnnnn.

Código (cpp) [Seleccionar]
// Para crear conexión con los puertos COM1 - COM9.
// Serial* Arduino = new Serial("COM7");

// Para crear conexión con los puertos COM10 en adelante.
// Serial* Arduino = new Serial("\\\\.\\COM10");

#include <iostream>
#include <fstream>
#include <Windows.h>
#include "SerialClass.h"
using namespace std;

void main()
{
// Título de la ventana
SetConsoleTitle("Control Led Arduino.");

// Puerto serie.
Serial* Puerto = new Serial("COM4");

// Comandos para Arduino.
char Luz_ON[] = "Luz_ON"; // Envía "Luz_ON" al puerto serie.
char Luz_OFF[] = "Luz_OFF";
char lectura[50] = "\0"; // Guardan datos de entrada del puerto.

int opc; // Guarda un 1 o 2 tipo entero queintroduces desde la consola.

while (Puerto->IsConnected())
{
cout << endl; // Dejamos un retorno.
cout << "Introduzca la opcion deseada: " << endl << endl; // Muestra texto en pantalla.

cin >> opc; // Aquí introduces un número, el 1 o el 2.

switch (opc) // Espera recibir un 1 o un 2.
{
case 1:
// Encener luz.
cout << "Enviando: " << Luz_ON << endl; // Muestra en pantalla textos.
Puerto->WriteData(Luz_ON, sizeof(Luz_ON) - 1); // Envía al puerto el texto "Luz_ON".
break;

case 2:
// Apagar luz.
cout << "Enviando: " << Luz_OFF << endl;
Puerto->WriteData(Luz_OFF, sizeof(Luz_OFF) - 1);
break;

default: // Si haz pulsado otro número distinto del 1 y 2, muestra
cout << "Puse del 1 al 2."; // este mensaje.
}


Sleep(500);
int n = Puerto->ReadData(lectura, 49);
if (n > 0)
{
lectura[n + 1] = '\0';
cout << "Recibido: " << lectura << endl;
cout << "-------------------" << endl;
}
}
}


A pesar de que funciona bien en apariencia, hay que seguir mejorando ya que si pulso una letra, sale un bucle repetitivo en default, no sale de ahí ni loco.

@ ivancea96 :
La abreviación que hiciste para ahorrar código está muy curioso, antes debo resolver problemas indicado arriba, a parte de eso, lo de pulsar una tecla y automáticamente ejecuta el envio. ;)

¿Cómo resolvemos el bucle este si pulso letras?

Código (cpp) [Seleccionar]
default: // Si haz pulsado otro número distinto del 1 y 2, muestra
cout << "Puse del 1 al 2."; // este mensaje.


Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

MAFUS

Vacía el buffer cin después de obtener el dato.

Meta

#55
Hola:

Lo he intentado así:
Código (c,15) [Seleccionar]

default: // Si haz pulsado otro número distinto del 1 y 2, muestra
cout << "Puse del 1 al 2."; // este mensaje.
}


Sleep(500);
int n = Puerto->ReadData(lectura, 49);
if (n > 0)
{
lectura[n + 1] = '\0';
cout << "Recibido: " << lectura << endl;
cout << "-------------------" << endl;
}

opc = NULL; // Vaciar el buffer.
}
}


Actúa de la misma manera.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

MAFUS


Meta

#57
Hola:

Voy a probar, mientras hay que entretenerse actualizarse del futuro C++ 17 y C++ 20.
[youtube=640,360]https://www.youtube.com/watch?v=wGYY90vq2VU[/youtube]

Usé esto:
Código (c++,10) [Seleccionar]
Sleep(250);
int n = Puerto->ReadData(lectura, 49);
if (n > 0)
{
lectura[n + 1] = '\0';
cout << "Recibido: " << lectura << endl;
cout << "-------------------" << endl;
}

cin.sync(); // Limpiar.
}
}


Ese no es el problema, todo funciona bien menos una cosa.

Si escribo letras, se vuelve loco. Si escribo cualquier número, funciona de maravilla.
Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

ivancea96

Cita de: Meta en 26 Marzo 2017, 08:39 AM
La abreviación que hiciste para ahorrar código está muy curioso, antes debo resolver problemas indicado arriba, a parte de eso, lo de pulsar una tecla y automáticamente ejecuta el envio. ;)

No era una abreviación, era la forma de corregir el flujo del programa :/


Cita de: Meta en 26 Marzo 2017, 13:25 PM
Si escribo letras, se vuelve loco. Si escribo cualquier número, funciona de maravilla.

Al usar el operator>> de istream (cin), le estás pasando una variable numérica. Si no recibe una entrada válida, pone activa alguna de sus flags internas: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
Para ver si está la flag de error (la que te interesa en este caso), tienes el método fail(). Si quieres ver si hay errores de cualquier tipo, tienes el operator bool de la clase ios.

Usando el operator bool:
Código (cpp) [Seleccionar]
#include <iostream>

using namespace std;

int main(){
while(true){
int n;
cin >> n;
if(!cin){
cout << "Error" << endl;
cin.clear();
cin.sync();
}else{
cout << "Ok: " << n << endl;
}
}
}

Meta

Entendido. Muy buena explicación.

Fíjate que fuí a probar el código en CODE::BLOCKS para saber como se comporta, más bien creyendo que funconaría igual y me da errores por todas partes.

Citar||=== Build: Debug in Arduino_Led (compiler: GNU GCC Compiler) ===|
C:\Users\Meta\Documents\Code Blocks\Arduino_Led\Arduino_Led\main.cpp|13|error: '::main' must return 'int'|
C:\Users\Meta\Documents\Code Blocks\Arduino_Led\Arduino_Led\main.cpp||In function 'int main()':|
C:\Users\Meta\Documents\Code Blocks\Arduino_Led\Arduino_Led\main.cpp|19|warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]|
||=== Build failed: 1 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|



En Visual Studio 2017 funciona muy bien.

Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/