alguna idea para mejorar este codigo SOLUCIONADO

/tres pulsadores by peperruno

//boton 1
const int buttonPin = 2;
int estado = 0;
const int ledPin = 13;
//boton 2
const int buttonPin2 = 4;
int estadobutton2 = 0;
const int ledPin2 = 12;
//boton 3
const int buttonPin3 = 7;
int estadobutton3 = 0;
const int ledPin3 = 8;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(ledPin2, OUTPUT);
pinMode(buttonPin2, INPUT);
pinMode(ledPin3, OUTPUT);
pinMode(buttonPin3, INPUT);
}

void loop(){

if (digitalRead(buttonPin) == HIGH) {
delay(500);
if(estado)
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
estado = ~estado;
}
if (digitalRead(buttonPin2) == HIGH) {
delay(500);
if(estado)
digitalWrite(ledPin2, HIGH);
else
digitalWrite(ledPin2, LOW);
estado = ~estado;
}
if (digitalRead(buttonPin3) == HIGH) {
delay(500);
if(estado)
digitalWrite(ledPin3, HIGH);
else
digitalWrite(ledPin3, LOW);
estado = ~estado;
} }

funciona bien pero no es preciso en cuanto al tiempo que hay que mantener presionados los pulsadores y eso hace que parezca que falla al encender y apagar sobre todo si lo maneja alguien sin conocimiento alguno del proceso real , alguna idea para mejorar este sistema , he probado con varios valores de delay y bueno mejora pero no es definitivo, muchas gracias

Si, leer mucho... :slight_smile:

alguna recomendación de lectura concreta sobre este tema , :fearful: principalmente no quiero molestar gracias.-

Una pregunta,

estado = ~estado;

if(estado) vario

¿que se supone que tienen que hacer? ¿Te compila bien?

si creo que si , si esta encendido lo apaga y si esta apagado lo enciende eso lo hace bien pero claro el delay es para dar tiempo a pulsar y ese es el problema que no siempre pulsas el mismo tiempo y a veces no se enciende y hay que volver a pulsar , perdona pero soy muy nuevo y tengo que ir mejorando.- perdona lo de vario fue un error al copiarlo no esta en el codigo.-

Utiliza la función millis() en vez de utilizar delay's, cada dalay es una pausa en el programa y en tu caso esos 500 ms no son de espera para que pulse alguien sino que se queda parado medio segundo sin más.

se queda parado para dar tiempo a pulsar y que no lo lea de nuevo , como lo haría millis() uso el mismo tiempo? gracias

Lo suyo sería capturar los botones mediante interrupciones, pero si llevas el tema de programación flojillo, mejor no complicarte la vida todavía. Todo se andará.
Por cierto, ¿no sería mejor usa un solo hilo para el código? llevas 2 hilos abiertos y puede que te lies (o te liemos) con varios frentes abiertos.

Con millis(), da juego a que el procesador haga otras tareas mientras hace la espera, pero yo te aconsejo que, de momento, lo dejes así y te mires los ejemplos que hay en el IDE de Arduino y en el playground. Igual allí encuentras código que te ayuda en tu cometido.

hola PepeChorva , toda la razon lo he probado y va mucho mejor eres un crack queda como sigue , gracias.-//tres pulsadores by peperruno

//boton 1
const int buttonPin = 2;
int estadobuttonPin = 0;
const int ledPin = 13;
//boton 2
const int buttonPin2 = 4;
int estadobuttonPin2 = 0;
const int ledPin2 = 12;
//boton 3
const int buttonPin3 = 7;
int estadobuttonPin3 = 0;
const int ledPin3 = 8;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
pinMode(ledPin2, OUTPUT);
pinMode(buttonPin2, INPUT);
pinMode(ledPin3, OUTPUT);
pinMode(buttonPin3, INPUT);
}

void loop(){

if (digitalRead(buttonPin) == HIGH) {
delay(500);
if(estadobuttonPin)
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
estadobuttonPin = ~estadobuttonPin;
}
if (digitalRead(buttonPin2) == HIGH) {
delay(500);
if(estadobuttonPin2)
digitalWrite(ledPin2, HIGH);
else
digitalWrite(ledPin2, LOW);
estadobuttonPin2 = ~estadobuttonPin2;
}
if (digitalRead(buttonPin3) == HIGH) {
delay(500);
if(estadobuttonPin3)
digitalWrite(ledPin3, HIGH);
else
digitalWrite(ledPin3, LOW);
estadobuttonPin3 = ~estadobuttonPin3;
} }

¿Ves lo que te decía? Esta contestación iba para el otro hilo :grin:
Me alegro que te funcione bien

Vamos a ver "a modo" tutorial cómo mejorar un poco el código que nos has planteado. Una alternativa, consiste en codificar de forma eficiente. En esta entrega veremos la utilidad que tienen las funciones, cómo se utilizan y por qué son nuestras aliadas.

En el fragmento de código que nos has planteado, podemos ver que hay ciertos factores comunes y ciertos patrones. Qué sucedería si esto lo sacamos fuera del código en una función que acepta unos valores de entrada y unos valores de salida:

//boton 1
const uint8_t buttonPin = 2;
uint8_t estadobuttonPin = 0;
const uint8_t ledPin =  13;

//boton 2
const uint8_t buttonPin2 = 4;
uint8_t estadobuttonPin2 = 0;
const uint8_t ledPin2 = 12;

//boton 3
const uint8_t buttonPin3 = 7;
uint8_t estadobuttonPin3 = 0;
const uint8_t ledPin3 = 8;
 
void scanAndSet ( uint8_t inPin, uint8_t outPin, uint8_t &state )
{
   if ( digitalRead ( inPin ) == HIGH )
   {
      digitalWrite ( outPin, state );
   }
   state = ~state;
}
 
void setup()
{
   pinMode(ledPin, OUTPUT);     
   pinMode(buttonPin, INPUT);
   pinMode(ledPin2, OUTPUT);
   pinMode(buttonPin2, INPUT);
   pinMode(ledPin3, OUTPUT);
   pinMode(buttonPin3, INPUT);
}
 
void loop()
{
   scanAndSet ( buttonPin, ledPin, estadobuttonPin );
   scanAndSet ( buttonPin2, ledPin2, estadobuttonPin2 );
   scanAndSet ( buttonPin3, ledPin3, estadobuttonPin3 );
   delay ( 500 );
}

Donde "&" (sin entrar mucho en detalles y simplificando, le dice a C++ que es un valor de "entrada y de salida" de tal forma que las modificaciones que se hagan tengan efecto en quien las llama. Este código hace lo mismo que has publicado, pero en vez de tardar 1.5s, funciona de la misma forma pero usando 0.5s.

¿Pero para qué sirven las funciones? vale, vale, que el código queda más compacto y más legible.

Supongamos que el autor de este código lo que realmente quería es conseguir que: al pulsar el botón el LED se encienda y cuando vuelva a pulsar el botón se apague, casi instantaneamente. En vez de que el LED se encienda y se apague cada 3 segundos y si dejo pulsado el botón, o que tarde en encenderse 1.5s (aprox).

En la próxima entrega, veremos cómo se puede hacer cambiar el comportamiento del programa solo cambiando en un punto el código, en vez de hacer recorta pega por doquier.

En esta segunda entrega vamos a ver cómo cambiando la función "scanAndSet", podemos conseguir que el programa se comporte como un interruptor. Es decir: pulso el botón, el LED se enciende, lo vuelvo a pulsar y el LED se apaga. Además, vamos a ver cómo puede hacerse para que de la sensación de que es muy rápido.

Si reemplazamos la función "scanAndSet" por esta:

void scanAndSet ( uint8_t inPin, uint8_t outPin, uint8_t &state )
{
   if ( digitalRead ( inPin ) == HIGH )
   {
      switch ( state )
      {
      case 0:
         state = 1;
         digitalWrite ( outPin, HIGH );
         break;
      case 2:
         digitalWrite ( outPin, LOW );
         state = 3;
         break;
      default:
        break;
      }
   }
   if ( digitalRead ( inPin ) == LOW )
   {
      switch ( state )
      {
      case 1:
         state = 2;
         break;
      case 3:
         state = 0;
         break;
      default:
         break;
      }
   }
}

Conseguimos el efecto que buscamos. ¿Pero cómo leñes funciona?

Para aclararnos un poco, veamos la imagen adjunta. Cuando el estado es 0, el LED asociado al pin está apagado. Si pulso el botón, cambio el estado a 1 y enciendo el LED. Si mantengo pulsado el botón, me quedo en el estado 1 la siguiente vez que lo llame (0.5s después). Si suelto el botón, estado (state) pasa a valer 2 y me mantengo en este estado hasta que alguien pulse el botón otra vez. Al pulsar el botón otra vez con estado en 2, apago el LED y mi cambio el estado a 3. Si sigo manteniendo el botón pulsado más de 0.5 segundos, me quedo como estoy, pero si lo suelto vuelvo a 0.

Ahora vamos a poner nombres útiles a 0, 1, 2, 3 y veremos lo importante que es dar un valor significativo a las variables y constantes de nuestro código:
0 - APAGADO
1 - ENCENDIDO_BOTON_PULSADO
2 - ENCENDIDO
3 - APAGADO_BOTON_PULSADO

Por ejemplo.

Si además, el delay anterior los reducimos a 100ms, el bucle se ejecutará cada 100ms, dando la percepción al usuario de que se ha encendido la luz de forma instantánea. El delay de 100ms, se puede reducir hasta 50us-100us, menos no, porque sino veríamos los efectos de los rebotes que tienen los pulsadores. Por cierto, esta es una forma muy fácil de implementar un código anti-rebotes.

Si os han parecido útiles estas entregas y os interesa, mañana podemos ver cómo crear un librería que implemente una "variable" tecla y una "variable" interruptor LED, que incluso podáis compartir con otros usuarios. Vamos, a lo C++.

switch.png

Todavía se podría depurar un poco con una matriz. Una matriz es una tabla de n elementos. Es como un armario con cajones, el primer cajón es el cajon cero,...
perruno, intentalo, mirate http://arduino.cc/es/Reference/Array

Efectivamente, el autómata se puede hacer mucho mas rápido con una mariz bidimensional y se puede definir una estructura de datos que modele el interuptor. Tal vez lo más importante es definir un tipo enumerado que defina los estados, por claridad.

Yo uso este código cuando tengo que usar muchos pins, asigno outputs/inputs(setup) y solo edito las lineas1 y2

byte pins_input[] = {0,1,2,3,4,5,6,7,16,17};//Pins donde están los inputs
byte pins_output[] = {8,9,10,11,12,13,14,15};//Pins donde están los outputs
#define NUMEROIN sizeof(pins_input)
#define NUMEROOUT sizeof(pins_output)


void setup() {
  byte i,j;
  // Asignar los inputs con pull ups.
  for (i=0; i< NUMEROIN; i++) {
    pinMode(pins_input[i], INPUT);
    digitalWrite(pins_input[i], HIGH);
  //Asignar outputs en estado LOW
  for (j=0; j< NUMEROOUT; j++) {
    pinMode(pins_output[j], OUTPUT);
    digitalWrite(pins_output[j], LOW);

  }
}

Pues como comentaba nayma, aparte de poder definir en vectores lo pines, en este ejemplo vamos a utilizar estructuras de datos para definir los interruptores, una matriz para definir la máquina de estados y finalmente otro vector (array) para ejecutar las acciones.

El código queda muy limpio y sencillo, la mayor parte de las cosas son declaración de tipos y variables.

#include <Arduino.h>

#define OFF            0
#define SWITCHING_ON   1
#define ON             2
#define SWITCHING_OFF  3

// Defino la estructura de datos de mi interruptor
typedef struct
{
  uint8_t  buttonPin;
  uint8_t  miEstado;  
  uint8_t  ledPin;
} t_switch;

// Variable con mis interruptores
t_switch miInterruptor[] = 
  {
    // boton, estado, LED
    { 2, OFF, 13 },  
    { 4, OFF, 12 },
    { 7, OFF, 8 }
  };

// Definir transiciones de mi maquina de estados
// ---------------------------------------------
const uint8_t maquinaInterruptor[2][4] =
{
  // Estados
  //OFF,          SWITCHING_ON, ON,            SWITCHING_OFF  
  { OFF,          ON,           ON,            SWITCHING_OFF }, // transiciones cuando boton sin pulsar
  { SWITCHING_ON, SWITCHING_ON, SWITCHING_OFF, SWITCHING_OFF }  // transiciones cuando boton pulsado
};

// Definir las acciones en cada estado
const uint8_t accion[4] = { LOW, HIGH, HIGH, LOW };

// Numero de interruptores
#define NUM_SWITCH    ( sizeof(miInterruptor)/sizeof(t_switch) )

 
void scanAndSet ( uint8_t inPin, uint8_t outPin, uint8_t &state )
{
  uint8_t nuevoEstado;
  
  // Saco mi nuevo estado, sando la lectura del boton y mi estado actual
  nuevoEstado = maquinaInterruptor[digitalRead(inPin)][state];
  
  // Si el nuevo estado es diferente del antiguo ejecuto la accion
  // en este caso actuar sobre el LED
  if ( nuevoEstado != state )
  {
    digitalWrite ( outPin, accion[nuevoEstado] );
    state = nuevoEstado;
  }
}
 
void setup()
{
  for ( uint8_t i = 0; i < NUM_SWITCH; i++ )
  {
    pinMode ( miInterruptor[i].buttonPin, INPUT );
    pinMode ( miInterruptor[i].ledPin, OUTPUT );
  }
}


void loop()
{
  for ( uint8_t i = 0; i < NUM_SWITCH; i++ )
  {
    scanAndSet ( miInterruptor[i].buttonPin, miInterruptor[i].ledPin, miInterruptor[i].miEstado );
  }
  delay ( 100 );
}

Como veis, el código que ejecuta la maquina de estados, es muy simple. Lo único que hace es cambiar, el estado (utilizando la matriz de transiciones indexada por: el estado del pin y el estado actual). Funcionaría de la siguiente forma:
Supongamos que mi estado actual es SWITCHING_ON y el botón está a low, por lo tanto: maquinaInterruptor[1][0] == ON. Mi nuevo estado sería ON, ahora compruebo si ha habido cambio de estado e indexo la acción de digitalWrite con mi acción.

Espero que os haya gustado la solución. Esta es una solución muy rápida y fácil de implementar para una máquina de estados que no cambie mucho. Para rizar el rizo, se podría haber definido unos "functores" que ejecutasen la acción del estado en vez de usar el digitalWrite tal cual.

La solución algorítmica hace exactamente lo mismo que esta. Esta es más rápida pero consume un poco más de memoria, las matrices se podrían haber definido en memoria flash con lo que habríamos ganado en RAM.

El siguiente paso sería hacer lo mismo pero orientado a objetos.

Por cierto, por la razón que sea no me ha dejado definir el nombre de los estados como un tipo enumerado, que hubiese sido lo suyo. Ha saltado con un error de compilación absurdo.

typedef enum {OFF, SWITCHING_ON, ON, SWITCHING_OFF} t_estado;

@fm es un problema de arduino ide, solución chapuza crearte

//hender.h
typedef enum {OFF, SWITCHING_ON, ON, SWITCHING_OFF} t_estado;

Leñe!!! Pues si que es peculiar este chisme, en la vida se me hubiese ocurrido ponerlo dentro de un fichero de cabecera =(!