PCOMP Week 5

I especially struggled to come up with an idea for this assignment. My original plan was to make a force gamer using FSRs, though I’ve burnt all the FSRs I had, trying to solder them. The issue of fixing the electronic parts firmly to the board or wires is always a stressful job so that’s why I tried to solder them to wires but miserably failed and got even more stressed. I shouldn’t have directly soldered to their leads. It was warned here: https://itp.nyu.edu/physcomp/labs/labs-arduino-digital-and-analog/analog-in-with-an-arduino/, but I totally forgot.

They were even quite expensive sensors! My heart is broken… :'(

To be honest, I tried to make a force gamer using two potentiometers instead, but they worked weirdly when I turned on both of them. They worked fine separately but, for some reasons, a potentiometer’s signal got bigger than 0 even when it turned off in the situation that another potentiometer turned on. I wasn’t able to figure out the cause and gave up to make it this time.

So I had to come up with another idea. Meanwhile, I suddenly got to have an idea to make a little washing machine while I was doing laundry. Washing machines have motors, speakers for beep sounds and some models also have light indicators on them. And for the inputs, they usually have buttons and also have sensors which can detect their doors open. Fortunately, I had all of the input and output devices and started to make a circuit that works like a washing machine.

More detailed functions and requirements were like below:

  1. The machine has a button that turns it on and off
  2. There are three states: Wash, Rinse and Dry, and you can see in which state the machine is seeing its light indicators
  3. The motor speed is different depending on the states
  4. The washer has to be able to detect its door open
  5. If the door opens while operating, it has to pause its job right away and make beep sounds until the door is closed
  6. It continues the previous work after the door is closed
  7. If you turn off the machine in the middle of the laundry, it stops and starts from the beginning of the laundry process when it after turns on again
  8. When the whole steps complete, it let you know with a light signal and a melody and then turns off automatically

 

DESIGNING THE CIRCUIT

Below is the schematic diagram I designed:

As many devices had to work at the same time and the rule was a bit complicated, I worked on each part and function separately and combined them later.

Firstly, I tested on the tilt sensor as it was the first time to use it. I thought it was an analogue sensor but realised, actually was a digital sensor having the states of 0 and 1 like a switch. In the following video, I made the speaker beeps when the sensor is tilted.

But it sometimes shows 0 signal when it stands straight. To compensate it, I made the board monitor the recent five signals of the sensor and judge it is tilted only when all of the signals are 0:


void loop() {
sumOfRecentTiltValues += digitalRead(TILT_PIN);
...
if((state!=OFF) && (sumOfRecentTiltValues>0)) {
...
}
if((state!=OFF) && (state!=COMPLETE) && (sumOfRecentTiltValues==0)) {
warning();
}
...
}

Next, I combined the tilt sensor and the speaker with a switch so that the speaker only beeps when the switch is on and the sensor is tilted. Here, the circuit keeps its state being on if the button is once pressed:

 

I also added three LEDs which show the state of Wash, Rinse and Dry, respectively. Each LED blinks when the tilt sensor is tilted and all three LEDs blink together three times when the laundry process completes:

 

I used millis() instead of delay() to make all the parts can operate independently. The full source code for this Arduino washing machine is like below:


#include
#include "Pitches.h"
////////////////////////
#define TILT_PIN 12
#define SPEAKER_PIN 11
#define MOTOR_PIN 9
#define WASH_PIN 5
#define RINSE_PIN 6
#define DRY_PIN 7
#define SWITCH_PIN 2
////////////////////////
#define OFF 0
#define WASH 1
#define RINSE 2
#define DRY 3
#define COMPLETE 4
////////////////////////
#define TILT_VALUES_NUM 5
#define WARNING_BEEP_INTERVAL 200
#define WARNING_MUTE_INTERVAL 50
#define WARNING_LED_INTERVAL 300
////////////////////////
#define WASH_MOTOR_INTERVAL 1000
#define RINSE_MOTOR_INTERVAL 500
#define DRY_MOTOR_INTERVAL 200
#define COMPLETE_LED_INTERVAL 500
#define COMPLETE_MELODY_INTERVAL 200
////////////////////////
int previousSwitchValue = 0;
////////////////////////
int sumOfRecentTiltValues = 0;
int currentTiltNum = 0;
////////////////////////
int numBeep = 0;
long previousSpeakerTime = 0;
int currentSpeakerInterval = 0;
////////////////////////
long previousLEDTime = 0;
int warningLEDState = HIGH;
////////////////////////
Servo washerMotor;
int motorAngle = 0;
long previousMotorTime = 0;
int washMotorCount = 0;
int rinseMotorCount = 0;
int dryMotorCount = 0;
int completeLEDCount = 0;
int completeLEDState = LOW;
int completeMelody[] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C5, NOTE_D5, NOTE_E5, NOTE_C6};
int completeNoteDuration[] = {200, 200, 200, 200, 200, 200, 400};
int completeMelodyCount = 0;
////////////////////////
int state = OFF;
////////////////////////
void setup() {
pinMode(TILT_PIN, INPUT);
pinMode(SWITCH_PIN, INPUT);
pinMode(WASH_PIN, OUTPUT);
pinMode(RINSE_PIN, OUTPUT);
pinMode(DRY_PIN, OUTPUT);
washerMotor.attach(MOTOR_PIN);
Serial.begin(9600);
}
////////////////////////
void loop() {
sumOfRecentTiltValues += digitalRead(TILT_PIN);
////////////////////////
int currentSwitchValue = digitalRead(SWITCH_PIN);
if(currentSwitchValue==HIGH && previousSwitchValue!=HIGH) {
if(state == OFF) state = WASH;
else state = OFF;
}
////////////////////////
Serial.print("switch: ");
Serial.print(digitalRead(SWITCH_PIN));
Serial.print("\tstate: ");
Serial.println(state);
////////////////////////
previousSwitchValue = currentSwitchValue;
////////////////////////
if((state!=OFF) && (sumOfRecentTiltValues>0)) {
if(state == WASH) {
wash();
}
else if(state == RINSE) {
rinse();
}
else if(state == DRY) {
dry();
}
else if(state == COMPLETE) {
complete();
}
}
if((state!=OFF) && (state!=COMPLETE) && (sumOfRecentTiltValues==0)) {
warning();
}
if(state == OFF) {
off();
}
if(currentTiltNum == TILT_VALUES_NUM) {
currentTiltNum = 0;
sumOfRecentTiltValues = 0;
}
else if(currentTiltNum < TILT_VALUES_NUM) currentTiltNum++;
}
////////////////////////
void wash() {
digitalWrite(WASH_PIN, HIGH);
////////////////////////
unsigned long currentMotorTime = millis();
////////////////////////
if((washMotorCount<5) && ((currentMotorTime - previousMotorTime)>=WASH_MOTOR_INTERVAL)) {
previousMotorTime = currentMotorTime;
if(motorAngle == 0) {
motorAngle = 180;
washMotorCount++;
}
else motorAngle = 0;
////////////////////////
washerMotor.write(motorAngle);
}
else if(washMotorCount>=5) {
motorAngle = 30;
washerMotor.write(motorAngle);
washMotorCount = 0;
previousMotorTime = 0;
state = RINSE;
digitalWrite(WASH_PIN, LOW);
}
}
////////////////////////
void rinse() {
digitalWrite(RINSE_PIN, HIGH);
////////////////////////
unsigned long currentMotorTime = millis();
////////////////////////
if((rinseMotorCount<5) && ((currentMotorTime - previousMotorTime)>=RINSE_MOTOR_INTERVAL)) {
previousMotorTime = currentMotorTime;
if(motorAngle == 30) {
motorAngle = 120;
rinseMotorCount++;
}
else motorAngle = 30;
////////////////////////
washerMotor.write(motorAngle);
}
else if(rinseMotorCount>=5) {
motorAngle = 70;
washerMotor.write(motorAngle);
rinseMotorCount = 0;
previousMotorTime = 0;
state = DRY;
digitalWrite(RINSE_PIN, LOW);
}
}
////////////////////////
void dry() {
digitalWrite(DRY_PIN, HIGH);
////////////////////////
unsigned long currentMotorTime = millis();
////////////////////////
if((dryMotorCount<10) && ((currentMotorTime - previousMotorTime)>=DRY_MOTOR_INTERVAL)) {
previousMotorTime = currentMotorTime;
if(motorAngle == 70) {
motorAngle = 110;
dryMotorCount++;
}
else motorAngle = 70;
////////////////////////
washerMotor.write(motorAngle);
}
else if(dryMotorCount>=10) {
motorAngle = 0;
washerMotor.write(motorAngle);
dryMotorCount = 0;
previousMotorTime = 0;
state = COMPLETE;
digitalWrite(DRY_PIN, LOW);
}
}
////////////////////////
void complete() {
unsigned long currentLEDTime = millis();
unsigned long currentSpeakerTime = millis();
////////////////////////
if((completeLEDCount<6) && ((currentLEDTime - previousLEDTime) >= COMPLETE_LED_INTERVAL)) {
previousLEDTime = currentLEDTime;
if(completeLEDState==LOW) completeLEDState = HIGH;
else completeLEDState = LOW;
digitalWrite(WASH_PIN, completeLEDState);
digitalWrite(RINSE_PIN, completeLEDState);
digitalWrite(DRY_PIN, completeLEDState);
////////////////////////
completeLEDCount++;
}
if((completeMelodyCount<7) && ((currentSpeakerTime - previousSpeakerTime) >= COMPLETE_MELODY_INTERVAL)) {
previousSpeakerTime = currentSpeakerTime;
tone(SPEAKER_PIN, completeMelody[completeMelodyCount], completeNoteDuration[completeMelodyCount]+COMPLETE_MELODY_INTERVAL);
completeMelodyCount++;
}
if((completeLEDCount >= 6) && (completeMelodyCount >= 7)) {
completeLEDCount = 0;
previousLEDTime = 0;
completeMelodyCount = 0;
previousSpeakerTime = 0;
state = OFF;
}
}
////////////////////////
void warning() {
unsigned long currentSpeakerTime = millis();
unsigned long currentLEDTime = millis();
////////////////////////
if((currentSpeakerTime - previousSpeakerTime) >= WARNING_BEEP_INTERVAL) {
if(numBeep <2) { tone(SPEAKER_PIN, 900, 100); numBeep++; previousSpeakerTime = currentSpeakerTime; } else { currentSpeakerInterval++; if(currentSpeakerInterval > WARNING_MUTE_INTERVAL) {
numBeep = 0;
currentSpeakerInterval = 0;
}
}
}
if((currentLEDTime - previousLEDTime) >= WARNING_LED_INTERVAL) {
previousLEDTime = currentLEDTime;
if(state == WASH) {
if(warningLEDState == HIGH) warningLEDState = LOW;
else warningLEDState = HIGH;
digitalWrite(WASH_PIN, warningLEDState);
}
else if(state == RINSE) {
if(warningLEDState == HIGH) warningLEDState = LOW;
else warningLEDState = HIGH;
digitalWrite(RINSE_PIN, warningLEDState);
}
else if(state == DRY) {
if(warningLEDState == HIGH) warningLEDState = LOW;
else warningLEDState = HIGH;
digitalWrite(DRY_PIN, warningLEDState);
}
}
}
////////////////////////
void off() {
digitalWrite(WASH_PIN, LOW);
digitalWrite(RINSE_PIN, LOW);
digitalWrite(DRY_PIN, LOW);
motorAngle = 0;
washerMotor.write(motorAngle);
////////////////////////
sumOfRecentTiltValues = 0;
currentTiltNum = 0;
////////////////////////
numBeep = 0;
previousSpeakerTime = 0;
currentSpeakerInterval = 0;
////////////////////////
previousLEDTime = 0;
warningLEDState = HIGH;
////////////////////////
previousMotorTime = 0;
washMotorCount = 0;
rinseMotorCount = 0;
dryMotorCount = 0;
completeLEDCount = 0;
completeLEDState = LOW;
completeMelodyCount = 0;
}

 

Fabrication
Enclosing an Arduino circuit is the most difficult and stressful job because all the electrical parts deny to stay still and keep being apart from the board or wires. I tried male/female jumper wires and electronic tape but they weren’t good enough to hold them firmly. As a student with a limited budget, it’s critical to keep as many parts as possible to be reusable, so I  try to avoid glueing or nailing them to the enclosing materials. For this washing machine, I used Blu Tack to fix the motor in the box or keep the wires attaching to the components. It was better than jumper wires or electronic tape but still wasn’t enough. I need another better solution.

Anyway, I made a cardboard washing machine for this circuit. It worked quite well except the fact that the motor sometimes fell from the box while working. It was a shame that the speaker’s sound was barely audible. It should’ve been out of the box to be heard louder but I couldn’t make it because if so, it was easily parted from the circuit.

Leave a Reply

Your email address will not be published. Required fields are marked *