Work 8 (Oma projekt — Lockbox — Сейф)

Описание

Сейф — ящик для хранения ценностей, защищенный замочным кодом, при наборе правильной комбинации — открывается на 10 секунд.
Код сейфа в примере: 1324
Цифры считаются с верху в низ.

Использованые компоненты

4x кнопки
1x потенциометр
1x 1602 LCD экран
1x RGB LED
1x Servo мотор
7x 220 Ω резисторы
30x стандартные одиночные провода «папа-папа»

Код программы

#include <Servo.h>
#include <LiquidCrystal.h>

#define DEBUG
//#define DEBUG_SERVO

#define BUTTON_STATE_HANDLE(x) do { \
	if (digitalRead(LOCKBOX_NUPP_ ## x) == LOW) { \
		lcd.setCursor(button_counter++, 1); \
		lcd.print(x); \
		if (!(button_state & (1 << x)) || x == 4) { \
			button_state_old = button_state; \
			button_state ^= (1 << x); \
			delay(100); \
		} \
	} \
} while (false)

const int LED_PIN_RED = 3;
const int LED_PIN_GREEN = 2;

const int LOCKBOX_NUPP_1 = 13;
const int LOCKBOX_NUPP_2 = 12;
const int LOCKBOX_NUPP_3 = 11;
const int LOCKBOX_NUPP_4 = 10;

Servo servo_;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int button_state = 0, button_state_old = 0, button_counter = 0;
int lockbox_state = 0;
bool lockbox_open = false;

void setup()
{
  	pinMode(LED_PIN_RED, OUTPUT);
	pinMode(LED_PIN_GREEN, OUTPUT);

	pinMode(LOCKBOX_NUPP_1, INPUT);
	pinMode(LOCKBOX_NUPP_2, INPUT);
	pinMode(LOCKBOX_NUPP_3, INPUT);
	pinMode(LOCKBOX_NUPP_4, INPUT);

	servo_.attach(A0);

  	lcd.begin(16, 2);
	lcd.setCursor(0, 0);
	lcd.print("Close");

#ifdef DEBUG
	Serial.begin(9600);
#ifdef DEBUG_SERVO
	delay(100);
	servo_.write(180);
	delay(1000);
	servo_.write(90);
	delay(1000);
#endif
#endif
}

void clear_states()
{
	lockbox_state = button_state = button_state_old = button_counter = 0;
}

void open_lockbox()
{
  	digitalWrite(LED_PIN_RED, LOW);
	digitalWrite(LED_PIN_GREEN, HIGH);

	for (int pos = servo_.read(); pos < 180; pos += 2)
		servo_.write(pos > 180 ? 180 : pos);

	lcd.clear();
	lcd.setCursor(0, 0);
	lcd.print("Open ");

	delay(1000);
}

void close_lockbox()
{
  	digitalWrite(LED_PIN_RED, HIGH);
	digitalWrite(LED_PIN_GREEN, LOW);

	for (int pos = servo_.read(); pos > 90; pos -= 2)
		servo_.write(pos < 90 ? 90 : pos);

	lcd.setCursor(0, 0);
	lcd.print("Close");

	delay(1000);
}

void loop()
{
#ifdef DEBUG
	Serial.println("---");
	Serial.println(button_state);

	delay(1000);
#endif

	BUTTON_STATE_HANDLE(1);
	BUTTON_STATE_HANDLE(2);
	BUTTON_STATE_HANDLE(3);
	BUTTON_STATE_HANDLE(4);

	// kood 1324

	if (button_state & 2 && button_state_old == 0 && lockbox_state == 0) {
		lockbox_state++;
	}

	if (button_state & 4 && button_state_old == 10 && lockbox_state == 2) {
		lockbox_state++;
	}

	if (button_state & 8 && button_state_old == 2 && lockbox_state == 1) {
		lockbox_state++;
	}

	if (button_state & 16 && button_state_old == 14 && lockbox_state == 3) {
		lockbox_state++;
	}

	if ((!(button_state & 16) && button_state_old & 16) || button_counter > 4) {
		// 2 korda nupp 4 = reset
		clear_states();
		lcd.clear();
		lcd.setCursor(0, 0);
		lcd.print("Close");
	}

	if (lockbox_state >= 4) {
		clear_states();

		open_lockbox();
		delay(10000); // Open for 10 sec
		close_lockbox();
	}

	delay(100);
}

Ссылка на проект в Tinkercad

https://www.tinkercad.com/things/adj2paSSVwR-brilliant-inari/editel?sharecode=m4Sl1HUV1aPXSdNiAxxBqo0vSU1z1yGnQAhPMzyhZrI