DIY Safecracking – Making a stupidly cheap autodialer (Work in Progress)

Note – This project is a living one, and as such I’m going to update it as I work on it. The views I express are those of someone currently working on a project, and I may be doing dumb things. Put down the pitchforks.

Don’t lose your safe combination.

If everyone just followed that bit of wisdom no one would get locked out of their safe. Heck, you can even write it down if you want, just don’t make it obvious. I used to tell people “just write it down on something you won’t lose easily. Like, in a phone book disguised as a number, or buy a lotto ticket with your combo and keep it next to your birth certificate.” The point is, other than having your house burn down in a fire, there is no reason why you shouldn’t be able to open your safe.

I’ve figured out combinations to exactly two safes in my life. Both of those times the door was open, I just didn’t have the combination. That is the kind of scenario you generally want. You simply take the back panel off of the front door and then just observe the wheels as they go into place. The fence drops, and if you recorded the numbers correctly, you will have your combination. Then you write that combination down, and you don’t forget it… again.

This time is a little different; I have a safe with the door closed and locked. Now, there are plenty of destructive ways to open a safe, but I’m told that there may be legal documents inside of it (a deed to a graveyard plot is suspected to be inside). I was really hoping that I could finally learn how to drill a safe, but I was told not to drill if I could help it. 🙁 So that only really leaves one thing left…

I have to make an electronic safe cracker, aka an “Auto Dialer.” In my case I will attempt to do this as cheaply as possible. Hopefully for under $20. It might not be exactly $20, heck it might even be $40, but I’m aiming for $20.

In the planning phase of this project I originally, I wanted to do something like sparkfun did where they had an optical encoder, frames, and pure craziness. That looks like a lot of work, though, and I’m kind of a lazy scumbag. You see, I don’t need the combination to the safe. I just need to have the door open. I can remove the back panel and figure it out the combination later. The goal for this project isn’t to discover the combination, it is merely to get the door open.

If you’ve ever opened a safe, then you’ll know that when you put in the right combination, you have to rotate the dial a little bit after the last number to actually unlock the thing. This is because of a part called the fence which drops into wheel notches inside the dial mechanism. Here’s a really out of focus video on how safe dials work if you’ve never seen the inner workings of a safe before.

As can be seen in the video this extra movement forces the bar(s) that lock your safe out of the way so the door may swing open. The dial can only turn so much before there is a hard stop preventing it from turning further, which can also be seen in the video. This little tidbit of information is very important to this project.

Because I don’t care what the safe combination is, there isn’t anything stopping me from just programming a microcontroller to spin a servo randomly. So long as I can detect when the motor cannot rotate anymore I should be all set, even if it’s random and could take days. When the motor is physically prevented from turning any further, the motor is said to be “stalled.” For this project, I simply need to create an adapter for the servo to interface with the safe, determine if a motor is stalled, and write the code necessary to spin the dial randomly enough to put it in an unlocked state.

First, let’s start with the adapter. By using a caliper out I was able to determine the diameter of the safe knob and make an adapter for a servo using a 3D printer. I intentionally made the diameter about .5mm bigger than what I measured and made a 4mm gap in the middle. I did this so I could fit the adapter on, and then clamp it onto the dial using bolts.

FreeCAD safe adapter model

You might be saying, “but Lee, I don’t have a 3D printer, this isn’t under $20 bucks at all!” … Yeah, it’s true. I mean, I could have made this part with wood, or metal, or even just by using duct tape. For this part you just have to use what you have. I didn’t buy a 3D printer specifically for this job, so for me it’s just easier to use FreeCAD and print anything I need. I won’t get into the nitty gritty of how to use FreeCAD, but this part of the auto dialer didn’t take long. Maybe 1 hour to model the adapter, and 4-5 hours to print it.

Now let’s figure out how to detect when a servo stalls. A servo is like any other motor, and a motor, at its heart, is a long insulated wire wrapped around a core. When an electric motor stalls it is unable to rotate and electrically it is similar to a wire going straight to ground. During a motor stall current will measure much higher than if the motor were spinning freely. With that in mind, we now have to figure out how to actually measure current. Luckily, there’s already a solution out there.

INA169 Current Sensor Breakout

I purchased this board from Adafruit for $10. Looking at the INA169 datasheet I’m pretty certain that it meets all of my requirements for a current sensor. Sparkfun also has a version of this board with example code. The same code will work with this board with some tweaking for my particular setup. I found that the board as it currently is setup won’t detect current below a certain threshold. If you DO decide to follow the Sparkfun hookup and code example with an Adafruit board, you might find that you’ll have to use a blue LED without a series resistor in order to get any readings at all. Also, bear in mind that I’m using a continuous servo. These servos are essentially motors that accept PWM input and will rotate 360 degrees. So here’s my first take at it:

#include <Servo.h>

#define STALL_CURRENT .68f

Servo myservo;
int pos = 0;
long positionRandNumber;
long delayRandNumber;
int motorStallCount = 0;
bool isMotorStalledFlag = false;

const int SENSOR_PIN = A5;
const int RS = 100;
const int VOLTAGE_REF = 4.93;
float sensorValue;
float current;



inline static float currentSensorRead(){
  sensorValue = analogRead(SENSOR_PIN);
  sensorValue = (sensorValue * VOLTAGE_REF) / 1023;
  return sensorValue / (.01 * RS);
}

inline static void updateMotorStallStatus(float _inputCurrent){
  if(_inputCurrent > STALL_CURRENT){
    ++motorStallCount;
  } else {

  }

  if(motorStallCount > 10){
    isMotorStalledFlag = true;
  }
}

inline static void resetState(){
  motorStallCount = 0;
  isMotorStalledFlag = false;
}

inline static void moveServo(int _position){
  
  if(false == isMotorStalledFlag){
    myservo.write(_position);
    current = currentSensorRead();
    updateMotorStallStatus(current);
    Serial.print(current);
    Serial.println(" A");
  } else {
    myservo.write(90);
  }
  
}

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(4));
  myservo.attach(3);
}


void loop() {

  resetState();

  positionRandNumber = random(180);
  delayRandNumber = random(15);
  
  for(int i = 0; i < 100; ++i){
    moveServo(positionRandNumber);
    delay(delayRandNumber);
  }

  if(true == isMotorStalledFlag){
    while(1){
      myservo.write(90);
    }
  }#include <Servo.h>

#define STALL_CURRENT .68f

Servo myservo;
int pos = 0;
long positionRandNumber;
long delayRandNumber;
int motorStallCount = 0;
bool isMotorStalledFlag = false;

const int SENSOR_PIN = A5;
const int RS = 100;
const int VOLTAGE_REF = 4.93;
float sensorValue;
float current;



inline static float currentSensorRead(){
  sensorValue = analogRead(SENSOR_PIN);
  sensorValue = (sensorValue * VOLTAGE_REF) / 1023;
  return sensorValue / (.01 * RS);
}

inline static void updateMotorStallStatus(float _inputCurrent){
  if(_inputCurrent > STALL_CURRENT){
    ++motorStallCount;
  } else {

  }

  if(motorStallCount > 10){
    isMotorStalledFlag = true;
  }
}

inline static void resetState(){
  motorStallCount = 0;
  isMotorStalledFlag = false;
}

inline static void moveServo(int _position){
  
  if(false == isMotorStalledFlag){
    myservo.write(_position);
    current = currentSensorRead();
    updateMotorStallStatus(current);
    Serial.print(current);
    Serial.println(" A");
  } else {
    myservo.write(90);
  }
  
}

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(4));
  myservo.attach(3);
}


void loop() {

  resetState();

  positionRandNumber = random(180);
  delayRandNumber = random(15);
  
  for(int i = 0; i < 100; ++i){
    moveServo(positionRandNumber);
    delay(delayRandNumber);
  }

  if(true == isMotorStalledFlag){
    while(1){
      myservo.write(90);
    }
  }
  
}
  
}

Now, before you jump on the “your code sucks” band wagon, understand for a moment that I could care less about code reusability. I also can see some problems with my code already, and that was before any testing. With that being said I decided “screw it, let’s just upload this thing and see what it does.

To get this thing attached to my safe, I took an old PCB vice that I had, put it on top of a camera case. To clamp the adapter to the safe dial I used an automotive hose clamp. As it turns out I didn’t have bolts long enough for the adapter. So here’s what it looks like right now:

Autodialer doing its thing

The concept is certainly there, but it conks out after about a minute or two of running. I’ll update this post as to why it’s not 100% when I figure it out. I’m almost certain it’s got something to do with my code.

edit – After watching this thing rotate a bit, I said… “Man this is going to take a long time…

Before anyone calls me out on “why didn’t you use a stepper motor” I’d like to say, “because I’m an idiot.” I’d also like to point out that this project is a living project, not a how-to guide, so I don’t mind making mistakes. Anyway, I don’t think I truly appreciated the word random until right now.

You see, as I watch this thing run, the dial rotates, and often times the dial rotates around too much in one direction or another. While this is fine (as this clears the safe and possibly rotates all of the wheels in the correct position), I sometimes see it perform a full clear in the opposite direction. You see… I think this thing is TOO random.

Anyway, I’m going to let this thing run in the background all night. I was hoping to just use this servo, but I think I might use a spare stepper motor and driver I have lying around.

Leave a Reply

Your email address will not be published. Required fields are marked *