Arduino Roller Door

My Arduino Roller Door project has been something my colleague and I┬áhave been putting off for a while. Although riding to work is much more enjoyable and less stressful than driving, arriving outside the factory door and stopping our motorbikes to remove our keys, dismounting, and manually opening the roller door had gotten very irritating very quickly. We have both been interested in adding keyless entry to the office’s feature set for over a year now, and finally decided to do so with this quick and fun project early in 2016!

Our implementation was a graceless solution to the problem, but since the facility is used by other people, reliability and safety were of paramount importance; at the very least to avoid having to come back to the office after getting halfway home to fix a door that is stuck half way down. Jamie put the hardware together, mostly utilising knick-knacks and leftovers from around the office; only purchasing the break beam which we used to stop the door in case of obstruction, and the receiver with remote controls. He also put together a ‘sample’ unit, which I used to compose a simple sketch to run the implementation.

Simple representation of the hardware for development.
A simple representation of the hardware for development.

The break beam was an interesting unit, with actively powered components on either side of the passage. It featured 3 individual beams with some kind of diffuser covering each one, beam adjustability, and a concealing cover. The interface out of this was pretty simplistic; a relay that actuated once an obstruction was present and released once the obstruction was removed.

arduino-roller-door-5
Break Beam

The door’s existing componentry included a motor with electrical limit switches mechanically coupled to the gearbox, a simple latching relay circuit, and a control panel.
arduino-roller-door-4

The door had limit switches set to stop it half way open; this was presumably due to the lowered ceiling. The workshop area is over two stories tall, however, it has a ceiling at the standard height, supporting lighting and heating/cooling. It seemed logical to retain these limit switches as a final assurance measure to prevent overdriving in either direction. It would have been desirable to include limit switches in our implementation, and this is something I will likely add at a later date, either with aditional switches, or by incoorporating the existing switches without compromising their current function. The fritizing scetch below gives a breif idea of how everything hangs together – there isn’t much to it really.

arduino-roller-door-7

The software was splurged out sometime between 11pm and sleep, and didn’t take long at all. Using the test device my colleague put together simplified the process, and in an hour or so I had everything functional. I used Visual Micro, which is an exceptionally well featured add-in for Visual Studio, allowing for Arduino projects, and even deploying to the hardware. Interestingly the deployments are about 4 times quicker using Visual Micro than the Arduino IDE; I have been a relatively early adopter of Visual Micro, and this has always been the case.

My implementation to control the door is neither elegant, nor beautiful, but has worked reliably thus far (GitHub link and bottom of page). The code however is reasonably clean, and easy to follow. I have seperated input and output helpers to their own files, keeping the sketch slim and readable.

The input helpers simplify the process of evaluating the state of an input, without having to think about the logic (positive/negative logic) or invest much effort into tracking state for uperations, like ‘pressing’ and ‘releasing’. It also has some simple debouncing incorporated.

#include "inputFunctions.h"
#include <arduino.h>

void UpdateInput(Input * input, unsigned long * interval)
{
 input->previousState = input->currentState;

 // Check if a debounce is underway
 if (input->debounce <= 0)
 {
 // If not, update inputs
 input->currentState = digitalRead(input->pin) == input->activeState;

 // If state changed, so start a debounce
 if (input->previousState != input->currentState) input->debounce = DEBOUNCE_TIME;
 }
 else
 {
 // This accounts for irregularities in the time taken to loop through the main program
 int dTime = (int)(*interval);
 if (dTime > MAX_THRESHOLD || dTime < MIN_THRESHOLD) dTime = MIN_THRESHOLD;

 // Count the loop time towards the debounce
 input->debounce -= dTime;
 }
}

bool ButtonPressed(Input * input)
{
 return (!input->previousState) && input->currentState;
}

bool ButtonReleased(Input * input)
{
 return (!input->currentState) && input->previousState;
}

bool InputActive(Input * input)
{
 return input->currentState;
}

bool InputInactive(Input * input)
{
 return !(input->currentState);
}

void InitialiseInput(Input * input)
{
 pinMode(input->pin, INPUT);

 input->currentState = digitalRead(input->pin) && input->activeState;
 input->previousState = input->currentState;
}

The output helpers work towards the same simplification, by abstracting the active state from the application logic. Although this is generally wastefully of memory to a small degree, at this stage, there is plenty to spare.

#include "outputFunctions.h"
#include <arduino.h>

void UpdateOutput(Output * output)
{
 // Write the output buffer
 digitalWrite(output->pin, output->currentState == output->activeState);
}

void InitialiseOutput(Output * output)
{
 pinMode(output->pin, OUTPUT);
 UpdateOutput(output);
}

void SetOutput(Output * output, bool state)
{
 output->currentState = state;
}

These are underpinned by some simple types to track inputs and outputs:

#ifndef _ROLLERDOOR_TYPES_H_
#define _ROLLERDOOR_TYPES_H_

typedef struct {
 int pin;
 bool currentState;
 bool previousState;
 bool activeState;
 int debounce;
} Input;

typedef struct {
 int pin;
 bool currentState;
 bool activeState;
} Output;

#endif

This all contributes to simple uses throughout the main sketch, such as declaring an input, with some active state:

Input buttonUp = { 4<, false, false, LOW, 0 };

Initialising the input:

InitialiseInput(&buttonUp);

Updating the input (where the interval time is the time since the previous loop-pass):

UpdateInput(&buttonUp, &intervalTime);

And simple use:

if (ButtonPressed(&buttonUp) || ButtonPressed(&buttonStop))) doorState = DoorUp;

The code, although stable, has a few irritating aspects I would like to clear up, and will likely do so as time permits throughout the year. This includes:

  • Adding support for different types of doors.
  • Adding a web server, with simple endpoints to perform operations or query the door’s state.
  • Cleaning up the code and state management generally.
  • Adding simple configuration of options and accessories (such as enabling/disabling limit switches, break beams, and remote contol.
arduino-roller-door-8
Mocked up hardware, ready for its first day of use before formalising and tidying up the implementation.

You can download the source, or add to it on GitHub.