Loading

plotclock with more detailed instructions

by yajdlanor, published

plotclock with more detailed instructions by yajdlanor Jul 18, 2015
2 Share
Download All Files

Thing Apps Enabled

Order This Printed View All Apps

Contents

Remixed From

Liked By

View All

Give a Shout Out

If you print this Thing and display it in public proudly give attribution by printing and displaying this tag.

Print Thing Tag

Makes

Thing Statistics

33482Views 3569Downloads Found in DIY

Summary

I made a plot clock too... Thanks joo! http://www.thingiverse.com/thing:248009

I had a hard time with a few things, so I documented my process in the instructions. Hopefully these will help someone else.

My modification is really minor, and it looks like there are others that do the same. I created a scad file of the part that connects to the arm servos that fits the single horn that came with my servos and used the following projects in addition to my horn part. I also modified the ino file to use some different constants that made it easier for me during the calibration process. See the instructions for more on this.

  1. 3d printable parts: http://www.thingiverse.com/thing:250204
  2. Expo marker arm: http://www.thingiverse.com/thing:261999
  3. Battery holder: http://www.thingiverse.com/thing:456900

Video of it in action:
https://goo.gl/photos/qACTKfDJhuQvSEaRA

Instructions

Printing

  1. Print the servohorn.stl (x2)
  2. Print all but the servo arms and arm that holds the marker from http://www.thingiverse.com/thing:250204
  3. Print the Expo parts from http://www.thingiverse.com/thing:261999
  4. Optionally print the battery holder (in ABS!) from http://www.thingiverse.com/thing:456900 and wire it for series operation. If you don't do this, you will need a power supply for your arduino that has sufficient ampherage to drive all 3 servos. My USB port was not enough to power the servos, and it took a while to figure out why it would start to move, then restart.

Electronics Assembly

  1. I created a servo header complex by soldering (sloppily, don't judge!) 4 x 3-pin headers together with some wire (see picture), but you could also use a breadboard. The servo's red and brown or black go to +5V and GND. Each servo's yellow wire goes to it's pin
    That is really all you need to do for the sample clock. A real time clock would be a good thing, or you can look at some of the other plotclock mods out there for other ideas (serial time, drawing, etc)

Mechanical Assembly

  1. Put the printed parts of the base together and sand / file as appropriate to get them to fit together. They should be snug. Use Joo's skp file as a guide for where parts go.
  2. use a 3mm drill bit or file to make sure that the arm part holes all have enough give to allow them to move freely with M3 bolts attached.
  3. attach the servo horns to my part with a wire or small screw
  4. attach the servo horn to the lifter servo and make sure it rotates from basically flat toward the other servos up to 90 degrees.
  5. attach the driving arm for the lifter servo to the horn with a small screw.
  6. attach all the arms to one another (refer to all the pictures there are on these plot clocks. It is especially important with the expo marker to make sure the expo arm is on the bottom side so the marker can reach the drawing surface.
  7. I used self-locking nuts to fasten the bolts so that they won't work off while the arms are moving.
  8. rotate the arm servos by hand counter-clockwise to the end stop.
  9. attach the arm parts with the left arm facing left 100 degrees (counter clockwise of flat) and the right arm facing straight up. don't screw them on until you do the calibration.
  10. I did not put in the clip for the pen/eraser head, since it does not quite fit. I will upload a new clip when I get one that works for me.
  11. Use a rubber band or elastic string to attach a paper towel or other soft eraser like material to the expo pen holder. Trim anything that comes up over the sides so the pen won't catch on anything.

Calibration

  1. manually position the arms so that the left arm is roughly horizontal and the right arm is vertical and the bottom servo so the arms are well above the surface
  2. upload the ino file to the arduino (with calibration uncommented).
  3. What you should see is that the two arms move back and forth.

You will adjust some numbers in the ino file to get these arms to move correctly, then you will turn off calibration and adjust some more.

The lines you will be adjusting are:

#define SERVOFAKTORLEFT xxx
#define SERVOFAKTORRIGHT xxx
#define SERVOLEFTNULL xxx
#define SERVORIGHTNULL xxx
#define LIFT0 xxx
#define LIFT1 xxx
#define LIFT2 xxx

Here is what mine looks like during calibration: https://goo.gl/photos/JceryoG6WuWsPQMy6

  • If you increase the LIFTx numbers, the arms should get closer to the platform.
  • if you increase the SERVOFAKTORxxx numbers, a bigger angle will be used in the arms
  • if you increase the SERVOXXXNULL numbers, the point at which the servos stop changes

I just played around with these numbers, then uploaded to see the results. Once you are happy with these, comment out the CALIBRATION line and upload again.

At this point, you should see the arm go up to the upper right, wipe back and forth to "erase", then draw the canned time "19:38" from the hardcoded numbers in the ino file. It will repeat this once per minute, adding a minute to the time until you stop it. This is where you can adjust the LIFTx numbers and get the pen to come down right and clar the top of the holder just right.

More from DIY

view more

All Apps

Auto-magically prepare your 3D models for 3D printing. A cloud based 3D models Preparing and Healing solution for 3D Printing, MakePrintable provides features for model repairing, wall thickness...

App Info Launch App

Kiri:Moto is an integrated cloud-based slicer and tool-path generator for 3D Printing, CAM / CNC and Laser cutting. *** 3D printing mode provides model slicing and GCode output using built-in...

App Info Launch App
KiriMoto Thing App

With 3D Slash, you can edit 3d models like a stonecutter. A unique interface: as fun as a building game! The perfect tool for non-designers and children to create in 3D.

App Info Launch App

Print through a distributed network of 3D printing enthusiasts from across the US, at a fraction of the cost of the competitors. We want to change the world for the better through technology, an...

App Info Launch App

Quickly Scale, Mirror or Cut your 3D Models

App Info Launch App

3D Print a wide range of designs with Treatstock. Easy to use tools to get the perfect result. The global 3D printing network that connects you with high-quality and fast working print services nea...

App Info Launch App

void set_XY(double Tx, double Ty) {
...
servo2.writeMicroseconds(floor(((a2 + a1 - M_PI) SERVOFAKTORLEFT) + SERVOLEFTNULL));
//What do SERVOFAKTORLEFT and SERVOLEFTNULL do here ?
...
// calculate joint arm point for triangle of the right servo arm
a2 = return_angle(L2, L1, c);
Hx = Tx + L3
cos((a1 - a2 + 0.621) + M_PI); //36,5° ? 35.6
Hy = Ty + L3 * sin((a1 - a2 + 0.621) + M_PI);
// Can anyone explain in detailed these 3 line please

hi. how to write character's instead of writing numbers. for my case i need to write "hai". i need code for this please help me... thank you

since you put stl files in a different page I find this more confusing
why do you do so ?
why is servohorn on this page instead

Thanks for the comment, Phil. I made this post only to add to Joo's and other's great work. The servohorn here is the only thing I created myself, and the rest of the items I used were created by others, so I posted links to them in the instructions.

hello!!!

Thanks for this great idea. I builded up this project and since 1 week I have a hard time to figure out

how to make this arms move exactly to the eraser and also for it to wipe and write correctly without going off the white board.

the more I increased the value on drawing surface the more it goes off the white board.

all what I succeeded to do is to calibrate it to go 90 degree. Please please can anyone help me with the code values that works perfect???
Right now I am just crazy that I will present this idea next week. I am really desperate about it.

thanks in advance for any help!!! this is my modified code so far

// Plotclock
// cc - by Johannes Heberlein 2014
// v 1.01
// thingiverse.com/joo wiki.fablab-nuernberg.de

// units: mm; microseconds; radians
// origin: bottom left of drawing surface

// time library see http://playground.arduino.cc/Code/time

// delete or mark the next line as comment when done with calibration

define CALIBRATION

// When in calibration mode, adjust the following factor until the servos move exactly 90 degrees

define SERVOFAKTOR 500

// Zero-position of left and right servo
// When in calibration mode, adjust the NULL-values so that the servo arms are at all times parallel
// either to the X or Y axis

define SERVOLEFTNULL 2250

define SERVORIGHTNULL 500

define SERVOPINLIFT 2

define SERVOPINLEFT 3

define SERVOPINRIGHT 4

// lift positions of lifting servo

define LIFT0 11000 // on drawing surface

define LIFT1 1925 // between numbers

define LIFT2 725 // going towards sweeper

// speed of liftimg arm, higher is slower

define LIFTSPEED 1500

// length of arms

define L1 35

define L2 55.1

define L3 13.2

// origin points of left and right servo

define O1X 22

define O1Y -25

define O2X 47

define O2Y -25

include // see http://playground.arduino.cc/Code/time

include

int servoLift = 1500;

Servo servo1; //
Servo servo2; //
Servo servo3; //

volatile double lastX = 75;
volatile double lastY = 47.5;

int last_min = 0;

void setup()
{
// Set current time only the first to values, hh,mm are needed
setTime(19,38,0,0,0,0);

drawTo(75.2, 47);
lift(0);
servo1.attach(SERVOPINLIFT); // lifting servo
servo2.attach(SERVOPINLEFT); // left servo
servo3.attach(SERVOPINRIGHT); // right servo
delay(1000);

}

void loop()
{

ifdef CALIBRATION

// Servohorns will have 90° between movements, parallel to x and y axis
drawTo(-3, 29.2);
delay(500);
drawTo(74.1, 28);
delay(500);

else

int i = 0;
if (last_min != minute()) {
if (!servo1.attached()) servo1.attach(SERVOPINLIFT);
if (!servo2.attached()) servo2.attach(SERVOPINLEFT);
if (!servo3.attached()) servo3.attach(SERVOPINRIGHT);

lift(0);

hour();
while ((i+1)*10 <= hour())
{
i++;
}

number(3, 3, 111, 1);
number(5, 25, i, 0.9);
number(19, 25, (hour()-i*10), 0.9);
number(28, 25, 11, 0.9);

i=0;
while ((i+1)10 <= minute())
{
i++;
}
number(34, 25, i, 0.9);
number(48, 25, (minute()-i
10), 0.9);
lift(2);
drawTo(74.2, 47.5);
lift(1);
last_min = minute();

servo1.detach();
servo2.detach();
servo3.detach();

}

endif

}

// Writing numeral with bx by being the bottom left originpoint. Scale 1 equals a 20 mm high font.
// The structure follows this principle: move to first startpoint of the numeral, lift down, draw numeral, lift up
void number(float bx, float by, int num, float scale) {

switch (num) {

case 0:
drawTo(bx + 12 scale, by + 6 scale);
lift(0);
bogenGZS(bx + 7 scale, by + 10 scale, 10 scale, -0.8, 6.7, 0.5);
lift(1);
break;
case 1:
drawTo(bx + 3
scale, by + 15 scale);
lift(0);
drawTo(bx + 10
scale, by + 20 scale);
drawTo(bx + 10
scale, by + 0 * scale);
lift(1);
break;

case 2:
drawTo(bx + 2 scale, by + 12 scale);
lift(0);
bogenUZS(bx + 8 scale, by + 14 scale, 6 scale, 3, -0.8, 1);
drawTo(bx + 1 scale, by + 0 scale);
drawTo(bx + 12 scale, by + 0 scale);
lift(1);
break;
case 3:
drawTo(bx + 2 scale, by + 17 scale);
lift(0);
bogenUZS(bx + 5 scale, by + 15 scale, 5 scale, 3, -2, 1);
bogenUZS(bx + 5 scale, by + 5 scale, 5 scale, 1.57, -3, 1);
lift(1);
break;
case 4:
drawTo(bx + 10 scale, by + 0 scale);
lift(0);
drawTo(bx + 10 scale, by + 20 scale);
drawTo(bx + 2 scale, by + 6 scale);
drawTo(bx + 12 scale, by + 6 scale);
lift(1);
break;
case 5:
drawTo(bx + 2 scale, by + 5 scale);
lift(0);
bogenGZS(bx + 5 scale, by + 6 scale, 6 scale, -2.5, 2, 1);
drawTo(bx + 5 scale, by + 20 scale);
drawTo(bx + 12 scale, by + 20 scale);
lift(1);
break;
case 6:
drawTo(bx + 2 scale, by + 10 scale);
lift(0);
bogenUZS(bx + 7 scale, by + 6 scale, 6 scale, 2, -4.4, 1);
drawTo(bx + 11 scale, by + 20 scale);
lift(1);
break;
case 7:
drawTo(bx + 2 scale, by + 20 scale);
lift(0);
drawTo(bx + 12 scale, by + 20 scale);
drawTo(bx + 2 scale, by + 0);
lift(1);
break;
case 8:
drawTo(bx + 5 scale, by + 10 scale);
lift(0);
bogenUZS(bx + 5 scale, by + 15 scale, 5 scale, 4.7, -1.6, 1);
bogenGZS(bx + 5 scale, by + 5 scale, 5 scale, -4.7, 2, 1);
lift(1);
break;

case 9:
drawTo(bx + 9 scale, by + 11 scale);
lift(0);
bogenUZS(bx + 7 scale, by + 15 scale, 5 scale, 4, -0.5, 1);
drawTo(bx + 5 scale, by + 0);
lift(1);
break;

case 111:
lift(0);
drawTo(70, 46);
drawTo(65, 43);

drawTo(65, 49);
drawTo(5, 49);
drawTo(5, 45);
drawTo(65, 45);
drawTo(65, 40);

drawTo(5, 40);
drawTo(5, 35);
drawTo(65, 35);
drawTo(65, 30);

drawTo(5, 30);
drawTo(5, 25);
drawTo(65, 25);
drawTo(65, 20);

drawTo(5, 20);
drawTo(60, 44);

drawTo(75.2, 47);
lift(2);

break;

case 11:
drawTo(bx + 5 scale, by + 15 scale);
lift(0);
bogenGZS(bx + 5 scale, by + 15 scale, 0.1 scale, 1, -1, 1);
lift(1);
drawTo(bx + 5 scale, by + 5 scale);
lift(0);
bogenGZS(bx + 5 scale, by + 5 scale, 0.1 scale, 1, -1, 1);
lift(1);
break;

}
}

void lift(char lift) {
switch (lift) {
// room to optimize !

case 0: //850
if (servoLift >= LIFT0) {
while (servoLift >= LIFT0)
{
servoLift--;
servo1.writeMicroseconds(servoLift);
delayMicroseconds(LIFTSPEED);
}
}
else {
while (servoLift <= LIFT0) {
servoLift++;
servo1.writeMicroseconds(servoLift);
delayMicroseconds(LIFTSPEED);

}

}

break;

case 1: //150
if (servoLift >= LIFT1) {
while (servoLift >= LIFT1) {
servoLift--;
servo1.writeMicroseconds(servoLift);
delayMicroseconds(LIFTSPEED);

}
}
else {
while (servoLift <= LIFT1) {
servoLift++;
servo1.writeMicroseconds(servoLift);
delayMicroseconds(LIFTSPEED);
}

}

break;

case 2:
if (servoLift >= LIFT2) {
while (servoLift >= LIFT2) {
servoLift--;
servo1.writeMicroseconds(servoLift);
delayMicroseconds(LIFTSPEED);
}
}
else {
while (servoLift <= LIFT2) {
servoLift++;
servo1.writeMicroseconds(servoLift);
delayMicroseconds(LIFTSPEED);
}
}
break;

}
}

void bogenUZS(float bx, float by, float radius, int start, int ende, float sqee) {
float inkr = -0.05;
float count = 0;

do {
drawTo(sqee radius cos(start + count) + bx,
radius * sin(start + count) + by);
count += inkr;
}
while ((start + count) > ende);

}

void bogenGZS(float bx, float by, float radius, int start, int ende, float sqee) {
float inkr = 0.05;
float count = 0;

do {
drawTo(sqee radius cos(start + count) + bx,
radius * sin(start + count) + by);
count += inkr;
}
while ((start + count) <= ende);
}

void drawTo(double pX, double pY) {
double dx, dy, c;
int i;

// dx dy of new point
dx = pX - lastX;
dy = pY - lastY;
//path lenght in mm, times 4 equals 4 steps per mm
c = floor(4 sqrt(dx dx + dy * dy));

if (c < 1) c = 1;

for (i = 0; i <= c; i++) {
// draw line point by point
set_XY(lastX + (i dx / c), lastY + (i dy / c));

}

lastX = pX;
lastY = pY;
}

double return_angle(double a, double b, double c) {
// cosine rule for angle between c and a
return acos((a a + c c - b b) / (2 a * c));
}

void set_XY(double Tx, double Ty)
{
delay(1);
double dx, dy, c, a1, a2, Hx, Hy;

// calculate triangle between pen, servoLeft and arm joint
// cartesian dx/dy
dx = Tx - O1X;
dy = Ty - O1Y;

// polar lemgth (c) and angle (a1)
c = sqrt(dx dx + dy dy); //
a1 = atan2(dy, dx); //
a2 = return_angle(L1, L2, c);

servo2.writeMicroseconds(floor(((a2 + a1 - M_PI) * SERVOFAKTOR) + SERVOLEFTNULL));

// calculate joinr arm point for triangle of the right servo arm
a2 = return_angle(L2, L1, c);
Hx = Tx + L3 cos((a1 - a2 + 0.621) + M_PI); //36,5°
Hy = Ty + L3 sin((a1 - a2 + 0.621) + M_PI);

// calculate triangle between pen joint, servoRight and arm joint
dx = Hx - O2X;
dy = Hy - O2Y;

c = sqrt(dx dx + dy dy);
a1 = atan2(dy, dx);
a2 = return_angle(L1, 45, c);

servo3.writeMicroseconds(floor(((a1 - a2) * SERVOFAKTOR) + SERVORIGHTNULL));

}

I made one follow your instructions. Calibration is a bit difficult, but once it's done the clock works really well. Thanks!

Glad it worked for you!

Thanks for the work :) Added a link to this instruction from my thing page

My pleasure. I hope they help someone else to get up and running faster.

Top