So we hot glued two servos together and the to a mirror.

We’re aiming a laser at it. A blindingly powerful laser

Essentially Servo B controls the angle in the x-y plane of the mirror and servo A controls the z angle to that plane.

The mirror law is

Where all are unit vectors. is the incoming, is the mirror normal and is the outgoing unit vector.

We fixed the laser to the base so

The outgoing ray must hit the ceiling (at a height R) at position x,y.

Here’s a nice observation:

So we have an algorithm for finding n right there. Find v2, subtract off 1 and then normalize the resulting vector to get $latex \hat{n}$.

Then finally we can write n in terms of the angles , which heavily depend on our conventions of where angle 0 is and whether the servo spin clockwise or counterclockwise.

I believe ours came out to be something like:

In all honesty, we coded her up, then fiddled with minus signs until it was working. Not necessarily a bad way of going about things. Find the things to think about and find the things to just try.

Then here is the code:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
#include <Servo.h> #define ARATIO 425/(PI/4) #define AZERO 1595 //#define AZERO 2020 #define BZERO 1585 #define D 200. Servo servoA, servoB; // create servo object to control a servo int v = 0; int sign = 1; float x = 0.; float y = 0.; float x_temp; float y_temp; void setup() { servoA.attach(9); servoB.attach(10); // attaches the servo on pin 9 to the servo object move('a',0); move('b',0); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: if ( Serial.available()) { char ch = Serial.read(); switch(ch) { case '0'...'9': //Pretty goddamn clever right here. Not mine. v = v * 10 + ch - '0'; break; case '-': //Pretty goddamn clever right here. This time ours. sign *= -1; break; case 'a': move('a',v*sign); resetV(); break; case 'b': move('b',v*sign); resetV(); break; case 'x': x_temp = float(v*sign); moveLineXY(x_temp ,y,100); x = x_temp; resetV(); break; case 'y': y_temp = float(v*sign); moveLineXY(x ,y_temp,100); y = y_temp; resetV(); break; default: Serial.write("...the fuck is that?"); resetV(); break; } } } void resetV() { sign = 1; v = 0; } void move(char ch, float angle) { switch(ch) { case 'a': servoA.writeMicroseconds(floor(angle*ARATIO) + AZERO); break; case 'b': servoB.writeMicroseconds(floor(angle*ARATIO) + BZERO); break; } } void moveLineXY(float end_x, float end_y, int n_steps) { float start_x = x; float start_y = y; float delta_x = (end_x - start_x)/n_steps; float delta_y = (end_y - start_y)/n_steps; for (int i = 0; i < n_steps; i++) { moveXY(start_x + (delta_x * i), start_y + (delta_y * i)); delay(10); } } void moveXY(float x, float y) { Serial.println(x); Serial.println(y); float r = getNorm(x,y,D); float vx = x/r; float vy = y/r; float vz = D/r; float nx = vx; float ny = vy - 1; float nz = vz; float nnorm = getNorm(nx,ny,nz); nx = nx/nnorm; ny = ny/nnorm; nz = nz/nnorm; float alpha = asin(nz); //float phi = atan2(y,x); float beta = atan2(nx,-ny); /* if (phi > PI/2) { phi = phi - PI; theta = theta * -1; } else if (phi < -PI/2) { phi = phi + PI; theta = theta * -1; } */ Serial.println(alpha); Serial.println(beta); move('a',alpha); move('b',-beta); } float getNorm(float x, float y, float z) { return sqrt(sq(x) + sq(y) + sq(z)); } |