给狗子和猫咪的福利:激光逗狗/逗猫玩具-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 18470|回复: 12

[项目] 给狗子和猫咪的福利:激光逗狗/逗猫玩具

[复制链接]
发表于 2019-4-29 16:55 | 显示全部楼层 |阅读模式
Honeyview_IMG_7923.png

以前是直接拿一个激光笔和狗子玩的,后来感觉挺累的,所以做了个这个,放在高处,只需要按一下,就能让狗嗨几分钟,太省心了……


因为是要放在高的地方,所以里面用了一个18650电池。用一个充电管理的模块,给电池充电,同时供电给Arduino Nano。背面是开关,和一个充电口。


Honeyview_IMG_7919.png


红外遥控的,以免狗子发现是我在弄。。。在远处哪怕隔着玻璃都能开起来玩。这个外壳原来是白色的,用手喷漆喷成了黑色。


Honeyview_IMG_7925.png


打开看看,没有意外的很乱,线也接的很随缘。推荐按照:VCC=红,GND=黑,IO=黄 这样接线的话,以后坏了也方便查找问题。


Honeyview_IMG_7920.png


舵机可能是价格太便宜了还是怎么,空载的时候会抖。所以随缘给它加了一个104电容(手边只有这个了),就不抖了。。。


然后重点是那颗电解,没有它的话,舵机一启动,一下会拉低很多电压,单片机就复位。有了它,就没问题了。用的是 3300μF 的(手边只有这个了)。


Honeyview_IMG_7921.png


感觉自带了点忧郁的气质。


Honeyview_IMG_7922.png


合影来一张。遥控器的方向键可以设置横向、纵向的范围,也就是狗子嗨的幅度,数字1-9是设置运行的时长的。

OK 是开始嗨。嗨到设置的时长为止。不然狗容易累到打人。


Honeyview_IMG_7926.png
游客,如果您要查看本帖隐藏内容请回复

视频在此:
注:因为狗嗨的太智障所以只有机器的运行视频因此并没有狗出镜。




 楼主| 发表于 2019-4-29 23:17 | 显示全部楼层
源码在此:
[mw_shl_code=arduino,true]#include <Servo.h>
#include <IRremote.h>
#include "TM1637.h"

#define pinIR 2
#define pinIndicatorLed 3
#define pinLaser 4
#define pinServoH 7
#define pinServoV 8
#define picLcdCLK 9
#define pinLcdDIO 10

Servo servoH;
Servo servoV;

IRrecv irrecv(pinIR);
decode_results results;

TM1637 tm1637(picLcdCLK, pinLcdDIO);

unsigned int rangeH = 25;
unsigned int rangeH_pre;
unsigned int rangeV = 20;
unsigned int rangeV_pre;
unsigned int rangeT = 60;
unsigned int rangeT_pre;
unsigned int limitH = 75;
unsigned int limitV = 35;
unsigned int midH = 80;
unsigned int midV = 40;
unsigned int heartBeat = 5;
bool preButton ;
bool playing = false;
unsigned long lastDisplay = 0;
unsigned long lastButtonChange = 0;
unsigned long gameStartTime = 0;
unsigned int buttonWaitDelay = 2000;
unsigned long lastCheckTime = 0;
bool displayCleared = false;
unsigned int tmp_second;
int gameTimeRemain = 0;
bool timerPoint = false;


void setup() {
  pinMode(pinLaser, OUTPUT);
  pinMode(pinIndicatorLed, OUTPUT);
  digitalWrite(pinLaser, HIGH);
  randomSeed(analogRead(0));
  irrecv.enableIRIn();

  // welcome
  tm1637.init();
  tm1637.set(BRIGHT_TYPICAL);
  hi();

  // debug
  // Serial.begin(9600);
}

void hi() {
  tm1637.display(3, 0);
  delay(400);
  tm1637.display(2, 0);
  tm1637.display(3, 0);
  delay(400);
  tm1637.point(1);
  tm1637.display(1, 0);
  tm1637.display(2, 0);
  tm1637.display(3, 0);
  delay(400);
  tm1637.display(0, 0);
  tm1637.display(1, 0);
  tm1637.display(2, 0);
  tm1637.display(3, 0);
  delay(400);
  tm1637.clearDisplay();
  delay(200);
  tm1637.point(1);
  tm1637.display(0, 0);
  tm1637.display(1, 0);
  tm1637.display(2, 0);
  tm1637.display(3, 0);
  delay(200);
  tm1637.clearDisplay();
  delay(200);
  tm1637.point(1);
  tm1637.display(0, 0);
  tm1637.display(1, 0);
  tm1637.display(2, 0);
  tm1637.display(3, 0);
  delay(1000);
  servoH.attach(pinServoH);
  servoV.attach(pinServoV);
  servoMigrateOne(servoH, 90, 15);
  servoMigrateOne(servoV, 10, 15);
  servoH.detach();
  servoV.detach();
}

void servoMigrateOne(Servo &myServo, int newPos, int wait) {
  int pos = myServo.read();
  if (pos < newPos) {
    for (int i = pos; i < newPos; i++) {
      myServo.write(i);
      delay2(wait);
    }
  } else {
    for (int i = pos; i > newPos; i--) {
      myServo.write(i);
      delay2(wait);
    }
  }
  flashOnboardLed();
}

void servoMigrateHV(int h, int v, int wait) {
  int posH = servoH.read();
  int posV = servoV.read();
  int maxSteps = max(abs(h - posH), abs(v - posV));

  for (int i = 0; i <= maxSteps; i++) {
    if (posH < h) {
      servoH.write(posH + i * (h - posH) / maxSteps);
      delay2(wait);
    } else {
      servoH.write(posH - i * (posH - h) / maxSteps);
      delay2(wait);
    }
    if (posV < v) {
      servoV.write(posV + i * (v - posV) / maxSteps);
      delay2(wait);
    } else {
      servoV.write(posV - i * (posV - v) / maxSteps);
      delay2(wait);
    }
  }
  flashOnboardLed();
}

void flashLaser() {
  digitalWrite(pinLaser, HIGH);
  delay2(1000);
  for (int i = 0; i <= 10; i++) {
    digitalWrite(pinLaser, LOW);
    delay2(25);
    digitalWrite(pinLaser, HIGH);
    delay2(50);
  }
  digitalWrite(pinLaser, LOW);
}

void loop() {
  if (irrecv.decode(&results))  {
    // Serial.println(results.value, HEX);
    switch (results.value) {
      case 0xFF38C7:
        // ok
        if (playing) {
          pauseGame();
        } else {
          delay(1000);
          servoH.attach(pinServoH);
          servoV.attach(pinServoV);
          playing = true;
          gameStartTime = millis();
          digitalWrite(pinLaser, LOW);
        }
        break;
      case 0xFFA25D:
        // 1
        rangeT = 10;
        break;
      case 0xFF629D :
        // 2
        rangeT = 20;
        break;
      case 0xFFE21D :
        // 3
        rangeT = 30;
        break;
      case 0xFF22DD :
        // 4
        rangeT = 40;
        break;
      case 0xFF02FD :
        // 5
        rangeT = 50;
        break;
      case 0xFFC23D :
        // 6
        rangeT = 60;
        break;
      case 0xFFE01F :
        // 7
        rangeT = 70;
        break;
      case 0xFFA857 :
        // 8
        rangeT = 80;
        break;
      case 0xFF906F :
        // 9
        rangeT = 90;
        break;

      case 0xFF18E7 :
        //up
        if (rangeV + 5 <= limitV) {
          rangeV += 5;
        }
        break;
      case 0xFF10EF :
        //left
        if (rangeH   >= 5) {
          rangeH -= 5;
        }
        break;
      case 0xFF5AA5 :
        //right
        if (rangeH + 5 <= limitH) {
          rangeH += 5;
        }
        break;
      case 0xFF4AB5 :
        //down
        if (rangeV  >= 5) {
          rangeV -= 5;
        }
        break;

    }
    irrecv.resume(); // Receive the next value
  }

  // check range
  if (rangeH != rangeH_pre) {
    rangeH_pre = rangeH;
    // display new H value
    tm1637.point(1);
    tm1637.display(0, 21);
    tm1637.display(1, 16);
    tm1637.display(2, rangeH / 10);
    tm1637.display(3, rangeH % 10);
    lastDisplay = millis();
    displayCleared = false;
  }
  if (rangeV != rangeV_pre) {
    rangeV_pre = rangeV;
    tm1637.point(1);
    tm1637.display(0, 21);
    tm1637.display(1, 18);
    tm1637.display(2, rangeV / 10);
    tm1637.display(3, rangeV % 10);
    lastDisplay = millis();
    displayCleared = false;
  }

  if (rangeT != rangeT_pre) {
    rangeT_pre = rangeT;
    // display new T value
    tm1637.point(1);
    tm1637.display(0, 20);
    tm1637.display(1, rangeT / 60);
    tmp_second = rangeT - 60 * (rangeT / 60);
    tm1637.display(2, tmp_second / 10);
    tm1637.display(3, tmp_second % 10);
    lastDisplay = millis();
    displayCleared = false;
  }

  // clear display
  if (millis() - lastDisplay > 2000 && !displayCleared) {
    //tm1637.point(0);
    //tm1637.clearDisplay();
    displayCleared = true;
  }

  if (playing) {
    playGame();
    tasks();
    if (gameTimeRemain <= 0) {
      // stop game
      pauseGame();
    }
  }
}

void playGame() {
  servoMigrateHV(random(midH - rangeH, midH + rangeH), random(midV - rangeV, midV + rangeV), random(10, 30));
  if (random(15) <= 1) {
    flashLaser();
  }
}

void pauseGame() {
  // debug
  digitalWrite(pinLaser, HIGH);
  // Serial.println("sleep");
  delay(1000);
  servoMigrateOne(servoH,90,15);
  servoMigrateOne(servoV,30,15);
  delay(1000);
  servoH.detach();
  servoV.detach();
  playing = false;
  tm1637.point(1);
  tm1637.display(0, 0);
  tm1637.display(1, 0);
  tm1637.display(2, 0);
  tm1637.display(3, 0);
}

void flashOnboardLed() {
  digitalWrite(pinIndicatorLed, HIGH);
  delay(15);
  digitalWrite(pinIndicatorLed, LOW);
}

void displayTimer() {
  gameTimeRemain = (rangeT_pre - (millis() - gameStartTime) / 1000) ;
  if (gameTimeRemain < 0) {
    gameTimeRemain = 0;
  }
  if (!displayCleared) {
    return;
  }
  timerPoint = !timerPoint;
  tm1637.point(timerPoint);
  tm1637.display(0, 21);
  tm1637.display(1, gameTimeRemain / 60);
  tmp_second = gameTimeRemain - 60 * (gameTimeRemain / 60);
  tm1637.display(2, tmp_second / 10);
  tm1637.display(3, tmp_second % 10);
}
void tasks() {
  if (millis() - lastCheckTime >= 500) {
    lastCheckTime = millis();
    displayTimer();
  }
}

void delay2(int delayMs) {
  int loops = delayMs / heartBeat;
  for (int i = 0; i <= loops; i++) {
    tasks();
    delay(heartBeat);
  }
}

[/mw_shl_code]
发表于 2019-4-30 09:47 | 显示全部楼层
厉害厉害,膜拜大佬
发表于 2019-4-30 13:06 | 显示全部楼层
社区有在送舵机的活动,了解下:https://www.arduino.cn/thread-85565-1-1.html
发表于 2019-4-30 17:49 | 显示全部楼层
看楼主头像,想必是给自家二哈准备的吧
 楼主| 发表于 2019-5-5 12:06 | 显示全部楼层
syl312 发表于 2019-4-30 13:06
社区有在送舵机的活动,了解下:https://www.arduino.cn/thread-85565-1-1.html

多谢提醒~ 很早就在群里看到这个活动了,一时还没啥想法哈哈……
 楼主| 发表于 2019-5-5 12:06 | 显示全部楼层
jpolo 发表于 2019-4-30 17:49
看楼主头像,想必是给自家二哈准备的吧

自家是只智障拉布拉多 感觉闹起来跟二哈没区别。。
发表于 2019-8-6 20:37 | 显示全部楼层
厉害厉害,顶!!!!
发表于 2019-8-7 23:22 | 显示全部楼层
神乎其神,不得不服!
发表于 2019-8-8 23:11 | 显示全部楼层
想看智障狗子
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-1 01:19 , Processed in 0.098760 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表