From 2cb03e64d015ca94bc3d45cff5052b23ab90b4e7 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 22 Oct 2021 00:06:51 +0300 Subject: [PATCH] Initial commit --- README.md | 34 +++++++++++++++ cat_ball.ino | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 README.md create mode 100644 cat_ball.ino diff --git a/README.md b/README.md new file mode 100644 index 0000000..e1f3fcc --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Cat Ball + +The code I wrote to make a cat toy that will come to life when touched or +can be controlled remotely via Wi-Fi. + +I found that my cat loses interest in a toy as soon as he sees it not +reacting to him catching it. + +The idea is that a relatively strong motor with some mass attached to it's +axis off center is glued to a spherical housing along with all the needed +electronics. The violent vibration made by turning that motor on when +something touches the ball makes this an interesting toy for a cat. + + +### Components: +- NodeMCU +- SW-18010P vibration sensor +- DC motor +- MX1508 DC motor driver (depends on what motor you'll use) +- battery + +## Assembly +I glued the biggest coin (a nut would be fine too) I could find off axis to +the motor and hooked the motor to the nodeMCU through the motor driver (pin 1). +And the vibration sensor to pin 3. The same battery powers both the motor and +the nodeMCU. + +Flash the .ino and now you can connect to the toy via Wi-Fi. + +``` +SSID: Cat Ball +KEY: churchill +``` +Navigate to `192.168.4.1` when connected. diff --git a/cat_ball.ino b/cat_ball.ino new file mode 100644 index 0000000..302c7bd --- /dev/null +++ b/cat_ball.ino @@ -0,0 +1,120 @@ +#include +#include +#include + +#ifndef APSSID +#define APSSID "Cat Ball" +#define APPSK "churchill" +#endif + +const char *ssid = APSSID; +const char *password = APPSK; + +ESP8266WebServer server(80); + +const int ledPin = 2; +const int motorPin = 1; +const int sensorPin = 3; +bool motorStatus = true; +bool manualControl = false; + +const int onTime = 1000*2; +const int offTime = 1000*60; +const int liveTime = 1000*60*5; +unsigned long ticker = millis(); +unsigned long touchedAt = millis() - liveTime; + +String createHtml() { + String res = "\n"; + res += "\n"; + res += "Cat Ball\n"; + res += "\n"; + res += "\n"; + res += "\n"; + res += "

Cat Ball

\n"; + + if (manualControl) { + res += "Disable manual mode\n"; + res += "Turn motor on\n"; + res += "Turn motor off\n"; + } else { + res += "Enable manual mode\n"; + } + + res += "\n"; + res += "\n"; + + return res; +} + +void handleRoot() { + server.send(200, "text/html", createHtml()); +} + +void manual() { + manualControl = !manualControl; + motorStatus = false; + server.send(200, "text/html", createHtml()); +} + +void motorOn() { + motorStatus = true; + server.send(200, "text/html", createHtml()); +} + +void motorOff() { + motorStatus = false; + server.send(200, "text/html", createHtml()); +} + +void setup() { + pinMode(ledPin, OUTPUT); + pinMode(motorPin, OUTPUT); + pinMode(sensorPin, INPUT); + WiFi.softAP(ssid, password); + server.on("/", handleRoot); + server.on("/manual", manual); + server.on("/motoron", motorOn); + server.on("/motoroff", motorOff); + server.begin(); +} + +void loop() { + server.handleClient(); + if (manualControl) { + digitalWrite(motorPin, motorStatus); + } else { + if (millis()-touchedAt < liveTime) { // If touched less than 5 minutes ago then act alive + if (motorStatus) { + if (millis()-ticker > onTime) { + ticker = millis(); + motorStatus = false; + digitalWrite(motorPin, false); + } + } else { + if (millis()-ticker > offTime) { + ticker = millis(); + motorStatus = true; + digitalWrite(motorPin, motorStatus); + } + } + } else { + motorStatus = false; + digitalWrite(motorPin, false); + digitalWrite(ledPin, true); + + if (digitalRead(sensorPin)) { + touchedAt = millis(); + digitalWrite(ledPin, false); + } + } + } +}