Решил впервые поработать с электроникой, а точнее с Arduino, и сделать электронный замок, который будет открываться по карточке.
Замок будет питаться от постоянного тока и иметь запасной источник питания (эта схема пока пробная и собрана на аккумуляторах 18650 и батарейках 1,5 в).
первая версия кода:
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Пин сброса RC522
#define SS_PIN 10 // Пин выбора RC522
#define LOCK_PIN 6 // для управления транзистором замка
MFRC522 mfrc522(SS_PIN, RST_PIN); // Создание MFRC522
byte validUID1[] = {0xC3, 0xAE, 0xD9, 0x2C};
byte validUID2[] = {0x44, 0xB9, 0xB4, 0x02};
void setup() {
Serial.begin(9600); // Serial для отладки
SPI.begin(); // SPI
mfrc522.PCD_Init(); // RC522
pinMode(LOCK_PIN, OUTPUT); // Настройка пина LOCK_PIN как выход
digitalWrite(LOCK_PIN, HIGH); // HIGH - подача напряжения
Serial.println("Замок закрыт.");
}
void loop() {
// Проверка наличия новой карты
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Чтение карты
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Выводим UID карты в Serial
Serial.print("Card UID:");
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
// Проверка UID карты
if (compareUID(mfrc522.uid.uidByte, validUID1) || compareUID(mfrc522.uid.uidByte, validUID2)) {
Serial.println("Access granted! Opening lock...");
digitalWrite(LOCK_PIN, LOW); // открываем замок
Serial.println("Замок открыт.");
delay(5000); // Задержка 5 секунд
digitalWrite(LOCK_PIN, HIGH); // (закрываем замок)
Serial.println("Замок закрыт.");
} else {
Serial.println("Access denied!");
}
// Останавливаем чтение карты
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
// для сравнения UID карты с разрешенным UID
bool compareUID(byte cardUID[], byte validUID[]) {
for (byte i = 0; i < mfrc522.uid.size; i++) { // Проверка по размеру UID
if (cardUID[i] != validUID[i]) {
return false;
}
}
return true;
}
вторая версия кода:
#include <SPI.h>
#include <MFRC522.h>
#define RELAY_PIN 2 // Пин управления реле
#define BATTERY_VOLTAGE_PIN A0 // Аналоговый пин для измерения напряжения батареи
#define ERROR_LED_PIN 13 // LED для индикации ошибки
#define OUTPUT_ENABLE_PIN 8 // Пин управления включением/выключением нагрузки #define PWM_PIN 9 // Пин для PWM управления (если есть
//Параметры батареи
#define MIN_BATTERY_VOLTAGE 10.5 // Минимальное напряжение батареи
#define MAX_BATTERY_VOLTAGE 12.6 // Максимальное напряжение батареи
#define REFERENCE_VOLTAGE 5.0 // Опорное напряжение Arduino
//Порог напряжения сети
#define MAIN_VOLTAGE_PRESENT 200 //Если аналоговый порт выдает больше этого значения - сеть есть.
#define MAIN_VOLTAGE_PIN A1 // Пин для измерения напряжения сети
#define RST_PIN 9 // Пин сброса RC522
#define SS_PIN 10 // Пин выбора RC522
#define LOCK_PIN 6 // для управления транзистором замка
MFRC522 mfrc522(SS_PIN, RST_PIN); // Создание MFRC522
bool errorState = false;
byte validUID1[] = {0xC3, 0xAE, 0xD9, 0x2C};
byte validUID2[] = {0x44, 0xB9, 0xB4, 0x02};
void setup() {
Serial.begin(9600);
pinMode(RELAY_PIN, OUTPUT);
pinMode(BATTERY_VOLTAGE_PIN, INPUT);
pinMode(ERROR_LED_PIN, OUTPUT);
pinMode(OUTPUT_ENABLE_PIN, OUTPUT);
pinMode(PWM_PIN, OUTPUT);
pinMode(MAIN_VOLTAGE_PIN, INPUT);
digitalWrite(RELAY_PIN, LOW); // LOW = Питание от сети
digitalWrite(OUTPUT_ENABLE_PIN, HIGH);//Включаем выход нагрузки если есть.
analogWrite(PWM_PIN, 255);//включаем нагрузку на максимум(если используем)
}
void loop() {
checkPowerSource();
checkBatteryState(); //Проверяем состояние батареи - чтобы не перезарядить ее
if (errorState) {
handleError();
}
//Дальнейший код управления системой, если нужно.
}
void checkPowerSource() {
if (isMainsPowerPresent()) {
// Есть напряжение в сети, питаемся от сети
switchToMains();
} else {
// Нет напряжения в сети, переключаемся на батарею
switchToBattery();
}
}
bool isMainsPowerPresent() {
// Используйте делитель напряжения для безопасного измерения напряжения сети
int mainsVoltageRaw = analogRead(MAIN_VOLTAGE_PIN);
if(mainsVoltageRaw > MAIN_VOLTAGE_PRESENT){
return true; //Сеть есть
} else {
return false;//Сети нет
}
}
void checkBatteryState() {
float batteryVoltage = measureBatteryVoltage();
Serial.print("Battery Voltage: ");
Serial.println(batteryVoltage);
if (batteryVoltage < MIN_BATTERY_VOLTAGE && isMainsPowerPresent() ) { Serial.println("Battery low, but mains are present.");
//Ничего не делаем, заряжаем.
}
else if (batteryVoltage > MAX_BATTERY_VOLTAGE && isMainsPowerPresent()) {
Serial.println("Battery OVERCHARGED turning off battery connection!");
digitalWrite(RELAY_PIN, LOW); //Возвращаемся к сети
errorState = true;
}
else{
errorState = false;
}
digitalWrite(ERROR_LED_PIN, errorState ? HIGH : LOW);
}
void switchToMains() {
digitalWrite(RELAY_PIN, LOW); // LOW = Питание от сети (Настройка зависит от типа реле!)
Serial.println("Switching to Mains Power");
}
void switchToBattery() {
digitalWrite(RELAY_PIN, HIGH); // HIGH = Питание от батареи (Настройка зависит от типа реле!)
Serial.println("Switching to Battery Power");
}
float measureBatteryVoltage() {
int sensorValue = analogRead(BATTERY_VOLTAGE_PIN);
float voltage = sensorValue * (REFERENCE_VOLTAGE / 1023.0);
return voltage;
}
void handleError() {
digitalWrite(OUTPUT_ENABLE_PIN, LOW);
analogWrite(PWM_PIN, 0);
// Мигаем LED при ошибке
static unsigned long lastBlink = 0;
static bool ledState = false;
if (millis() - lastBlink > 500) {
lastBlink = millis();
ledState = !ledState;
digitalWrite(ERROR_LED_PIN, ledState);
}
}
float measureSolarVoltage() {
return 0;
}
float measureSolarCurrent() {
Serial.begin(9600); // Serial для отладки
SPI.begin(); // SPI
mfrc522.PCD_Init(); // RC522
pinMode(LOCK_PIN, OUTPUT); // Настройка пина LOCK_PIN как выход
digitalWrite(LOCK_PIN, HIGH); // HIGH - подача напряжения
Serial.println("Замок закрыт.");
}
void loop() {
// Проверка наличия новой карты
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Чтение карты
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Выводим UID карты в Serial
Serial.print("Card UID:");
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
// Проверка UID карты
if (compareUID(mfrc522.uid.uidByte, validUID1) || compareUID(mfrc522.uid.uidByte, validUID2)) {
Serial.println("Access granted! Opening lock...");
digitalWrite(LOCK_PIN, LOW); // открываем замок
Serial.println("Замок открыт.");
delay(5000); // Задержка 5 секунд
digitalWrite(LOCK_PIN, HIGH); // (закрываем замок)
Serial.println("Замок закрыт.");
} else {
Serial.println("Access denied!");
}
// Останавливаем чтение карты
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
// для сравнения UID карты с разрешенным UID
bool compareUID(byte cardUID[], byte validUID[]) {
for (byte i = 0; i < mfrc522.uid.size; i++) { // Проверка по размеру UID
if (cardUID[i] != validUID[i]) {
return false;
}
}
return true;
}
третья версия кода:
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 9 // Пин сброса RC522
#define SS_PIN 10 // Пин выбора RC522
#define LOCK_PIN 6 // для управления транзистором замка
#define PWR_SW_PIN 7 // для управления PNP транзистором питания
#define VBAT_SENSE_PIN A0 // для контроля напряжения сети
MFRC522 mfrc522(SS_PIN, RST_PIN); // Создание MFRC522
byte validUID1[] = {0xC3, 0xAE, 0xD9, 0x2C};
byte validUID2[] = {0x44, 0xB9, 0xB4, 0x02};
bool isPowerBackup = false;
unsigned long lastPowerCheck = 0;
const unsigned long POWER_CHECK_INTERVAL = 1000; // Проверка питания каждую секунду
void setup() {
Serial.begin(9600);
pinMode(LOCK_PIN, OUTPUT);
digitalWrite(LOCK_PIN, HIGH); // Замок закрыт
pinMode(PWR_SW_PIN, OUTPUT);
digitalWrite(PWR_SW_PIN, HIGH); // Изначально питание от сети
SPI.begin();
mfrc522.PCD_Init();
Serial.println("Система запущена. Замок закрыт.");
}
void loop() {
// Проверка питания
if (millis() - lastPowerCheck > POWER_CHECK_INTERVAL) {
checkPowerSource();
lastPowerCheck = millis();
}
// Проверка наличия новой карты
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Чтение карты
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Выводим UID карты
Serial.print("Card UID:");
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
// Проверка UID карты
if (compareUID(mfrc522.uid.uidByte, validUID1) || compareUID(mfrc522.uid.uidByte, validUID2)) {
Serial.println("Access granted! Opening lock...");
digitalWrite(LOCK_PIN, LOW); // открываем замок
Serial.println("Замок открыт.");
delay(5000); // Задержка 5 секунд
digitalWrite(LOCK_PIN, HIGH); // закрываем замок
Serial.println("Замок закрыт.");
} else {
Serial.println("Access denied!");
}
// Останавливаем чтение карты
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
// Функция проверки источника питания
void checkPowerSource() {
int vbatValue = analogRead(VBAT_SENSE_PIN);
float voltage = vbatValue * (5.0 / 1023.0) * 2; // Предполагаем делитель 1:1
if (voltage < 4.5 && !isPowerBackup) { // Если сетевое питание пропало
Serial.println("Переключение на резервный аккумулятор!");
digitalWrite(PWR_SW_PIN, LOW); // Включаем питание от аккумулятора
isPowerBackup = true;
}
else if (voltage >= 4.7 && isPowerBackup) { // Если сетевое питание восстановилось
Serial.println("Переключение на сетевое питание!");
digitalWrite(PWR_SW_PIN, HIGH); // Возвращаемся к сетевому питанию
isPowerBackup = false;
}
}
// Функция сравнения UID
bool compareUID(byte cardUID[], byte validUID[]) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
if (cardUID[i] != validUID[i]) {
return false;
}
}
return true;
}