Erica
Published © GPL3+

IoT Cat Toys using Arduino

A paired set of two cat toys for long distance friends and their felines. When one cat plays with their toy - the other toy starts to move!

IntermediateFull instructions provided8 hours268
IoT Cat Toys using Arduino

Things used in this project

Hardware components

Adafruit Feather HUZZAH with ESP8266 WiFi
Adafruit Feather HUZZAH with ESP8266 WiFi
×2
Adafruit Micro servo (TowerPro SG92R)
Arduino IDE
×2
Adafruit Fast vibration sensor switch (Easy to trigger)
×2
Micro-USB to USB Cable (Generic)
Micro-USB to USB Cable (Generic)
×2
USB wall adapter
×1
5 mm LED: Green
5 mm LED: Green
×2
5 mm LED: Yellow
5 mm LED: Yellow
×2
Resistor 100 ohm
Resistor 100 ohm
×4
Wall wand attachment
×2
18 gauge steel wire
×1
Basswood (1/4 in)
×1
Hot glue, super glue, and wood glue
×1

Software apps and online services

Arduino IDE
Arduino IDE
https://io.adafruit.com/

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Laser cutter (generic)
Laser cutter (generic)

Story

Read more

Custom parts and enclosures

Laser cut template

Schematics

Circuit Diagrams

Code

Cat-to-cat code per toy

C/C++
// Combining Inputs and Outputs for paired cat toys
// Flick (vibration sensor) switch sends command to AIO feed
// LED and vibrating motor flash/buzz according to feed data
//
// Modified from Becky Stern's code by Erica Fink 2023
// based on examples from Adafruit IO Arduino Library:
// https://github.com/adafruit/Adafruit_IO_Arduino
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Written by Todd Treece for Adafruit Industries
// Copyright (c) 2016 Adafruit Industries
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.


/************************ Adafruit IO Configuration *******************************/

// update with your io.adafruit.com information
#define IO_USERNAME    "enter your user name here"
#define IO_KEY         "enter your key here"

/******************************* WIFI Configuration **************************************/

// update with your wifi information
#define WIFI_SSID       "enter your wifi name here"
#define WIFI_PASS       "enter your wifi password here"

#include "AdafruitIO_WiFi.h"
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);

/************************ Main Code Starts Here *******************************/

#include <ESP8266WiFi.h>
#include <AdafruitIO.h>
#include <Adafruit_MQTT.h>
#include <ArduinoHttpClient.h>
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

#define ToyLEDsentIndicator_PIN 13
#define ToyLEDreceivedInidicator_PIN 12
#define ToyFLICKswitch_PIN 4 // this pin needs pullup capability

// Define some items that will be used to set your FLICK switch into a sleeper mode
unsigned long previousMillis = 0;  // this will store last time FLICKswitch was set “on”/activated

// This constant won’t change. 
// Set the interval to the time you want the toy to "sleep" in between plays (so that the motor is not constantly setting the other toy off)
// The toy will sleep on reading the FLICKswitch. It is set to sleep for 20 minutes (milliseconds*seconds*minutes)
const long interval = 1000*60*20;

// set up the 'digital' feed
// create your own feed on io.adafruit.com and use the name for "toyforcats" here and throughout below
AdafruitIO_Feed *toyforcatsfeed = io.feed("toyforcatsfeed");

void setup() {

  myservo.attach(5);  // this is the pin number on your board that the servo is connected to

 // set FLICK switch pins as inputs with internal pull-up resistor
 pinMode(ToyFLICKswitch_PIN, INPUT_PULLUP);

 // set LED pins and motor pin as a digital outputs
 pinMode(ToyLEDsentIndicator_PIN, OUTPUT);
 pinMode(ToyLEDreceivedInidicator_PIN, OUTPUT);

 //pinMode(ToyMOTOR_PIN, OUTPUT);

 // start the serial connection
 Serial.begin(115200);

 // connect to io.adafruit.com
 Serial.print("Connecting to Adafruit IO");
 io.connect();
  // set up a message handler for the 'toyforcatsfeed' feed.
 // the handleMessage function (defined below)
 // will be called whenever a message is
 // received from adafruit io.
toyforcatsfeed->onMessage(handleMessage);

 // wait for a connection
 while(io.status() < AIO_CONNECTED) {
   Serial.print(".");
   delay(500);
 }

 // we are connected
 Serial.println();
 Serial.println(io.statusText());

}

void loop() {

 // io.run(); is required for all sketches.
 // it should always be present at the top of your loop
 // function. it keeps the client connected to
 // io.adafruit.com, and processes any incoming data.
 io.run();

 //code that needs to be running all the time.
 // check to see if it's time to read the FLICKswitch; that is, if the difference
 // between the current time and last time you activated the FLICKswitch is bigger than
 // the interval at which you want to activate the FLICKswitch.
 unsigned long currentMillis = millis();

 if (currentMillis - previousMillis <= interval) {
   // If it is still less than the interval (20 minutes), then return back to this mini loop (doing nothing) until it has been greater than the interval (20 minutes).
   return;
 }

 // grab the current state of the FLICK switch.
 // we have to flip the logic because we are
 // using INPUT_PULLUP
 if(digitalRead(ToyFLICKswitch_PIN) == LOW) {
  // save the flick activation state to the 'digital' toyforcatsfeed feed on adafruit io
 Serial.print("sending FLICK switch -> ");
 //switch 1 for 2 on opposite toy chip
 Serial.println(2);
 toyforcatsfeed->save(2);

 digitalWrite(ToyLEDsentIndicator_PIN, HIGH);
 delay(1000);
 digitalWrite(ToyLEDsentIndicator_PIN, LOW);

//Reset the sleeper timer so that it has to reach 20 minutes before it reads for a FLICK switch activation again.
 previousMillis = currentMillis;
   }

}

// this function is called upon whenever a 'toyforcatsfeed' message
// is received from Adafruit IO. it was attached to
// the toyforcatsfeed feed in the setup() function above.
void handleMessage(AdafruitIO_Data *data) {

 int toyforcatsfeed = data->toInt();

//switch 2 for 1 on opposite toy chip
 if (toyforcatsfeed == 1){ //light up the "received" LED and move the motor sequentially
   Serial.print("received <- ");
   Serial.println(toyforcatsfeed);
     digitalWrite(ToyLEDreceivedInidicator_PIN, HIGH);
     delay(1000);
     digitalWrite(ToyLEDreceivedInidicator_PIN, LOW);

//move the motor back and forth 3 times
   Serial.print("received <- ");
   Serial.println(toyforcatsfeed);
    myservo.write(50);  // tell servo to go to position in variable 'pos'
    delay(500);
    myservo.write(0);  // tell servo to go to position in variable 'pos'
    delay(500);
    myservo.write(50);  // tell servo to go to position in variable 'pos'
  delay(500);

 } else {
   Serial.print("unexpected value <- ");
   Serial.println(toyforcatsfeed);
 }
}

Credits

Erica

Erica

1 project • 0 followers
Thanks to Becky Stern.

Comments