├── LICENSE ├── README.md └── collar.ino /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino controlling a shocking collar. 2 | 3 | This code is based on [Deviant Designs work](http://deviant-designs.co.uk/2019/03/29/arduino-controlled-shock-collar/) 4 | 5 | I only fixed timing issue, caused by sligtly different RF protocol of the new collar. 6 | 7 | ## Warning! 8 | 9 | This project is to control a shock collar - a device traditionally used in "training" dogs and pets. while I cannot stop you from using it for this purpose, I condemn in the strongest possible terms the use of shock collars, and by extension, the use of this software to control shock collars, that are used on any entity that can feel pain that is unable to (i.e. non-human animals, human children) or does not (i.e. unwilling adults) consent to it's use on them. 10 | 11 | This project uses commecial products that are intended for use on non-human animals, and involve electricity. I offer no guarantee that use outside (or within) the manifacturers intended use are safe and I reccomend you seek medical advice on the issue before use. 12 | 13 | *Warning copied form [smouldery original repo](https://github.com/smouldery/shock-collar-control)* 14 | 15 | 16 | ## Hardware 17 | 18 | * [Shocking Collar](https://www.aliexpress.com/item/Rechargeable-And-Waterproof-300-Meters-Remote-Electric-Shock-Anti-bark-Pet-Dog-Training-Collar-With-LCD/2052492035.html?channel=twinner) 19 | * [433 MHz transmitter](https://www.curiua.com/p/bqlzr-1-set-433mhz-rf-wireless-transmitter-und-empf-ngermodul-gr-n-pcb/0700443095464) - you can buy this, but I've tried 2 different version from Aliexpress and both are ok. 20 | * An arduino, I've used a Mega2560 because was on my desk. 21 | 22 | ## How to use 23 | Connect (on a breadbord, solder it, use hotglue, use jumpwire...) the pin 11 to the data pin of the trasmitter. 24 | Reset the collar as descripted on the collar instructions. The collar make a beep noise. 25 | Connect the pin 9 to GND. Now the collar emit a new beep noise. You are paired! 26 | If you press/connect again the pin 9, the collar should vibrate. 27 | 28 | Change the loop() function to do different mode and power settings. 29 | 30 | If you have an SDR, you can grab a transmitted RF signal from the original remote, and extract the remote ID. If you change the const String key in the code with your remote ID, you can use both remote and arduino to control the collar. 31 | -------------------------------------------------------------------------------- /collar.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Originally developed by Smouldery and Mikey who very kindly allowed us the use of their code. 3 | 4 | Link to Smoulderys original code: https://github.com/smouldery/shock-collar-control/blob/master/Arduino%20Modules/transmitter_vars.ino 5 | 6 | adapted by Deviant Designs 7 | 8 | Link to Deviant Design work: http://deviant-designs.co.uk/2019/03/29/arduino-controlled-shock-collar/ 9 | 10 | some timing changes to match the new RF protocol by DpMartee 11 | */ 12 | 13 | 14 | byte buttonPin = 9; 15 | 16 | //=================================================== START OF COLLAR SETUP CODE ====================================================================== 17 | 18 | //const int shock_min = 0; // Minimum of power a command will be executed at 19 | const int shock_delay = 10; // Maximum rate at which the shock function can be used at 20 | //const int cmd_max = 1000; // Maximum of milliseconds which a command can be executed at 21 | 22 | // Constant variables 23 | const int pin_led = LED_BUILTIN; // Pin for indication LED 24 | const int pin_rtx = 11; // Pin to transmit over 25 | const String key = "00101100101001010"; // Key of the transmitter, dont touch if you dont know how it works 26 | 27 | // Variables which do change 28 | int collar_chan = 0; // Can be channel 0 or 1 29 | int collar_duration = 500; // Duration of the command in milliseconds 30 | int collar_power = 10; // Strength of the command, can be 0-100, but will be limited by shock_min and shock_max 31 | 32 | // Define values for easier recognition 33 | #define COLLAR_LED 1 34 | #define COLLAR_BEEP 2 35 | #define COLLAR_VIB 3 36 | #define COLLAR_ZAP 4 37 | 38 | // Strings used for building up the command sequence 39 | String sequence, power, channelnorm, channelinv, modenorm, modeinv; 40 | 41 | // Store the last time anything was transmitted to the collar 42 | unsigned long transmit_last = 0; 43 | unsigned long shock_last = 0; 44 | void transmit_command(int c, int m, int p = 0) 45 | { 46 | transmit_last = millis(); 47 | switch (c) // Check the channel 48 | { 49 | case 1: // Channel 1 50 | channelnorm = "111"; 51 | channelinv = "000"; 52 | break; 53 | default: // Channel 0 54 | channelnorm = "000"; 55 | channelinv = "111"; 56 | break; 57 | } 58 | 59 | switch (m) // Check the mode 60 | { 61 | case 1: // Light 62 | modenorm = "1000"; 63 | modeinv = "1110"; 64 | break; 65 | case 2: // Beep 66 | modenorm = "0100"; 67 | modeinv = "1101"; 68 | break; 69 | case 4: // Shock 70 | modenorm = "0001"; 71 | modeinv = "0111"; 72 | shock_last = millis(); 73 | break; 74 | default: // Vibrate 75 | modenorm = "0010"; 76 | modeinv = "1011"; 77 | // p = 10; // Set strengh to 10 for the command to be executed properly 78 | break; 79 | } 80 | 81 | // Convert power to binary 82 | int zeros = String(p, BIN).length(); 83 | 84 | String power; 85 | for (int i = 0; i < 7 - zeros; i++) 86 | { 87 | power = power + "0"; 88 | } 89 | power = power + String(p, BIN); 90 | 91 | String sequence = "1" + channelnorm + modenorm + key + power + modeinv + channelinv + "00"; 92 | 93 | digitalWrite(pin_led, LOW); 94 | // d = constrain(d, 50, cmd_max); // Clamp duration of the command 95 | unsigned long cmd_start = millis(); 96 | // while (millis() - cmd_start < d) 97 | // { 98 | // start bit 99 | digitalWrite(pin_rtx, HIGH); 100 | delayMicroseconds(400); // chnged to new protocol 101 | digitalWrite(pin_rtx, LOW); 102 | delayMicroseconds(750);// wait 750 uS 103 | 104 | for (int n = 0; n < 41 ; n++) 105 | { 106 | if (sequence.charAt(n) == '1') // Transmit a one 107 | { 108 | digitalWrite(pin_rtx, HIGH); 109 | delayMicroseconds(200); // chnged to new protocol 110 | digitalWrite(pin_rtx, LOW); 111 | delayMicroseconds(1500); // chnged to new protocol 112 | } 113 | else // Transmit a zero 114 | { 115 | digitalWrite(pin_rtx, HIGH); 116 | delayMicroseconds(200); // chnged to new protocol 117 | digitalWrite(pin_rtx, LOW); 118 | delayMicroseconds(750); // chnged to new protocol 119 | } 120 | } 121 | delayMicroseconds(9000); // chnged to new protocol 122 | // } 123 | digitalWrite(pin_led, HIGH); 124 | } 125 | 126 | void collar_keepalive() 127 | { 128 | if (millis() - transmit_last >= 120000) // Send command to the collar at least every 2 minutes to make it stay on 129 | { 130 | Serial.println("Keep-alive:\tCollar"); 131 | transmit_command(collar_chan, COLLAR_LED, 50); 132 | } 133 | } 134 | 135 | //=================================================== END OF COLLAR SETUP CODE ====================================================================== 136 | 137 | void setup() 138 | { 139 | //=================================================== START OF COLLAR SETUP CODE ====================================================================== 140 | pinMode(pin_rtx, OUTPUT); // Set transmitter pin as output 141 | pinMode(pin_led, OUTPUT); // Set LED pin as output 142 | Serial.begin(115200); 143 | //=================================================== END OF COLLAR SETUP CODE ====================================================================== 144 | pinMode(buttonPin, INPUT_PULLUP); 145 | } 146 | 147 | void loop() 148 | { 149 | collar_keepalive(); 150 | 151 | if (digitalRead(buttonPin) == LOW) { 152 | transmit_command(collar_chan, COLLAR_VIB, 100); 153 | } 154 | } 155 | --------------------------------------------------------------------------------