Low Voltage Disconnect for 0 to 5 Volt Range

We build and sell a wide range of low voltage disconnects for use with 12V and (less frequently) 24V battery systems to protect batteries from being overly discharged and therefore damaged.

Low voltage disconnect with oled display for very low voltages

Pictured above is a device for a slightly different application, but which is based around our REUK Programmable Low Voltage Disconnect with OLED Display.

This Arduino powered device is designed to interrupt a signal line (using an on board relay) when an input voltage is measured to be below a user set value expected to be in the range 0 to 5V. Since the input voltage could be too low to power the microcontroller and display etc, the board is powered by an external 12V supply with a common ground connection to the voltage to be measured.

The user can set the low voltage threshold below which the signal line will be cut (by the relay being de-energised), and then a higher voltage threshold above which the signal line connection will be restored (by the relay being re-energised). Timers are built in to this device so that 10 seconds of consistent low or high voltage is required for a change of state of the relay to occur so any brief input voltage spikes and dips, or interference do not have an effect.

If you need any kind of low voltage disconnect or automatic voltage monitoring device, please email neil@reuk.co.uk with details of your specific requirements.

Full Arduino Code for Poultry Egg Incubator with Humidity Sensor

We are frequently asked for the source code used on the Arduino-based products which we design and build. Unfortunately we cannot do that for commercial reasons. However, more than 80 percent of the requests we receive are for the code used in our poultry egg incubation controllers, with almost 100 percent of those requests coming from the developing world.

Therefore, as a one-off, we are releasing the full Arduino source code for our most popular (and easiest to build with commonly available components) device of this type, our Poultry Egg Incubator with Humidity Sensor.

egg incubator with humidity sensor, fan, heater, and humidifier

egg incubator controller status summary display

This device makes use of an always on motor which turns the eggs six full turns every 24 hours. Many of our other incubators have motors which have to be set up to run for a certain length of time a certain number of times per day, but the code for these is either specific to a particular motor or far more complicated (but of course more flexible) if the end-user of the incubator is to set these timings.

This device makes use of a DS18b20 digital temperature sensor, a 1602 LCD display module, a DHT11 humidity sensor, and is based around an Arduino Pro Mini, together with some relays, resistors, buttons, terminals, and other components available everywhere – easily salvaged from old and broken electronics even.

In time we will add a circuit diagram together with a suggested parts list, but the design is very flexible in terms of the components which can be used to put it together (with exception of the sensors and display for which the code provided is specific…and which together with an Arduino Pro Mini clone can be purchased for well under US$10 total including delivery.

Click here for details on how to connect and use a DHT11 Humidity Sensor with Arduino, and here for information on using DS18B20 sensors and 1602 LCD modules with Arduino.

Here is the full Arduino sketch (source code) for the egg incubator.

// (C) 2017-2020 REUK.CO.UK - Free for non-commercial use.
// Egg incubation temperature and humidity controller with display.
// Connection to an always on motor - e.g. 6 rotations per day.
// Fan for cooling, heater for heating, humidifier to humidify.

// For the temperature sensor.
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3

// For the non-volatile storage.
#include <EEPROM.h> //EEPROM.write(addr, val); val = EEPROM.read(address);

// For the DHT11 humidity sensor.
#include <dht.h>
dht DHT;
#define DHT11_PIN 10

//for the LCD
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27 // This i2c address depends on the display.
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

// Setup a oneWire instance to communicate with the OneWire 
// device (Dallas temperature IC)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensor1(&oneWire);

// Set up the input and output pins used on the Arduino.
const int button1 = 2;
const int button2 = 8;
const int heater = 9;
const int fan = 4;
const int humidifier = 5;

// Define variables to store the humidity and 
// temperature readings froms sensors.
float sensorOneTemperature;
float humidity;

// Define variables for the upper and lower 
// thresholds (read in from EEPROM).
float heaterOnThreshold;
float heaterOffThreshold;
float fanOnThreshold;
float fanOffThreshold;
float humidifierOnThreshold;
float humidifierOffThreshold;

// Define the memory locations of the thresholds in EEPROM.
int heaterOnEEPROM = 100;
int heaterOffEEPROM = 120;
int fanOnEEPROM = 140;
int fanOffEEPROM = 160;
int humidifierOnEEPROM = 180;
int humidifierOffEEPROM = 200;

// Set some default values for the thresholds.
const float heaterOnDefault = 37.0;
const float heaterOffDefault = 39.0;
const float fanOnDefault = 40.0;
const float fanOffDefault = 37.0;
const float humidifierOnDefault = 45.0;
const float humidifierOffDefault = 70.0;

// Define variables to keep track of the status of 
// the system (0=off,1=on)
int heaterStatus;
int fanStatus;
int humidifierStatus;

void setup(void)
{
 // Start up the temperature sensor library.
 sensor1.begin();
 // Set the temperature measurement resolution to 
 // 12 bit ADC (0.0625°C resolution)
 sensor1.setResolution(12);

 // Read in the threshold values from EEPROM.
 heaterOnThreshold = EEPROM_readFloat(heaterOnEEPROM);
 heaterOffThreshold = EEPROM_readFloat(heaterOffEEPROM);
 fanOnThreshold = EEPROM_readFloat(fanOnEEPROM);
 fanOffThreshold = EEPROM_readFloat(fanOffEEPROM);
 humidifierOnThreshold = EEPROM_readFloat(humidifierOnEEPROM);
 humidifierOffThreshold = EEPROM_readFloat(humidifierOffEEPROM);

 // Make sure that we at least have read in values, or read in defaults.
 if(isnan(heaterOnThreshold)) heaterOnThreshold = heaterOnDefault;
 if(isnan(heaterOffThreshold)) heaterOffThreshold = heaterOffDefault;
 if(isnan(fanOnThreshold)) fanOnThreshold = fanOnDefault;
 if(isnan(fanOffThreshold)) fanOffThreshold = fanOffDefault;
 if(isnan(humidifierOnThreshold)) humidifierOnThreshold = humidifierOnDefault;
 if(isnan(humidifierOffThreshold)) humidifierOffThreshold = humidifierOffDefault;
 
 // Set up the inputs and outputs on the Arduino IO
 pinMode(button1, INPUT);
 digitalWrite(button1, HIGH); //turn on the pull up resistor
 pinMode(button2, INPUT);
 digitalWrite(button2, HIGH); //turn on the pull up resistor
 pinMode(heater, OUTPUT);
 digitalWrite(heater, LOW);
 pinMode(fan, OUTPUT);
 digitalWrite(fan, LOW);
 pinMode(humidifier, OUTPUT);
 digitalWrite(humidifier, LOW);
 
 // Need to keep track of the status of the heater, fan, and humidifier
 // so we know whether they are on or off.
 heaterStatus = 0; // Start with the heating element off (=0)
 fanStatus = 0; // Start with the fan off
 humidifierStatus = 0; // Start with humidifier turned off
 
 // Set up the LCD
 lcd.begin (16,2);
 // Switch on the backlight.
 lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
 lcd.setBacklight(HIGH);
 // Clear the display.
 lcd.clear();
 delay(200);
}

void loop(void)
{ 
 // Read in the temperature and humidity and display across 
 // the top line of the display.
 readInAndDisplayTemperature();
 readInAndDisplayHumidity();
 // Display the current system status on the bottom line of the display.
 displaySystemStatus();

 // If heater is currently off, and temperature is low, turn on the heater.
 if(heaterStatus == 0 and sensorOneTemperature < heaterOnThreshold){
 digitalWrite(heater, HIGH);
 heaterStatus = 1;
 }
 
 // If heater is currently on, and temperature is high, turn off the heater.
 if(heaterStatus == 1 and sensorOneTemperature > heaterOffThreshold){
 digitalWrite(heater, LOW);
 heaterStatus = 0;
 }

 // If fan is currently off, and temperature is high, turn on the fan.
 if(fanStatus == 0 and sensorOneTemperature > fanOnThreshold){
 digitalWrite(fan, HIGH);
 fanStatus = 1;
 }
 
 // If fan is currently on, and temperature is low, turn off the fan.
 if(fanStatus == 1 and sensorOneTemperature < fanOffThreshold){
 digitalWrite(fan, LOW);
 fanStatus = 0;
 }

 // If humidifier is currently off, and humidity is low, turn on the humidifier.
 if(humidifierStatus == 0 and humidity < humidifierOnThreshold){
 digitalWrite(humidifier, HIGH);
 humidifierStatus = 1;
 }
 
 // If humidifier is currently on, and humidity is high, turn off the humidifier.
 if(humidifierStatus == 1 and humidity > humidifierOffThreshold){
 digitalWrite(humidifier, LOW);
 humidifierStatus = 0;
 }

 // Press and hold button1 for half a second to briefly show 
 // the thresholds currently set.
 if(digitalRead(button1)==LOW){
 int i;
 for(i = 0; i < 5; i++){
 delay(100);
 if(digitalRead(button1) == HIGH) i = 20;
 }
 // If button was held for at least 1/2 second, display thresholds...
 if(i < 11){
 displayThresholds();
 }
 }
 
 // Press and hold button2 for half a second to enter programming mode.
 if(digitalRead(button2)==LOW){
 int i;
 for(i = 0; i < 5; i++){
 delay(100);
 if(digitalRead(button2) == HIGH) i = 20;
 }
 // If button was held for at least 1/2 second we go into programming mode.
 if(i < 11){
 programmingMode();
 }
 }
}

void programmingMode(){
 // We arrive in here with the button2 currently being pressed 
 // and entering programming mode.
 lcd.clear();
 lcd.setCursor(0,0);
 // Make sure that the user has released the programming button
 while (digitalRead(button1) == LOW) {
 delay(100);
 }
 lcd.print("PROGRAMMING MODE");

 // Wait for button2 to be released.
 do{
 delay(50);
 }while(digitalRead(button2) == LOW);

 // FIRST of all we are going to programme in the new value 
 // for heaterOnThreshold
 lcd.setCursor(0,0);
 lcd.print("set Heater ON T ");
 displayANumberDuringProgramming(heaterOnThreshold);
 for(int i = 0; i < 50; i++){
 delay(100);
 if(digitalRead(button1) == LOW){ // go down
 heaterOnThreshold = heaterOnThreshold - 0.2;
 displayANumberDuringProgramming(heaterOnThreshold);
 i = 0; 
 waitForButton1Release();
 }
 if(digitalRead(button2) == LOW){ // go up
 heaterOnThreshold = heaterOnThreshold + 0.2;
 displayANumberDuringProgramming(heaterOnThreshold);
 i = 0;
 waitForButton2Release();
 }
 }
 EEPROM_writeFloat(heaterOnEEPROM, heaterOnThreshold);

 // SECOND we set the new value for heaterOffThreshold.
 lcd.setCursor(0,0);
 lcd.print("set Heater OFF T ");
 displayANumberDuringProgramming(heaterOffThreshold);
 for(int i = 0; i < 50; i++){
 delay(100);
 if(digitalRead(button1) == LOW){ // go down
 heaterOffThreshold = heaterOffThreshold - 0.2;
 displayANumberDuringProgramming(heaterOffThreshold);
 i = 0; 
 waitForButton1Release();
 }
 if(digitalRead(button2) == LOW){ // go up
 heaterOffThreshold = heaterOffThreshold + 0.2;
 displayANumberDuringProgramming(heaterOffThreshold);
 i = 0;
 waitForButton2Release();
 }
 }
 EEPROM_writeFloat(heaterOffEEPROM, heaterOffThreshold);

 // THIRD we are going to programme in the new value 
 // for fanOnThreshold.
 lcd.setCursor(0,0);
 lcd.print("set fan ON T ");
 displayANumberDuringProgramming(fanOnThreshold);
 for(int i = 0; i < 50; i++){
 delay(100);
 if(digitalRead(button1) == LOW){ // go down
 fanOnThreshold = fanOnThreshold - 0.2;
 displayANumberDuringProgramming(fanOnThreshold);
 i = 0; 
 waitForButton1Release();
 }
 if(digitalRead(button2) == LOW){ // go up
 fanOnThreshold = fanOnThreshold + 0.2;
 displayANumberDuringProgramming(fanOnThreshold);
 i = 0;
 waitForButton2Release();
 }
 }
 EEPROM_writeFloat(fanOnEEPROM, fanOnThreshold);

 // FOURTH we are going to programme in the new value
 // for fanOnThreshold.
 lcd.setCursor(0,0);
 lcd.print("set fan OFF T ");
 displayANumberDuringProgramming(fanOffThreshold);
 for(int i = 0; i < 50; i++){
 delay(100);
 if(digitalRead(button1) == LOW){ // go down
 fanOffThreshold = fanOffThreshold - 0.2;
 displayANumberDuringProgramming(fanOffThreshold);
 i = 0; 
 waitForButton1Release();
 }
 if(digitalRead(button2) == LOW){ // go up
 fanOffThreshold = fanOffThreshold + 0.2;
 displayANumberDuringProgramming(fanOffThreshold);
 i = 0;
 waitForButton2Release();
 }
 }
 EEPROM_writeFloat(fanOffEEPROM, fanOffThreshold);

 // FIFTH we are going to programme in the new value
 // for humidifierOnThreshold
 lcd.setCursor(0,0);
 lcd.print("set Humidi ON % ");
 displayANumberDuringProgramming(humidifierOnThreshold);
 for(int i = 0; i < 50; i++){
 delay(100);
 if(digitalRead(button1) == LOW){ // go down
 humidifierOnThreshold = humidifierOnThreshold - 2;
 displayANumberDuringProgramming(humidifierOnThreshold);
 i = 0; 
 waitForButton1Release();
 }
 if(digitalRead(button2) == LOW){ // go up
 humidifierOnThreshold = humidifierOnThreshold + 2;
 displayANumberDuringProgramming(humidifierOnThreshold);
 i = 0;
 waitForButton2Release();
 }
 }
 EEPROM_writeFloat(humidifierOnEEPROM, humidifierOnThreshold);

 // SIXTH we are going to programme in the new value
 // for humidifierOffThreshold
 lcd.setCursor(0,0);
 lcd.print("set Humidi OFF % ");
 displayANumberDuringProgramming(humidifierOffThreshold);
 for(int i = 0; i < 50; i++){
 delay(100);
 if(digitalRead(button1) == LOW){ // go down
 humidifierOffThreshold = humidifierOffThreshold - 2;
 displayANumberDuringProgramming(humidifierOffThreshold);
 i = 0; 
 waitForButton1Release();
 }
 if(digitalRead(button2) == LOW){ // go up
 humidifierOffThreshold = humidifierOffThreshold + 2;
 displayANumberDuringProgramming(humidifierOffThreshold);
 i = 0;
 waitForButton2Release();
 }
 }
 EEPROM_writeFloat(humidifierOffEEPROM, humidifierOffThreshold);
}

void waitForButton1Release(){
 do{
 delay(50);
 }while(digitalRead(button1) == LOW);
}

void waitForButton2Release(){
 do{
 delay(50);
 }while(digitalRead(button2) == LOW);
}

void displayANumberDuringProgramming(float theNumber){
 lcd.setCursor(0,1);
 lcd.print(" ");
 lcd.print(theNumber,1);
 lcd.print(" ");
}

void readInAndDisplayTemperature(){
 readTemperatureSensor();
 displayTemperature(); 
}
void readTemperatureSensor(){
 sensor1.requestTemperatures();
 sensorOneTemperature = sensor1.getTempCByIndex(0); 
}
void displayTemperature(){
 // Need to deal with below zero temperatures and also 
 // with above 100 degree temperatures. Adjust number of
 // decimal places to result in similar number of overall 
 // digits used.
 int dp; //number of decimal places to show
 
 // Show the temperature on the screen
 lcd.setCursor(0,0);
 dp = 2; //by default
 if (sensorOneTemperature > 99.9) dp = 0; 
 if (sensorOneTemperature < 0) dp = 0;
 lcd.print("T=");
 lcd.print(sensorOneTemperature,dp);
 lcd.print((char)223);
 lcd.print("C");
 lcd.print(" ");
}

void readInAndDisplayHumidity(){
 readInHumidity();
 displayHumidity(); 
}

void readInHumidity(){
 // Read in the humidity from the sensor and set it 
 // to the global variable 'humidity'.
 int chk = DHT.read11(DHT11_PIN);
 humidity = DHT.humidity;
}

void displayHumidity(){
 // Note - always call this function immediately
 // after displaying the temperature.
 lcd.print("H=");
 lcd.print(humidity,0);
 lcd.print("% ");
}

void displaySystemStatus(){
 lcd.setCursor(0,1);
 // We need to display the status of the heater, fan,
 // and humidifier which can be ON or OFF. If status is
 // ON, fill in character in front of device name.
 if(heaterStatus == 1) 
 lcd.write(255);
 else lcd.print(" ");
 lcd.print("Heat ");
 if(fanStatus == 1)
 lcd.write(255);
 else lcd.print(" ");
 lcd.print("Fan ");
 if(humidifierStatus == 1)
 lcd.write(255);
 else lcd.print(" ");
 lcd.print("Hum ");
}

void displayThresholds(){
 // Arrive here with button1 currently depressed.
 // Show the six programmed thresholds on the screen
 // for three seconds each.

 // First of all show the heater thresholds.
 lcd.clear();
 lcd.print("Heater ");
 lcd.setCursor(0,1);
 lcd.print(heaterOnThreshold,1);
 lcd.print((char)223);
 lcd.print("C to ");
 lcd.print(heaterOffThreshold,1);
 lcd.print((char)223);
 lcd.print("C ");
 delay(3000);

 // Now show the fan thresholds.
 lcd.setCursor(0,0);
 lcd.print("Fan ");
 lcd.setCursor(0,1);
 lcd.print(fanOnThreshold,1);
 lcd.print((char)223);
 lcd.print("C to ");
 lcd.print(fanOffThreshold,1);
 lcd.print((char)223);
 lcd.print("C ");
 delay(3000);

 // Now show the humidifier thresholds.
 lcd.setCursor(0,0);
 lcd.print("Humidifier ");
 lcd.setCursor(0,1);
 lcd.print(humidifierOnThreshold,0);
 lcd.print("% to ");
 lcd.print(humidifierOffThreshold,0);
 lcd.print("% ");
 delay(3000);
}

//---------------------------------------------------------
// Utility functions to write float values to EEPROM and to 
// read them back in again.
void EEPROM_writeFloat(int ee, float value)
{
 byte* p = (byte*)(void*)&value;
 for (int i = 0; i < sizeof(value); i++)
 EEPROM.write(ee++, *p++);
}

float EEPROM_readFloat(int ee)
{
 float value = 0;
 byte* p = (byte*)(void*)&value;
 for (int i = 0; i < sizeof(value); i++)
 *p++ = EEPROM.read(ee++);
 return value;
}

Controller for Simple Rainwater Toilet Flush System

We continue to make a wide range of controllers for rainwater toilet flush systems. Pictured below is one of the simpler units for use in systems with just one float switch located near the top of a toilet cistern, with the supply coming from a water butt that has a pump with run dry protection or a well with a 100% consistent supply of water.Controller for rainwater pump to fill toilet cistern with one float switch

As the inside of a toilet cistern can have very turbulent water, this controller is built with automatic time delays. The float switch has to be detected to be down (after toilet flushing) continuously for two seconds before the pump will be turned on, and then the float switch has to be detected to be up continuously for two seconds before the pump will be turned off again (cistern refilled above the height of the float switch).

We also make controllers for systems with header tanks feeding multiple toilets, up to three float switches, with displays to show system status, and/or dataloggers to keep track of number of flushes and/or the volume of rainwater used etc. Some of these are detailed in our rainwater category.

If you require any kind of rainwater toilet flush pump controller, please email neil@reuk.co.uk with details of your planned system and requirements.

Timer to Protect Solenoids Used in One Man Band Drum Kit

We were recently commissioned to design a device to protect the solenoids used as components within a one-man band drum kit. Rather than wearing the drums on the back, this drum kit is made to sit alongside the one-man controlled by foot pedals leaving hands free to play the guitar or a keyboard.

Each foot pedal contains two micro-switches. Rocking the foot backwards and forwards, the heel and toe trigger those switches which activate solenoids which pull a cord which impacts the drumstick on a drum. A bass drum could be connected to the toe switch and a snare drum to the heel switch on one pedal, and a second pedal could control the high hats for example enabling complicated rhythms to be played.

This system all works well except that if the foot is left resting on the pedal so that one of the micro-switches remains closed, the solenoid will burn out. It is also difficult to depress a micro-switch for the correct length of time so that the drumstick hits the drum and bounces immediately off rather than being left pressed against the skin of the drum affecting the sound.

The timer we came up with detects when a drum pedal micro-switch is pressed. It then supplies an output to the solenoid for exactly 0.10 seconds (which has been proven experimentally to be the perfect length of time with this setup). The solenoid will not be activated again until after at least 0.40 seconds has passed and also the micro-switch has been seen to be released before being pressed again. Therefore, if the micro-switch is kept pressed down, the solenoid will not be activated (and not kept activated) and so it will not burn out.

Solenoid protection timer for single drum

Pictured above is the first prototype unit used for testing purposes with one drum pedal micro-switch and one solenoid only.

Pictured below is the control board for three foot pedal inputs and three solenoid outputs, so heel and toe in one foot pedal and heel or toe in a second foot pedal to control three drums.

Solenoid protection timer for three drums

If you need any type of timer controller device, email neil@reuk.co.uk with details of your requirements.

Automatic Scarecrow Motor Timer Controller

Pictured below is the controller board we made for an automatic motorised scarecrow used to scare pigeons and crows from an orchard.

Timer Controller board to automatically run a motorised scarecrowThis scarecrow has two arms. As a motor turns, the arms flap up and down which scares birds away. We designed this device so that the orchard owner can set a motor running time of 1,2,3,4,5…etc seconds, and then a waiting time of 5,10,15,20..etc minutes before the scarecrow operates again. User programmability is important to enable optimal settings to be found to make the scarecrow as effective as possible.

If a motorised scarecrow is left with its arms up or out to the side, they can catch the wind which can lead to the scarecrow being damaged during bad weather. Our controller protects against this. When the motor running time countdown has finished, the motor continues to run until a microswitch detects that the arms are in the down position. The motor then stops.

Crows are dawn and dusk feeders, whereas pigeons are day feeders. Therefore the scarecrow is only required to operate from the start of dawn until the end of dusk. To that end, this controller includes a light detector, and the operator can calibrate the ambient light level above which the scarecrow will operate.

If you need any kind of timer controller, email neil@reuk.co.uk with details of your requirements.

Target Shooting Timer Controller to Replace Jackcast

Original JackCast shooting timer controllerPictured above is an old Jackcast shooting target timer controller which needed replacing. This timer could be set to repeat sequences 1-8 times or forever, the target edge times to 1, 2, 3, 5, 7, 10, 15, or 30 seconds, and the target face times to 1, 2, 3,4, 5, 6, 8, 10, 15, 20, and 150 seconds. Buttons are provided to manually face or edge the target, and there are start and stop buttons to run and stop the timer.

Pictured below is the Arduino-based replacement controller board we built to replicate the features of the original unit.Display for target shooting timer controllerThis will be fitted into an enclosure with panel mounted buttons, and the display as shown below mounted to show system settings and the timer status.shooting-target-controller-display

Here are some photographs of the finished controller installed into its case and connected up by its owner ready for use.

shooting-target-controller-panel

shooting target controller fitted into enclosure

Wireless operation has been added in parallel to the hard wired output from the relay on our controller. The right hand board above provides this functionality.

shooting-target-controller-connections

If you require any kind of shooting target controller, email neil@reuk.co.uk with details of your specific requirements.

Converting Digital Watch into a Timer Stopwatch for Projects

Pictured below are the inner workings of a cheap digital watch which has been modified to enable remote operation of the buttons so it can be used for automatic stopwatch timing.

Modified digital watch used as stopwatch with remote buttons or relay control

This particular watch had a broken backlight and broken strap, but it had always kept very good time. Therefore it was a perfect candidate to be re-purposed.

The watch had rubber button tops integrated into the watch case. When the workings are removed from the case, the buttons themselves are exposed. They comprise a thin strip of metal separated from a metal pad on the watch PCB. When the rubber button top is pressed down, the metal strip makes contact with the metal pad making an electrical connection.

Inside look at a digital watch button

All of the metal strips are connected to the watch battery ground, so the watch detects button presses by waiting for 0V to appear on one of the metal pads (which are electrically connected to the microcontroller inside the watch).

We soldered wires to the three metal pads of the buttons we wanted to control, and a ground wire to one of the commonly connected metal strips. Shorting the end of this ground wire to the end of any of the other wires causes the relevant button operation to take place.

relay board to control a stopwatch for timing arduino projectsWe next made the above pictured board. We put three tactile switches on the board and wired them up so that when pressed, they would short a mode button input to ground. These tact switches make it much easier to interact with the wired-up watch manually.

Then we added a small 5V coil relay and connected its NO and COM pins to the Start/Stop button connection and to ground for the watch. When the relay is energised (closed) it will simulate the Start/Stop button of the watch being held down.

The final component is an Arduino Pro Mini in a socket. This board will be used to calibrate the internal clocks of Arduino Pro Mini clones as their crystals are not accurate enough for some of the projects we build.

(Note that we are powering this board with 12VDC for convenience as that is the voltage we use for all of our testing rigs with a bench power supply, but for a one off it would have been 5VDC powered – 4 AA cells for example.)

Controlling the Stopwatch via Arduino and Calibrating the Arduino’s Internal Clock

 digitalWrite(relay, HIGH);
 delay(50);
 digitalWrite(relay, LOW);

The Arduino code above is used to briefly energise the relay which starts and stops the stopwatch. We used a 50 millisecond delay so that the relay has time to energise (physically close its internal contacts) and button presses of under 20 milliseconds were ignored by this watch. When someone presses a button, they typically keep it held down for from 30-70 milliseconds, so we replicated that.

To roughly measure how long is 10 seconds for the Arduino, we used the following code:

digitalWrite(relay, HIGH);
delay(50);
digitalWrite(relay, LOW);

delay(10000);

digitalWrite(relay, HIGH);
delay(50);
digitalWrite(relay, LOW);

It starts the stopwatch, waits 10,000 milliseconds, and then stops the stopwatch. If the Arduino is accurate, the stopwatch will stop with 10.00 seconds displayed. In a few quick runs we got 10.03, 10.07, 10.06, 10.06, 10.03, 10.03, and 10.06 seconds. This seems to show that this particular Arduino Pro Mini was running a little slow (it could also be that it takes longer for the relay to energise than de-energise which could be significant when only timing 10 seconds).

The delay() function is not accurate in general since we do not know how long the loop execution time is. Instead for accurate time testing we use millis().
Replacing delay(10000); with the following:

unsigned long startTime = millis();
do{
  delay(1);
} while (startTime + 10000> millis());

we got 10.00, 10.00, 10.00, 10.00, 10.00, 10.00, and 10.00 seconds on the stopclock in initial testing.

For calibration we test for a minimum of 8 hours, but sometimes 12 or 24 hours. The longer the test, the greater the accuracy of the results and therefore the better we can calibrate the Arduino’s internal clock.

There are 28800000 milliseconds in 8 hours for example. So we’d modify the code above to have while(startTime + 28800000 > millis()); . After 8 hours, the stopwatch will show a time. We found that that this Arduino Pro Mini was running 4 seconds slow….so after 8 hours the clock showed 8h 00m 04s.
There are 28,000 seconds in 8 hours, so the error in the Arduino clock is
1 – 28,000/28004 = 0.0001428 = 0.01428%.
We can save this percentage error in memory on this Arduino Pro Mini and take it into account when using it in timing applications. If we want to use this Pro Mini to time 5 hours accurately, we’d run the timer for 5 hours minus 0.01428% of 5 hours.

Modified Spot Welder Timer from 555 Circuit

555 timer for weldingPictured above is a standard circuit design for controlling a spot welder for use in building battery packs and other applications. The welder is 12VDC powered from a large battery, and the 555 timer circuit controls the duration of the brief (sub one second) pulse of high current required to perform the spot welds.

We sell a selection of programmable timers with displays which are much simpler to use and set up than a 555 timer circuit with just a potentiometer used to set the current pulse duration. One of these user programmable options is our dual pulse welder timer controllerhttp://www.reuk.co.uk/wordpress/dual-pulse-spot-welder-timer-controller/ . A dual pulse when spot welding gives much better results, but requires a complicated circuit and many components to achieve using a 555 timer.

Therefore we put together the following controller which can work with the output side of a standard 555 spot welding circuit to give much better control and dual pulse capability for customers who already have an array of power MOSFETS set up to supply current to their 12V welding apparatus.

modified welder timer circuit based around old 555 timer circuitry, but giving dual pulse capability

The duration of the first pulse, pause, and second pulse can each be set by the user from 0.01 to 1.99 seconds duration with 0.01 second resolution facilitating consistent welds which can be reproduced again and again.

If you need any kind of spot welding timer controller, please email neil@reuk.co.uk with details of your requirements.

Multiple Switch Bathroom Fan Controller

Pictured below is a bathroom extractor fan controller we were recently commissioned to build.three switch bathroom extractor fan controller

The client has a house with a newly renovated bathroom and three existing light switches which are to be used to control a mains powered extractor fan in the new bathroom. If any of the three light switches is on, the fan is to run.

If the output from these three switches were to be connected directly to the fan, then the fan would turn on if any of the switches is on, but it would also result in the lights controlled by the three switches (in different rooms) all turning on simultaneously. This would be a problem.

Therefore, the output from the three switches is connected to three independent relays with 240V AC coils on the board pictured. These three relays each switch a single 12V signal from a nearby mains transformer to energise a 12V DC coil relay which in turn switches mains live to supply power to the fan when one or more of the light switches is on.

If you require any kind of bespoke controller, please email neil@reuk.co.uk with details of your requirements.

PPC 1500 Target Shooting Timer

PPC 1500 target shooting timer controller relay

Pictured above is a timer we recently built to control the start and finish horn for PPC 1500 shooting competitions.

In competition a button is pressed followed by a 3 second delay. Then the timer begins counting down from 8 secs,12 secs, 20 secs, 35 secs, 90 secs, or 165 secs with a horn sounding for 0.75 seconds as the timer starts, and again for 0.5 seconds after the timer has finished.

The user can select the timing option using the on board button, an external button, or using a remote control switch.

The on board display shows the current setting while the timer is not running, and then shows the countdown ticking down while it is running. The start button can also be used to stop the timer when it is running to reset the system.

A second button enables the user to sound the horn at any time while the button is being pressed.

If you need any time of timer controller, please email neil@reuk.co.uk with details of your specific requirements.