HOW DO I DIY MY OWN REMOTE CONTROL SWITCH IN MY DORMITORY

脑洞

2017-02-14

242

0

HOW DO I DIY MY OWN REMOTE CONTROL SWITCH IN MY DORMITORY

Jack Mo

BACKGROUND

It’s really a hard winter. The biting cold stopped me from sitting on the chair working on my project. I had to take a warm shower and go to bed quickly. It’s just 22:00. Sleeping that early would make me unsaturated. So I picked up a book and then jumped into bed happily. I was reading on my bed. Soon it’s 23:00, and my willingness to sleep was coming up. I needed to go off bed to turn off the light. At that moment how I wished the light in my dormitory could be controlled remotely! The second day, I got my hands on that.

THE SWITCH MECHANISM

As I couldn’t change the original electrical structure of my dormitory (the student dormitory management department wouldn’t permit this kind of behavior), I had to think of another way to control the switch. So I adopted a mechanical method, which could be demonstrated by figure 1.

Figure 1. The Switch Mechanism

The switch servo device has two “fingers”, one of which controls “on” state and the other controls “off” state. They are driven by a servo and can press the switch just like human do.

BUILDING THE ELECTRICAL BLOCKS

Actually I was building my electrical blocks not depending on what I needed, but what I had. I had rummaged through my electronic tool boxes and finally found an Arduino Nano board (figure 2), an HC-05 bluetooth module (figure 3), a makeblock IR transmitter (figure 4), a VS1838B IR receiver (figure 5), a MG995 digital servo (figure 6), and other helpful components such as wires and raw circuit boards. They met my needs perfectly.

Figure 2. Arduino Nano

Figure 3. HC-05 Bluetooth Module

Figure 4. Makeblock IR Transmitter

Figure 5. VS1838B IR Receiver

Figure 6. MG995 Digital Servo

With these components above I drew an electrical diagram of the whole system (figure 7). It looked fully functional, as my wish.

Figure 7. The Electrical Blocks Diagram

CIRCUIT DESIGN

The circuit only contains the signal part (figure 8). The power supplies and other unnecessary pins were left out.

Figure 8. The Electric Circuit

SOFTWARE DESIGN

The main workflow of the system was drew out as figure 9. There IR stands for infrared, BT stands for Bluetooth and SP stands for serial port.

Figure 9. Software Flowchart

ARDUINO PROGRAM

#include <IRremote.h>
#include <SoftwareSerial.h>
#include <Servo.h>

const uint8_t SWITCH_CMD_ON = 0x68; // Key : 0
const uint8_t SWITCH_CMD_OFF = 0x30; // Key : 1

const uint32_t SERVO_ANGLE_SWITCH_OFS = 25;
const uint32_t SERVO_ANGLE_SWITCH_RST = 97;
const uint32_t SERVO_ANGLE_SWITCH_ON = SERVO_ANGLE_SWITCH_RST - SERVO_ANGLE_SWITCH_OFS;
const uint32_t SERVO_ANGLE_SWITCH_OFF = SERVO_ANGLE_SWITCH_RST + SERVO_ANGLE_SWITCH_OFS;

#define SWITCH_DELAY() delay(500)

#define LED_PIN LED_BUILTIN
#define IR_RX_PIN 3
#define BT_RX_PIN 10
#define BT_TX_PIN 11
#define SERVO_PIN 9

#define MIN(A,B) (A<B?A:B)
#define MAX(A,B) (A>B?A:B)

const int SERVO_ANGLE_MIN = MIN(SERVO_ANGLE_SWITCH_ON,SERVO_ANGLE_SWITCH_OFF);
const int SERVO_ANGLE_MAX = MAX(SERVO_ANGLE_SWITCH_ON,SERVO_ANGLE_SWITCH_OFF);;

typedef enum {
  SWITCH_STATE_ON,
  SWITCH_STATE_OFF,
}SwitchState_e;

IRrecv ir(IR_RX_PIN, LED_PIN);
SoftwareSerial bt(BT_RX_PIN, BT_TX_PIN); // RX, TX
Servo servo;

#define SERVO_ATTACH() servo.attach(SERVO_PIN,SERVO_ANGLE_MIN,SERVO_ANGLE_MAX)
#define SERVO_DETACH() servo.detach()
#define SERVO_ATTACHED() servo.attached()
#define SWITCH_ON() servo.write(SERVO_ANGLE_SWITCH_ON)
#define SWITCH_OFF() servo.write(SERVO_ANGLE_SWITCH_OFF)
#define SWITCH_RST() servo.write(SERVO_ANGLE_SWITCH_RST)
#define LED_ON() digitalWrite(LED_PIN, HIGH)
#define LED_OFF() digitalWrite(LED_PIN, LOW)
#define LED_TOG() digitalWrite(LED_PIN, !digitalRead(LED_PIN))

decode_results results;
uint8_t irKeyCode = 0;
uint8_t btKeyCode = 0;
uint8_t spKeyCode = 0;

#define MYPRINT(MSG) do { \
  Serial.print(MSG); \
  bt.print(MSG); \
} while(0)

#define MYPRINT_FMT(MSG,FMT) do { \
  Serial.print(MSG,FMT); \
  bt.print(MSG,FMT); \
} while(0)

#define MYPRINTLN(MSG) do { \
  Serial.println(MSG); \
  bt.println(MSG); \
} while(0)

#define MYPRINTLN_FMT(MSG,FMT) do { \
  Serial.println(MSG,FMT); \
  bt.println(MSG,FMT); \
} while(0)

void myprint(const char* msg)
{
  MYPRINT(msg);
}

void myprint(uint32_t val, int fmt = DEC)
{
  MYPRINT_FMT(val, fmt);
}

void myprintln(const char* msg)
{
   MYPRINTLN(msg);
}

void myprintln(uint32_t val, int fmt = DEC)
{
  MYPRINTLN_FMT(val, fmt);
}

void startup() {
  SERVO_ATTACH();
  SWITCH_RST();
  SWITCH_DELAY();
  SERVO_DETACH();
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
  bt.begin(9600);
  ir.enableIRIn(); // Start the IR receiver
}

void welcome() {
  myprintln("Welcome, Jack.");
  myprint("/*********************");
  myprint("SYSTEM INFOMATION");
  myprintln("*********************/");
  myprint("IR_RX_PIN: ");
  myprintln(IR_RX_PIN);
  myprint("BT_RX_PIN: ");
  myprintln(BT_RX_PIN);
  myprint("BT_TX_PIN: ");
  myprintln(BT_TX_PIN);
  myprint("SERVO_PIN: ");
  myprintln(SERVO_PIN);
  myprint("SWITCH_CMD_ON: ");
  myprintln(SWITCH_CMD_ON, HEX);
  myprint("SWITCH_CMD_OFF: ");
  myprintln(SWITCH_CMD_OFF, HEX);
  myprint("SERVO_ANGLE_SWITCH_ON: ");
  myprintln(SERVO_ANGLE_SWITCH_ON);
  myprint("SERVO_ANGLE_SWITCH_RST: ");
  myprintln(SERVO_ANGLE_SWITCH_RST);
  myprint("SERVO_ANGLE_SWITCH_OFF: ");
  myprintln(SERVO_ANGLE_SWITCH_OFF);
}

void setup()
{
  startup();
  welcome();
}

void showSwitchState(SwitchState_e switchState)
{
  if (switchState == SWITCH_STATE_ON) {
    myprintln("Switch state: on");
  } else if (switchState == SWITCH_STATE_OFF) {
    myprintln("Switch state: off");
  } 
}

void setSwitchState(SwitchState_e switchState)
{
  if (switchState == SWITCH_STATE_ON) {
    SERVO_ATTACH();
    SWITCH_ON();
    SWITCH_DELAY();
    SWITCH_RST();
    SWITCH_DELAY();
    switchState = SWITCH_STATE_ON;
    SERVO_DETACH();
  } else if (switchState == SWITCH_STATE_OFF) {
    SERVO_ATTACH();
    SWITCH_OFF();
    SWITCH_DELAY();
    SWITCH_RST();
    SWITCH_DELAY();
    switchState = SWITCH_STATE_OFF;
    SERVO_DETACH();
  }
  showSwitchState(switchState);
}

void switchStateCmd(uint8_t cmd)
{
  if (cmd == SWITCH_CMD_ON) {
    setSwitchState(SWITCH_STATE_ON);
  } else if (cmd == SWITCH_CMD_OFF) {
    setSwitchState(SWITCH_STATE_OFF);
  }
}

void blinkLed() {
  static uint32_t count = 0;
  if (++count == 10000) {
    count = 0;
    LED_TOG();
  }
}

void loop() {
  if (ir.decode(&results)) {
    if (results.bits == 32) {
      irKeyCode = (results.value >> 8) & 0xFF;
      if (irKeyCode + ((uint8_t)(results.value & 0xFF)) == 0xFF) {
        myprint("IR key code received: ");
        myprintln(irKeyCode, HEX);
        switchStateCmd(irKeyCode);
      }
    }
    ir.resume(); // Receive the next value
  }
  if (bt.available()) {
    btKeyCode = bt.read();
    myprint("BT key code received: ");
    myprintln(btKeyCode, HEX);
    switchStateCmd(btKeyCode);
    while (bt.available()) bt.read();
  }
  if (Serial.available()) {
    spKeyCode = Serial.read();
    myprint("SP key code received: ");
    myprintln(spKeyCode, HEX);
    switchStateCmd(spKeyCode);
    while (Serial.available()) Serial.read();
  }
  blinkLed();
}

The code was hosted at github.

PHOTOS

Figure 10. The Real Switch Mechanism

Figure 11. The Real Control Board

Figure 12. The Whole Device

TESTING VIDEO

Video 1. Switch IR Remote Control

Video 2. Switch BT Remote Control

发表评论

全部评论:0条

帮杰

疯狂于web和智能设备开发,专注人机互联。