Pro Micro - code review help please.

Hi All,

I had code up and running on a Nano with just one button to test interrupts and turning power off to an Xbee explorer board to extend battery life. I use the output from a pin to toggle the state of a 2N3904 as a switch with the collector connected to the ground pin of the explorer board.

I would love a pair of "fresh" eyes on this code, I can't figure out why it no longer works when trying to adapt it for a Pro Micro instead of the Nano I was using. The Pro Micro as more interrupts so I can monitor 3 buttons for a button press. Any one that is pressed triggers the same routine to power up the Xbee board.

On the Nano I was using SoftwareSerial and created a "mySerial" instance and used mySerial.write('L') when light was to be on. On the Micro, I want to use the actual RX - TX pins, so my understanding is that it is pointless to create a Software Serial instance to end up using the actual hardware pins. I also read that I should use Serial1.... because Serial is for the USB port.

Thanks in advance for the help.
Dan

#include <avr/sleep.h>

// Declare pin numbers for feedback LEDs 1 thru 4
const int LED1_pin = 10;
const int LED2_pin = 16;
const int LED3_pin = 14;
const int LED4_pin = 15;

// Declare pin numbers for bell and light buttons and power
const int BTN_Bell = 7;
const int BTN_Light_ON = 2;
const int BTN_Light_OFF = 3;
const int Xbee_Pwr_Toggle = A1; 
int BTN_Light_state = HIGH;    
int BTN_Bell_state = HIGH;    
int previousBTN_Bell_state = LOW;    



void setup()
{
  pinMode(LED1_pin, OUTPUT);
  pinMode(LED2_pin, OUTPUT);
  pinMode(LED3_pin, OUTPUT);
  pinMode(LED4_pin, OUTPUT);
  pinMode(Xbee_Pwr_Toggle, OUTPUT);
  
  pinMode(BTN_Bell, INPUT_PULLUP);       
  pinMode(BTN_Light_ON, INPUT_PULLUP);
  pinMode(BTN_Light_OFF, INPUT_PULLUP);

  
// Open Serial com ports to send data via Xbee board,
// rate matches your XBee setting (9600 is default).
  Serial1.begin(9600); 
}


void loop()
{
  // button send portion to remote units
  // on button press turn remote light (relay) on or off
  sleepNow();
  BTN_Light_state = digitalRead(BTN_Light_ON);
  if (BTN_Light_state == LOW) {         
       delay(50);                               // pause to give it time to wake up
       Serial1.write('L');               // light btn is pressed
       delay(275);                              // long delay to wait out the bounce
  }     

  BTN_Light_state = digitalRead(BTN_Light_OFF);
  if (BTN_Light_state == LOW) {         
       delay(50);                               // pause to give it time to wake up
       Serial1.write('Z');               // light btn is pressed
       delay(275);                              // long delay to wait out the bounce
  }     
  
  BTN_Bell_state = digitalRead(BTN_Bell);  
  if (BTN_Bell_state != previousBTN_Bell_state) {          
    delay(10);                               // pause to give it time to wake up
    if (BTN_Bell_state == LOW) {
        Serial1.write('B');                        // bell btn is pressed
    }
    else {
         Serial1.write('O');                       // bell btn is released
    }
    previousBTN_Bell_state = BTN_Bell_state;
    delay(50);
   }
  
  
  // feedback section from remote units - who got the message ?
  // turn corresponding LED on or off to know that remote light is on or off
  if (Serial1.available() > 0) { 
      char Msg = Serial1.read();
      switch (Msg) {
        case '1':                         // If received '1' station 1 at OFF
          digitalWrite(LED1_pin, LOW);
          break;
        case '2':                         // If received '2' station 2 at OFF
          digitalWrite(LED2_pin, LOW);
          break;
        case '3':                         // If received '3' station 3 at OFF
          digitalWrite(LED3_pin, LOW);
          break;
        case '4':                         // If received '4' station 4 at OFF
          digitalWrite(LED4_pin, LOW);
          break;
        case '5':                         // If received '5' station 1 at ON
          digitalWrite(LED1_pin, HIGH);
          break;
        case '6':                         // If received '6' station 2 at ON
          digitalWrite(LED2_pin, HIGH);
          break;
        case '7':                         // If received '7' station 3 at ON
          digitalWrite(LED3_pin, HIGH);
          break;  
        case '8':                         // If received '8' station 4 at ON
          digitalWrite(LED4_pin, HIGH);
          break;  
      }
      delay(50);        
  }   
}


void sleepNow()         
{
  digitalWrite(Xbee_Pwr_Toggle, LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  attachInterrupt(digitalPinToInterrupt(BTN_Light_ON), wakeUp, LOW);
  attachInterrupt(digitalPinToInterrupt(BTN_Light_OFF), wakeUp, LOW);
  attachInterrupt(digitalPinToInterrupt(BTN_Bell), wakeUp, LOW);
   sleep_mode();
}


void wakeUp()
{
  sleep_disable();
  detachInterrupt(digitalPinToInterrupt(BTN_Light_ON));
  detachInterrupt(digitalPinToInterrupt(BTN_Light_OFF));
  detachInterrupt(digitalPinToInterrupt(BTN_Bell));
  digitalWrite(Xbee_Pwr_Toggle, HIGH);
}

blh64:
The Pro Micro is an Atmel 328 which has 1 Serial port.

For me a Pro Micro is a Pro Micro ATmega32U4 5V 16MHz.

The Pro Micro as more interrupts so I can monitor 3 buttons for a button press. Any one that is pressed triggers the same routine to power up the Xbee board.

You could have done that with a 3 input logic-OR gate (or an AND gate for active LOW) either way just 1 UART

Pinchange interrupts should work just like the external interrupts, which are available on all pins IIRC.

Only port B supports pin change interrupts on a 32u4.
That's pins 8 to 11 and the SPI pins (14 to 16 and RX LED on a Pro Micro).

Hi All,

I just realized that I was not very specific in my "it no longer works" comment.

Now that I have set-up 3 interrupts instead of just the one I tested with, my Xbee explorer board stays on after a button press. Yet my "sleep" and "wake" code is the same as before - I just added (attached) 2 more interrupts.

Also now that I am NOT using SoftwareSerial, my remote stations don't seem to be receiving any message from this "sender" code. Does an instance of SoftwareSerial like this code :

void loop()
{
  if (XBee.available() > 0) { 
        char Msg = XBee.read();
        switch (Msg) {    
          case 'B':                                 // B = bell btn was pressed
              digitalWrite(BELLrelay_pin, LOW);     // Relay triggers on low
              break;
          case 'L':                                 // light ON btn was pressed                      
              digitalWrite(LIGHTrelay_pin, LOW);    // light gets turned on
              XBee.write('6');                      // say remote station 1 got the ON message
              delay(15);
              break;                              
          case 'O':                                 // O = bell btn was released
              digitalWrite(BELLrelay_pin, HIGH);     
              break;
          case 'Z':                                 // light OFF btn was pressed                    
              digitalWrite(LIGHTrelay_pin, HIGH);   // light gets turned OFF
              XBee.write('2');                      // say remote station 1 got the OFF message
              delay(15);
              break;                     
        }
    }
}

behave differently than when I send the same data with :

  sleepNow();
  BTN_Light_state = digitalRead(BTN_Light_ON);
  if (BTN_Light_state == LOW) {         
       delay(50);                               // pause to give it time to wake up
       Serial1.write('L');               // light btn is pressed
       delay(275);                              // long delay to wait out the bounce
  }     

  BTN_Light_state = digitalRead(BTN_Light_OFF);
  if (BTN_Light_state == LOW) {         
       delay(50);                               // pause to give it time to wake up
       Serial1.write('Z');               // light btn is pressed
       delay(275);                              // long delay to wait out the bounce
  }     
  
  BTN_Bell_state = digitalRead(BTN_Bell);  
  if (BTN_Bell_state != previousBTN_Bell_state) {          
    delay(10);                               // pause to give it time to wake up
    if (BTN_Bell_state == LOW) {
        Serial1.write('B');                        // bell btn is pressed
    }
    else {
         Serial1.write('O');                       // bell btn is released
    }
    previousBTN_Bell_state = BTN_Bell_state;
    delay(50);
   }

Is there a conversion that is different between Serial1 and SoftwareSerial that 'L' being sent is not what the receiver unit is looking for ??

Thanks in advance for the "fresh eyes" on this.
Dan

Update.....After more testing today.

Communication between Xbee radios is OK with Serial1.

My issue seems to be with the interrupts and the fact that I power down the radios.
When the sending Xbee wakes up there seem to be garbage sent on the 1st button press.
Also if the user holds the button down - like to ring the bell in my code - the radio no longer sends any data.