2014/10/29

Arduino Sketch for Address Settable RF Wireless Power Supply Socket/Switch

Updated Sketch (Nov. 15,2014)

// Released by abocanegra on Dec. 11, 2009 using 4 pins, "DIP Switch 8 Position to Address Sensor" in Arduino Forum
// This sketch uses VirtualWire
// Connect the Receiver data pin to Arduino pin 11
// Modified by Befun Hung on Nov. 14, 2014 by combining sketches on May. 11, 2014 (Arduino RF Wireless Message Display)
// and Jul. 30, 2014 (Use DIP Switch To Set Arduino Device Net ID And Node ID for Wireless Communication - Updated Sketch) 
// and removing LCD Keypad Shield display function as a new sketch for Arduino addressable RF wireless power supply socket 
// Modified by Befun Hung on Nov. 12, 2014 to use
// 4 digital pins(D2-D5) to set node ID1 and
// 4 digital pins(D6-D9) to set node ID2 by using 10K pull-up resistors.
// Totally 8x16x16=2,048 devices can be used for wireless communication
// For practical use 8x10x10=800 devices can be controlled using digital key of 3x4 telephone keypad
// Wire and DIP switch connections from high bit to low bit are A1, A2, A3, D2, D3, D4, D5, D6, D7, D8 and D9  
// A0 is reserved for analog sensor or digital sensor/actuator 
// A4-A5 are reserved for I2C
// D0-D1 are reserved for RX/TX
// D13 is used for singal output
// Don't run this sketch on Arduino Pro Mini, it may reboot repeatedly owing to bootloader not supporting watchdog 

#include <VirtualWire.h>
// include avr/wdt for watchdog reset
#include <avr/wdt.h>
// include <EEPROM.h> to save switch staus to EEPROM
#include <EEPROM.h>
// keys to turn switch on and off
#define keyOn '*'
#define keyOff '#'

//Create and Define Global Variables
int bits=4, netID, nodeID1, nodeID2;
int dipNet[] = {15, 16, 17}; // DIP Switch Pins for Net ID
int dipNode1[] = {2, 3, 4, 5}; // DIP Switch Pins for Node ID1
int dipNode2[] = {6, 7, 8, 9}; // DIP Switch Pins for Node ID2

byte message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages
byte messageLength = VW_MAX_MESSAGE_LEN; // the size of the message
unsigned long counter = 1;

// digital pin 13 connected with a 1K resistor and a LED
int led = 13;

// Address of EEPROM for saving switch status and variable to store value
int address = 5;
int value;

void setup()
{
  Serial.begin(9600);
  int i;
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  netID = netAddress();
  // delay(100);
  Serial.print("Net ID: ");
  Serial.println(netID);
  
  for(i = 0; i<bits; i++){
    pinMode(dipNode1[i], INPUT);      // sets the digital pin 2-5 as input
  }
  nodeID1 = node1Address(bits);
  // delay(100);
  Serial.print("Node ID1: ");
  Serial.println(nodeID1);
  
  for(i = 0; i<bits; i++){
    pinMode(dipNode2[i], INPUT);      // sets the digital pin 2-5 as input
  }
  nodeID2 = node2Address(bits);
  // delay(100);
  Serial.print("Node ID2: ");
  Serial.println(nodeID2);
  Serial.println("Device is ready");
  // Initialize the IO and ISR
  vw_setup(2000); // Bits per sec
  vw_rx_start(); // Start the receiver
  
  //initialize the digital 13 pin as output
  pinMode(led, OUTPUT);
  // When the receiver is unstable and reboot, reading stored status from EEPROM 
  value = EEPROM.read(address);
  if (value == '1')
    {
      digitalWrite(led, HIGH);
    }
  if (value == '0')
    {
      digitalWrite(led, LOW);
    }
}

void loop()
{
   if (vw_get_message(message, &messageLength)) // Non-blocking
  {
    Serial.print(counter);
    Serial.print(": ");
    for (int i = 0; i < messageLength; i++)
    {
      Serial.write(message[i]);
    }
    // if length of received message is less than transmitter sent meaning the receiver is unstable 
    if (messageLength < 4)
      {
        software_Reboot();
      }
    else 
      {
        // netID and nodeID are numbers and message is charactor array, so convention is required
        if ((message[0] == (netID + '0')) && (message[1] == (nodeID1 + '0')) && (message[2] == (nodeID2 + '0')))
          {
            if (message[3] == keyOn) 
              {
              digitalWrite(led, HIGH);
              EEPROM.write(address, '1');
              }
            else 
              {
                if (message[3] == keyOff)
                  {
                    digitalWrite(led, LOW);
                    EEPROM.write(address, '0');
                  }
              }
          }
      }
    Serial.println();
    counter++;
  }
}

// Software reboot function
void software_Reboot()
{
  wdt_enable(WDTO_15MS);
  while (1)
  {
  }
}

//Create Net Address from DIP Switch (3 positions used A1-A3)
byte netAddress(){
  int i,j=0;
  
  //Get the switches state
  j = (j << 1) | (! digitalRead(A1));   // read the input pin
  j = (j << 1) | (! digitalRead(A2));   // read the input pin
  j = (j << 1) | (! digitalRead(A3));   // read the input pin
  return j; //return address
}

//Create Node1 Address from DIP Switch (4 positions used D2-D5)
byte node1Address(int k){
  int i,j=0;
  
  //Get the switches state
  for(i=0; i<k; i++){
  j = (j << 1) | (! digitalRead(dipNode1[i]));   // read the input pin
  }
  return j; //return address
}

//Create Node1 Address from DIP Switch (4 positions used D6-D9)
byte node2Address(int k){
  int i,j=0;
  
  //Get the switches state
  for(i=0; i<k; i++){
  j = (j << 1) | (! digitalRead(dipNode2[i]));   // read the input pin
  }
  return j; //return address
}

Sketch

// Released by abocanegra on Dec. 11, 2009 using 4 pins, "DIP Switch 8 Position to Address Sensor" in Arduino Forum
// This sketch uses VirtualWire
// Connect the Receiver data pin to Arduino pin 11
// Modified by Befun Hung on Oct. 29, 2014 by combining sketches on May. 11, 2014 (Arduino RF Wireless Message Display)
// and Jul. 30, 2014 (Use DIP Switch To Set Arduino Device Net ID And Node ID for Wireless Communication) 
// and removing LCD Keypad Shield display function as a new sketch for Arduino addressable RF wireless power socket 
// The sketch uses 3 analog pins(A1-A3) to set net ID and 8 digital pins(D2-D9) to set node ID by using 10K pull-up resistors.
// Totally 8x256=2,048 devices can be used for wireless communication
// When using a 3x4 telephone keypad, 8x10(0-9)=80 devices can be used
// A0 is reserved for analog sensor or digital sensor/actuator 
// A4-A5 are reserved for I2C
// D0-D1 are reserved for RX/TX
// D13 is used for singal output

#include <VirtualWire.h>
// include avr/wdt for watchdog reset
#include <avr/wdt.h>
// include <EEPROM.h> to save switch staus to EEPROM
#include <EEPROM.h>
// keys to turn switch on and off
#define keyOn '1'
#define keyOff '0'

//Create and Define Global Variables
int bits=8;
byte netID, nodeID;
int dipNet[] = {15, 16, 17}; //DIP Switch Pins for Net ID
int dipNode[] = {2, 3, 4, 5, 6, 7, 8, 9}; //DIP Switch Pins for Node ID

byte message[VW_MAX_MESSAGE_LEN]; // a buffer to store the incoming messages
byte messageLength = VW_MAX_MESSAGE_LEN; // the size of the message
unsigned long counter = 1;

// digital pin 13 connected with a 1K resistor and a LED
int led = 13;

// Address of EEPROM for saving switch status and variable to store value
int address = 5;
int value;

void setup()
{
  Serial.begin(9600);
  int i;
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  netID = netAddress();
  Serial.print("Net ID: ");
  Serial.println(netID);
  for(i = 0; i<bits; i++){
    pinMode(dipNode[i], INPUT);      // sets the digital pin 2-9 as input
  }
  nodeID = nodeAddress(bits);
  Serial.print("Node ID: ");
  Serial.println(nodeID);
  Serial.println("Device is ready");
  // Initialize the IO and ISR
  vw_setup(2000); // Bits per sec
  vw_rx_start(); // Start the receiver
  
  //initialize the digital 13 pin as output
  pinMode(led, OUTPUT);
  // When the receiver is unstable and reboot, reading stored status from EEPROM 
  value = EEPROM.read(address);
  if (value == '1')
    {
      digitalWrite(led, HIGH);
    }
  if (value == '0')
    {
      digitalWrite(led, LOW);
    }
}
void loop()
{
  if (vw_get_message(message, &messageLength)) // Non-blocking
  {
    Serial.print(counter);
    Serial.print(": ");
    for (int i = 0; i < messageLength; i++)
    {
      Serial.write(message[i]);
    }
    // if length of received message is less than transmitter sent meaning the receiver is unstable 
    if (messageLength < 3)
      {
        software_Reboot();
      }
    else 
      {
        // netID and nodeID are numbers and message is charactor array, so convention is required
        if ((message[0] == (netID + '0')) && (message[1] == (nodeID + '0')))
          {
            if (message[2] == keyOn) 
              {
              digitalWrite(led, HIGH);
              EEPROM.write(address, '1');
              }
            else 
              {
                if (message[2] == keyOff)
                  {
                    digitalWrite(led, LOW);
                    EEPROM.write(address, '0');
                  }
              }
          }
      }
    Serial.println();
    counter++;
  }
}

// Software reboot function
void software_Reboot()
{
  wdt_enable(WDTO_15MS);
  while (1)
  {
  }
}

//Create Net Address from DIP Switch (3 positions used)
byte netAddress(){
  int i,j=0;
  
  //Get the switches state
  j = (j << 1) | (! digitalRead(A1));   // read the input pin
  j = (j << 1) | (! digitalRead(A2));   // read the input pin
  j = (j << 1) | (! digitalRead(A3));   // read the input pin
  return j; //return address
}

//Create Node Address from DIP Switch (8 positions used D2 - D9)
byte nodeAddress(int k){
  int i,j=0;
  
  //Get the switches state
  for(i=0; i<k; i++){
  j = (j << 1) | (! digitalRead(dipNode[i]));   // read the input pin
  }
  return j; //return address
}