The idea is simple set the number of sucks. Set how fast you have to suck. If you don't do it fast enough you get a shock!
The device uses a photoresistor to tell when a suck has happened.
This device can also control a mains powered vibrator(hitachi) and an electromagnet.
The standard warnings apply. BE SURE TO HAVE MULTIPLE BACKUPS AND TEST BEFORE USING. I added a mechanical timer as an additional safety measure.
I HOPE YOU ALL ENJOY. PLEASE FEEL FREE TO GIVE ME CONSTRUCTIVE FEEDBACK.
=====================================================PARTS LIST====================================================================
Arduino uno - https://www.amazon.com/ELEGOO-Board-ATm ... 623&sr=8-4
relay bank - https://www.amazon.com/MCIGICM-Channel- ... 66&sr=8-20
photo resistor module - https://www.amazon.com/Photosensitive-R ... 35&sr=8-16
RF transmitter - https://www.amazon.com/SMAKN%C2%AE-433M ... 189&sr=8-9
20 column by 4 row I2C LCD display. https://www.amazon.ca/gp/product/B01GPU ... UTF8&psc=1 You can run this program without the LCD and just use Serial Monitor
breadboard - https://www.amazon.com/AkoMatial-Solder ... 067&sr=8-2
Or if you are handy and can solder, PCB boards - https://www.amazon.com/ELEGOO-Prototype ... 220&sr=8-6
Shock collar - https://www.amazon.com/Petrainers-PET99 ... 61&sr=8-11
transperant dildo - https://www.amazon.com/Silicone-Transpa ... 359&sr=8-6
Pipe and pipe fittings - https://www.homedepot.com/b/Plumbing-Pi ... ,2831,3701
Small leather strap (dog collar) don't get it too thick the screw posts of the shocking module have to reach through.
2 strand wire to go from the dildo to the arduino (speaker wire works)
Soldering iron and solder
======================================================ARDUINO + ELECTRONICS===================================================================
Connect the RF Transmitter data pin to pin 12
you may want to add an antenna to your RF transmitter there is a hole marked ant on the board and many tutorials online how to do it.
connect the photoresistor module data pin to pin 9
Connect the LCD to SDA and SCL
You need to remove the sensor from the module with a soldering iron and add a length of wire from the sensor to the module so you can place the sensor into a dildo
========================================================HARDWARE============================================================================
drill a half inch hole down the middle of your dildo from the base (your sensor will be in this hole so your mouth has to reach the depth of your hole)
push a section of half inch black pipe half an inch from the bottom of your hole (to leave space for the sensor)
Use a 1/2in to 3/4in adaptor and then build whatever frame you want out of 3/4in black pipe fittings leaving a spot for you to thread your wire with sensor attached into the dildo
unscrew the contact points on the shock module
Drill or punch holes in the leather strap for the threads of the contact points to fit snugly through and attach the shock module
========================================================CODE AND PAIRING=====================================================================
Using Arduino IDE on your computer
Code: Select all
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 20 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Constant variables
const int shock_delay = 10; // Maximum rate at which the shock function can be used at
const int pin_led = LED_BUILTIN; // Pin for indication LED
const int pin_rtx = 12; // Pin to transmit over
const String key = "00101100101001010"; // Key of the transmitter, dont touch if you dont know how it works
// Variables which do change
int collar_chan = 0; // Can be channel 0 or 1
int collar_duration = 800; // Duration of the command in milliseconds
int collar_power = 1; // Strength of the command, can be 0-100, but will be limited by shock_min and shock_max
// Define values for easier recognition
#define COLLAR_LED 1
#define COLLAR_BEEP 2
#define COLLAR_VIB 3
#define COLLAR_ZAP 4 // Change these pins if you want to use different ones
#define ledTrigger 13
#define btnHIT 6 //=======================this is the photoresistor================
#define magnet 8 //=======================electromagnet release====================
#define vib 11 //=======================reward vibrator==========================
unsigned long startMillis;
unsigned long currentMillis;
unsigned long failed = 0;
long timeTotal = 0;
long timeReaction;
long maxTime = 900000;//================THIS IS THE TIME LIMIT FOR THE EMERGENCY RELEASE===========
int times = 5; //=====================THIS IS THE NUMBER OF SUCKS================================
// Strings used for building up the command sequence
String sequence, power, channelnorm, channelinv, modenorm, modeinv;
// Store the last time anything was transmitted to the collar
unsigned long transmit_last = 0;
unsigned long shock_last = 0;
void transmit_command(int c, int m, int p = 0)
{
transmit_last = millis();
switch (c) // Check the channel
{
case 1: // Channel 1
channelnorm = "111";
channelinv = "000";
break;
default: // Channel 0
channelnorm = "000";
channelinv = "111";
break;
}
switch (m) // Check the mode
{
case 1: // Light
modenorm = "1000";
modeinv = "1110";
break;
case 2: // Beep
modenorm = "0100";
modeinv = "1101";
break;
case 4: // Shock
modenorm = "0001";
modeinv = "0111";
shock_last = millis();
break;
default: // Vibrate
modenorm = "0010";
modeinv = "1011";
// p = 10; // Set strengh to 10 for the command to be executed properly
break;
}
// Convert power to binary
int zeros = String(p, BIN).length();
String power;
for (int i = 0; i < 7 - zeros; i++)
{
power = power + "0";
}
power = power + String(p, BIN);
String sequence = "1" + channelnorm + modenorm + key + power + modeinv + channelinv + "00";
digitalWrite(pin_led, LOW);
// d = constrain(d, 50, cmd_max); // Clamp duration of the command
unsigned long cmd_start = millis();
// while (millis() - cmd_start < d)
// {
// start bit
digitalWrite(pin_rtx, HIGH);
delayMicroseconds(1500); // wait 1500 uS
digitalWrite(pin_rtx, LOW);
delayMicroseconds(741);// wait 741 uS
for (int n = 0; n < 41 ; n++)
{
if (sequence.charAt(n) == '1') // Transmit a one
{
digitalWrite(pin_rtx, HIGH);
delayMicroseconds(741);
digitalWrite(pin_rtx, LOW);
delayMicroseconds(247);
}
else // Transmit a zero
{
digitalWrite(pin_rtx, HIGH);
delayMicroseconds(247);
digitalWrite(pin_rtx, LOW);
delayMicroseconds(741);
}
}
delayMicroseconds(4500);
// }
digitalWrite(pin_led, HIGH);
}
void collar_keepalive()
{
if (millis() - transmit_last >= 60000) //======= Send command to the collar at least every 1 minute to keep it awake======================
{
transmit_command(collar_chan, COLLAR_VIB, 1);
delay(50);
transmit_command(collar_chan, COLLAR_VIB, 1);
Serial.println("Keep-alive:\tCollar");
}
}
void sendVIB()
{
transmit_command(collar_chan, COLLAR_VIB, 10);//============currently set to level 10 VIBRATE. Most collars go to 100==========================
delay(50);
transmit_command(collar_chan, COLLAR_VIB, 10);//============currently set to level 10 VIBRATE. Most collars go to 100==========================
Serial.println("VIB transmit");
}
void sendZAP()
{
transmit_command(collar_chan, COLLAR_ZAP, 1);//============currently set to level 1 SHOCK. Most collars go to 100==========================
delay(50);
transmit_command(collar_chan, COLLAR_ZAP, 1);//============currently set to level 1 SHOCK. Most collars go to 100==========================
Serial.println("ZAP transmit");
}
void period1() {
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= maxTime){ //test whether the period has elapsed{
for (int x = 0; x < 30; x++){
digitalWrite (magnet, HIGH);
Serial.println("EMERGENCY TIMED RELEASE");
delay (2000);}
}
}
void setup(){
// initialize the LCD
lcd.begin();
pinMode(btnHIT, INPUT);
pinMode(ledTrigger, OUTPUT);
pinMode(vib, OUTPUT);
pinMode(magnet, OUTPUT);
pinMode(pin_rtx, OUTPUT); // Set transmitter pin as output
pinMode(pin_led, OUTPUT); // Set LED pin as output
// Turn off the RELAYS
digitalWrite(ledTrigger, HIGH);
digitalWrite(vib, HIGH);
digitalWrite(magnet, HIGH);
// Start the Serial port
Serial.begin(9600);
Serial.println("Arduino Suck Light");
Serial.println("By Mtlsub");
lcd.setCursor(1,0);
lcd.print("Arduino Suck Light");
lcd.setCursor(5,1);
lcd.print("By Mtlsub");
randomSeed(analogRead(0));
Serial.println("Suck if ready to start");
lcd.setCursor(3,2);
lcd.print("SUCK IF READY");
failed = 0;
// Wait for the START button
while (digitalRead(btnHIT)) {}
// Then wait for it to be released
delay(10);
while (!digitalRead(btnHIT)) {}
digitalWrite(magnet, LOW); //==========================Magnet gets powered on=============================
sendVIB();
delay(10);
startMillis = millis();
lcd.clear();
}
void loop(){
for (int i = 0; i < times; i++) {
lcd.setCursor(13,3);
lcd.print(times - i);
lcd.print(" LEFT");
delay(random(200, 600));
timeReaction = millis();
digitalWrite(ledTrigger, LOW);
Serial.println ();
Serial.println ("SUCK");
lcd.setCursor (7,0);
lcd.print ("SUCK");
period1();
collar_keepalive();
// Wait for btnHit
while (!digitalRead(btnHIT) && millis() < timeReaction + 5000) { //===== change the 5000 value for longer wait before auto-fail (must be higher than time to suck)======
}
timeReaction = millis() - timeReaction;
timeTotal += timeReaction;
delay(10);
while (digitalRead(btnHIT)) {}
digitalWrite(ledTrigger, HIGH);
lcd.clear();
Serial.print(times - 1 - i );
lcd.setCursor(13,3);
lcd.print(times - 1 - i);
Serial.println(" left");
lcd.print(" LEFT");
if (timeReaction <= 1500) { //=======================change value for how long you want to have to complete a suck======================
digitalWrite (vib, LOW);
Serial.println ("GOOD");
lcd.setCursor(7,1);
delay (500); //==========================activates the relay for the vibrator reward for 500 millis===============================
digitalWrite (vib, HIGH);
}
else {
sendVIB(); //====================================CHANGE TO sendZAP to enable the shock for failed sucks=======================================
Serial.print ("FASTER YOU FAILED ");
lcd.setCursor(1,1);
lcd.print ("FASTER YOU FAILED!");
Serial.print (failed + 1);
lcd.setCursor(5,2);
lcd.print(failed + 1);
Serial.println (" TIMES");
lcd.print(" TIMES");
failed = failed + 1;
delay(1000);
lcd.clear();
}
}
lcd.clear();
lcd.setCursor(2,1);
digitalWrite (magnet, LOW);
Serial.print ("DONE ALL ");
lcd.print ("DONE ALL ");
Serial.print (times);
lcd.print (times);
Serial.println (" SUCKS");
lcd.print (" SUCKS");
Serial.print ("YOU FAILED ");
lcd.setCursor(1,2);
lcd.print ("YOU FAILED ");
Serial.print (failed);
lcd.print (failed);
Serial.println (" SUCKS");
lcd.print (" SUCKS");
while(1);
}