AdSense

Sunday, 16 February 2014

"Home Automation" with Arduino and 433 MHz - The complete remote control

(Deutsche Version) I finally merged the control for my shutters and the power outlet into one program and built a small remote control.


Hardware

There is not much to say about the hardware:

It's an Attiny44A, a pullup resistor for the RESET-pin, three buttons (up, down, stopp), a button cell holder and the 433Mhz transmitter. Each button is connected toan input of the Attiny. If the button is triggered, the input is pulled to ground.

Software

The functions for controlling the shutters and the power outlet have been explained in my other posts (unfortunately at the moment these posts are only available in german), so I'm not going to explain the following source code in detail.

#include <RCSwitch.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

RCSwitch mySwitch = RCSwitch();
unsigned char buttonDown = 10;
unsigned char buttonStopp = 9;
unsigned char buttonUp = 7;
unsigned char buttonPressed = 0;

char stopRequest = 0;

void setup() {
  //disable interrupts
  cli();

  //initialize pins
  pinMode(buttonDown, INPUT_PULLUP);
  pinMode(buttonStopp, INPUT_PULLUP);
  pinMode(buttonUp, INPUT_PULLUP);

  //initialize transmitter and switch off power outlet
  mySwitch.enableTransmit(0);  //transmitter is connected to pin 0
  mySwitch.setProtocol(1);
  mySwitch.switchOff("11011", "10000");

  //save energy!
  ADCSRA &= ~(1<<ADEN); //disable ADC
  ACSR = (1<<ACD); //disable Analog Comparator

  //initialize Pin-Change-Interrupt
  PCMSK1 |= (1<<PCINT8); //Pin-Change-Interrupt at pin 2 (Arduino Pin  10)
  PCMSK1 |= (1<<PCINT9); //Pin-Change-Interrupt at pin 3 (Arduino Pin 9)
  PCMSK0 |= (1<<PCINT7); //Pin-Change-Interrupt at pin 6 (Arduino Pin 7)
 
  //prepare Power-Down-Mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  //enable interrupts
  sei();
}
void loop() {
  sendCommand();
  powerDown();
} 

void sendCommand() {
  if (buttonPressed == buttonDown) {
    mySwitch.switchOn("11011", "10000");
    delay(750);
    sendCommandDown();
    powerDown(25);
    mySwitch.switchOff("11011", "10000");
    buttonPressed = 0;
  }

  else if (buttonPressed == buttonUp) {
    mySwitch.switchOn("11011", "10000");
    delay(750);
    sendCommandUp();
    powerDown(25);
    mySwitch.switchOff("11011", "10000");
    buttonPressed = 0;
  }
}

//command shutters up
void sendCommandUp() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100F0F0F");
  mySwitch.sendQuadState("0F0F0100QQ0F100F0F1Q");
  mySwitch.setProtocol(1);
}

//command shutters stopp
void sendCommandStopp() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100FFFFF");
  mySwitch.setProtocol(1);
}

//command shutters down
void sendCommandDown() {
  mySwitch.setProtocol(4);
  mySwitch.sendQuadState("0F0F0100QQ0F100F0101");
  mySwitch.sendQuadState("0F0F0100QQ0F100F0110");
  mySwitch.setProtocol(1);
}

//let Attiny wait for time secinds
void powerDown(char time) {
  GIMSK |= (1<<PCIE1); //enable Pin-Change-Interrupt
  GIMSK |= (1<<PCIE0);
  
  stopRequest = 0;

  for (char i = 1; i<= time*1000; i++) {
    if (stopRequest == 0) {
      delay(1);
    }
  }

  GIMSK &= ~(1<<PCIE1); // disable Pin-Change-Interrupt
  GIMSK &= ~(1<<PCIE0);
}

//set Attiny to Powerdown-Mode until Pin-Change-Interrupt
void powerDown() {
  GIMSK |= (1<<PCIE1); //enable Pin-Change-Interrupt
  GIMSK |= (1<<PCIE0);
  sleep_mode();  //go to sleep
  //software will continue here after leaving sleep mode
  GIMSK &= ~(1<<PCIE1); //disable Pin-Change-Interrupt
  GIMSK &= ~(1<<PCIE0);
}

void checkButton() {
  if (digitalRead(buttonDown) == LOW) {
    buttonPressed = buttonDown;
  }

  else if (digitalRead(buttonStopp) == LOW) {
    stopRequest = 1;
    mySwitch.switchOff("11011", "10000");
  }

  else if (digitalRead(buttonUp) == LOW) {
    buttonPressed = buttonUp;
  }
}

//ISR for PCINT1 and PCINT0 (Pin-Change-Interrupts)
ISR(PCINT1_vect)
{
  checkButton();
} 
ISR(PCINT0_vect)
{
  checkButton();
} 


The remote control is powered by a CR2032 button cell, so the amount of available energy is limited. Since the control isn't doing anything 99.999% of the time, the Attiny enters sleep mode using the powerdown() function. It sleeps until a button is triggered (Pin-Change-Interrupt). To save as much energy as possible, ADC and AC are switched off.

No comments:

Post a Comment