Final code for our 4180 Drawing Robot!

Dependencies:   4DGL-uLCD-SE gCodeParser mbed

Committer:
jford38
Date:
Tue Apr 29 21:51:29 2014 +0000
Revision:
0:40576dfac535
Child:
1:ad895d72e9ed
Before I fuck all this up.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jford38 0:40576dfac535 1 #ifndef DRAWBOT_H
jford38 0:40576dfac535 2 #define DRAWBOT_H
jford38 0:40576dfac535 3
jford38 0:40576dfac535 4 #include "mbed.h"
jford38 0:40576dfac535 5 #include "motor.h"
jford38 0:40576dfac535 6 #include "pen.h"
jford38 0:40576dfac535 7
jford38 0:40576dfac535 8 #define PI 3.1415926535
jford38 0:40576dfac535 9 #define DEG_PER_STEP 1.8
jford38 0:40576dfac535 10 #define INCHES_PER_SEG 4
jford38 0:40576dfac535 11 #define START_Y 10
jford38 0:40576dfac535 12
jford38 0:40576dfac535 13 Serial pc(USBTX, USBRX);
jford38 0:40576dfac535 14
jford38 0:40576dfac535 15 class DrawBot {
jford38 0:40576dfac535 16
jford38 0:40576dfac535 17 public:
jford38 0:40576dfac535 18 DrawBot(Motor*, Motor*, PinName, float, float);
jford38 0:40576dfac535 19 ~DrawBot();
jford38 0:40576dfac535 20 void drawCrap();
jford38 0:40576dfac535 21 void line_safe(float x, float y);
jford38 0:40576dfac535 22 inline void pen_up();
jford38 0:40576dfac535 23 inline void pen_down();
jford38 0:40576dfac535 24 inline void disable();
jford38 0:40576dfac535 25
jford38 0:40576dfac535 26 private:
jford38 0:40576dfac535 27 float px, py; // Position
jford38 0:40576dfac535 28 float fr; // Feed rate
jford38 0:40576dfac535 29 float step_delay; // How long to delay between steps.
jford38 0:40576dfac535 30 float rad; // Pulley Radius (inches)
jford38 0:40576dfac535 31 float STEP_PER_INCH;
jford38 0:40576dfac535 32 float width; // Distance from Pulley to Pulley (inches)
jford38 0:40576dfac535 33
jford38 0:40576dfac535 34 Motor* mL;
jford38 0:40576dfac535 35 Motor* mR;
jford38 0:40576dfac535 36
jford38 0:40576dfac535 37 Pen* pen;
jford38 0:40576dfac535 38
jford38 0:40576dfac535 39 inline void pause(long ms);
jford38 0:40576dfac535 40 inline void IK(float x, float y, long &l1, long &l2);
jford38 0:40576dfac535 41 void line(float newx,float newy);
jford38 0:40576dfac535 42
jford38 0:40576dfac535 43 };
jford38 0:40576dfac535 44
jford38 0:40576dfac535 45 DrawBot::DrawBot(Motor* mL, Motor* mR, PinName s_pin, float rad, float width) {
jford38 0:40576dfac535 46
jford38 0:40576dfac535 47 this->mL = mL;
jford38 0:40576dfac535 48 this->mR = mR;
jford38 0:40576dfac535 49 pen = new Pen(s_pin, 90);
jford38 0:40576dfac535 50
jford38 0:40576dfac535 51 STEP_PER_INCH = mL->get_msLevel()*360.0/(DEG_PER_STEP * 2*PI * rad);
jford38 0:40576dfac535 52 this->rad = rad;
jford38 0:40576dfac535 53 this->width = width;
jford38 0:40576dfac535 54 px = width/2.0;
jford38 0:40576dfac535 55 py = START_Y;
jford38 0:40576dfac535 56 step_delay = 80;
jford38 0:40576dfac535 57 }
jford38 0:40576dfac535 58
jford38 0:40576dfac535 59 DrawBot::~DrawBot() {
jford38 0:40576dfac535 60 delete mL;
jford38 0:40576dfac535 61 delete mR;
jford38 0:40576dfac535 62 }
jford38 0:40576dfac535 63
jford38 0:40576dfac535 64 inline void DrawBot::pause(long us) {
jford38 0:40576dfac535 65 wait_ms(us/1000);
jford38 0:40576dfac535 66 wait_us(us%1000);
jford38 0:40576dfac535 67 }
jford38 0:40576dfac535 68
jford38 0:40576dfac535 69 inline void DrawBot::pen_up() {
jford38 0:40576dfac535 70 pen->up();
jford38 0:40576dfac535 71 }
jford38 0:40576dfac535 72
jford38 0:40576dfac535 73 inline void DrawBot::pen_down() {
jford38 0:40576dfac535 74 pen->down();
jford38 0:40576dfac535 75 }
jford38 0:40576dfac535 76
jford38 0:40576dfac535 77 inline void DrawBot::disable() {
jford38 0:40576dfac535 78 pen->up();
jford38 0:40576dfac535 79 mL->disable();
jford38 0:40576dfac535 80 mR->disable();
jford38 0:40576dfac535 81 }
jford38 0:40576dfac535 82
jford38 0:40576dfac535 83 inline void DrawBot::IK(float x, float y, long &l1, long &l2) {
jford38 0:40576dfac535 84 long w = width * STEP_PER_INCH;
jford38 0:40576dfac535 85 l1 = sqrt(x*x + y*y - rad*rad);
jford38 0:40576dfac535 86 l2 = sqrt(y*y + (w-x)*(w-x) - rad*rad);
jford38 0:40576dfac535 87 }
jford38 0:40576dfac535 88
jford38 0:40576dfac535 89 void DrawBot::line(float newx, float newy) {
jford38 0:40576dfac535 90
jford38 0:40576dfac535 91 pc.printf("LINE: (%f, %f) -> (%f, %f)\n",px,py,newx,newy);
jford38 0:40576dfac535 92
jford38 0:40576dfac535 93 long L1, L2, oldL1, oldL2;
jford38 0:40576dfac535 94 IK(px*STEP_PER_INCH, py*STEP_PER_INCH, oldL1, oldL2);
jford38 0:40576dfac535 95 IK(newx*STEP_PER_INCH, newy*STEP_PER_INCH, L1, L2);
jford38 0:40576dfac535 96
jford38 0:40576dfac535 97 long d1=L1-oldL1;
jford38 0:40576dfac535 98 long d2=L2-oldL2;
jford38 0:40576dfac535 99 int dir1=d1>0?1:0;
jford38 0:40576dfac535 100 int dir2=d2>0?1:0;
jford38 0:40576dfac535 101 d1=abs(d1);
jford38 0:40576dfac535 102 d2=abs(d2);
jford38 0:40576dfac535 103
jford38 0:40576dfac535 104 long i;
jford38 0:40576dfac535 105 long over = 0;
jford38 0:40576dfac535 106
jford38 0:40576dfac535 107 if(d1>d2) {
jford38 0:40576dfac535 108 for(i=0;i<d1;++i) {
jford38 0:40576dfac535 109 mL->one_step(dir1);
jford38 0:40576dfac535 110 over+=d2;
jford38 0:40576dfac535 111 if(over>=d1) {
jford38 0:40576dfac535 112 over-=d1;
jford38 0:40576dfac535 113 mR->one_step(dir2);
jford38 0:40576dfac535 114 }
jford38 0:40576dfac535 115 pause(step_delay);
jford38 0:40576dfac535 116 }
jford38 0:40576dfac535 117 } else {
jford38 0:40576dfac535 118 for(i=0;i<d2;++i) {
jford38 0:40576dfac535 119 mR->one_step(dir2);
jford38 0:40576dfac535 120 over+=d1;
jford38 0:40576dfac535 121 if(over>=d2) {
jford38 0:40576dfac535 122 over-=d2;
jford38 0:40576dfac535 123 mL->one_step(dir1);
jford38 0:40576dfac535 124 }
jford38 0:40576dfac535 125 pause(step_delay);
jford38 0:40576dfac535 126 }
jford38 0:40576dfac535 127 }
jford38 0:40576dfac535 128
jford38 0:40576dfac535 129 px=newx;
jford38 0:40576dfac535 130 py=newy;
jford38 0:40576dfac535 131 }
jford38 0:40576dfac535 132
jford38 0:40576dfac535 133 void DrawBot::line_safe(float x,float y) {
jford38 0:40576dfac535 134
jford38 0:40576dfac535 135 // split up long lines to make them straighter?
jford38 0:40576dfac535 136 float dx=x-px;
jford38 0:40576dfac535 137 float dy=y-py;
jford38 0:40576dfac535 138
jford38 0:40576dfac535 139 float len=sqrt(dx*dx+dy*dy);
jford38 0:40576dfac535 140
jford38 0:40576dfac535 141 if(len<=INCHES_PER_SEG) {
jford38 0:40576dfac535 142 line(x,y);
jford38 0:40576dfac535 143 return;
jford38 0:40576dfac535 144 }
jford38 0:40576dfac535 145
jford38 0:40576dfac535 146 // too long!
jford38 0:40576dfac535 147 long pieces=floor(len/INCHES_PER_SEG);
jford38 0:40576dfac535 148 float x0=px;
jford38 0:40576dfac535 149 float y0=py;
jford38 0:40576dfac535 150
jford38 0:40576dfac535 151 float a;
jford38 0:40576dfac535 152 for(long j=0;j<=pieces;++j) {
jford38 0:40576dfac535 153 a=(float)j/(float)pieces;
jford38 0:40576dfac535 154
jford38 0:40576dfac535 155 line((x-x0)*a+x0,
jford38 0:40576dfac535 156 (y-y0)*a+y0);
jford38 0:40576dfac535 157 }
jford38 0:40576dfac535 158 line(x,y);
jford38 0:40576dfac535 159 }
jford38 0:40576dfac535 160
jford38 0:40576dfac535 161 void DrawBot::drawCrap() {
jford38 0:40576dfac535 162 pc.printf("\nSTARTING\n");
jford38 0:40576dfac535 163 line_safe(width/2.0+4, START_Y);
jford38 0:40576dfac535 164 line_safe(width/2.0+4, START_Y+4);
jford38 0:40576dfac535 165 line_safe(width/2.0, START_Y+4);
jford38 0:40576dfac535 166 line_safe(width/2.0, START_Y);
jford38 0:40576dfac535 167
jford38 0:40576dfac535 168 mL->disable();
jford38 0:40576dfac535 169 mR->disable();
jford38 0:40576dfac535 170 }
jford38 0:40576dfac535 171 /*
jford38 0:40576dfac535 172 //------------------------------------------------------------------------------
jford38 0:40576dfac535 173 // This method assumes the limits have already been checked.
jford38 0:40576dfac535 174 // This method assumes the start and end radius match.
jford38 0:40576dfac535 175 // This method assumes arcs are not >180 degrees (PI radians)
jford38 0:40576dfac535 176 // cx/cy - center of circle
jford38 0:40576dfac535 177 // x/y - end position
jford38 0:40576dfac535 178 // dir - ARC_CW or ARC_CCW to control direction of arc
jford38 0:40576dfac535 179 static void arc(float cx,float cy,float x,float y,float z,float dir) {
jford38 0:40576dfac535 180 // get radius
jford38 0:40576dfac535 181 float dx = posx - cx;
jford38 0:40576dfac535 182 float dy = posy - cy;
jford38 0:40576dfac535 183 float radius=sqrt(dx*dx+dy*dy);
jford38 0:40576dfac535 184
jford38 0:40576dfac535 185 // find angle of arc (sweep)
jford38 0:40576dfac535 186 float angle1=atan3(dy,dx);
jford38 0:40576dfac535 187 float angle2=atan3(y-cy,x-cx);
jford38 0:40576dfac535 188 float theta=angle2-angle1;
jford38 0:40576dfac535 189
jford38 0:40576dfac535 190 if(dir>0 && theta<0) angle2+=2*PI;
jford38 0:40576dfac535 191 else if(dir<0 && theta>0) angle1+=2*PI;
jford38 0:40576dfac535 192
jford38 0:40576dfac535 193 theta=angle2-angle1;
jford38 0:40576dfac535 194
jford38 0:40576dfac535 195 // get length of arc
jford38 0:40576dfac535 196 // float circ=PI*2.0*radius;
jford38 0:40576dfac535 197 // float len=theta*circ/(PI*2.0);
jford38 0:40576dfac535 198 // simplifies to
jford38 0:40576dfac535 199 float len = abs(theta) * radius;
jford38 0:40576dfac535 200
jford38 0:40576dfac535 201 int i, segments = floor( len / CM_PER_SEGMENT );
jford38 0:40576dfac535 202
jford38 0:40576dfac535 203 float nx, ny, nz, angle3, scale;
jford38 0:40576dfac535 204
jford38 0:40576dfac535 205 for(i=0;i<segments;++i) {
jford38 0:40576dfac535 206 // interpolate around the arc
jford38 0:40576dfac535 207 scale = ((float)i)/((float)segments);
jford38 0:40576dfac535 208
jford38 0:40576dfac535 209 angle3 = ( theta * scale ) + angle1;
jford38 0:40576dfac535 210 nx = cx + cos(angle3) * radius;
jford38 0:40576dfac535 211 ny = cy + sin(angle3) * radius;
jford38 0:40576dfac535 212 nz = ( z - posz ) * scale + posz;
jford38 0:40576dfac535 213 // send it to the planner
jford38 0:40576dfac535 214 line(nx,ny,nz);
jford38 0:40576dfac535 215 }
jford38 0:40576dfac535 216
jford38 0:40576dfac535 217 line(x,y,z);
jford38 0:40576dfac535 218 }*/
jford38 0:40576dfac535 219
jford38 0:40576dfac535 220 #endif