# Individual assignment
For this week's assignment, I elected to try to complete a mini project. Since I already have experience with embedded programming, I have two goals I want to accomplish over these coming weeks with no access to the lab:
- explore Atmel Studio and native AVR programming more; I decided to push this back to next week to focus instead on...
- accomplish something practical, in a reasonable amount of time, without letting myself go down my usual rabbit holes of research that lead projects to take way too long
To achieve that second goal, I picked something that would be immediately useful, if slightly silly: turning a regular, human powered soap dispenser at home into an automated dispenser.
The first step of achieving this was controlling a servo motor from an Arduino. This is thankfully pretty simple:
#include <Servo.h>
int servoPin = 9;
Servo servo;
int angle = 0; // servo position in degrees
void setup() {
servo.attach(servoPin);
}
void loop() {
// scan from 0 to 180 degrees
for(angle = 0; angle < 180; angle++) {
servo.write(angle);
delay(15);
}
// now scan back from 180 to 0 degrees
for(angle = 180; angle > 0; angle--) {
servo.write(angle);
delay(15);
}
}
This immediately begs the question of converting the rotation of a servo motor to linear motion, however. Thanks to one of my classmates (thank you again Madison!), I temporarily have access to a Prusa i3 MK3 printer at home.
I decided to prototype a simple rack and pinion mechanism. This turned out to be pretty trivial to design in Solidworks, print and connect to a servo running the above program:
The next step was to enhance the code to also read an ultrasonic distance sensor and move the servo when triggered:
#include <Servo.h>
Servo servo;
#define angle_min 0
#define angle_max 70
const int servoPin = 9;
const int trigPin = 11;
const int echoPin = 12;
void setup()
{
Serial.begin(9600);
servo.attach(servoPin);
servo.write(angle_max);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
float distance = measureDistance();
Serial.println(distance);
if (distance < 5.0f) {
pump();
}
Serial.println("done pumping");
delay(500);
}
void pump() {
static const uint8_t move_speed = 5;
for(uint8_t angle = angle_max; angle > angle_min; angle--) {
servo.write(angle);
delay(move_speed);
}
delay(50);
for(uint8_t angle = angle_min; angle < angle_max; angle++) {
servo.write(angle);
delay(move_speed);
}
}
float measureDistance() {
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
float echoTime = pulseIn(echoPin, HIGH);
float distance = echoTime / 58.0f;
return distance;
}
This code is pretty basic and needs several enhancement in the future: most notably, it essentially busy waits between triggers, which will result in significant power usage, when the MCU could instead be put to sleep and awakened at regular intervals by a timer to save on battery. This simple version will have to do for this week, though!
To go with this code, I designed a simple holder for the previous rack and pinion design, as well as a top piece to press on the soap dispenser.
Unfortunately, in this design, the top piece and the rack are printed separately (for ease of printing as well as design); this might have worked if I had some stronger glue on hand, but I did not, and a small screw to attach both was not enough: the servo would simply cause the top to bend away from the rack.
A subsequent design made the rack and top piece a single part:
Unfortunately, this design turned out to also have issues:
As you can see, once the rack and top piece were made into a single part, the rack itself started bending away from the slot it was supposed to ride in.
At this point, I went back to the drawing board and redesigned the base piece from scratch, with two (somewhat competing) goals in mind:
- improve rigidity
- improve printability
While I was at it, I added a holder for the ultrasonic sensor.
This final design completely encloses the rack, which now also extends to the sides to ride in "rails" in the base piece.
This design took a little while to print but came out looking quite nice, and was very easy to assembly since it is now only three parts:
- the base, which holds the soap dispenser, has attachment points for the motor and a slot for the ultrasonic sensor
- the rack and top actuator as a single part
- a gear to connect both
This design was finally a success! It works much better than I was expecting for a project done in under a week, to be honest.
If I had more time, I would love to investigate the following:
- integrating the Arduino and batteries more cleanly in the design
- lowering power consumption significantly
- re-writing the code for bare AVR, both to save power and for better control of the servo
# Class notes
Useful things:
- list of sensors in class text
- PIR sensors for motion?
- "radar" (microwave radar)
- need a microphone? use MEMS, don't use regular microphones anymore