基于LPR的智能地锁的实现

该博客介绍了全自动地锁产品,其通过车牌识别模块判断是否解锁。产品特点为全自动、识别率高、成本低、能耗小,优势是避免车位被占、减少停车步骤。还介绍了产品功能、软硬件系统设计及部分代码,同时指出串口连接不稳定、交互方式需改进等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 产品定位

本产品为全自动地锁,通过车牌识别模块采集识别车牌号并判断是否为可解锁车辆,并由地锁控制模块做出相应动作。

特点

全自动,识别率高,成本低,能耗小。

优势

车位主人无需顾虑车位被占,使车主停车步骤大幅减少,确定车主车辆的车牌号为唯一确定车主身份的方式,避免其他车主占位。

二.产品介绍

产品功能

在车主停车时通过摄像头拍摄的车辆的车牌号的照片,并判断它是否有权限在此车位停车,如果有权限,则自动打开地锁允许车辆停车。

软件系统设计

软件系统设计

硬件系统设计

硬件系统设计

部分代码

#Arduino部分
#include<LiquidCrystal.h>
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 53
#define RST_PIN 5
MFRC522 rfid(SS_PIN, RST_PIN); //实例化类
// 初始化数组用于存储读取到的NUID
byte nuidPICC[4];
byte id[4] = {198, 147, 88, 249};
LiquidCrystal lcd(30, 31, 35, 34, 33, 32);
int buttom = 10;
int isl = 0;
int servopin = 9; //设置舵机驱动脚到数字口9
int myangle;//定义角度变量
int pulsewidth;//定义脉宽变量
int inputPin = 6; // 定义超声波信号接收接口
int outputPin = 7; // 定义超声波信号发出接口
void servopulse(int servopin, int myangle) /*定义一个脉冲函数,用来模拟方式产生PWM值*/
{
  pulsewidth = (myangle * 11) + 500; //将角度转化为500-2480 的脉宽值
  digitalWrite(servopin, HIGH); //将舵机接口电平置高
  delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  digitalWrite(servopin, LOW); //将舵机接口电平置低
  delay(20 - pulsewidth / 1000); //延时周期内剩余时间
}
void duoji(char val)
{
  if (val > '0' && val <= '9') //判断收到数据值是否符合范围
  {
    val = val - '0'; //将ASCII码转换成数值,例'9'-'0'=0x39-0x30=9
    val = val * (180 / 9); //将数字转化为角度,例9*(180/9)=180
    for (int i = 0; i <= 50; i++) //产生PWM个数,等效延时以保证能转到响应角度
    {
      servopulse(servopin, val); //模拟产生PWM
    }
  }
}
void lock()
{
  duoji('1');
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Locked!!");
  delay(2000);
  isl = 1;
}
void unlock()
{
  duoji('5');
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("unlock");
  delay(10000);
  isl = 0;
}
float getdis()
{
  digitalWrite(outputPin, LOW); // 使发出发出超声波信号接口低电平2μs
  delayMicroseconds(2);
  digitalWrite(outputPin, HIGH); // 使发出发出超声波信号接口高电平10μs,这里是至少10μs
  delayMicroseconds(10);
  digitalWrite(outputPin, LOW); // 保持发出超声波信号接口低电平
  float distance = float(pulseIn(inputPin, HIGH)); //存储回波等待时间,
  distance = (distance * 17 ) / 1000;
  return distance;
}
int rf()
{ // 找卡
  if (!rfid.PICC_IsNewCardPresent())
    return 0;   // 验证NUID是否可读
  if (!rfid.PICC_ReadCardSerial())
    return 0;
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  // 检查是否MIFARE卡类型
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&      piccType != MFRC522::PICC_TYPE_MIFARE_1K &&    piccType != MFRC522::PICC_TYPE_MIFARE_4K)
  {
    return;
  }
  // 将NUID保存到nuidPICC数组
  for (byte i = 0; i < 4; i++)
  {
    nuidPICC[i] = rfid.uid.uidByte[i];
  }
  if (nuidPICC[0] == id[0])
  {
    rfid.PICC_HaltA();
    rfid.PCD_StopCrypto1();
    return 1;
  }

  // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡

  return 0;
}
void setup()
{
  lcd.begin(16, 2);
  pinMode(servopin, OUTPUT); //设定舵机接口为输出接口
  Serial.begin(9600);//设置波特率为9600
  pinMode(buttom, INPUT);
  pinMode(inputPin, INPUT);
  pinMode(outputPin, OUTPUT);
  SPI.begin(); // 初始化SPI总线
  rfid.PCD_Init(); // 初始化 MFRC522
}
int temp[4];
int j = 1;
int sysjudge = 1;
void loop()
{
  int id;
  if (sysjudge)
  {
j:
    if (getdis() >= 20)
    {
      delay(5000);
      if (getdis() >= 20)
      {
        if (!isl)
          lock();
        sysjudge = 0;
        return;
      }
    } else
    {
      goto j;
    }
  } else
  {
t:
    lcd.clear();
    lcd.print("wait for signal");
    delay(200);
    id = rf();
    if (id)
      goto op;
uu:
    if (getdis() <= 10)
    {
      Serial.print('o');
      while (1)
      {
        id = rf();
        if (id)
          goto op;
        char a='k';
        a = Serial.read();
        if (a == 'q')
        {
          break;
        }
        else if (a == 'k')
        {
          lcd.clear();
          lcd.print("wrong");
          delay(500);
          goto t;
        } else
        {
          goto t;
        }
      }
    }
    else
    {
      goto uu;
    }
op:
    if (isl)
      unlock();
    sysjudge = 1;
  }
}

# 上位机部分
from hyperlpr import *
import cv2
import time
import threading
import serial
from goto import with_goto

t = 0
a = 0


def destroyed():
    with open('information.txt', 'w') as f:
        f.write('')
    return 0


def write(s):  # 写入车牌信息
    with open('information.txt', 'a+') as f:
        f.writelines(s + '\n')
    return 0

def judge(s):  # 判断识别到的车牌号是否开锁
    with open('information.txt', 'r') as fr:
        list1 = fr.readlines()
    for i in range(0, len(list1)):
        list1[i] = list1[i].strip('\n')
        if s == list1[i]:
            print('识别成功')  # 加串口传开锁信号
            ser.write(b'q')
            return True
    ser.write(b'k')
    return False


def cont():
    global t
    t = 1


ser = serial.Serial('com4', 9600)
while 1:
    print(ser)
    while 1:
        a = ser.read()
        print(a)
        if a == b'o':
            break
    cap = cv2.VideoCapture(0)
    while (1):
        # get a frame
        ret, frame = cap.read()
        # show a frame
        # cv2.imshow("capture", frame)
        cv2.imwrite("demo1.png", frame)
        break
    cap.release()
    cv2.destroyAllWindows()
    # 读入图片
    image = cv2.imread("demo1.png")
    # 识别结果
    qqq = HyperLPR_PlateRecogntion(image)
    if qqq:
        strt = qqq[0][0][1:7]
        print(strt)
    else:
        ser.write(b'k')
        strt = ''
    ans = strt
    jt = 0
    judge(ans)

问题

  1. 串口连接不稳定 过多的数据会存在缓冲区
  2. 交互方式需要改进
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值