Suck Light V1.0

Ideas and instructions how you can make your own bondage toys.
Post Reply
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Suck Light V1.0

Post by mtlsub »

The following is how I made a stand alone self bondage blowjob device.
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);
   
}
Attachments
temp3.jpg
temp3.jpg (29.39 KiB) Viewed 6240 times
temp2.jpg
temp2.jpg (25.58 KiB) Viewed 6240 times
temp1.jpg
temp1.jpg (21 KiB) Viewed 6240 times
Last edited by mtlsub on 18 Jan 2020, 22:04, edited 7 times in total.
User avatar
Shannon SteelSlave
Moderator
Posts: 6531
Joined: 03 Feb 2019, 19:49
Location: New England, USA

Re: Suck Light V1.0

Post by Shannon SteelSlave »

mtlsub wrote:I HOPE YOU ALL ENJOY. PLEASE FEEL FREE TO GIVE ME CONSTRUCTIVE FEEDBACK.
How's this : I asked MTL Sub to assist in the Development board recently. This was his answer. Thanx for the help MTL. Glad I could be the 1st to reply, before everyone starts building and using this.
Bondage is like a foreign film without subtitles. Only through sharing and practice can we hope to understand.
A Jedi uses bondage for knowledge and defense, never for attack.
I am so smart! I am so smart! S-M-R-T!....I, I mean S-M-A-R-T!
👠👠
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Re: Suck Light V1.0

Post by mtlsub »

There is no way I could have gotten to this point without the help of the talented programmers here.

As a little bonus if you build your own Suck Light. You can up load this (admittedly basic) code without any hardware change. If you start your arduino at the same time as you start the linked video you can get shocked in time with the video.
https://xhamster.com/videos/goddess-tor ... er-7277853

Code: Select all

byte buttonPin = 6;

//=================================================== START OF COLLAR SETUP CODE ======================================================================


//const int shock_min = 0; // Minimum of power a command will be executed at
const int shock_delay = 10; // Maximum rate at which the shock function can be used at
//const int cmd_max = 1000; // Maximum of milliseconds which a command can be executed at

// Constant variables
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 = 500; // Duration of the command in milliseconds
int collar_power = 10; // 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
unsigned long mmillis = 0;
// 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 >= 120000) // Send command to the collar at least every 2 minutes to make it stay on
  {
    Serial.println("Keep-alive:\tCollar");
    transmit_command(collar_chan, COLLAR_LED, 50);
  }
}

void sendVIB()
   {
    transmit_command(collar_chan, COLLAR_VIB, 5);//============currently set to level 10 VIBRATE. Most collars go to 100==========================
    delay(50);
    transmit_command(collar_chan, COLLAR_VIB, 5);//============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("VIB transmit");
}
//=================================================== END OF COLLAR SETUP CODE ======================================================================

void setup()
{
  
//=================================================== START OF COLLAR SETUP CODE ======================================================================
  pinMode(pin_rtx, OUTPUT); // Set transmitter pin as output
  pinMode(pin_led, OUTPUT); // Set LED pin as output
  Serial.begin(9600);
  //=================================================== END OF COLLAR SETUP CODE ======================================================================
  pinMode(buttonPin, INPUT_PULLUP);
}


void loop()
{
  delay(14214);//g
  sendZAP();

  delay(6088);//g
  sendZAP();

  delay(14426);//g 
  sendZAP();

  delay(11590);//g
  sendZAP();

  delay(4703);//g
  sendZAP();

  delay(12900);//g 
  sendZAP();

  delay(11800);//g
  sendZAP();

  delay(14230);//g 
  sendZAP();

  delay(10408);//g
  sendZAP();

  delay(12110);//g
  sendZAP();

  delay(18143);//g
  sendZAP();

  delay(8126);//g 
  sendZAP();

  delay(14818);//g 
  sendZAP();

  delay(20302);//g
  sendZAP();

  delay(3514);//g
  sendZAP();

  delay(6497);//g
  sendZAP();

 delay(5340);//g
  sendZAP();

  delay(7406);//g
  sendZAP();

 delay(2574);//g
  sendZAP();

 delay(10804);//g 
  sendZAP();

 delay(10000);//
  sendZAP();

  delay(20124);// 
  sendZAP();

 delay(15290);//
  sendZAP(); 

 delay(9900);// g
  sendZAP();

 delay(13000);// g
  sendZAP();

  delay(6950);// 
  sendZAP();

 delay(4175);//g
  sendZAP();

 delay(2821);//
  sendZAP();

 delay(8358);//g
  sendZAP();

  delay(4101);//g
  sendZAP();

 delay(6636);//
  sendZAP(); 

delay(21569);//g 
  sendZAP();

 delay(4509);//g
  sendZAP();

  delay(8016);//g
  sendZAP();

 delay(24088);//
  sendZAP();
while(1);
}
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Re: Suck Light V1.0

Post by mtlsub »

The following code uses the same hardware simply up load this code and you now have a predicament bondage machine.
The dildo must me "in the dark" so where you stick it does not matter, mouth ..... other places :lol:
if you remove the dildo before the set time is up you get shocked until you put it back in.

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);
byte buttonPin = 6;

//const int shock_min = 0; // Minimum of power a command will be executed at
const int shock_delay = 10; // Maximum rate at which the shock function can be used at
//const int cmd_max = 1000; // Maximum of milliseconds which a command can be executed at

// Constant variables
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 = 500; // Duration of the command in milliseconds
int collar_power = 10; // 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
#define buttonPin 6
#define magnet 8
 long currentMillis = 0;
 long startMillis = 0;
 long maxTime = 20000; //====================================this is your time to hold in millis====================================
 long loopMillis = 0;

// 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 >= 120000) // Send command to the collar at least every 2 minutes to make it stay on
  {
    Serial.println("Keep-alive:\tCollar");
    transmit_command(collar_chan, COLLAR_LED, 50);
  }}
  void sendVIB()
   {
    transmit_command(collar_chan, COLLAR_VIB, 1);//============currently set to level 1 VIBRATE. Most collars go to 100==========================
    delay(50);
    transmit_command(collar_chan, COLLAR_VIB, 1);//============currently set to level 1 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 setup()
{
//=================================================== START OF COLLAR SETUP CODE ======================================================================
  pinMode(pin_rtx, OUTPUT); // Set transmitter pin as output
  pinMode(pin_led, OUTPUT); // Set LED pin as output
  lcd.begin();
  Serial.begin(9600);
  Serial.println("Arduino Predicament");
  Serial.println("By Mtlsub");
  lcd.setCursor(1,0);
  lcd.print("Arduino Predicament");
  lcd.setCursor(5,1);
  lcd.print("By Mtlsub");
  
 

Serial.println("Suck if ready to start");
lcd.setCursor(3,2);
lcd.print("SUCK IF READY");
lcd.setCursor(3,3);
lcd.print (maxTime/60000);
lcd.print (" MINUTES");
  // Wait for the START button
  while (digitalRead(6)) {}
  // Then wait for it to be released
  delay(10);
  while (!digitalRead(6)) {}
  sendVIB();
  delay(10);
  startMillis = millis();
  lcd.clear();

  pinMode(6, INPUT);
  
}

void loop()
{
  currentMillis = millis();
  collar_keepalive();
  if (digitalRead(buttonPin) == LOW) {
    sendZAP();
  }
  lcd.setCursor (4,1);
    lcd.print ("KEEP HOLDING");
    lcd.setCursor (4,2);
    lcd.print ((maxTime - currentMillis)/1000); 
    lcd.print (" SECONDS");
    delay(50);
    lcd.clear();

  if ((maxTime - currentMillis)<= 0){
    lcd.setCursor (6,1);
    lcd.print ("RELEASE");
    Serial.println("RELEASE");
    sendVIB();
    while(1);}   
  }  
Fatalnemesis85
*
Posts: 2
Joined: 17 Jan 2020, 01:00

Re: Suck Light V1.0

Post by Fatalnemesis85 »

Wow I’ve been wanting to make something like this for quite a while. Could you possibly provide a few more pics or explanations on how you connected everything? I’m new to the arduino world but I’m pretty hands-on. Also for some reason the links to the items needed don’t work, could you possibly re-share which items you purchased?
I think I understand most of the build, except how the signal is relayed to the shock collar receiver. Are you using the remote in the setup? Also if you’d be willing to share how the box was wired including the timer and AC plug, that would be awesome. Apologies for any seemingly basic questions. Thanks!
User avatar
Shannon SteelSlave
Moderator
Posts: 6531
Joined: 03 Feb 2019, 19:49
Location: New England, USA

Re: Suck Light V1.0

Post by Shannon SteelSlave »

Welcome to Bound Anna, Fatalnemesis85. Send me a PM when you get a chance.
Bondage is like a foreign film without subtitles. Only through sharing and practice can we hope to understand.
A Jedi uses bondage for knowledge and defense, never for attack.
I am so smart! I am so smart! S-M-R-T!....I, I mean S-M-A-R-T!
👠👠
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Re: Suck Light V1.0

Post by mtlsub »

Thanks for the heads up on the links not working. I don't know why they are not even old links. I'm not home at the moment but I would be happy to explain in detail whatever you need. PM me your questions.

Links have been updated. They all work as of Jan 18th 2020.
I want to point out that you do not have to use the exact products in the links. arduino stuff is very interchangeable. Be sure the RF transmitter is 433Mhz.
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Re: Suck Light V1.0

Post by mtlsub »

Here is a super professional drawing of the AC circuit.
acwiring.jpg
Here is part of the arduino wiring. note I do not use the remote that came with the collar I use a 433Mhz transmitter.
arduino.jpg
arduino.jpg (24.52 KiB) Viewed 5718 times
The only wires not shown are:
the relay connection. Very easy. Power to VCC, ground to ground then each relay has a data wire to the pin you choose in the code
The LCD display. Power to vcc. ground to ground. SCL to SCL and SDA to SDA (the names of the pins are printed on the arduino)

Hope this helps.
Fatalnemesis85
*
Posts: 2
Joined: 17 Jan 2020, 01:00

Re: Suck Light V1.0

Post by Fatalnemesis85 »

Wow super helpful. I’ll take a look at your replies. Thanks and the diagrams look good!
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Re: Suck Light V1.0

Post by mtlsub »

Now with audio prompts

This is an update to the Sucklight code for simultaneous prompts thru serial monitor, LCD, and now Audio
requires a serial MP3 player https://www.amazon.com/Aideepen-YX5300- ... B01JCI23JG
you must include <softwareSerial.h> and a 1k resistor on the TX line.
Audio files need to be recorded in .WAV and the naming scheme is alphabetical so name your tracks with 001, 002, 003 at the beginning of each title to make playback easier.
My first track is a readout of what program you have running and instructions to suck to start. second track says "FASTER!". Third track says "SUCK!". Fourth track says "ALL DONE! YOU ARE NOW RELEASED!"

you can of course make it say whatever you want just change the track number, 3 in this case, in the following command. sendCommand(CMD_PLAY_W_VOL, 0X1E03);

PLEASE NOTE THE PIN MAPPING HAS CHANGED FROM THE PREVIOUS VERSION TO AVOID CONFLICTS.

Code: Select all

 #include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);// Set the LCD address to 0x27 for a 20 chars and 4 line display

// 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 =  8; // 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 btnHIT 9 //=======================this is the photoresistor================
#define magnet 13 //=======================electromagnet release====================
#define vib 12   //=======================reward vibrator==========================
#define ARDUINO_RX 11//should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 10//connect to RX of the module

SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);
static int8_t Send_buf[8] = {0} ;

#define CMD_SEL_DEV 0X09
#define DEV_TF 0X02
#define CMD_PLAY_W_VOL 0X22
#define CMD_PLAY 0X0D
#define CMD_PAUSE 0X0E
#define CMD_PREVIOUS 0X02
#define CMD_NEXT 0X01

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 = 100 ;  //=====================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, 50);//============currently set to level 10 VIBRATE. Most collars go to 100==========================
    delay(50);
    transmit_command(collar_chan, COLLAR_VIB, 50);//============currently set to level 10 VIBRATE. Most collars go to 100==========================
    Serial.println("VIB transmit");
    }
void sendZAP()
   {
    lcd.setCursor (0,3);
    lcd.print ("!!!!!!SHOCKING!!!!!!");
    delay(50);
    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{
    lcd.clear();
    lcd.setCursor (1,1);
    lcd.print ("TIMED RELEASE");
    sendCommand(CMD_PLAY_W_VOL, 0X1E04);
    for (int x = 0; x < 30; x++){
    digitalWrite (magnet, HIGH);
    Serial.println("EMERGENCY TIMED RELEASE");
    delay (2000);}
}
}
void sendCommand(int8_t command, int16_t dat)

{  //delay(50);
  Send_buf[0] = 0x7e; //starting byte
  Send_buf[1] = 0xff; //version
  Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command; //
  Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);//datah
  Send_buf[6] = (int8_t)(dat); //datal
  Send_buf[7] = 0xef; //ending byte
  for(uint8_t i=0; i<8; i++)
  {
    mySerial.write(Send_buf[i]) ;
  }
}


void setup(){

  // initialize the LCD
  lcd.begin();
 
  pinMode(btnHIT, INPUT);
  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(vib, HIGH);
  digitalWrite(magnet, HIGH);

 
  // Start the Serial port
  {
    mySerial.begin(9600);
          Serial.begin(9600);
          sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
          sendCommand(CMD_PLAY_W_VOL, 0X1E01);//play the first song with volume 30 class
  }
  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(700, 1200));
    timeReaction = millis();
    Serial.println ();
    Serial.println ("SUCK");
    lcd.setCursor (6,0);
    lcd.print ("-SUCK-");
    sendCommand(CMD_PLAY_W_VOL, 0X1E03);
    period1();
    collar_keepalive();
   
    // Wait for btnHit
    while (!digitalRead(btnHIT) && millis() < timeReaction + 3000) {  //===== change the value for longer wait before auto-fail (must be higher than time to suck)======
    }

    timeReaction = millis() - timeReaction;
    timeTotal += timeReaction;
    delay(10);
    while (digitalRead(btnHIT)) {}
       lcd.clear();
       Serial.print(times - 1 - i );
       lcd.setCursor(13,3);
       lcd.print(times - 1 - i);
       Serial.println(" left");
       lcd.print(" LEFT");

    if (timeReaction <= 1300) { //=======================change value for how long you want to have to complete a suck======================
      Serial.println ("GOOD");
      //digitalWrite (vib, LOW); //
      //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!");
      sendCommand(CMD_PLAY_W_VOL, 0X1E02);
      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 ");
    sendCommand(CMD_PLAY_W_VOL, 0X1E04);
    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);
   
}
mtlsub
**
Posts: 170
Joined: 12 Oct 2010, 05:23
Location: Great kinky North

Re: Suck Light V1.0

Post by mtlsub »

Same project New container :whip:
Attachments
new box (4).jpg
Post Reply