我正在参加「构思开发 投稿大赛」概况请看:构思开发大赛来了!
前言
作为一个在互联网时代生长起来的人,怎么能忍受自己的爱车不支撑长途操控呢。
连我的小电驴都支撑手机挨近主动解锁,蓝牙/网络长途控车。而我的轿车却不支撑,实在是说不过去,所以萌发了自己改造一下让它支撑挨近主动解锁,一起能够长途控车。
基本情况及全体完结思路
基本需求
开端我想完结的功用只有一个:无需带着车钥匙,挨近车辆主动解锁,熄火后脱离车辆主动上锁。
当我萌宣布这个主意时,第一时间想到的便是魔改车钥匙来完结我想要的功用。
前期我在 V2 发了一个帖子,原车不支撑手机解锁,可是支撑钥匙感应解锁,有没有或许改装成支撑手机解锁的?试图寻求有经历的大佬的灵感,可是收效甚微。后来灵机一动,上某宝搜索了一下,终究找到了大量和我主意共同的改装套件。这证明我的主意是可行的,而且现已有前人实践过了。
至于我为什么不直接在某宝买成品而是要自己完结,无非三个理由:
- 淘宝成品略贵,我认为不值这个价钱
- 想要完结更多的功用,而套件只提供了固定的一两个功用,无法自在扩展
- 想自己折腾
改装思路
确认了方案可行,下一步便是实践测验。
钥匙支撑的功用
经过查阅资料,我的车钥匙支撑如下功用:
- 挨近车辆后车辆主动解锁(需求拉主驾门把手激活)
- 远离车辆后车辆主动上锁
- 长按解锁按键能够一键翻开车窗(轿车未发动时)
- 长按上锁键则反之
- 接连短按两次多功用按键敞开寻车
- 短按上锁按键后长按多功用按键,长途发动车辆
- 长按多功用按键可退出长途发动
改装方案概述
我的改装思路是,将车钥匙主板拆出,从头焊接一块开发板,并由这块开发板接纳操控车钥匙的电源和按键。
然后将改装后的开发板放入车内,平时车钥匙电源设置为断开状态,在接纳到手机的指令或检测到手机信号强度到必定阈值后给钥匙供电并配合接通特定按键完结感应解锁。而锁车则反之。
供电方案挑选
前期测验了我的车支撑的取电接口:USB充电口、点烟器、后视镜预留取电接口、OBD取电、保险盒取电。
经过测验,USB口、点烟器、预留接口均不支撑熄火后持续供电,故抛弃运用。
仅剩余 OBD 和 保险盒 取电,可是保险盒取电过于费事,故抛弃。
而 OBD 支撑熄火持续供电,且只需求运用转接头即可直接转接成 USB 口,运用起来很便利。
故终究挑选 OBD 供电作为供电方案。
资料准备与技能挑选
确认了改装思路,接下来便是挑选改装资料。
线材,焊接工具等周边资料不过多赘述。
主要是需求选定一块合适的开发板。
根据我的需求,这块开发板应该至少支撑蓝牙、至少有四个可用的 IO 接口(别离用于操控车钥匙电源、车钥匙上锁键、车钥匙解锁键、车钥匙多功用按键)、价格应该尽或许的低。
开端我方案挑选 Arduino NANO 配合蓝牙模块,可是这样本钱过高,现已快挨近某宝成品模块的价格了,后来在B大佬的推荐下,我购买了 ESP32C3 开发板,而且调配 MicroPython 进行开发。ESP32C3的优势在于价格极其廉价,一块仅需9.9还包邮。(在我写这篇文章的时分,它现已提价了)、一起支撑蓝牙(BLE)和WiFi、全体体积很小。
可是,经过一段时间的熟悉和测验,我发现 ESP32C3 仅支撑 BLE 不支撑经典蓝牙,而且 MicroPython 关于 BLE 的支撑也不完善,不支撑配对设备,这就导致我无法验证设备真伪,由于现在智能手机的 MAC 都是随机的,除非你和手机完结配对,否则无法得到手机的真实 MAC。
因此我开端将目光转向经典蓝牙,后来仍是在B大佬的推荐下,我挑选了 ESP32 开发板,优势依然是廉价,20元多一点包邮,而且支撑经典蓝牙和BLE双模,一起也支撑WIFI。
可是这次我没有挑选 MicroPython 作为开发渠道,而是挑选了 Arduino。理由也很简略,MicroPython 不支撑 ESP32 的经典蓝牙……
可行性研讨测验
硬件焊接
拆开车钥匙主板后,结构十分简略,一眼就能看出各个元器件的作用。
首要将主板的正负极供电别离焊接引出一条线,接下来把需求的按键也别离引出线就OK了。
有一点需求注意的是,由于按键焊点特别的小,十分不容易焊接,好在这块主板上贴心的打了十分多的测验用的触点,所以我直接把线焊在了检测点上。
此时出现了一个问题,按键应该焊接那两条线?
我首要想到的是白嫖某宝店家的成熟方案:
只不过我搜遍了某宝,几乎都是相同的焊接方式,可是他们都是四脚的按键,而我的是六脚按键啊,这能相同吗?
看来白嫖不成只能自己琢磨了,经过我用放大镜仔细研讨,发现其实这个按键只接了两脚,那么问题就不大了,不用关心它的完结原理,只要无脑把这两个脚引出即可。由于不论几脚的开关,一般来说都是坚持常开,按下按键后接通。
那么,我要如何完结模仿按键的接通与断开呢?
仍是在B大佬的推荐下,我购买了 NMOS 管,可是买的时分没注意看参数,买的 MOS 管是贴片 MOS 管,十分的小,压根没法焊接……还好我买 MOS 管时为了以防万一,随手买了两个继电器。已然 MOS 管无法运用,那就运用继电器吧。
反正中心原理便是要在接纳到 ESP32 的信号后接通从按键引出的两条线。
焊接并排线完结后如图:
(原谅我第一次焊接,全焊的糊成一团了)
硬件衔接方案
经过直接测验,上述焊接和排线都没有问题。
可是,当我把 ESP32 接上时却出问题了: ESP32 带不动这个继电器! 一旦发动继电器 ESP32 就直接过载重启……
接下来怎么办?测验倒腾比车钥匙触点还小的 MOS 管?仍是外接一个电源模块?
或许,能够直接抛弃接通按键两条引脚的方案,改为直接给衔接芯片一端的引脚高电平以模仿按下按键?
说干就干,快速写了一个 demo 后开端测验,结果发现并不可。
后来仍是在B大佬的提醒下,我才知道原来这个车钥匙按键是默认接通高电平,给低电平才触发按键功用。
详细如图示:
上述为按键的接线图,实践上车钥匙只用了两个引脚,其间一个引脚直接引向电源负极,别的一个在串联电阻后引向芯片的某个引脚。
ps: 上面图像反了,电阻是串联在引向芯片这条线的。
按照这个方案,从头衔接后如图:
确认了按键实践上是给低电平触发后,衔接起来就简略多了,由于车钥匙电源和 ESP32 现已共地,所以现在只需求把按键引向芯片这个引脚衔接上 ESP32 ,默认给高电平,需求触发时给低电平即可,别的一条线不需求衔接任何东西,也不需求再外接继电器或 MOS 管。
对了,上图中的 LED 是用来确认车钥匙是否上电的,这个车钥匙太质朴了,没有任何提示(蜂鸣或者LED),我无法得知是否正常上电,所以我额定接了一个 LED 便利测验。
操控软件
操控软件直接运用的 Arduino 官方的蓝牙串口示例代码改的:
//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Richard Li - 2020
//
//This example creates a bridge between Serial and Classical Bluetooth (SPP with authentication)
//and also demonstrate that SerialBT have the same functionalities of a normal Serial
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
#endif
#define LED_CONNECT 2
#define LED_POWER 15
#define PIN_POWER 13
#define PIN_LOCK 12
#define PIN_LOOP 14
boolean isConnectDevice = false;
BluetoothSerial SerialBT;
boolean confirmRequestPending = true;
void BTConfirmRequestCallback(uint32_t numVal)
{
confirmRequestPending = true;
Serial.println(numVal);
}
void BTAuthCompleteCallback(boolean success)
{
confirmRequestPending = false;
if (success)
{
Serial.println("Pairing success!!");
}
else
{
Serial.println("Pairing failed, rejected by user!!");
}
}
// Bt_Status callback function
void Bt_Status (esp_spp_cb_event_t event, esp_spp_cb_param_t *param) {
if (event == ESP_SPP_SRV_OPEN_EVT) {
Serial.println ("Client Connected");
digitalWrite(LED_CONNECT, HIGH);
isConnectDevice = true;
confirmRequestPending = false;
// Do stuff if connected
}
else if (event == ESP_SPP_CLOSE_EVT ) {
Serial.println ("Client Disconnected");
digitalWrite(LED_CONNECT, LOW);
isConnectDevice = false;
// Do stuff if not connected
}
}
void get_start() {
digitalWrite(LED_POWER, HIGH);
digitalWrite(PIN_POWER, HIGH);
}
void cut_power() {
digitalWrite(LED_POWER, LOW);
digitalWrite(PIN_POWER, LOW);
}
void lock_car() {
digitalWrite(PIN_LOCK, LOW);
delay(500);
digitalWrite(PIN_LOCK, HIGH);
delay(10000);
digitalWrite(LED_POWER, LOW);
digitalWrite(PIN_POWER, LOW);
}
void luncher_car() {
digitalWrite(PIN_LOCK, LOW);
delay(300);
digitalWrite(PIN_LOCK, HIGH);
delay(1000);
digitalWrite(PIN_LOOP, LOW);
delay(8000);
digitalWrite(PIN_LOOP, HIGH);
}
void shut_down_car() {
digitalWrite(PIN_LOOP, LOW);
delay(8000);
digitalWrite(PIN_LOOP, HIGH);
}
void find_my_car() {
digitalWrite(PIN_LOOP, LOW);
delay(200);
digitalWrite(PIN_LOOP, HIGH);
delay(300);
digitalWrite(PIN_LOOP, LOW);
delay(200);
digitalWrite(PIN_LOOP, HIGH);
}
void click_loop() {
digitalWrite(PIN_LOOP, LOW);
delay(200);
digitalWrite(PIN_LOOP, HIGH);
}
void click_lock() {
digitalWrite(PIN_LOCK, LOW);
delay(200);
digitalWrite(PIN_LOCK, HIGH);
}
void read_status() {
int power_value = digitalRead(PIN_POWER);
int loop_value = digitalRead(PIN_LOOP);
int lock_value = digitalRead(PIN_LOCK);
char s[200];
sprintf(s, "power %d, loop %d, lock %da\n", power_value, loop_value, lock_value);
SerialBT.print(s);
}
void setup()
{
Serial.begin(115200);
pinMode(LED_CONNECT, OUTPUT);
pinMode(LED_POWER, OUTPUT);
pinMode(PIN_POWER, OUTPUT);
pinMode(PIN_LOCK, OUTPUT);
pinMode(PIN_LOOP, OUTPUT);
digitalWrite(PIN_LOCK, HIGH);
digitalWrite(PIN_LOOP, HIGH);
SerialBT.enableSSP();
SerialBT.onConfirmRequest(BTConfirmRequestCallback);
SerialBT.onAuthComplete(BTAuthCompleteCallback);
// Define the Bt_Status callback
SerialBT.register_callback (Bt_Status);
SerialBT.begin("equationl's Auto"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop()
{
if (confirmRequestPending)
{
if (Serial.available())
{
int dat = Serial.read();
if (dat == '1')
{
SerialBT.confirmReply(true);
}
else
{
SerialBT.confirmReply(false);
}
}
}
else
{
if (Serial.available())
{
SerialBT.write(Serial.read());
}
if (SerialBT.available())
{
int msg = SerialBT.read();
Serial.write(msg);
if (msg == '1') {
get_start();
}
if (msg == '2') {
cut_power();
}
if (msg == '3') {
lock_car();
}
if (msg == '4') {
luncher_car();
}
if (msg == '5') {
shut_down_car();
}
if (msg == '6') {
find_my_car();
}
if (msg == '7') {
click_loop();
}
if (msg == '8') {
click_lock();
}
if (msg == 'r') {
read_status();
}
}
delay(5);
}
}
代码很简略,我就不逐个介绍了,大概说一下这段代码完结的功用:
- 接受其他设备的配对请求,而且配对需求校验避免任何人都能衔接(现在便是简略的接纳到串口发送的 ‘1’ 即视为校验经过,由于严厉意义上来说,除了我自己,没有人能够衔接 ESP32 的串口,所以这样就足够安全了,仅仅这样有个问题,无法便利的配对新设备)
- 接纳已配对的设备衔接后发送的指令,别离为:
指令 | 动作 | 阐明 |
---|---|---|
1 | 给车钥匙上电 | 需求上电才干持续下面的其他操作 |
2 | 断开车钥匙供电 | 无 |
3 | 上锁 | 触发上锁按键后,推迟 10s 断开车钥匙供电 |
4 | 长途焚烧 | 模仿触发短按上锁按键后长按多功用键 |
5 | 长途熄火 | 模仿触发长按多功用按键 |
6 | 寻车 | 模仿双击多功用按键 |
7 | 触发多功用按键 | 无 |
8 | 触发上锁按键 | 无 |
r | 回来各个 IO 口状态 | 经过蓝牙串口回来当前 IO 口状态 |
终究作用
终究完结作用能够看我在 B站 的这个视频: 【改装车钥匙完结手机操控演示-哔哩哔哩】 (视频没拍好,或许需求戴上耳机才干听见发动机的声音)
视频里边只演示了经过手机操控长途焚烧这一个功用,可是实践上表中的功用经过测验都是可用的。
缺点与后续
缺点
由于这次仅仅为了验证手机操控的可行性,所以没有做太多功用,只做了手动触发按键测验是否可行。
别的,在测验中我发现了两点比较致命的问题:
- 钥匙在车内时无法运用感应解锁功用,有必要触发解锁按钮才干解锁车辆
- 钥匙在车内时无法触发长途焚烧功用(上述演示视频拍摄时,我把测验模块放在了车外面,没放车内)
关于问题 1 ,能够经过触发解锁按键来替代,问题不大。
关于问题 2,为了安全考虑,也为了便利供电,模块有必要放置在车内,所以这个问题暂时无解,或许需求抛弃;或者也能够想办法把车钥匙的天线延长到车外以欺骗车辆的钥匙位置感知功用。
后期方案
1.感应解锁 添加手机挨近车辆主动解锁,我的主意是能够利用蓝牙的 RSSI 感知手机与模块的距离,到达必定阈值后主动解锁。一起手机脱离模块后主动上锁。
2.手动衔接 当前已完结的手动衔接模块触发相应功用也予以保留,不过应该在这个基础上添加能够设置一些参数,例如感应距离,按键触发时间,解锁时是否同步焚烧或翻开窗户(焚烧后车辆会主动敞开空调,能够在夏天主动提前降温,开窗同理)。
3.优化配对 应该优化一下配对新的手机,在保证安全的情况下尽或许简化配对新手机的流程、
4.真长途操控 后期能够添加一个4G模块完结真正的长途操控,不过现在这个功用暂时想不到有完结它的必要,除了夏天在出门前先在家里长途焚烧给车辆降温外,好像的确没有其他的优势。
原文发布于我的博客:likehide.com