1 / 1
Deaf dog gentle training device — zdjęcie 1

Deaf dog gentle training device

Zamów wydruk tego modelu

Obliczymy ostateczną cenę na podstawie wybranego pliku. Sprawdzisz ją i zaakceptujesz przed płatnością.

Zapisane na tym urządzeniu.

Gentle way to alert a deaf dog when they can’t hear you call them.

Ocena
0 / 5
Polubienia
7
Pobrania
5
Wydruki
0
Wyświetlenia
126
Oceny
0

Aktualizacja u źródła:

Informacje o modelu

Źródło
Printables
Kategoria
Pets
Licencja
Creative Commons — Attribution — Noncommercial

We foster small dogs that need to be rehomed and periodically we get an older, deaf dog in. We needed a way to get these dogs to alert to us since we can’t call them vocally. Shock collars are out – they destroy trust and are inhumane. But vibration is kind and non-threatening, so I built this device. It hangs on the dog’s collar and when we press an icon on a phone it sends a request to the device to vibrate the collar and alert the dog. 

Design:

The design is pretty simple. Use an Arduino or compatible board configured as a local web server to listen for the command from a web browser to activate a small motorized vibrator inside the device. At the time this was first built, I used an Adafruit Feather ESP8266.  But for the purpose of this contest, I changed to an Arduino MKR1000. These boards can easily be powered by a small LiPo battery and all of that is enclosed in a small 3D printed box that attaches to the collar. Both the MKR1000 and Feather have the advantage that they can charge the battery when the collar is not in use. The code (below) is also pretty simple and is compiled using the Arduino IDE.

Parts:

  • 3D printed case with cover
  • Arduino MKR1000 (alternate Adafruit Feather ESP8266)
  • LiPo 1200 mAh battery (Adafruit #258)
  • Motorized vibrator (Adafruit #1201)
  • TN0604N3-G MOSFET Transistor
  • 100K 1/4W Resistor
  • 1K 1/4W Resistor
  • Stripboard (AKA Veroboard) or similar 61.2mm x 31.8mm 

Cost should be less than $35 for everything.

Schematic:

When assembling the board, the two resistors fit easily under the MCU. Only pins of the MCU that were used were soldered in via header pins. 

3D Printed Case:

The case is designed to hold the MCU with the MOSFET and Vibrator next to it. That will slide into the slots built into the case and still leave room for the battery and battery wires.

 Charging is done through the MCU’s USB connector and an opening was designed into the case to facilitate this. Also included is a cover that snaps onto the case and keeps everything nicely contained inside. It is held in place by 2 detents and a friction fit. This way when not in use you can open it up and unplug the battery. I wouldn’t be hard to add a tiny on/off slide switch.  

The dog’s collar squeezes into the holders that are part of the main case.  This was designed for a collar for a 20-25 pound dog.

I’ve included the OpenSCAD design so that you can modify the size or change it to accept a different size PCB. 

Both STL files were printed on a Prusa XL using Prusament PLA, 0.2mm layer height, 15% infill. The only supports used were for the collar attachment area. No other supports are needed. Both files are printed with the flat side down. You may need to rotate each item depending on what slicer you use. A copy of the .3MF file is included. 

If you don’t get a good friction fit for the cover, you may want to scale the cover in the X axis only, such as 101%. 

Code: 

The Arduino Sketch starts by establishing outputs for the onboard LED and motor control. A MOSFET is used to switch the motorized vibrator on and off due to possible current limitations of the MCU.  Serial communication is started but not required for normal operation. A Wifi connection is established and also outputs the IP address that the unit will be communicating on. Take note of this, you’ll need it later. For the purpose of this article, assume 192.168.1.125. Then the web server is defined for three options, one for root confirmation if someone hits the device using its IP address alone, one for the vibration activation:  192.168.1.125/Vib and one for all other “not expected” hits. When the unit receives a request with /Vib, it activates the motorized vibrator and LED for 2 seconds. 

Be sure to enter your router’s SSID and Password where indicated on the sketch. No other changes should be needed to compile and run. 

I've included the code for both below, starting with the MKR1000 version:

 

#include <WiFi101.h>
#include <WiFiUdp.h>

const char* ssid = "YourRouterSSID"; const char* password = "YourRouterPassword";

WiFiServer server(80); WiFiClient client; // = server.available();

IPAddress myIP(0,0,0,0);

#define led LED_BUILTIN #define motor 5

void setup(void) { // Setup Outputs pinMode(led, OUTPUT); digitalWrite(led, LOW); pinMode(motor, OUTPUT); digitalWrite(motor, LOW);

// Start Serial port and Wifi Connection Serial.begin(115200); delay(2000);

// Initialize Wifi Connection

WiFi.begin(ssid, password); while ((WiFi.status() != WL_CONNECTED) ) { delay(500); Serial.print("."); }

// Wait for connection Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); myIP = WiFi.localIP(); Serial.print(myIP[0]); Serial.print("."); Serial.print(myIP[1]); Serial.print("."); Serial.print(myIP[2]); Serial.print("."); Serial.println(myIP[3]);

// And start the server server.begin(); Serial.println("HTTP server started"); }

void loop(void) { client = server.available(); if (client) { if (client.connected() && client.available()) { ProcessWebpage(); } } }

void ProcessWebpage() { String NewLine = "\n"; String piece = "";
String reply = "File Not Found."; String currentLine = ""; // String to hold incoming data from the client

while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then if (c == '\n') { // if the byte is a newline character // if current line is blank, we got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); client.print(reply); client.println(""); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: if (currentLine.substring(0,5) == "GET /") { if (currentLine.substring(0,8) == "GET /Vib") { reply = "Vib Request Sent."; digitalWrite(led, HIGH); digitalWrite(motor, HIGH); delay(2000); digitalWrite(motor, LOW); digitalWrite(led, LOW); } else if (currentLine.substring(0, 6) == "GET / ") { reply = "OK"; } } currentLine = ""; } } else if (c != '\r') { // if you got anything else but a CR character, currentLine += c; // add it to the end of the currentLine } } } // close the connection: client.stop(); }

 

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

#ifndef STASSID #define STASSID "yourRouterSSID" #define STAPSK "yourRouterPassword" #endif const char* ssid = STASSID; const char* password = STAPSK;

ESP8266WebServer server(80);

#define led 2 #define motor 5

// If someone hits the root IP address, respond void handleRoot() { digitalWrite(led, LOW); server.send(200, "text/plain", "hello from Dog Collar Vibrator!"); delay(200); digitalWrite(led, HIGH); }

// If someone hits the /Vib command, fire motorized vibrator and LED for 2 seconds void handleVibrate() { digitalWrite(led, LOW); digitalWrite(motor, HIGH); server.send(200, "text/html", SendHTML()); // 2020-06-12 delay(2000); digitalWrite(motor, LOW); digitalWrite(led, HIGH); }

// If someone unexpected is trying to access this device, respond with File Not Found void handleNotFound() { digitalWrite(led, LOW); String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); delay(200); digitalWrite(led, HIGH); }

void setup(void) { // Setup Outputs pinMode(led, OUTPUT); digitalWrite(led, LOW); pinMode(motor, OUTPUT); digitalWrite(motor, LOW);

// Start Serial port and Wifi Connection Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println("");

// Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP());

if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); } digitalWrite(led, HIGH);

// Set up web server for 3 possible accessess server.on("/", handleRoot); server.on("/Vib", handleVibrate); server.onNotFound(handleNotFound);

// And start the server server.begin(); Serial.println("HTTP server started"); }

void loop(void) { server.handleClient(); MDNS.update(); }

String SendHTML() { String ptr = "<!DOCTYPE html> <html>\n"; ptr +="<head><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">\n"; ptr +="<title>Vibrate Control</title>\n"; ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"; ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n"; ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n"; ptr +="</style>\n"; ptr +="</head>\n"; ptr +="<body>\n"; ptr +="<h1>Vibrate Sent!</h1>\n"; ptr +="</body>\n"; ptr +="</html>\n"; return ptr; }

Compile the code, upload to the MCU, run it once from the Arduino IDE and take not of the IP address for your new web server. 

Fire it off: 

To activate it, you’ll need to make web requests from your phone's browser. This is simpler than it sounds. For an iPhone, go to Safari, and enter 192.168.1.125/Vib   If the device is on, it should vibrate. Once you’ve confirmed that, it’s easy to make this into an icon. Touch Share and then select Add to Home Screen and give it a name. Now any time you touch that icon, the device will vibrate. Also if the original request is still on your phone's screen, just hitting refresh will initiate a vibrate. Instructions for doing this on an Android phone should be similar. 

You may need to go into your router and make the IP address for the device Static.  Otherwise, after a period of no activity, the router may assign a different IP address. 

In use:

Attach the device to the dog’s collar and position it so it hangs below the dog’s neck. The collar should be snug so that the dog can feel the vibration. Pictures below show how to insert the collar into the device. 

To remove, pinch the collar at one end of the attachment area and then slide it out toward the other end. 

 

To train your dog, you’ll need to shape the dog’s response to the collar. Begin by activating it and when the dog notices it, give a reward. The idea is to have the dog associate vibration with you and respond to you. This would be similar to having a “hearing” dog respond to his name. Once you’ve achieved that, you can begin to train with hand motion commands for Come, Stay, Sit, etc.  

Future work:

It would be very easy to move this to the Arduino IoT Cloud/Dashboard.  That would simplify the MKR1000 code even more and make a polished user interface with a simple pushbutton. I only discovered this contest a few days before the deadline or I would have included instructions and code to do that. 

It would be simple to create other vibration patterns for other commands. For example a long 2 second vibration could be used for getting the dog’s attention, while two short bursts could mean “Stay” or something else.