Created
January 18, 2021 16:26
-
-
Save jes/e3cbc0e10c0b1041d073bbe7531c7ac4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Cat Laser */ | |
#include <Servo.h> | |
// pin configuration | |
const int xservopin = 2; | |
const int yservopin = 3; | |
const int speedpin = A0; | |
const int dwellpin = A1; | |
const int xrangepin = A2; | |
const int yrangepin = A3; | |
// parameter configuration | |
const float minspeed = 100.0; // servo usecs/sec (1000 usecs == 180 degrees) | |
const float maxspeed = 1200.0; // servo usecs/sec | |
const unsigned long mindwell = 100; // millisecs | |
const unsigned long maxdwell = 3000; // millisecs | |
const float xmin = 800, xmax = 1800; // servo usecs | |
const float ymin = 1000, ymax = 1800; // servo usecs | |
const float xmid = (xmin+xmax)/2; | |
const float ymid = (ymin+ymax)/2; | |
const float epsilon = 0.1; // for floating point comparison | |
float xpos = xmin; | |
float ypos = ymin; | |
float xtarget = xpos; | |
float ytarget = ypos; | |
bool dwelling = false; | |
unsigned long dwell_start; | |
Servo xservo, yservo; | |
void setup() { | |
xservo.attach(xservopin); | |
yservo.attach(yservopin); | |
Serial.begin(9600); | |
} | |
void new_target(int xrange, int yrange) { | |
xtarget = random(xmid-xrange/2, xmid+xrange/2); | |
ytarget = random(ymid-yrange/2, ymid+yrange/2); | |
Serial.print("Target: "); Serial.print(xtarget); Serial.print(","); Serial.println(ytarget); | |
dwelling = false; | |
} | |
void loop() { | |
static unsigned long last_tick = 0; | |
float speed = map(analogRead(speedpin), 0, 1023, minspeed, maxspeed); | |
unsigned long dwell_ms = map(analogRead(dwellpin), 0, 1023, mindwell, maxdwell); | |
int xrange = map(analogRead(xrangepin), 0, 1023, 0, xmax-xmin); | |
int yrange = map(analogRead(yrangepin), 0, 1023, 0, ymax-ymin); | |
// if the range has been updated such that we're now outside it, or | |
// we were dwelling and the dwell time is now over, pick a new target | |
if ( xpos > (xmid+xrange/2) || xpos < (xmid-xrange/2) | |
|| ypos > (ymid+yrange/2) || ypos < (ymid-yrange/2) | |
|| (dwelling && millis() > dwell_start+dwell_ms)) { | |
new_target(xrange, yrange); | |
} | |
// if we're not dwelling, but we should be, start dwelling | |
if (!dwelling && abs(xtarget-xpos) < epsilon && abs(ytarget-ypos) < epsilon) { | |
Serial.println("Dwelling..."); | |
dwell_start = millis(); | |
dwelling = true; | |
} else if (!dwelling && last_tick != 0) { | |
// if we're not dwelling and we know how long ago the last tick was, move the servos | |
unsigned long elapsed_ms = millis() - last_tick; | |
float stepdist = (elapsed_ms * speed / 1000); | |
float dx = xtarget-xpos; | |
float dy = ytarget-ypos; | |
float hypotenuse = sqrt(dx*dx + dy*dy); | |
if (stepdist > hypotenuse) // don't overshoot | |
stepdist = hypotenuse; | |
dx = dx * (stepdist / hypotenuse); | |
dy = dy * (stepdist / hypotenuse); | |
xpos += dx; | |
ypos += dy; | |
xservo.writeMicroseconds(xpos); | |
yservo.writeMicroseconds(ypos); | |
} | |
last_tick = millis(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment