Problemas al introducir dos números por Puerto Serie

Buenas tardes,

resulta que he querido hacer un programa que controle por un lado un nivel de tensión y por otro el ángulo de un servomotor. He conseguido por separado que funcionen correctamente, pero al unirlos me da problemas. Cuando he unido ambas partes he puesto un menú donde se introduce un “0” para el servomotor y un “1” para el control de tensión y con un if controlo el flujo del programa.

PROBLEMA: Puedo introducir el valor del menú y aparentemente se mete en el if, pero se me imprimen cosas en la pantalla que no deberían así como no me deja introducir los valores de tensión o ángulo.

Adjunto códigos por separado y el código integrado

CONTROL DEL SERVOMOTOR (0)

#include <Servo.h>

int posicion = 0;    // Se declara y se inicializa la variable posición a cero.

Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este


int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);         //Iniciamos la comunicación serie
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("Escribe el angulo (0 - 180):  "); // Imprimimos en la pantalla el rótulo para el ingreso del ángulo
}

void loop() {

  if (Serial.available() > 0) {   // Se comprueba si la conexión es posible, envía datos si los recibe
    String grados = "";           //
    do {
      grados =  grados + (char)Serial.read(); //Grados toma el valor anterior y el valor de Serial.read()
      //Serial.println(grados); //Aqui ya tenemos el valor del angulo
      delay(5);  
    }
    while (Serial.available() > 0);  // Mientras haya conexión, hace el bucle
    
    Serial.println("Movido a la posición: " + (String)grados);
    posicion = grados.toInt();
    myservo.write(posicion);
    Serial.println("Escribe el angulo (0 - 180)");
  }
}

CONTROL DE TENSIÓN (1)

//Programa más cercano al que buscamos (05/04/2018). 

//Arpoximadamente la tensión de la salida puede variar 0.05V
//para que la tensión de referencia se note un cambio. 
//Esto es debido a que en la salida la tensión va desde los 5V
// hasta los 21V y en la referencia desde 1V hasta 4.2V, provocando
// que un leve cambio en la salida no se refleje un cambio de tensión
// en la referencia.

float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

void setup()
{
  //Abrimos conexión Serial con una tasa de transmisión de datos
  // de 9600 baudios.(este valor es importante porque depende del
  //equipo con el que se vaya a comunicar)
   Serial.begin(9600);
  Serial.println(" ");
  Serial.print("Introduzca tension a la salida: ");
}
 
void loop()
{
   if (Serial.available() > 0)
   {
     //Se captura valor desde el teclado y se transforma a float
      String str = Serial.readStringUntil('\n');
      float TensionSalida = str.toFloat();
     
     //A continuacion se muestra una condicion con 
     // el fin de despreciar tensiones fuera de nuestro rango
     if(TensionSalida<5)
       TensionSalida=5;
     if(TensionSalida>21)
       TensionSalida=21;
      
     //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
     //Se ha eliminado la función de mapeado por problemas
     //Se introduce expresión de proporcionalidad.
      
     TensionRef=(214*TensionSalida)/21;
     analogWrite(9, TensionRef);
    
     //Se muestra valor que queremos
     Serial.println(TensionSalida);
     Serial.print("Tension de Referencia: ");
     Serial.println(TensionRef*resolucion);
     Serial.print("Nivel de tension: ");
     Serial.println(TensionRef);
     Serial.println("  ");
     
     Serial.print("Introduzca tension a la salida: ");
   }
  
}

CÓDIGO INTEGRADO

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}
void loop() {
 
   while (!Serial.available() > 0); // Observa el ; al final es una instrución vacía, es decir, permanece bloqueado mientras no haya dato disponible
   eleccion = Serial.parseInt();
   Serial.println(eleccion);
   
  
  if(eleccion==0)
  {
    Serial.print("Introduzca angulo: ");
  if (Serial.available() > 0) {   // Se comprueba si la conexión es posible, envía datos si los recibe
    String grados = "";           //
    do {
      grados =  grados + (char)Serial.read(); //Grados toma el valor anterior y el valor de Serial.read()
      //Serial.println(grados); //Aqui ya tenemos el valor del angulo
      delay(5);  
    }
    while (Serial.available() > 0);  // Mientras haya conexión, hace el bucle
    
    Serial.println("Movido a la posición: " + (String)grados);
    posicion = grados.toInt();
    myservo.write(posicion);
    
      Serial.println("CONTROL");
      Serial.println("0. ServoMotor ");
      Serial.println("1. Tension");
      Serial.println(" ");
      }
  }
  
  
  if(eleccion==1) //OPCION TENSION
  {
    Serial.print("Introduzca tension a la salida: ");
    if (!Serial.available() > 0)
   {
     //Se captura valor desde el teclado y se transforma a float
      String str = Serial.readStringUntil('\n');
      float TensionSalida = str.toFloat();
     
     //A continuacion se muestra una condicion con 
     // el fin de despreciar tensiones fuera de nuestro rango
     if(TensionSalida<5)
       TensionSalida=5;
     if(TensionSalida>21)
       TensionSalida=21;
      
     //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
     //Se ha eliminado la función de mapeado por problemas
     //Se introduce expresión de proporcionalidad.
      
     TensionRef=(214*TensionSalida)/21;
     analogWrite(9, TensionRef);
    
     //Se muestra valor que queremos
     Serial.println(TensionSalida);
     Serial.print("Tension de Referencia: ");
     Serial.println(TensionRef*resolucion);
     Serial.print("Nivel de tension: ");
     Serial.println(TensionRef);
     Serial.println("  ");
     
       Serial.println("CONTROL");
     Serial.println("0. ServoMotor ");
     Serial.println("1. Tension");
       Serial.println(" ");
   }
  }
    
  if(eleccion!=0 && eleccion!=1)
    {
     Serial.println("ERROR");
     Serial.println();
    
    Serial.println("");
    Serial.println("CONTROL");
    Serial.println("0. ServoMotor ");
    Serial.println("1. Tension");
    Serial.println(" ");
     }
    
 }

Cualquier ayuda es bien recibida,
gracias de antemano.

Una guía aproximada:

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}

void loop() {
  if (Serial.available()) { // Ya no observes nada
    eleccion = Serial.read();
    Serial.println(eleccion);
    switch (eleccion) {
        case '0': // Fíjate que es el carácter '0', no el valor 0
          Serial.print("Introduzca angulo: ");
          while (!Serial.available()); // Ahora sí espero a que llegue algo. Bucle vacío.
          posicion=Serial.parseInt(); 
          Serial.print("Movido a la posición: ");
          Serial.println(posicion);
          myservo.write(posicion);
          break;
        case '1':
          Serial.print("Introduzca tension a la salida: ");
          while (!Serial.available());
          TensionSalida=Serial.parseFloat();
          if(TensionSalida<5)
            TensionSalida=5;
          if(TensionSalida>21)
            TensionSalida=21;
          //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
          //Se ha eliminado la función de mapeado por problemas
          //Se introduce expresión de proporcionalidad.

          TensionRef=(214*TensionSalida)/21;
          analogWrite(9, TensionRef);

          //Se muestra valor que queremos
          Serial.println(TensionSalida);
          Serial.print("Tension de Referencia: ");
          Serial.println(TensionRef*resolucion);
          Serial.print("Nivel de tension: ");
          Serial.println(TensionRef);
          Serial.println("  ");
          break;
        default:
          Serial.println("Opción inválida");
    }
    Serial.println("CONTROL");
    Serial.println("0. ServoMotor ");
    Serial.println("1. Tension");
    Serial.println(" ");
  }   
}

Saludos.

Muchas gracias por la ayuda,

no se si se ha solucionado el problema, pero si que me ha surgido otro. ahora al correr el programa se me imprime infinitamente lo siguiente

PUERTO SERIE CONTROL 0. ServoMotor 1. Tension

-1 Opción inválida CONTROL 0. ServoMotor 1. Tension

Sospecho que puede ser el if cuando se pide la opción, cambiarlo por witch, pero ese cambio lo hiciste expresamente, por eso me tiene loco.

Un saludo.

Cierto. Ya te dije que no lo probé; pero creo que el error está en uno de los pasos que corregí. Ya lo he modificado en el código original. He cambiado la línea siguiente:

  if (Serial.available()) { // Ya no observes nada

que anteriormente estaba como

  if (!Serial.available()) { // Ya no observes nada

Prueba y cuenta.

Vale lo he comprobado, y es cierto que ahora no se repite el bucle infinitamente, dejándome introducir opción. Pero sigue apareciéndome el problema inicial. Expongo lo que me aparece en puerto serial.

CONTROL 0. ServoMotor 1. Tension

0 Introduzca angulo: Movido a la posición: 0 //(Aquí no me deja poner ángulo) CONTROL 0. ServoMotor 1. Tension

CONTROL 0. ServoMotor 1. Tension

1 //Aquí no me deja poner nivel de tensión Introduzca tension a la salida: 5.00 Tension de Referencia: 1.00 Nivel de tension: 50.95

La verdad es que no se de que puede ser, porque llevo semanas probando cosas y publicarlo ha sido la última opción.

Supongo que esté provocado porque tras leer el carácter selector, queda “basura” (el salto de línea) en el buffer. Prueba a poner antes y después del switch el siguiente comando, para vaciar el buffer:

    while(Serial.available()) Serial.read();

Quedaría el código tal que así:

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}

void loop() {
  if (Serial.available()) { // Ya no observes nada
    eleccion = Serial.read();
    Serial.println(eleccion);
    while(Serial.available()) Serial.read();
    switch (eleccion) {
        case '0': // Fíjate que es el carácter '0', no el valor 0
          Serial.print("Introduzca angulo: ");
          while (!Serial.available()); // Ahora sí espero a que llegue algo. Bucle vacío.
          posicion=Serial.parseInt();
          Serial.print("Movido a la posición: ");
          Serial.println(posicion);
          myservo.write(posicion);
          break;
        case '1':
          Serial.print("Introduzca tension a la salida: ");
          while (!Serial.available());
          TensionSalida=Serial.parseFloat();
          if(TensionSalida<5)
            TensionSalida=5;
          if(TensionSalida>21)
            TensionSalida=21;
          //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
          //Se ha eliminado la función de mapeado por problemas
          //Se introduce expresión de proporcionalidad.

          TensionRef=(214*TensionSalida)/21;
          analogWrite(9, TensionRef);

          //Se muestra valor que queremos
          Serial.println(TensionSalida);
          Serial.print("Tension de Referencia: ");
          Serial.println(TensionRef*resolucion);
          Serial.print("Nivel de tension: ");
          Serial.println(TensionRef);
          Serial.println("  ");
          break;
        default:
          Serial.println("Opción inválida");
    }
    while(Serial.available()) Serial.read();
    Serial.println("CONTROL");
    Serial.println("0. ServoMotor ");
    Serial.println("1. Tension");
    Serial.println(" ");
  }   
}

He probado eso que me has dicho, y no funciona, sin embargo se me ha ocurrido poner un delay antes de la lectura del segundo dato (sea ángulo o tensión) y parece que funciona aunque es poco ortodoxo, por el momento me vale.

Pero me surge, un último problema, y es que el pin9 me da solo valor 0 o 5v, pero lo tengo configurado para con analogRead(pin, valor); no se que ha pasado. Repito lo que dije anteriormente, esto funcionaba por separado, y este error me extraña bastante.

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}

void loop() {
  if(Serial.available()) { // Ya no observes nada
    eleccion = Serial.read();
    
    switch (eleccion) {
        case '0': // Fíjate que es el carácter '0', no el valor 0
          Serial.print("Introduzca angulo: ");
          while (!Serial.available()); // Ahora sí espero a que llegue algo. Bucle vacío.
          delay(3000);                    //delay para que de tiempo de poner el ángulo
          posicion=Serial.parseInt(); 
          Serial.print("Movido a la posicion: ");
          Serial.println(posicion);
          myservo.write(posicion);
          break;
        case '1':
          Serial.print("Introduzca tension a la salida: ");
          while (!Serial.available());
          delay(3000);                     // delay para que de tiempo de poner la tensión
          TensionSalida=Serial.parseFloat();
          if(TensionSalida<5)
            TensionSalida=5;
          if(TensionSalida>21)
            TensionSalida=21;
          //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
          //Se ha eliminado la función de mapeado por problemas
          //Se introduce expresión de proporcionalidad.

          TensionRef=(214*TensionSalida)/21; 
          analogWrite(9, TensionRef);

          //Se muestra valor que queremos
          Serial.println(TensionSalida);
          Serial.print("Tension de Referencia: ");
          Serial.println(TensionRef*resolucion);
          Serial.print("Nivel de tension: ");
          Serial.println(TensionRef);
          Serial.println("  ");
          break;
        default:
          Serial.println("Opcion invalida");
    }
    Serial.println("CONTROL");
    Serial.println("0. ServoMotor ");
    Serial.println("1. Tension");
    Serial.println(" ");
  }   
}

Hola:

Vamos a ver.

¿Quieres enviar un 1 y active la tensión?

¿Enviar un 0 para activar el SERVO?

¿Quieres eso?

Si es como creo que dices, si te he entendido bien. Solo tienes que poner dos if en cada uno, el servo y la tensión.

if (comando.equals("0") == true)
  {
    digitalWrite(13, HIGH);
    Serial.println("Servo.");
  }

  if (comando.equals("1") == true)
  {
    digitalWrite(13, LOW);
    Serial.println("Tensión.");
  }

  // Limpiamos la cadena para volver a recibir el siguiente comando.
  comando = "";

¿Lo pillas?

Saludos

Sigo pensando que el problema es de la basura residual que queda en el puerto serie. Prueba a ver si con este otro código (utilizo un par de delays pequeños para dar tiempo a que lleguen los bytes de posible basura).

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}

void loop() {
  if (Serial.available()) { // Ya no observes nada
    delay(100);
    eleccion = Serial.read();
    while(Serial.available()) Serial.read();
    Serial.println(eleccion);
    switch (eleccion) {
        case '0': // Fíjate que es el carácter '0', no el valor 0
          Serial.print("Introduzca angulo: ");
          while (!Serial.available()); // Ahora sí espero a que llegue algo. Bucle vacío.
          posicion=Serial.parseInt();
          Serial.print("Movido a la posición: ");
          Serial.println(posicion);
          myservo.write(posicion);
          break;
        case '1':
          Serial.print("Introduzca tension a la salida: ");
          while (!Serial.available());
          TensionSalida=Serial.parseFloat();
          if(TensionSalida<5)
            TensionSalida=5;
          if(TensionSalida>21)
            TensionSalida=21;
          //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
          //Se ha eliminado la función de mapeado por problemas
          //Se introduce expresión de proporcionalidad.

          TensionRef=(214*TensionSalida)/21;
          analogWrite(9, TensionRef);

          //Se muestra valor que queremos
          Serial.println(TensionSalida);
          Serial.print("Tension de Referencia: ");
          Serial.println(TensionRef*resolucion);
          Serial.print("Nivel de tension: ");
          Serial.println(TensionRef);
          Serial.println("  ");
          break;
        default:
          Serial.println("Opción inválida");
    }
    delay(100);
    while(Serial.available()) Serial.read();
    Serial.println("CONTROL");
    Serial.println("0. ServoMotor ");
    Serial.println("1. Tension");
    Serial.println(" ");
  }
}

En cuanto al problema del pin 9, no he entendido a qué te refieres.

Hola,

lo que propones Metaconta, ya lo había probado, no funciona. Por otro lado, Noter, creo que me va valiendo hasta donde habíamos llegado, es decir, poniendo un pequeño delay antes de capturar el segundo dato.

Lo que te decía sobre el pin 9 es lo siguiente. El sistema por un lado debe mover un servo y por otro dar una tensión de referencia para un circuito integrado (regulador de tensión) la cosa es que probando por separado podía usar el PWM del pin 9 y obtener diferentes niveles de tensión, pero ahora no me responde de esta manera, solo me responde al poner 255, que es el máximo es decir no me está funcionando con el PWM si no con LOW y HIGH, la verdad es que no se porque.

No tengo voltímetro para saberlo, por ello uso un LED y debería ir cambiando la intensidad deel brillo, pero lo dicho, solo encendido o apagado.

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  myservo.attach(10);          // attaches the servo on pin 9 to the servo object
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}

void loop() {
  if(Serial.available()) { // Ya no observes nada
    eleccion = Serial.read();
    
    switch (eleccion) {
        case '0': // Fíjate que es el carácter '0', no el valor 0
          Serial.print("Introduzca angulo... ");
          while (!Serial.available()); // Ahora sí espero a que llegue algo. Bucle vacío.
          delay(3000);
          posicion=Serial.parseInt(); 
          Serial.print("movido a la posicion: ");
          Serial.println(posicion);
          myservo.write(posicion);
          break;
        case '1':
          Serial.print("Introduzca tension a la salida: ");
          while (!Serial.available());
          delay(3000);
          TensionSalida=Serial.parseFloat();
          
          if(TensionSalida<5)
            TensionSalida=5;
          if(TensionSalida>21)
            TensionSalida=21;
          //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM
          //Se ha eliminado la función de mapeado por problemas
          //Se introduce expresión de proporcionalidad.

          TensionRef=(214*TensionSalida)/21; 
          analogWrite(9, TensionRef);

          //Se muestra valor que queremos
          Serial.println(TensionSalida);
          Serial.print("Tension de Referencia: ");
          Serial.println(TensionRef*resolucion);
          Serial.print("Nivel de tension: ");
          Serial.println(TensionRef);
          Serial.println("  ");
          break;
        default:
          Serial.println(" ");
    }
    Serial.println("CONTROL");
    Serial.println("0. ServoMotor ");
    Serial.println("1. Tension");
    Serial.println(" ");
  }   
}

Si pueden ayudarme en esta dirección estaría muy agradecido.
Con esto solucionado y con un poco más de tiempo ya trataríamos de solucionar el problema original.

Hola:

Pongo un sencillo ejemplo de encender y apagar un Led. El Led apagado equivale a TENSIÓN y el Led encendido equivale al SERVO. Lo voy a poner lo má fácil posible.

pinMode(pinLed1, OUTPUT);  // Inicializa el pin del Led 1 como salida.
char caracter;
String comando;
void setup()
{
                Serial.begin(115200);
}
void loop()
{
/* Voy leyendo carácter a carácter lo que se recibe por el canal
 *  serie (mientras llegue algún dato allí), y los voy concatenando
*  uno tras otro en una cadena. En la práctica, si usamos el
*  "Serial monitor" el bucle while acabará cuando pulsemos Enter.
*  El delay es conveniente para no saturar el canal serie y que la
*  concatenación se haga de forma ordenada.
*/

while (Serial.available() > 0)
{
     caracter= Serial.read();
     comando.concat(caracter);
     delay(10);
}
/* Una vez ya tengo la cadena "acabada", compruebo su valor y hago
* que la placa Arduino reaccione según sea este. Aquí podríamos
* hacer lo que quiesiéramos: si el comando es "tal", enciende
* un Led, si es cual, mueve un motor... y así.
*/
if (comando.equals("TENSION") == true)
     {
          digitalWrite(pinLed, HIGH); // Enciende el Led.
          Serial.println("Led 13 encendido.");
     }
if (comando.equals("SERVO") == true)
     {
          digitalWrite(pinLed, LOW); // Apaga el Led.
          Serial.println("Led 13 apagado.");
     }

// Limpiamos la cadena para volver a recibir el siguiente comando.
 comando="";
}
// Fin del código.

Envia por el monitor serie o por donde sea al puerto serie de Arduino, escribes TENSION tal como puse, se enciende el Led, si le envias SERVO, activas el SERVO.

¿Se entiende?

Te tiene que servir si o si.

Saludos.

Edito:
No te había entendido. Primero deseas enviar un valor para elegir TENSION o SERVO. Luego haces lo que quieres con ella.

Una vez elegido TENSION o SERVO, ya tienes que enviar otros comandos a lo que hayas elegido.

Saludos.

Hay cosas del código, que no entiendo muy bien, pero ahora mismo no puedo probarlo.

Lo que si puedo adelantar es que el funcionamiento es el que describes más abajo (no sé si se corresponde con el código que has expuesto o lo expuesto se corresponde con lo primero que dijiste)

A ver lo que quiero es lo siguientes Un menú que me dé a elegir entre lo que quiero controlar 0. Servomotor 1. Tensión

Una vez elegido (0 o 1) 0. Quiero que me pida y me ponga el ángulo en el servomotor. 1. Quiero que me pida y me ponga la tensión determinada por PWM.

Con dije anteriormente con un delay de 3seg puedo introducir el valor del ángulo o tensión sea el caso. Pero en el caso de la tensión por alguna razón no me funciona el PWM es decir, no hay término medio, o está a LOW o a HIGH.

No sé si me explico.

Hola:

¿Ese menú lo eliges con pulsadores o por comandos enviando al puerto serie?

Me refiere este de abajo. 0. Servomotor 1. Tensión

Esa es la primera parte, el menú. Una vez elegido, por ejemplo, el 0. Servomotor, ya puedes maniobrar en él con el if que puse arriba.

Lo que te puse arriba, eliges esto. 0. Servomotor 1. Tensión

Dentro de lo que quiras, puedes poner los comandos que desees.

Saludos.

Exacto, eso es, una vez doy a 0 entra a servomotor y me debe pedir el ángulo. Eso del if es lo que hice al principio pero es realidad es lo mismo que poner un switch-case. Mi problema era que cuando entraba a poner el ángulo del servomotor (o la tensión) no esperaba a que lo diera y saltaba al menú, ahora con un delay parece que he parcheado eso.

Sin embargo, ahora en el pin 9 no me funciona el PWM, es decir, no me da 256 niveles de tensión, sino dos, low y HIGH. Esto último no entiendo porque, ya que he puesto en el código analogWrite y no digitalWrite

¿Has probado en Arduino?

 if (Serial.available() > 0)
    {
      angulo = Serial.parseInt();
      if ((angulo >= 0) && (angulo <= 180))
      {
        miservo.write(angulo);
        delay(15);
      }
    }

Código completo en Arduino. No hagas dos programas en uno. Primero haz uno y luego otro. Si too funciona, haz la mezcla que quieres hacer.

Prueba este código.

#include <Servo.h>
//Creamos una variable servo para poder usar las funciones con ella.
Servo miservo;
int valor = 0;
int angulo;
int x;

void setup()
{
  Serial.begin(115200); // Velocidad en baudios y configuraciçon de inicio.
  //Definimos el pin al que ira conectado el servo.
  miservo.attach(6); Como salida, el pin 6 con uso de PWM.
  //Movemos el servo al centro
  miservo.write(90);  // Coloca el servo en su posición central.
}
void loop() {


  if (Serial.available() > 0) // Espera entrada de datos de 0 a 180.
  {
    valor = Serial.read(); // Los datos leidos se almacena en la variable valor.
    if (valor > 0)
    {
      x = valor;
    }
  }
  else if ((x >= 0) && (x <= 180))
  {
    angulo = x;
    miservo.write(angulo); // Envía los comando finales de 0 a 180 al servo.
  }

}

Captura2.PNG

Si quieres esta interfaz para hacer pruebas, me avisas y lo envio por aquí.

En vez de llamarlo 1 ó 0. ¿Por qué no le llama por nombre?

Se puede confundir la elección con los valores del servo. Para esvitar confunciones.

Saludos.

¿Los valores Nivel de tension que te salen por la consola son coherentes? Porque si es así, no detecto a primera vista ninguna razón software para que el led no regule.

¿Tienes intención de crear una interfaz de escritorio Windows o te quedan con el monitor serie?

Lo cierto es que no he podido probarlo, lo intentaré luego.

La cosa es que he probado por separado, cómo dije anteriormente, ahora me debe dar un error que no veo, lo trataré de buscar. En cuanto a lo de la interfaz, no lo había pensado, pero por ahora no es la prioridad, muchas gracias de todas formas.

A ver el tema del LED, en el código, con el fin de probarlo, pongo manualmente ( en el código) los valores 0,..,254 y 255 y solo funciona con 255, es decir cuando está a 5V la salida, cómo si funcionará como un digitalWrite y no como analogWrite.

Finalmente, he conseguido que funcione, con el código original, pero cambiando de pin del 9 al 6, lo cierto es que no tiene lógica porque en Arduino UNO ambos están habilitados para PWM, pero estoy casi seguro que va bien, porque le he dado caña haciendo pruebas.

FUNCIONAMIENTO:

El programa pide que elijas lo que se quiere controlar 0 (ángulo del servo) o 1 (Tensión de Referencia, que está representado con el brillo de un LED)

Posteriormente el programa pide el ángulo en cuestión (entre 0 y 179) o la tensión de salida (para mi aplicación entre 5 y 21V, pero en el PWM se ve reflejado entre 1 y 4.2V)

regresa al Inicio.

#include <Servo.h>
int eleccion;

//Inicialización tensión
float resolucion=0.01953125; // 5/256. Valor de tensión de un nivel de tension

//Definimos valores
float TensionRef;
float TensionSalida;

//Inicialización variables servomotor
int posicion = 0;    // Se declara y se inicializa la variable posición a cero.
Servo myservo;       // create servo object to control a servo Se crea el objeto servo para el control de este
int pos = 0;         // variable to store the servo position Variable para almacenar la posición del Servo Motor

void setup() {
  Serial.begin(9600);
  pinMode(6, OUTPUT);
  myservo.attach(10);          
  Serial.println("");
  Serial.println("CONTROL");
  Serial.println("0. ServoMotor ");
  Serial.println("1. Tension");
  Serial.println(" ");
}

void loop() {
  if(Serial.available()) {     // Espera para leer caracter
    eleccion = Serial.read();
    
    switch (eleccion) {
        case '0': 

          //Se pide ángulo
          Serial.print("Introduzca angulo... ");
          while (!Serial.available()); // Ahora sí espero a que llegue algo. Bucle vacío.
          delay(3000);
          posicion=Serial.parseInt(); 

          //Se define el intervalo de giro
          if(posicion<0)
            posicion=0;
          if(posicion>179)
            posicion=179;

          // Se ejecuta acción
          Serial.print("movido a la posicion: ");
          Serial.println(posicion);
          myservo.write(posicion);
          
          //Rótulo de Inicio
           Serial.println(" ");
           Serial.println("CONTROL");
           Serial.println("0. ServoMotor ");
           Serial.println("1. Tension");
           Serial.println(" ");
          
          break;
       
        
        case '1':
          //Se pide tensión
          Serial.print("Introduzca tension a la salida: ");
          while (!Serial.available());
          delay(3000);
          TensionSalida=Serial.parseFloat();
     
          //A continuacion se muestra una condicion con 
          // el fin de despreciar tensiones fuera de nuestro rango
           if(TensionSalida<5)
             TensionSalida=5;
          if(TensionSalida>21)
            TensionSalida=21;
      
     //Mapea entre 51 (1V) y 214 (4.2V) niveles de PWM. Se ha eliminado la función de mapeado por problemas
     //Se introduce expresión de proporcionalidad.
     TensionRef=(214*TensionSalida)/21;

     //Se ejecuta acción
     analogWrite(6, TensionRef);
    
     //Se muestra valor que queremos
     Serial.println(TensionSalida);
     Serial.print("Tension de Referencia: ");
     Serial.println(TensionRef*resolucion);
     Serial.print("Nivel de tension: ");
     Serial.println(TensionRef);
     Serial.println("  ");

     //Rótulo de Inicio
     Serial.println(" ");
     Serial.println("CONTROL");
     Serial.println("0. ServoMotor ");
     Serial.println("1. Tension");
     Serial.println(" ");
     break;
        default:
          Serial.println(" ");
    }
    
  }   
          
}

Muchas gracias por la ayuda. :slight_smile: :slight_smile:

Felicidades.

Solo te hace falta hacer una interfaz para dejarlo más cómodo. ;)

A tu manera.

Saludos.