This project stemmed from a news article from which I learnt that domestic helpers in Singapore aren’t allowed to clean the outside of windows. Current window cleaning robots are expensive and I wanted to design something cheaper.
CAD Model
Initial Design and Sketches
Before starting on my own design, I researched other solutions to the same issue. While researching, I realized that there were two paths I could follow in terms of design. The first, and more popular design is to have a robot that attaches to a window through vacuum suction. The second is to use a x-y track system to allow the cleaner head to cover the cleaning area. I decided to go ahead with this second idea, as although it is window specific, vacuum suction leads to a higher cost, risk and power consumption.
Modeling the Robot
Using these reference sketches, I then modelled each of the components in Fusion360. Back when I worked on this project, I had no experience with CAD modelling and had to learn everything from scratch by myself.
To assist my CAD model, I used an Xbox 360 Kinect sensor to create a 3D scan of my window, which I then imported into Blender and cleaned up before importing the mesh into Fusion360. I then modelled the robot around this mesh as a reference. The key components include – cleaner head, platform, horizontal track and gear and the vertical track and gear.
Fabrication
Once the model was complete, it was time for fabricating each component. The majority of the parts such as the cleaner head, the gears and the rack and pinion system were 3D printed. As the track housing was quite a large part, I decided to manufacture it out of laser cut MDF. To do this, I first exported my drawings as a DXF and then used Adobe Illustrator to prepare it for laser cutting. I also made the clamp system by using a hot wire to fold sheets of 3mm acrylic.
Electronics and Coding
The main electrical components of this robot include an Arduino Uno, stepper motors for x-y movement and a servo motor to put the cleaner head into position. The main code can be broken down into 3 parts – code for the cleaner servo, code for the vertical motors and code for the horizontal motor. To use the motors, I had to use a motor shield that would allow me to connect motors to the Arduino.
//Import required libraries for the motor shield and stepper motor
#include <AFMotor.h>
#include <Servo.h>
// Connect stepper motor with 200 steps per revolution (1.8 degree)
AF_Stepper UDmotor(200, 2); //The vertical Movement Stepper
AF_Stepper LRmotor(200, 1); //Horizontal Movement Stepper
//initialize required variables
Servo cleanerHeadServo;
const uint32_t buttonSpringBack = 5;
const uint8_t switchPin = 2;
const bool switchOn = false;
const bool switchOff = true;
bool lastState = switchOff;
bool newState = switchOff;
bool toggleState = false;
//setup code
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
pinMode(switchPin, INPUT_PULLUP);
//set speed of stepper motors to 10 rpm
LRmotor.setSpeed(10);
UDmotor.setSpeed(10);
cleanerHeadServo.attach (9); //attatch servo on pin 10
Serial.begin(9600);
Serial.println("test");
cleanerHeadServo.write(0); //set servo to starting position
}
void goRight() {
LRmotor.setSpeed(10);
LRmotor.step(200, BACKWARD, DOUBLE); //Move right 1 rotation (16 cm)
LRmotor.setSpeed(0);
}
void goLeft() {
LRmotor.step(200, FORWARD, SINGLE); //move left 1 rotation
}
void goDown() {
UDmotor.step(1000, FORWARD, DOUBLE); //200 = 16.5cm move down 82.5 cm
}
void goUp() {
UDmotor.step(1000, BACKWARD, DOUBLE); //move up 82.5 cm
}
void servoMovePos(){
int pos = 10;
for (pos = 10; pos <=50; pos +=1) {
cleanerHeadServo.write(pos);
delay(10);
}
}
void servoCleanPos(){
int pos = 50;
for (pos = 50; pos >=10; pos -=1) {
cleanerHeadServo.write(pos);
delay(10);
}
}
void loop() {
//read serial monitor for input from laptop
char key = Serial.read();
// int val = digitalRead(button);
newState = digitalRead( switchPin );
//debugging scripts to test from laptop
if(key == 'u'){
servoMovePos();
goUp();
}
if(key == 'd'){
servoCleanPos();
goDown();
goRight();
}
if(key =='l'){
goLeft();
}
if(key =='r'){
goRight();
}
//code to trigger funtions when button pressed
if( lastState != newState ) // state changed
{
delay( buttonSpringBack );
lastState = newState;
// push on, push off
if( newState == switchOn && toggleState == false )
{
toggleState = true;
Serial.println( F ( "Switched OFF" ) );
}
else if( newState == switchOn && toggleState == true )
{
toggleState = false;
Serial.println( F ( "Switched ON" ) );
for (int i=1; i<= 5; i++){
servoMovePos();
goUp();
servoCleanPos();
goDown();
servoMovePos();
goRight();
}
}
}
}
Testing and changes
Once the code was complete and all parts fabricated, I tested the robot. There were multiple errors with my first build, with a few key ones being an insufficient torque on my chosen stepper motors and a lack of rigidity on the vertical track. After a few more iterations and adding features such as ball bearings to reduce friction, increasing the rigidity of the track by adding a metal rod through it, and upgrading the stepper motors, I settled on a final design.
Future Improvement
Overall, I was happy with the finished product, as I set out to make a robot that can clean windows without assistance and managed to deliver on this goal. However, there was still a lot of room for improvement. Firstly, due to time constraints, I was only able to design this robot to work on one window in my house and this is something I’d like to improve in the future. I could do this by using an extendable track, that has a stronger clamping mechanism to latch onto the window frame. Secondly, as this was just a prototype made with mostly off the shelf components, the wires are exposed, and it was not very safe around liquids. If this was a commercial product, I would design an integrated PCB as this would help miniaturize a lot of the components, making the robot more efficient as well as hiding any wiring. Finally, I would improve the stability of the vertical track and maybe add an infrared sensor, so the robot knows when to stop moving up/down.

















