📜 ⬆️ ⬇️

DDA for cat

We have in our family a cat named Kisa. Young and also cowardly and curious at the same time. The only thing that completely discourages all her cowardice is the red laser spot from the Bosch rangefinder. She is ready to hunt him recklessly. But. The range finder has a time limit, you can’t save enough on it, and you can’t lose time on long games with a cat.

I found all kinds of automatic cat teasers on the Internet - it's expensive, and the functionality is limited. Again, there is no guarantee that the ray will not fall on the curtains, and they will not be smashed.


')
Or are we not electronic engineers-arduinschiki ?! And most to collect?

First, I took the iron: Arduino Nano , a couple of simple servos (you can buy a set with Arduino in Master Kit) and a red semiconductor laser from a stray pointer with a speck aperture. At the moment, LUT made a handkerchief so that the serfs were sticking, well, and the key on the transistor for the laser, so that the Arduyn pin would not be overloaded.

Schematic diagram of the device:



Pay:




In the Arduino Nano, the usual USB-mini is plugged from any power supply for 5 V. Well, or into the computer to fill the sketch.

The design wanted to make, of course, as easy as possible to manufacture. Helped a 3D printer. Here is truly a wand for home craftsmen! I really liked to print small parts instead of cutting them with a file. In an hour MC5 DROVA printed four pieces for a two-axis pivoting device. The process of printing itself is so fascinating that this hour has flown by completely unnoticed!





Assembled rotary device together with the board fasten on trimming painted plywood. This farm and will program.





Here is the most interesting. It is necessary to interest Koshatin with non-standard motion of a speck, so that she does not lose interest, and to protect wallpaper and curtains from claws.

Experimentally, after a number of experiments, the following principles of movement of the object of hunting were chosen:

- laser movement does not happen all the time, but with random stops with the speck off, while the animal looks around nervously in search of it;
- the trajectory of movement varies from session to session, again randomly;
- the range of motion also varies within a given trajectory;
- after moving to the end of the trajectory, the point freezes, so that the beast can trample it in an attempt to grab;
- the stain should not fall on the walls and curtains, only on the floor!

Having indulged with the simplest movements of the line and square type from point to point by alternating movements of servos, I wanted to realize more complex trajectories. After a brief googling, I stopped at the good old algorithm of the DDA-line, rasterizing the straight line between two points. That is, we set the function of the trajectory, we set the abscissa, we calculate the ordinate, and move the laser in small successive steps in two coordinates to a new point. Trajectories made what came to my head: fan, sine wave, sector, square, etc. You can draw more complex functions if you want to.

Under the spoiler, the full text of the currently working sketch:

Sketch
#include <Servo.h> // servos library
#include <Metro.h> // timer library
#define laser 7 // laser is on this pin
#define led 13 // built-in LED in Arduino

// experimentally choose a safe spot moving zone
int minv = 85; //ten; // extreme lower position of the spot
int maxv = 115; // 55; // uppermost
int minh = 90; // 45; // far left, look in front
int maxh = 145; // 120; // far right, look in front

unsigned long DelayBetweenMovements = 1000; // delay in ms
unsigned long second = 1000; // one second = 1000 ms

Servo myservo_ver; // move vertically
Servo myservo_hor; // move horizontally

void setup ()
{
pinMode (laser, OUTPUT);
pinMode (led, OUTPUT);
digitalWrite (led, HIGH);
ServoOn ();
myservo_hor.write ((maxh + minh) / 2); // set the laser
myservo_ver.write ((maxv + minv) / 2); // in the middle position
delay (2000); // and watch for a couple of seconds

}

// - Main ----------------------------------------------
void loop ()
{
randomSeed (analogRead (0)); // initialize random with random value from port 0
int g = random (1.7); // randomly choose one of the seven trajectories
randomSeed (analogRead (0));
int tg = random (1,3); // randomly select the session duration 30, 60 or 90 seconds
DelayBetweenMovements = second * random (1,5) / 2; // choose randomly the time of moving between points of the trajectory
switch (g) {
case 1: GameRandom (tg * 30 * second); break;
case 2: GameFan (tg * 30 * second); break;
case 3: GameFan1 (tg * 30 * second); break;
case 4: GameFan2 (tg * 30 * second); break;
case 5: GameCorners (tg * 30 * second); break;
case 6: GameSinHor (tg * 30 * second); break;
case 7: GameSinVer (tg * 30 * second); break;
}
delay (random (10.60) * second);

}

// - End Main -----------------------------------------

// vertical sine wave with random amplitude
void GameSinVer (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
servo_move ((maxh + minh) / 2, minv, 10);
while (! game_time.check ()) {
randomSeed (analogRead (0));
int i = minv;
int j = random (1,5);
for (i; i <maxv + 1; i = i + j) {
servo_move ((maxh + minh) / 2 + (maxh / (j + 1)) * sin (i), i, 10);
delay (DelayBetweenMovements);
}
// digitalWrite (laser, random (2));
}
ServoOff ();
}

// horizontal sine wave with random amplitude
void GameSinHor (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
servo_move ((maxv + minv) / 2, minh, 10);
while (! game_time.check ()) {
randomSeed (analogRead (0));
int i = minh;
int j = random (1,5);
for (i; i <maxh + 1; i = i + j) {
servo_move (i, (maxv + minv) / 2 + (maxv / (j + 1)) * sin (i), 10);
delay (DelayBetweenMovements);
}
// digitalWrite (laser, random (2));
}
ServoOff ();
}

// square with a random size
void GameCorners (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
servo_move ((maxh + minh) / 2, minv, 10);
randomSeed (analogRead (0));
int c = random (1,4);
while (! game_time.check ()) {
int i = random (1,5);
switch (i) {
case 1:
servo_move (minh, (minv + 1), random (1,4) * 10); break;
case 2:
servo_move (minh, (maxv + 1), random (1,4) * 10); break;
case 3:
servo_move (maxh, (maxv + 1), random (1,4) * 10); break;
case 4:
servo_move (maxh, (minv + 1), random (1,4) * 10); break;
}
delay (DelayBetweenMovements);
// digitalWrite (laser, random (2));
}
ServoOff ();
}

// fan motion with a random scale
void GameFan (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
servo_move ((maxh + minh) / 2, minv, 10);
while (! game_time.check ()) {
randomSeed (analogRead (0));
servo_move (random (minh, maxh + 1), maxv, random (1,4) * 10);
delay (DelayBetweenMovements);
servo_move ((maxh + minh) / 2, minv, random (1,4) * 10);
delay (DelayBetweenMovements);
// digitalWrite (laser, random (2));
}
ServoOff ();
}

// fan movements
void GameFan1 (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
servo_move ((maxh + minh) / 2, maxv, 10);
while (! game_time.check ()) {
randomSeed (analogRead (0));
servo_move (random (minh, maxh + 1), minv, random (1,4) * 10);
delay (DelayBetweenMovements);
servo_move ((maxh + minh) / 2, maxv, random (1,4) * 10);
delay (DelayBetweenMovements);
// digitalWrite (laser, random (2));
}
ServoOff ();
}

// fan movements
void GameFan2 (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
servo_move ((maxh + minh) / 2, (maxv + minv) / 2,10);
while (! game_time.check ()) {
randomSeed (analogRead (0));
servo_move (random (minh, maxh + 1), random (minv, maxv + 1), random (1,4) * 10);
delay (DelayBetweenMovements);
servo_move ((maxh + minh) / 2, (maxv + minv) / 2, random (1,4) * 10);
delay (DelayBetweenMovements);
// digitalWrite (laser, random (2));
}
ServoOff ();
}

// random moves in all directions
void GameRandom (unsigned long GameTime) {
Metro game_time = Metro (GameTime);
ServoOn ();
while (! game_time.check ()) {
randomSeed (analogRead (0));
servo_move (random (minh, maxh + 1), random (minv, maxv + 1), random (1,4) * 10);
delay (DelayBetweenMovements);
// digitalWrite (laser, random (2));
}
ServoOff ();
}

void ServoOn (void) {// activate serfs and turn on laser
myservo_ver.attach (9); // servo vertically connect on digital pin 9
myservo_hor.attach (8); // servo horizontally connect on digital pin 8
digitalWrite (laser, 1); // turn on the laser
}

void ServoOff (void) {// disable serfs and laser - rest
myservo_ver.detach ();
myservo_hor.detach ();
digitalWrite (laser, 0);
}

// move from the current point x1, y1 to point x2, y2 with delays between the steps delay_ms
void servo_move (double x2, double y2, int delay_ms)
{
double x1 = myservo_hor.read (); // read the current position of the serv
double y1 = myservo_ver.read ();

int iX1 = round (x1); // round coordinates
int iY1 = round (y1);
int iX2 = round (x2);
int iY2 = round (y2);

// Length and height of line
int deltaX = abs (iX1 - iX2);
int deltaY = abs (iY1 - iY2);

// Count the minimum number of iterations required
// to draw the segment. Choosing a maximum of length and height
// lines, provide line connectivity
int length = max (deltaX, deltaY);
if (length == 0) return;

// Calculate the increments at each step along the abscissa and ordinate axes
double dX = (x2 - x1) / length;
double dY = (y2 - y1) / length;

// Initial Values
double x = x1;
double y = y1;

// Main loop
length ++;
while (length--)
{
x + = dX;
y + = dY;
myservo_hor.write (x);
myservo_ver.write (y);
delay (delay_ms);

}
}



Practice.

The first laser failed after a week - the conclusions broke off, even though they were made from a multicore wire. The second formed the findings of a spiral. It helped. You can still glue drip from the glue gun to the place where the pins come out of the case.

Not all power adapters are suitable. From some Arduino does not start or the laser is twitching. Apparently, large ripple output. The condenser was too lazy to solder, just picked up a good adapter, the benefit of them lay around.
Tested on several cats. Young long rush. Older - run, and then lie and look, as the stain shies away, or at the very machine they stare, as it buzzes and moves. Paw machine did not try. But, just in case, I came up with a casing out of the paper box.



With the experiences of wallpaper, curtains and cats were not affected.

In general, I recommend such a thing to all electronic cat owners!

Source: https://habr.com/ru/post/259343/


All Articles