Open Arduino

Enter Your Project for a chance to win a grand prize for the most innovative use of Arduino or a $200 shopping cart! The Birthday Special: Arduino Projects for Arduino Day!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll


I know that mnay people will be puzzled by the title.

Every modern vehicle has wipers that you can adjust to suit the water on the screen, so what is it about.




This one started about 30 years ago.

Way back in my career making electronics was something you did.

There was no internet, no online shoppping like it is now, manufacturing was for the big boys and you recycled stuff to get parts you wanted to use.


I had spotted an article in a magazine where someone had added Intermittant Wipers to a vehicle.

It saved you having to turn the switch ON, then turn it OFF, back On, Off, etc.


This one was a bit more clever.

You pressed the Start button and it wiped.

If you pressed the Start button within a certain time, it continued wiping at that time period (between the first and second press).


When the conditions changed, you pressed the stop button and if you did nothing else it would stop.

If you pressed the Start button, it would use the time between Stop and Start for the wipe interval.


Pressing the Start button anytime changed the wipe interval period.


Pretty clever really. (Far better than the knob that never seems to have the right settings).



All of this was done in hardware.

I had to make the PCB layout using tape, then use UV sensitive film to make a negative, that got used to create the tracks on special UV sensitive PCB, etch it, drill it and finally populate the board.






Fast Forward

So many years later, the 1966 car I had, didn't have intermittant wipers.

Why not resurect the old hardware wiper project using an Arduino ...yes my favourite controller.


To be even more clever I could combine it with the Intelligent Idiot Light, and run both programs at the same time.

So this project found a reason to exist.






I was connecting other stuff (see A more Intelligent Idiot Light  )


The controller chosen was an Arduino but since I was going to do more with this, I added a shield for connections and interface components.

The regulator is a 7808 since vehicle charging can go as high as 15v, and many of the Arduino board regulators that aren't rated that high.

I call it insurance from spikes or other nasties in a vehicle.


One of the transistors drives a relay, and the onboard LED gets covered, so I added one on top.

As you can see some of the connections are shared with the alternative use for the hardware. A more Intelligent Idiot Light



The relay gets wired across the 'park' contact of the wiper motor.

The wiper switch actually operates in the ground part of the motor, and power remains on the motor.

Whenever you switch the wipers off, the park contact is still closed until they reach the parking position, and the contact gets opened.


So the relay gets wired across that contact, and the motor thinks it hasn't got home yet.






As I explained in the Intelligent Idiot Light, care was required to enable both sketches to work.

Therefore delay() was not used in the main loop.


The Start button would operate the relay and do a wipe (or two).

If it was pressed again within 30 seconds, then the wipe interval would be set to this time.


Press the Start button again and the time between the last wipe and the button press, would become the interval.


Press the Stop button and if nothing else was pressed within 30 seconds, it would stop wiping.

If you pressed the Start button, the time between Stop and Start became the onterval.


Just like the old hardware version, only much easier to make, and alter or fine tune.






The code for this is shown below.


  Automotive Series
  Variable Wiper
  This sketch controls a relay via a transistor, which is connected across the park contact on a Windscreen Wiper.
  Pressing the Start button, gives a single wipe, and if the button is pressed again within 30 secs, will continue at the interval between button press's.
  Pressing the Start button after a wipe cycle will change the interval to the time between wipe and press.
  Pressing of the Stop button halts the cycle, unless the start button is pressed within 30 secs.
  Wipe interval will be the interval between Stop and Start button being pressed.
  Delays have been removed to allow a secondary function to run at the same time.

 Pin assignments
 Pin 0  Rx
 Pin 1  Tx
 Pin 2  Wiper Relay Ouput
 Pin 3  
 Pin 4  Start Button Input
 Pin 5  Stop Button Input
 Pin 6  
 Pin 10 
 Pin 13 Led
 Pin A0 
 Pin A4 
 Created Dec 2011
 by Mark Beckett
 1.0  Initial Code completed Dec 2011
       Code finalised Feb 2012
 To Do :


// General Purpose
int IntWipe = 0;                       // Flag to show we mode we are in. 0= off, 1= first press, 2= 2nd press.
int LedState = LOW;                    // ledState used to set the LED

unsigned long WipeInterval = 0;         // Time between wipes as set by start/stop action                            [x secs]
unsigned long LastWipeTime =0;          // Time the last wipe was started.
unsigned long TimerTime =0;             // used in Timer(), = millis()-LastWipeTime.
int ButtonTimeout = 30;                 // Timeout if no button is pressed. Note wipe interval is lower than this.   [30 seconds]
int RelayOnTime = 1500;                 // Time the relay is held on to perform a single wipe.                       [1.5 secs]
boolean WiperRelayState = LOW;          // Relay Output state

// Button handling variables
unsigned long LastButtonCheck = 0;      // Time the Buttons were last checked.
unsigned long ButtonPressTime = 0;      // Time the last button was pressed.

boolean StartButtonState = HIGH;        // records the StartButton State
int StartCount = 0;                     // Start Button counter
boolean StopButtonState = HIGH;         // records the StopButton State
int StopCount = 0;                      // Stop Button counter

int StartButton = 4;
int StopButton = 5;
int CalButton = 6;
int val = 0;

int WiperRelay = 2;                     // Wiper relay output
const int LEDPin = 13;                  // Pin 13  LED Output


  Default values for the intermittant wiper
  Button timeout        = 30 secs
  ON time for relay     = 1.5 secs

void setup() 

  //Define the inputs
  pinMode (StartButton, INPUT);
  digitalWrite (StartButton, HIGH);
  pinMode (StopButton, INPUT);
  digitalWrite (StopButton, HIGH);
  //Define the outputs
  pinMode(LEDPin, OUTPUT);
  pinMode(WiperRelay, OUTPUT);

  ButtonTimeout = ButtonTimeout *1000;                    // Convert secs to milliseconds
  //RelayOnTime = RelayOnTime *1000;                      // Convert secs to milliseconds

void loop() 
  Check_Buttons();                                        //used for Int wiper
  Timer();                                                //See what is needed to be done

void Timer()
  // This controls the various routines and calls them as necessary
  TimerTime = millis() - LastWipeTime;
  if (((millis()-ButtonPressTime) > ButtonTimeout) && (IntWipe == 1))        // 30 Sec timeout for no button press, but only after stopped, or 1 start.
    IntWipe = 0;
    LastWipeTime = 0;
    WipeInterval = 0;   
      // The SingleWipe() will be called when the start button is pressed, we need to turn the relay off.
  if ((TimerTime > RelayOnTime) && WiperRelayState == true)    // RelayOnTime has been exceeded AND WipeRelay is HIGH
    SingleWipe();                                          // It will turn off the relay and not modify any variables
  // Time to wipe but only if there is a WipeInterval AND the relay is off.      
  if ((TimerTime > WipeInterval) && (IntWipe == 2) && WiperRelayState == false)       

void Check_Buttons()
  if (millis() - LastButtonCheck > 5)                      // Reads button state every 5mS and then updates button counts
    StartButtonState = digitalRead(StartButton);
    StopButtonState = digitalRead(StopButton);
    LastButtonCheck = millis(); 
    if (StartButtonState == LOW)
      StartCount ++;                                      // Increment the Count by 1
      if (StartCount > 10)                                // the button should be LOW for 10x5mS = 50mS
        ButtonPressTime = millis();                      // used for the Button press Timeout
        StartCount = 0;
        if (WiperRelayState == false)                    // No point in returning until its finished doing a wipe.
          switch (IntWipe)
            case 0:
              // not been pressed or fully stopped.
              IntWipe =1;
            break;                                            // Escape from the switch, so we don't do the next one
            case 1:
              // single press or stop button pressed.
              IntWipe = 2;
              WipeInterval = (millis() - LastWipeTime);       // Time will be in mS
            break;                                            // Escape from the switch, so we don't do the next one
            case 2:
              // 2nd press
              WipeInterval = (millis() - LastWipeTime);       // Time will be in mS
            break;                                            // Escape from the switch, so we don't do the next one
    else                                                  // StartButton is HIGH
      StartCount =0;
    if (StopButtonState == LOW)
      StopCount ++;
      if (StopCount >10)                                  // the button should be LOW for 50mS
        ButtonPressTime = millis();                       // used for the Button press Timeout
        IntWipe = 1;
        StopCount = 0;
        WipeInterval = 0;
        LastWipeTime = millis();                          // Set the wipe timer, so when the start is pressed the interval will be right
    else                                                  // StopButton is HIGH
      StopCount =0;

void SingleWipe()
  if (WiperRelayState == false)                          // Not much point in wiping if we already doing a wipe.
    LastWipeTime = millis();
    WiperRelayState = true;
    digitalWrite(WiperRelay, HIGH);
    digitalWrite(LEDPin, HIGH);
    WiperRelayState = false;
    digitalWrite(WiperRelay, LOW);
    digitalWrite(LEDPin, LOW);



In practice the wipe time was changed to do two wipes, but it didn't change the functioning.





As I indicated in the Intelligent Idiot Light, the car has been sold.

I can reproduce the function of the sketch.


I had to make a switch panel ... and as luck would have it the green pushbutton is a latching ...hence the double press.


Not sure what the motorboating noise is in the sound, but I did have the GoPro remotely controlled.



Hope you enjoy and gives someone some ideas.