WireLess Gate Shield V1.0

Introduction

WireLess Gate Shield is an Arduino-compatible expansion card designed to build a system of receiving / transmitting and broadcasting various wireless commands and data. For maximum coverage possible wireless communication interfaces on the board has an IR receiver interface for connecting popular transceiver nRF24L01 + and RFM69HW. Additionally, the board has a real time clock module DS1307.

Features


  • Interface to connect the transceiver 315/433/868/915 MHz (depending on the version) RFM69HW

  • Interface to connect the transceiver at 2.4 GHz nRF24L01 +

  • IR receiver

  • Real-time clock module based on DS1307 with battery backup
  • LED automatic activity radio modules
  • LED for user
  • Clock button to operate
  • GROVE-compatible connector: I2C
  • Fully compatible with Ethernet Shield

Layout and schematics


On the left side WireLess Gate Shield are interfaces to wireless modules:

  • nRF24l01 +, including the enhanced (“PA”) version (above)
  • RFM69HW (bottom).

Between wireless modules is U.FL connector for external antenna for RFM69HW. If you plan to use the regular antenna (bit of wire required length) - it is possible to solder directly to the board Schild (near the connector U.FL)

To the right and slightly above the module is RFM69HW LED LED1 “RF433”

In the central part of the board is a slot for a backup battery for clock module DS1307

To the right and slightly below the slot for the battery - I2C-connector.

On the right side is (top-down):

  • LED LED2 “RF24”
  • IR receiver
  • LED LED3 - user
  • Clock button S1

Basic functionality


In the basic version (without the use of Ethernet Shield) may organize a wireless gateway between the radios and the IR receiver.

Command (or data) can be broadcast between all three wireless interfaces according to the logic of that program the user.

Availability of real-time clock module will automate the sending of any data or commands with reference to the date / time.

Device Management can be organized using a button located on the Shield.

Expansion Capabilities


Additionally WireLess Gate Shield can connect any i2c device using Grove-compatible connections (sensors, displays, etc.).

WireLess Gate Shield was designed to be fully compatible with Ethernet Shield - so you can use these two together Schild to create even more advanced wireless control device (logging on SD-card and presenting data on a web page, manage wireless devices via the web).

Interfaces


  • Interface for RF-module nRF24L01 +:

    • D11 - MOSI

      • D12 - MISO

        • D13 - SCK
      • D7 - RF24_CE

      • D8 - RF24_CSN

      • D2 - RF24_IRQ

  • Interface for RF-module RFM69HW:

    • D11 - MOSI

      • D12 - MISO

        • D13 - SCK
      • D9 - RF433_NSS

      • A0 - RF433_RESET

      • D3 - RF433_IRQ

  • A4 (SDA), A5 (SCL) - displayed on the connector “I2C” (the other two pins in the connector - VCC and GND for sensor supply)

  • A4 (SDA), A5 (SCL) - are involved in parallel for RTC DS1307
  • A1 - Button
  • D6 - Custom LED (LED3)

Features WireLess Gate Shield


Wireless Modules

Both wireless module RFM69HW and nRF24l01 + connected hardware bus SPI.

Selection of a particular wireless module is a low potential for the establishment of the appropriate chip select pin:

  • CSN (D8) for the module nRF24l01 +
  • NSS (D9) for the module RFM69HW

_ ‘Warning’, ‘If you have installed, but the software is not involved RFM69HW, be sure to install NSS pin of this module in state HIGH (otherwise it will interfere with the normal operation nRF24l01 + and Ethernet Shield. _

Automatic display of the wireless modules

LED indication of the wireless module is implemented as follows:

  • LED cathode LED1 “RF24” connected to pin CSN (D8) module nRF24l01 +, the anode of the LED (through a current limiting resistor) - to pin SCK bus SPI (D13)
  • LED cathode LED2 “RF433” connected to pin NSS (D9) module RFM69HW, the anode of the LED (through a current limiting resistor) - to pin SCK bus SPI (D13)

When radios are not active - at the appropriate pines chip select (CSN and NSS) there is a high potential, with the appearance of the clock at pin SCK does not lead to the ignition of the LEDs. If the same MK “communicates” with any wireless module to select it at the appropriate Pina (CSN and NSS) is set low potential and at the same timing pulses at pin SCK “ignite” the corresponding LED.

Thus, the user is not required to arrange for any additional programming work on the MC to indicate operation of the module.

Features

If necessary, SMD-LED to replace the usual outs (eg to embed the finished device in a cute case with display):

  • The board is close to the equipment corresponding LED is seating where you can solder terminals LEDs (or the appropriate cable).
  • Current-limiting resistor is on the board (for the output of the LED series resistor is not required)
  • SMD-LED when setting the output of the LED must be removed from the board

Modification to control via IR

Custom LED can be replaced by LED3 pin IR LED and thereby further expand the use of WireLess Gate Shield (for example, a command sent via any wireless interface or LAN - control devices using infrared commands).

Libraries

Required Library

To use the WireLess Gate Shield requires the following libraries:

  • Work with the transceiver nRF24L01 + - RF24

  • Work with the transceiver RFM69HW - RFM69

  • Real-time clock (RTC) - RTClib

  • IR-receiver - IRremote

Additionally required libraries that are used when working RF24 and LCD-display:

  • SPI

Libraries are examples of them just to understand how they work.

Features use libraries

NRF24l01 +

Module Initialization nRF24l01 + as follows:

//RF24 radio(CE,CSN);
RF24 radio(7,8);

RFM69HW

To work with a wireless module RFM69HW need to make minor corrections to the file RFM69.h follows:

At the beginning of the file to find the line:

#define SPI_CS               SS // SS is the SPI slave select pin, for instance D10 on atmega328
#define RF69_IRQ_PIN          2 // INT0 on AVRs should be connected to DIO0 (ex on Atmega328 it's D2)

And replace them with:

//#define SPI_CS               SS // SS is the SPI slave select pin, for instance D10 on atmega328
//#define RF69_IRQ_PIN          2 // INT0 on AVRs should be connected to DIO0 (ex on Atmega328 it's D2)
#define SPI_CS               9 // SS is the SPI slave select pin, for WireLess Gate Shield - D9
#define RF69_IRQ_PIN          3 // INT1 on AVRs should be connected to DIO0 (ex on Atmega328 it's D3)

Additionally, the file RFM69.cpp need to find the line:

void RFM69::isr0() { selfPointer->interruptHandler(); }

And replace them with:

//void RFM69::isr0() { selfPointer->interruptHandler(); }
void RFM69::isr1() { selfPointer->interruptHandler(); }

Module Initialization RFM69HW as follows:

  resetRFM69();
  radio.setCS(9); // NSS - D9
  radio.initialize(FREQUENCY,NODEID,NETWORKID);

_ ‘Note:’ _ Working with RFM69HW determined by the state of its registers. For more tinctures for specific endpoints required by the rules in the file RFM69.cpp function RFM69 :: initialize To better understand the purpose registers read the file RFM69registers.h (also included in the library), and documentation radio RFM69HW

Demonstration

Code for the main unit with WireLess Gate Shield (works with RTC, IR, RFM69HW, nRF24l01 +)

  • Sends a structure to another RFM69HW and receives a response (ping-pong).
  • Listen nRF24l01 + comes and if appropriate package - outputs it to monitor
  • Accepts commands via IR receiver (the recognized commands are displayed in the monitor) and lights custom LED

All results are displayed in the Serial Monitor

#include <RFM69.h>
#include <SPI.h>
#include "RF24.h"
#include <IRremote.h>
#include <Wire.h>
#include "RTClib.h"

RF24 radio24(7,8);

RTC_DS1307 RTC;

int RECV_PIN = 5;

IRrecv irrecv(RECV_PIN);

decode_results results;

// create a framework for the transmission of values
typedef struct{
    int SensorID;        // ID sensor
    int CommandTo;       // command module number ...
    int Command;         // command
    // 0 - answer
    // 1 - get the value
    // 2 - set the value
    int ParamID;         // parameter identifier
    float ParamValue;    // value
    boolean Status;      // status
    // 0 - read-only (RO)
    // 1 -  can change the (RW)
    char Comment[16];    // comment
}
Message;

Message sensor;

const uint64_t pipes[2] = {
0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

volatile boolean waitRF24 = false;

#define NODEID      99
#define NETWORKID   100
#define GATEWAYID   1
#define FREQUENCY   RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY         "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define LED         6
#define SERIAL_BAUD 115200
#define ACK_TIME    30  // # of ms to wait for an ack

#define RFM69_RESET 14  //A0
#define RFM69_NSS 9
#define RFM69_DIO0 3

#define BUTTON 15 // A1

#define MOSI 11
#define MISO 12
#define SCK 13

int TRANSMITPERIOD = 500; //transmit a packet to gateway so often (in ms)
byte sendSize=0;
boolean requestACK = false;
RFM69 radio;

int delta=2000;

unsigned long blinkStop;
unsigned long timeReady;

typedef struct {
    int           nodeId; //store this nodeId
    unsigned long uptime; //uptime in ms
    float         temp;   //temperature maybe?
}
Payload;
Payload theData;

void setup() {
    Serial.begin(SERIAL_BAUD);

    pinMode(LED, OUTPUT);

    pinMode(RFM69_NSS, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(8, OUTPUT);
    pinMode(MOSI, OUTPUT);
    pinMode(MISO, INPUT);
    pinMode(SCK, OUTPUT);

    pinMode(RFM69_RESET, OUTPUT);
    pinMode(RFM69_DIO0, INPUT);

    pinMode(BUTTON, INPUT);

    digitalWrite(RFM69_NSS, HIGH);
    digitalWrite(7, HIGH);

    resetRFM69();
    radio.setCS(RFM69_NSS);
    radio.initialize(FREQUENCY,NODEID,NETWORKID);

    //radio.setHighPower(); //uncomment only for RFM69HW!

    radio.encrypt(KEY);
    char buff[50];
    sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
    Serial.println(buff);

    radio24.begin();
    // optionally, increase the delay between retries & # of retries
    radio24.setRetries(15,15);
    radio24.setChannel(119);
    // по умолчанию СЛУШАЕМ
    radio24.openWritingPipe(pipes[1]);
    radio24.openReadingPipe(1,pipes[0]);
    radio24.startListening();

    delay(20);

    attachInterrupt(0, isr_RF24, FALLING);

    irrecv.enableIRIn();

    Wire.begin();
    RTC.begin();

    if (! RTC.isrunning()) {
        Serial.println("RTC is NOT running!");
        // following line sets the RTC to the date & time this sketch was compiled
        RTC.adjust(DateTime(__DATE__, __TIME__));
    }
}

long lastPeriod = -1;
void loop() {

    //check for any received packets
    if (radio.receiveDone())
    {
        Serial.print('[');
        Serial.print(radio.SENDERID, DEC);
        Serial.print("] ");
        for (byte i = 0; i < radio.DATALEN; i++)
        Serial.print((char)radio.DATA[i]);
        Serial.print("   [RX_RSSI:");
        Serial.print(radio.readRSSI());
        Serial.print("]");

        if (radio.ACK_REQUESTED)
        {
            radio.sendACK();
            Serial.print(" - ACK sent");
            delay(10);
        }
        Serial.println();
    }

    int currPeriod = millis()/TRANSMITPERIOD;
    if (currPeriod != lastPeriod)
    {
        //fill in the struct with new values
        theData.nodeId = NODEID;
        theData.uptime = millis();
        theData.temp = radio.readTemperature();//91.23; //it's hot!

        Serial.print("Sending struct (");
        Serial.print(sizeof(theData));
        Serial.print(" bytes) ... ");
        if (radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)))
        Serial.print(" ok!");
        else Serial.print(" nothing...");
        Serial.println();
        lastPeriod=currPeriod;
    }

    listenRF24();

    if (irrecv.decode(&results)) {
        Serial.println(results.value, HEX);
        irrecv.resume(); // Receive the next value
        blinkStop=millis()+100;
        digitalWrite(LED, HIGH);
    }

    if (digitalRead(BUTTON)==LOW) {
        blinkStop=millis()+1000;
        digitalWrite(LED, HIGH);
    }

    if (millis()>blinkStop) {
        digitalWrite(LED, LOW);
    }

    if(millis()>timeReady){
        timeReady=millis()+2000;
        DateTime now = RTC.now();

        Serial.print(now.year(), DEC);
        Serial.print('/');
        Serial.print(now.month(), DEC);
        Serial.print('/');
        Serial.print(now.day(), DEC);
        Serial.print(' ');
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.print(':');
        Serial.print(now.second(), DEC);
        Serial.println();
    }
}

void Blink(byte PIN, int DELAY_MS)
{
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
}

void resetRFM69(){
    digitalWrite(RFM69_RESET, HIGH);
    delay(1);
    digitalWrite(RFM69_RESET, LOW);
    delay(10);
}

void isr_RF24(){
    waitRF24 = true;
}

void listenRF24() {
    if (waitRF24) {
        waitRF24 = false;
        if ( radio24.available() )
        {
            bool done = false;
            while (!done)
            {
                done = radio24.read( &sensor, sizeof(sensor) );
                if(sensor.Command == 0) {
                    Serial.print(sensor.SensorID);
                    Serial.print("  ");
                    Serial.print(sensor.ParamID);
                    Serial.print("  ");
                    Serial.print(sensor.ParamValue);
                    Serial.print(" ");
                    Serial.println(sensor.Comment);
                }
            }
        }
    }
}

Code for “receiver” (for the test used Arduino Nano and RFM69HW module on the breadboard)

  • Takes using RFM69HW structure
  • Accountable for admission
  • Prints additional information regarding the module RFM69HW (registers, etc.)
#include <RFM69.h>
#include <SPI.h>

#define NODEID      1
#define NETWORKID   100
#define FREQUENCY   RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY         "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define LED         6
#define SERIAL_BAUD 115200
#define ACK_TIME    30  // # of ms to wait for an ack

#define RFM69_RESET 14

RFM69 radio;
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

typedef struct {
    int           nodeId; //store this nodeId
    unsigned long uptime; //uptime in ms
    float         temp;   //temperature maybe?
} Payload;
Payload theData;

void setup() {
    Serial.begin(SERIAL_BAUD);
    pinMode(RFM69_RESET, OUTPUT);
    pinMode(3, INPUT);
    resetRFM69();
    radio.setCS(9);
    //delay(10);
    radio.initialize(FREQUENCY,NODEID,NETWORKID);

    //radio.setHighPower(); //uncomment only for RFM69HW!

    radio.encrypt(KEY);
    radio.promiscuous(promiscuousMode);
    char buff[50];
    sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
    Serial.println(buff);
}

byte ackCount=0;
void loop() {
    //process any serial input
    if (Serial.available() > 0)
    {
        char input = Serial.read();
        if (input == 'r') //d=dump all register values
        radio.readAllRegs();
        if (input == 'E') //E=enable encryption
        radio.encrypt(KEY);
        if (input == 'e') //e=disable encryption
        radio.encrypt(null);
        if (input == 'p')
        {
            promiscuousMode = !promiscuousMode;
            radio.promiscuous(promiscuousMode);
            Serial.print("Promiscuous mode ");Serial.println(promiscuousMode ? "on" : "off");
        }

        if (input == 'd') //d=dump flash area
        {
            Serial.println("Flash content:");
            int counter = 0;

            while(counter<=256){
                //Serial.print(flash.readByte(counter++), HEX);
                Serial.print('.');
            }
            //while(flash.busy());
            Serial.println();
        }
        if (input == 'D')
        {
            Serial.print("Deleting Flash chip content... ");
            //flash.chipErase();
            //while(flash.busy());
            Serial.println("DONE");
        }
        if (input == 'i')
        {
            Serial.print("DeviceID: ");
            //word jedecid = flash.readDeviceId();
            //Serial.println(jedecid, HEX);
        }
    }

    if (radio.receiveDone())
    {
        Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
        Serial.print(" [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("]");
        if (promiscuousMode)
        {
            Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] ");
        }

        if (radio.DATALEN != sizeof(Payload))
        Serial.print("Invalid payload received, not matching Payload struct!");
        else
        {
            theData = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
            Serial.print(" nodeId=");
            Serial.print(theData.nodeId);
            Serial.print(" uptime=");
            Serial.print(theData.uptime);
            Serial.print(" temp=");
            Serial.print(theData.temp);
        }

        if (radio.ACK_REQUESTED)
        {
            byte theNodeID = radio.SENDERID;
            radio.sendACK();
            Serial.print(" - ACK sent.");

            // When a node requests an ACK, respond to the ACK
            // and also send a packet requesting an ACK (every 3rd one only)
            // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY
            if (ackCount++%3==0)
            {
                Serial.print(" Pinging node ");
                Serial.print(theNodeID);
                Serial.print(" - ACK...");
                delay(3); //need this when sending right after reception .. ?
                if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0))  // 0 = only 1 attempt, no retries
                Serial.print("ok!");
                else Serial.print("nothing");
            }
        }
        Serial.println();
        Blink(LED,3);
    }
}

void Blink(byte PIN, int DELAY_MS)
{
    pinMode(PIN, OUTPUT);
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
}

void resetRFM69(){
    digitalWrite(RFM69_RESET, HIGH);
    delay(1);
    digitalWrite(RFM69_RESET, LOW);
    delay(10);
}

Product versions

**Revision** **Description** **Release**
0.9 Prototype 05.05.2014
1.0 Public version 05.07.2014

Applications

  • Universal Wireless Gateway RF2.4 GHz (nRF24l01 +), RF433 MHz (RFM69HW), IR and LAN (using Ethernet Shield)
  • Logging system commands and data wireless devices with the time (using the Ethernet Shield)
  • Design and construction of administering various wireless commands at a certain time (for example, “turn on the light August 23, 2014 at 18:02” or “every day to include an automatic watering at 5:00”)

Questions and Answers

How to buy

This product can be purchased:

China (shipping worldwide)

Elecrow store

Seeed store

Russia

Devicter store

Help us make it better

Thank you for choosing Seeed. A couple of months ago we initiated a project to improve our documentation system. What you are looking at now is the first edition of the new documentation system. Comparing to the old one, here is the progresses that we made:

  • Replaced the old documentation system with a new one that was developed from Mkdocs, a more widely used and cooler tool to develop documentation system.
  • Integrated the documentation system with our official website, now you can go to Bazaar and other section like Forum and Community more conveniently.
  • Reviewed and rewrote documents for hundreds of products for the system’s first edition, and will continue migrate documents from old wiki to the new one.

An easy-to-use instruction is as important as the product itself. We are expecting this new system will improve your experience when using Seeed’s products. However since this is the first edition, there are still many things need to improve, if you have any suggestions or findings, you are most welcome to submit the amended version as our contributor or give us suggestions in the survey below, Please don’t forget to leave your email address so that we can reply.

Happy hacking