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

NoteThis 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 do dumb things as I work on it and figure out what works and what doesn’t.

First Update – (12-MAR-2019)

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);
    }
  }
  
}
  
}

I 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 quits 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.

Second Update – (21-MAR-2019)

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.

With that said, I don’t think I truly appreciated the word “random” until right now. It seems like it’s going to take forever to unlock if I just let it keep going.

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.

I let my servo run in the background for a night, only to find that the servo detached from the adapter. Also, this hobby servo is extremely loud. For my own sanity while I work, I’m switching the project over to use a TCM2130. They look like this:

TCM2130 – SilentStepStick Drop in Stepper Driver

This stepper motor driver comes with a bunch of really amazing features that I like. I first learned about this stepper driver after watching Marco Reps build a laser CNC that uses them. This stepper driver is extremely quiet. So quiet that I don’t hear the motor turning while it is active. It also has programmatic current limiting and motor load detection which allows you to detect when the stepper has encountered a hard limit. This will be useful for determining when the safe is unlocked.

Bread boarding this driver wasn’t particularly difficult, but I couldn’t get it working with just a +5V like I was able to do with a servo motor. For this driver I needed to supply my own +9V from an external benchtop power supply.

All Hooked Up

One of the problems I had with using a servo was that it was not very good at determining how far it had rotated. My code was written so that it would be random enough for it to eventually unlock the safe given a long enough period of time. Now that I’m able to measure with some degree of accuracy how far the motor has spun, I can make a better autodialer… This will increase the final price of the project, but hey, it’s still going to be pretty cheap overall. This is the approximate wiring that I have right now:

Silent Step Stick Wiring to Arduino Uno

As for code, I modified code that I found over here: And I made it so that I could control how far the stepper rotates in terms of degrees. There’s a “magic” number hidden in the code, “int STEP2PI = 26250;” What this number represents is how many High/Low cycles I have to send to my specific stepper motor to get it to rotate 180 degrees. I found this number by empirically guessing and checking until I got an accurate enough number. Not ideal, but still much more accurate that what I had with a servo.


/*
Initializes the library and turns the motor in alternating directions.
*/
#define EN_PIN    7  // Nano v3:  16 Mega:  38  //enable (CFG6)
#define DIR_PIN   8  //      19      55  //direction
#define STEP_PIN  9  //      18      54  //step
#define CS_PIN    10  //      17      64  //chip select

bool dir = true;
int STEP2PI = 26250;
int STEPS_IN_DEG = (int)((float)STEP2PI/360.f);

#include <TMC2130Stepper.h>
TMC2130Stepper TMC2130 = TMC2130Stepper(EN_PIN, DIR_PIN, STEP_PIN, CS_PIN);


void spin_degree(int _inputDeg){
  
  int absDeg = abs(_inputDeg);
  int remainder = absDeg % 360;
  int quotient = (int)(absDeg/360);
  
  if(_inputDeg < 0){
    TMC2130.shaft_dir(1);
  } else {
    TMC2130.shaft_dir(0);
  }

  //For full turns we must rotate in
  for(int ii = 0; ii < quotient; ++ii){
    for(int i = 0; i < STEPS_IN_DEG * 360; ++i){
      digitalWrite(STEP_PIN, HIGH);
      delayMicroseconds(10);
      digitalWrite(STEP_PIN, LOW);
      delayMicroseconds(10);
    }
  
    for(int i = 0; i < STEPS_IN_DEG * 360; ++i){
      digitalWrite(STEP_PIN, HIGH);
      delayMicroseconds(10);
      digitalWrite(STEP_PIN, LOW);
      delayMicroseconds(10);
    }
  }

  for(int i = 0; i < STEPS_IN_DEG * remainder; ++i){
      digitalWrite(STEP_PIN, HIGH);
      delayMicroseconds(10);
      digitalWrite(STEP_PIN, LOW);
      delayMicroseconds(10);
    }
  
    for(int i = 0; i < STEPS_IN_DEG * remainder; ++i){
      digitalWrite(STEP_PIN, HIGH);
      delayMicroseconds(10);
      digitalWrite(STEP_PIN, LOW);
      delayMicroseconds(10);
    }
}

void setup() {
  Serial.begin(9600);
  TMC2130.begin(); // Initiate pins and registeries
  TMC2130.SilentStepStick2130(600); // Set stepper current to 600mA
  TMC2130.stealthChop(1); // Enable extremely quiet stepping
  
  digitalWrite(EN_PIN, LOW);
}

void loop() {

  spin_degree(720);
  spin_degree(-360);
  delay(3000);

}

There’s also the question of why I’m writing my High/Low cycles twice… That’s because for some reason if I send too many of these to the stepper driver it will start rotating counter clock wise.

The next thing I’m going to have to do is create another adapter to fit my new stepper motor, and also figure out how to program it’s load detection in software so that I can get it to stop turning if it meets too much resistance. Once I have those things figured out, I can then modify my code to more accurately autodial the safe.

Third Update – (27-MAR-2019)

I decided to make an Arduino Uno Shield for the TCM2130 Silent Step Stick. I sent the PCB off to manufacture, and I should be getting it in about a week or so.

It looks pretty good. I decided to make an actual Arduino Uno shield because I can see using this driver as a prototype for other projects after this project. The TCM2130 just has a lot of really cool features that I want to explore. In the mean time I’m going to get back to 3D printing an adapter to the safe for use with a stepper instead of a servo.

Fourth Update – (16-APR-2019)

Sure enough I got my boards in the mail. I received the boards and then ordered parts to populate the shield. What I didn’t anticipate were that pins 1 and (2 and 3) would need to be swapped. This lead me to cut some traces on the PCB and use bus wire as a fix. I also thought I had an 0805 SMD LED booklet lying around, but I guess not. I’ll have to order one now.

I’m not too upset about this not being 100%. This is a prototype after all. I didn’t want to spend too much time overthinking the design since after making this shield I’ve learned the following:

  1. The annular rings under the driver headers need to be bigger. Soldering them as they are right now is possible, but not as easy as the shield headers.
  2. The Terminal blocks need to be moved away from their current position as they can make contact with the USB A connector on an Arduino Uno. I’m using Kapton tape right now to insulate the terminal blocks, but that’s got to change.
  3. The name of the stepper shield should appear via silk screen somewhere on the board.
  4. Footprints should be 1206, not 0805. There’s plenty of room on the board and I think if I were to hand this to someone else they might appreciate the larger components.
  5. Pin 1 must be swapped with Pins 2 and 3 on the barrel jack.
  6. I should add some additional silk screening to indicate component directions.

Once I’m done with this project I think I’ll make a few kits and sell them. Not sure if there will be any interest, but you never know until you try.

Leave a Reply

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