Skip to content

Instantly share code, notes, and snippets.

@Fordi
Last active May 11, 2022 08:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fordi/61ab5f6fe1ab736446832a564723b68e to your computer and use it in GitHub Desktop.
Save Fordi/61ab5f6fe1ab736446832a564723b68e to your computer and use it in GitHub Desktop.
#include <Stepper.h>
#include <math.h>
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <stdint.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int stepsPerRevolution = 2038;
const int rpm = 12;
const int servoPin = 6;
const int buttonPin = 4; // the number of the pushbutton pin
const int startButtonPin = 3; // the number of the pushbutton pin
const int unlockButton = 2; // the number of the pushbutton pin
const float stn = 50.95; // how many steps equal one number on a 40 number combo (2038/40)
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
bool startButtonDebounce = false;
bool comboFound = false;
// Create a variable to store the servo position:
int angle = 0;
// used to get back to 0 after each combination to avoid error creep
int stepsFromZero = 0;
uint8_t currentCombo[3] = {0, 0, 0};
Servo myservo;
Stepper stepper1 = Stepper(stepsPerRevolution, 8, 10, 9, 11);
void setup() {
pinMode(unlockButton, INPUT_PULLUP);
digitalWrite(unlockButton, HIGH);
attachInterrupt(digitalPinToInterrupt(unlockButton), codeFound, CHANGE); // trigger when button pressed, but not when released.
stepper1.setSpeed(rpm);
myservo.attach(servoPin);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
pinMode(startButtonPin, INPUT);
Serial.begin(9600);
myservo.write(0);
Serial.println("Program started!");
}
void loop() {
display.clearDisplay();
display.setTextSize(1); // text size
display.setTextColor(SSD1306_WHITE); // text color
display.setCursor(10, 10); // position to display
display.println("Hello World!"); // text to display
display.display(); // show on OLED
if (digitalRead(startButtonPin) == HIGH && startButtonDebounce == false) {
startButtonDebounce = true; // toggle button debounce
Serial.println("Button Pressed");
for (uint8_t thirdNumber = 0; thirdNumber < 40; n++) {
uint8_t firstNumber = thirdNumber % 4;
uint8_t secondNumber = firstNumber + 2;
uint8_t ogSecondNumber = secondNumber;
Serial.println(String(firstNumber) + "-" + String(secondNumber) + "-" + String(thirdNumber));
while (firstNumber < 40) {
while (secondNumber < 40) {
decombo(firstNumber, secondNumber, thirdNumber);
secondNumber = secondNumber + 4;
}
firstNumber = firstNumber + 4;
secondNumber = ogSecondNumber;
}
}
}
// this will prevent subsequent button presses
if (digitalRead(startButtonPin) == LOW && startButtonDebounce == true) {
startButtonDebounce = false;
}
// Button used to get to 0
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn Stepper
stepper1.step(-51);
Serial.println("move 1 number right");
delay(100);
}
}
void decombo(uint8_t firstNumber, uint8_t secondNumber, uint8_t thirdNumber) {
currentCombo = [firstNumber, secondNumber, thirdNumber];
display.clearDisplay();
display.setTextSize(1); // text size
display.setTextColor(SSD1306_WHITE); // text color
display.setCursor(2, 2); // position to display
display.println("Attempting:"); // text to display
display.setCursor(3, 15); // position to display
display.setTextSize(2);
display.println(String(firstNumber) + "-" + String(secondNumber) + "-" + String(thirdNumber));
display.display(); // show on OLED
delay(200);
// turn right twice to clear lock
stepper1.step(-stepsPerRevolution * 2);
delay(200);
// turn to first number - negative is right
turnToNumber(firstNumber - 40);
// calculate second number - one full rev left first + positive number
//turn to second number
int a = 0;
if (firstNumber > secondNumber) {
a = 40;
}
turnToNumber(a + (40 - (firstNumber - secondNumber)));
//turn to third number
if (secondNumber > thirdNumber) {
turnToNumber(thirdNumber - secondNumber);
}
else {
turnToNumber((thirdNumber - secondNumber) - 40);
}
// Try opening lock
myservo.write(100);
// Check if button pressed here
delay(1000);
myservo.write(10);
delay(2000);
// Check if combo is correct
if (comboFound) {
display.clearDisplay();
display.setTextSize(1); // text size
display.setTextColor(SSD1306_WHITE); // text color
display.setCursor(2, 2); // position to display
display.println("Code is:"); // text to display
display.setCursor(3, 15); // position to display
display.setTextSize(2);
display.println(String(firstNumber) + "-" + String(secondNumber) + "-" + String(thirdNumber));
display.display(); // show on OLED
exit(0);
}
// return to zero
// Serial.println("returning to zero");
// Serial.println(-stepsFromZero);
stepper1.step(-stepsFromZero);
// reset steps from zero because we are on zero
stepsFromZero = 0;
delay(500);
}
void turnToNumber(int number) {
float exactSteps = stn * number;
int steps = round(exactSteps);
stepsFromZero = stepsFromZero + steps;
stepper1.step(steps);
delay(200);
}
void codeFound() {
Serial.println("Combo found!");
Serial.println(Serial.println(String(currentCombo[0]) + "-" + String(currentCombo[1]) + "-" + String(currentCombo[2]));
comboFound = true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment