Problema al unir 3 códigos: solo funciona switch case

Hola a todos, En realidad no estaba seguro que titulo poner, espero que ese sea el adecuado, al igual que el tema en el foro.
Mi problema es el siguiente:
Estoy trabajando en mi tesis utilizando un arduino y un xbee protoshield, conectado a 5 botones, 1 sensor hall (DN6851), 1 sensor de humedad y temperatura (SHT7x) y 7 LEDs. Todo el hardware y conexiones han sido probadas y están bien.
El problema es la lógica de ejecución o de la rutina (yo creo): Tengo 3 códigos, el programa 'principal', el programa del 'pluviometro' y el programa de los 'botones con debounce'. En realidad no sé como unir estos 3 códigos o más bien agregarlos al programa 'principal'.
El programa principal utiliza una función Task para enviar los valores del SHT7x cada 10s por el Xbee, ese código cuenta con las configuraciones del Xbee, asi como también con un Swtich Case el cual determina que LEDs encender o apagar dependiendo de la carga útil que reciba el Xbee en el protoshield.

El programa 'principal', traté de agregarle el programa 'botones con debounce' pero no funcionó, funciona el switch case pero el código de los botones no :blush:

#include "System_Defs.h"
#include <XBee.h>
#include <Sensirion.h>
#include <Bounce.h>
#define BUTTON0 A0
#define bombLed 4
#define BUTTON1 A1
#define blowLed 5
#define BUTTON2 A2
#define S0 6
#define BUTTON3 A3
#define S1 7
#define BUTTON12 12
#define S2 8
int salValue0 = LOW;
int salValue1 = LOW;
int salValue2 = LOW;
int salValue3 = LOW;
int salValue4 = LOW;

//TASKs
int medicion_id;
unsigned long medicion_var;
// allocate two bytes for to hold a 10-bit analog reading
uint8_t payload[] = {   0, 0, 0, 0};
// with Series 1 you can use either 16-bit or 64-bit addressing
// 16-bit addressing: Enter address of remote XBee, typically the coordinator
Tx16Request tx = Tx16Request(0x0001, payload, sizeof(payload));
XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle 
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();
//variables

boolean Manual=true;

//Salidas
int16_t statusLed = 9;
int16_t errorLed = 10;
/*int16_t bombLed = 4;
int16_t blowLed = 5;
int16_t S0 = 6;
int16_t S1 = 7;
int16_t S2 = 8;
*/

//SHT
const int16_t dataPin  =  2;
const int16_t clockPin =  3;
int16_t option = 0;
int16_t data = 0;
float temperature;
float humidity;
float dewpoint;

Sensirion tempSensor = Sensirion(dataPin, clockPin);

void flashLed(int16_t pin, int16_t times, int16_t wait) {

  for (int16_t i = 0; i < times; i++) {
    digitalWrite(pin, HIGH);
    delay(wait);
    digitalWrite(pin, LOW);

    if (i + 1 < times) {
      delay(wait);
    }
  }
}

//Task
void envio_medicion(int id, void * tptr) {
  //a partir de aquí es para la lectura del sensor y la impresión     
        tempSensor.measure(&temperature, &humidity, &dewpoint);
        delay (10);
        //envio de datos por el Xbee
        payload[0] = (int16_t) temperature >> 8 & 0xff; //cast a temperature para
        payload[1] = (int16_t) temperature & 0xff; //que pueda ser manipulada
        payload[2] = (int16_t) humidity >> 8 & 0xff; //cast a humedad para
        payload[3] = (int16_t) humidity & 0xff; //que pueda ser manipulada
        delay (20);
        xbee.send(tx);
        // flash TX indicator
        flashLed(statusLed, 1, 100); 
    }
    
Bounce bouncer0 = Bounce( BUTTON0, 50 ); 
Bounce bouncer1 = Bounce( BUTTON1, 50 );
Bounce bouncer2 = Bounce( BUTTON2, 50 );
Bounce bouncer3 = Bounce( BUTTON3, 50 );
Bounce bouncer12 = Bounce( BUTTON12, 50 );   

void setup() {

  pinMode(statusLed, OUTPUT);
  pinMode(errorLed, OUTPUT);
  pinMode(blowLed,  OUTPUT);
  pinMode(bombLed,  OUTPUT);
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2,  OUTPUT);
  
  pinMode(BUTTON0,INPUT);
  pinMode(BUTTON1,INPUT);
  pinMode(BUTTON2,INPUT);
  pinMode(BUTTON3,INPUT);
  pinMode(BUTTON12,INPUT);


  // start serial
  xbee.begin(9600);
  flashLed(statusLed, 3, 50);

  digitalWrite(blowLed, LOW);
  digitalWrite(bombLed, LOW);
  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  
  //Task
  medicion_id = createTask(envio_medicion, 5000, TASK_ENABLE, &medicion_var); 

}

// continuously reads packets, looking for RX16 or RX64
void loop() {
      
  xbee.readPacket();

  if (xbee.getResponse().isAvailable()) {
    // got something

    if (xbee.getResponse().getApiId() == RX_16_RESPONSE || xbee.getResponse().getApiId() == RX_64_RESPONSE) {
      // got a rx packet

      if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {
        xbee.getResponse().getRx16Response(rx16);
        option = rx16.getOption();
        data = rx16.getData(0);
      } 
      else {
        xbee.getResponse().getRx64Response(rx64);
        option = rx64.getOption();
        data = rx64.getData(0);
      }

      // TODO check option, rssi bytes    
      flashLed(statusLed, 1, 10);
      
       
      //MODOS DE OPERACIÓN
      switch (data){
        
      case 0x05: //MODO EMERGENCIA
        digitalWrite(blowLed, LOW);                        
        digitalWrite(bombLed, LOW);
        digitalWrite(S0, LOW);                             
        digitalWrite(S1, LOW);
        digitalWrite(S2, LOW);
        break;

      case 0x02: //Modo Manual
        Manual=true;
        digitalWrite(blowLed, LOW);                        
        digitalWrite(bombLed, LOW);
        digitalWrite(S0, LOW);                             
        digitalWrite(S1, LOW);
       digitalWrite(S2, LOW);
        break;

        //MODO "AUTOMATICO" *SOLO PARA PRUEBAS EN LV *
      case 0x03:
        Manual=false;
        digitalWrite(blowLed, HIGH);                        
        digitalWrite(bombLed, HIGH);
        digitalWrite(S0, HIGH);                             
        digitalWrite(S1, HIGH);
        digitalWrite(S2, HIGH);
        break;

        //Establece Salidas
      case 0x04:
        Manual=true;
        digitalWrite(blowLed, LOW);                        
        digitalWrite(bombLed, HIGH);
        digitalWrite(S0, HIGH);                             
        digitalWrite(S1, HIGH);
        digitalWrite(S2, LOW);
        break;

        //Caso 1: Soplador y Bomba Apagados
      case 0xAA:
        Manual=true;
        digitalWrite(blowLed, LOW);
        digitalWrite(bombLed, LOW);
        break;

        //Caso 2: Soplador ON & Bomba OFF
      case 0xFF:
        Manual=true;
        digitalWrite(blowLed, HIGH);
        digitalWrite(bombLed, LOW);
        digitalWrite(S0, LOW);                             
        digitalWrite(S1, LOW);
        digitalWrite(S2, LOW);
        break;

        //Caso 3: Soplador OFF & Bomba ON
      case 0xBB:
        Manual=true;
        digitalWrite(blowLed, LOW);
        digitalWrite(bombLed, HIGH);
        digitalWrite(S0, LOW);                             
        digitalWrite(S1, LOW);
        digitalWrite(S2, LOW);
        break;


        //Caso 4: Soplador ON & Bomba ON
      case 0xEE:
        Manual=true;
        digitalWrite(blowLed, HIGH);
        digitalWrite(bombLed, HIGH);
        digitalWrite(S0, LOW);                             
        digitalWrite(S1, LOW);
        digitalWrite(S2, LOW);
        break;

      }
  
          ///////////////Buttons w/debounce (doesn't work)
      if ( bouncer0.update() ) {
     if ( bouncer0.read() == HIGH) {
       if ( salValue0 == LOW ) {
         salValue0 = HIGH;
       } else {
         salValue0 = LOW;
       }
       digitalWrite(bombLed,salValue0);
     }
   }
   
   if ( bouncer1.update() ) {
     if ( bouncer1.read() == HIGH) {
       if ( salValue1 == LOW ) {
         salValue1 = HIGH;
       } else {
         salValue1 = LOW;
       }
       digitalWrite(blowLed,salValue1);
     }
   }
   
   if ( bouncer2.update() ) {
     if ( bouncer2.read() == HIGH) {
       if ( salValue2 == LOW ) {
         salValue2 = HIGH;
       } else {
         salValue2 = LOW;
       }
       digitalWrite(S0,salValue2);
     }
   }
   
      if ( bouncer3.update() ) {
     if ( bouncer3.read() == HIGH) {
       if ( salValue3 == LOW ) {
         salValue3 = HIGH;
       } else {
         salValue3 = LOW;
       }
       digitalWrite(S1,salValue3);
     }
   }
   
      if ( bouncer12.update() ) {
     if ( bouncer12.read() == HIGH) {
       if ( salValue4 == LOW ) {
         salValue4 = HIGH;
       } else {
         salValue4 = LOW;
       }
       digitalWrite(S2,salValue4);
     }
   }
////////////////////////////////     
      

      Serial.print(data);
    } 
    else {
      // not something we were expecting
      flashLed(errorLed, 1, 25);    
    }
  } 
  else if (xbee.getResponse().isError()) {
    //nss.print("Error reading packet.  Error code: ");  
    //nss.println(xbee.getResponse().getErrorCode());
    // or flash error led
  } 
}

El codigo del 'pluviometro' con el sensor hall cuenta los pulsos Altos empleando la función pulseIn, y resetea la cuenta despues de 10s de inactividad;

/*
Cuenta los pulsos altos, despues de 10s se resetea la cuenta C:

Arduino has a convenient function called pulseIn 
that you can use to count the HIGH or the LOW of a pulse. 
The difference between the LOW and HIGH 
must be at least greater than 3 volts.
http://note19.com/2008/12/28/circuit-gear-arduino-and-counting-pulses/
http://arduino.cc/en/Reference/PulseIn
*/

int pulsePin = 11;
unsigned long counter = 0;
unsigned long duration = 0;
unsigned long timeout = 10000000; // in microseconds
 
void setup() {
  pinMode(pulsePin, INPUT);
  // enable the 20K pull-up resistor to steer
  // the input pin to a HIGH reading.
  digitalWrite(pulsePin, HIGH);
  Serial.begin(9600);
  Serial.println("Here we go again");
}
 
void loop() {
  duration = pulseIn(pulsePin, HIGH, timeout);
  if (duration == 0) {
    Serial.print("Pulse started before the timeout.");
    Serial.println("");
    counter=0;
    
  } else {
    counter++;
    Serial.print(counter);
    Serial.print(", ");
    Serial.print(duration);
    Serial.println("");
  }
}

y el último código es 'botones con debounce' que hace un "toggle" al estado de los LEDs:

#include <Bounce.h>
#define BUTTON0 A0
#define bombLed 4
#define BUTTON1 A1
#define blowLed 5
#define BUTTON2 A2
#define S0 6
#define BUTTON3 A3
#define S1 7
#define BUTTON12 12
#define S2 8
int salValue0 = LOW;
int salValue1 = LOW;
int salValue2 = LOW;
int salValue3 = LOW;
int salValue4 = LOW;

// This example changes the state of the LED everytime the button is pushed
// Build the circuit indicated here: http://arduino.cc/en/Tutorial/Button


Bounce bouncer0 = Bounce( BUTTON0, 50 ); 
Bounce bouncer1 = Bounce( BUTTON1, 50 );
Bounce bouncer2 = Bounce( BUTTON2, 50 );
Bounce bouncer3 = Bounce( BUTTON3, 50 );
Bounce bouncer12 = Bounce( BUTTON12, 50 );

void setup() {
  
  
  pinMode(bombLed,  OUTPUT);
  pinMode(blowLed,  OUTPUT);
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2,  OUTPUT);
    
  pinMode(BUTTON0,INPUT);
  pinMode(BUTTON1,INPUT);
  pinMode(BUTTON2,INPUT);
  pinMode(BUTTON3,INPUT);
  pinMode(BUTTON12,INPUT);
  
  digitalWrite(blowLed, LOW);
  digitalWrite(bombLed, LOW);
  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  

}

void loop() {

   if ( bouncer0.update() ) {
     if ( bouncer0.read() == HIGH) {
       if ( salValue0 == LOW ) {
         salValue0 = HIGH;
       } else {
         salValue0 = LOW;
       }
       digitalWrite(bombLed,salValue0);
     }
   }
   
   if ( bouncer1.update() ) {
     if ( bouncer1.read() == HIGH) {
       if ( salValue1 == LOW ) {
         salValue1 = HIGH;
       } else {
         salValue1 = LOW;
       }
       digitalWrite(blowLed,salValue1);
     }
   }
   
   if ( bouncer2.update() ) {
     if ( bouncer2.read() == HIGH) {
       if ( salValue2 == LOW ) {
         salValue2 = HIGH;
       } else {
         salValue2 = LOW;
       }
       digitalWrite(S0,salValue2);
     }
   }
   
      if ( bouncer3.update() ) {
     if ( bouncer3.read() == HIGH) {
       if ( salValue3 == LOW ) {
         salValue3 = HIGH;
       } else {
         salValue3 = LOW;
       }
       digitalWrite(S1,salValue3);
     }
   }
   
      if ( bouncer12.update() ) {
     if ( bouncer12.read() == HIGH) {
       if ( salValue4 == LOW ) {
         salValue4 = HIGH;
       } else {
         salValue4 = LOW;
       }
       digitalWrite(S2,salValue4);
     }
   }
}

Agrego que he probado los 3 códigos por separado y funcionan correctamente, el problema es cuando trato de unirlos en el programa principal :~
Por favor ayuda! en realidad no busco que hagan mi trabajo, simplemente quiero entender lo que estoy haciendo mal, ¿donde debería poner los otros 2 códigos para que funcione bien? ¿Cual es la secuencia de la rutina? ¿Me estoy olvidando de algo? ¿La función Task está causando problemas?
Todos sus comentarios y sugerencias me pueden ser muy utiles.
Muchas gracias por su tiempo.

Hola.

Hasta donde yo sé los programas de arduino deben tener solo una función setup() y una función loop().
Si juntas estos tres programa en uno, no pueden tener tres loop y tres setup.

Lo que no se me ocurre es como los unes sin que te de error el compliador.

¿O no he entendido la pregunta?

Saludos.

laremi:
Lo que no se me ocurre es como los unes sin que te de error el compliador.
¿O no he entendido la pregunta?

Con unir no me referia a copiar y pegar todo el código, sino utilizar las variables, librerias y demás elementos de los 3 programas para hacer uno solo. Al final pude resolver el problema(: Gracias por tu respuesta!

Hola,

En el primer codigo creo que usas lo que recibes del Xbee (data) para escribir los leds y luego abajo usas los botones con debounce para escribir esos mismos leds, lo que me parece que sucede es que luego de que escribes lo de los botones vuelves a sobreescribir lo que dice data tan rapido que nunca vez lo de los botones.

Se me ocurre que luego de usar data le agregues un valor invalido data 0x00 por ejemplo y agregues un caso default donde no hagas nada, y asi si deberias ver lo de los botones.

Lo demas no lo vi.

Saludos.

Luis_AM3C:
Se me ocurre que luego de usar data le agregues un valor invalido data 0x00 por ejemplo y agregues un caso default donde no hagas nada, y asi si deberias ver lo de los botones......

Hola,
muchas gracias por la respuesta, me parece muy bien lo que dices, probaré a ver que tal :smiley: ....lo que hice fue poner el código de debounce al principio, así sí me funciona. Pero al agregarle el código del pluviometro ya no, pero podría ser por lo mismo que señalas. Probaré y les escribo.
Saludos y buen día! :slight_smile: