Port of the Arduino based Plotclock, initial commit untested.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
TheChrisyd
Date:
Fri Mar 21 18:01:22 2014 +0000
Commit message:
First commit of port for the Arduino based Plotclock, see: http://mbed.org/forum/mbed/topic/4801/

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r caca11342d59 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Mar 21 18:01:22 2014 +0000
@@ -0,0 +1,456 @@
+// Plotclock
+// cc - by Johannes Heberlein 2014 ported by Chris Dick
+// v 1.0
+// thingiverse.com/joo   wiki.fablab-nuernberg.de
+
+// units: mm; microseconds; radians
+// origin: bottom left of drawing surface (see sketchUp file)
+
+// todo detail m3, info grafik winkel, kalibr 
+
+#include "mbed.h"
+
+// #define CALIBRATION
+
+#define SERVOFAKTOR 650
+
+// 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
+// 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
+// Zero-position of left and right servo
+#define SERVOLEFTNULL 1890
+#define SERVORIGHTNULL 960
+
+// lift positions of lifting servo
+#define LIFT0 1080// on drawing surface
+#define LIFT1 925// between numbers
+#define LIFT2 725
+/* going towards sweeper */
+
+/* speed of liftimg arm, higher is slower */
+#define LIFTSPEED 1500
+
+/*
+    servo width:
+        Servo1: Write: 1080ms; Lift Sweep: 724; Lift Number: 924 
+        Servo2: 0.65-1.98
+        Servo3: 1.1-1.8ms 
+*/
+/*
+    Arduino defines
+*/
+#define delay(x)                  (wait_ms(x))
+#define delayMicroseconds(x)      (wait_us(x))
+#define M_PI                      3.141592653589793238462643  //line 70 math.h
+//#include <Time.h>   don't need this RTC clock does it
+//#include <Servo.h>  only using one function, writeMicroseconds(), can be done using period_us() on a PwmOut pin
+
+
+void number( float bx, float by, int num, float scale ) ;
+void lift( char lift ) ;
+void bogenUZS( float bx, float by, float radius, int start, int ende, float sqee );
+void bogenGZS( float bx, float by, float radius, int start, int ende, float sqee );
+void drawTo(double pX, double pY);
+double return_angle( double a, double b, double c );
+void set_XY( double Tx, double Ty );
+int minute( void );
+int hour( void );
+
+int servoLift = 1500;
+
+PwmOut servo1(p21);  //   lifting servo
+PwmOut servo2(p22);  //  left servo
+PwmOut servo3(p23);  //  right servo
+
+int val;    // variable to read the value from the analog pin 
+
+volatile double lastX = 75;
+volatile double lastY = 47.5;
+
+int last_min = 0;
+
+
+void setup() 
+{ 
+  // Set current time
+  set_time( (( 2014/*year*/ - 1970) * 31556926 ) 
+             + (  3/*month*/ * 2629743 ) 
+             + (  6/*day*/ * 86400 )
+             + ( 17/*hour*/ * 3600 )
+             + (  0/*minute*/ * 60 )
+             +    0/*second*/ );  
+  drawTo(75, 44);
+  lift(0);
+  /* replace pin assignments with PWM period  */
+ 
+    servo1.period(0.002);  // this is the PWM period used by the Arduino servo library
+    delay(1000);
+} 
+
+void loop() 
+{  
+    //servo2.period_us(M_PI *SERVOFAKTOR + SERVOLEFTNULL); // was writeMicroseconds 
+#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()) {
+    /* Assuming these are to save power - removed for first run of port */
+    //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(75, 47.5);
+    lift(1);
+    last_min = minute();
+    
+    //servo1.detach();
+    //servo2.detach();
+    //servo3.detach();
+  }
+#endif
+} 
+
+int minute( void )
+{
+    int minutes = 0;
+    time_t seconds = time(NULL)+ 19800; 
+    minutes = seconds / 60;
+    return ( minutes % 60 );
+}
+
+int hour( void )
+{
+    int hour = 0;
+    time_t seconds = time(NULL)+ 19800; 
+    hour = seconds / 3600;
+    return ( hour % 24 );
+}
+
+
+// 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(77, 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 optimise  !
+
+  case 0: //850
+
+      if (servoLift >= LIFT0) {
+      while (servoLift >= LIFT0) 
+      {
+        servoLift--;
+        servo1.period_us(servoLift);                
+        delayMicroseconds(LIFTSPEED);
+      }
+    } 
+    else {
+      while (servoLift <= LIFT0) {
+        servoLift++;
+        servo1.period_us(servoLift);
+        delayMicroseconds(LIFTSPEED);
+
+      }
+
+    }
+
+    break;
+
+  case 1: //150
+
+    if (servoLift >= LIFT1) {
+      while (servoLift >= LIFT1) {
+        servoLift--;
+        servo1.period_us(servoLift);
+        delayMicroseconds(LIFTSPEED);
+
+      }
+    } 
+    else {
+      while (servoLift <= LIFT1) {
+        servoLift++;
+        servo1.period_us(servoLift);
+        delayMicroseconds(LIFTSPEED);
+      }
+
+    }
+
+    break;
+
+  case 2:
+
+    if (servoLift >= LIFT2) {
+      while (servoLift >= LIFT2) {
+        servoLift--;
+        servo1.period_us(servoLift);
+        delayMicroseconds(LIFTSPEED);
+      }
+    } 
+    else {
+      while (servoLift <= LIFT2) {
+        servoLift++;
+        servo1.period_us(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.period_us(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, (L2 - L3), c);
+
+  servo3.period_us(floor(((a1 - a2) * SERVOFAKTOR) + SERVORIGHTNULL));
+}
+
+
+
+int main() {
+    setup();
+    while(1) {
+        loop();
+    }
+}
diff -r 000000000000 -r caca11342d59 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Mar 21 18:01:22 2014 +0000
@@ -0,0 +1,1 @@
+http://world3.dev.mbed.org/users/mbed_official/code/mbed/builds/824293ae5e43
\ No newline at end of file