DIY 个单片机,优雅地 “偷” 数据吧!#
起因#
最近因为个人项目需要,要将不允许联网的主机里数据库的数据发送至远程服务器。考虑到既然主机无法联网,不如用单片机作为中间人,通过串口将数据发送给单片机,再由联网的单片机将数据发送至服务器。这不就完美实现 “偷数据” 的操作了么!说干就干!
主机数据抓取#
既然要将数据发送至单片机,那首先我得先拿到数据。由于主机是离线且最高权限状态,果断装一个 python 环境(这样可以先分析一波数据,将异常值与有效的数据进行区分后选择发送),通过 pyserial 和 pymssql 进行数据抓取。详细的代码就不列了,说下在过程中碰到的一个坑。
最开始由于 python 程序中没有设计发送截至符,所以测试时,单片机无法确定数据截至位置在哪,导致发送至远端服务器的数据都是断断续续的。而在主程序中添加截至符发送后,完美解决该问题。
import serial
import json
import pymssql
def get_data():
"""
"""
return(data)
#后续增加截至符的发送
def deliver_data():
myChar='#'
#设置对应串口号与通讯波特率
ser = serial.Serial(port="COM4", baudrate=115200)
# 将json格式进行转换后,发送
data=get_data()
comdata=json.dumps(data)
write_len = ser.write(comdata.encode())
ser.write(myChar.encode())
print("串口发出{}个字节。".format(write_len))
ser.close()
def main():
deliver_data()
print('传输完毕')
if __name__=='__main__':
main()
对了,由于主机无法联网而且还是 windows7 操作系统,其实配置 python 环境也格外艰难!在趟过了各种坑后,成功运行抓数据的脚本时,我的眼角都湿润了。
单片机程序编写#
由于 esp8266 可以非常愉快的使用 arduino 框架进行开发,大大降低了我们这种萌新的上手难度。参考《arduino (2)-- 通过 ESP8266 模块实现串口接收数据,使用 TCP 协议进行局域网通信》文章,略作修改,就成功实现了串口数据的读取与发送。
#include "ESP8266WiFi.h"
#define led 2
const char *ssid = "wifi名称";
const char *password = "wifi密码";
const char *host = "服务器地址";
WiFiClient client;
const int tcpPort = 服务器端口;
static String comdata = "";
char myChar='#';
void setup()
{
Serial.begin(115200);
pinMode(led,OUTPUT);
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);//启动
//在这里检测是否成功连接到目标网络,未连接则阻塞。
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
}
//几句提示
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop()
{
/******************串口接受数据************************/
while (Serial.available() > 0 ) // 串口收到字符数大于零。
{
comdata = Serial.readStringUntil(myChar);
}
/******************串口打印数据************************/
if(comdata!="")//如果接受到数据
{
client.print(comdata);//向服务器发送数据
}
comdata="";//清空数据
if (client.connected()) //尝试访问目标地址,如果连接后LED灯灭,毕竟这种事情要低调
digitalWrite(led, HIGH);
else
digitalWrite(led, LOW);
while (!client.connected())//若未连接到服务端,则客户端进行连接。
{
if (!client.connect(host, tcpPort))//实际上这一步就在连接服务端,如果连接上,该函数返回true
{
Serial.println("连接中....");
delay(500);
}
}
}
事情到了这一步,整个流程其实已经完全跑通了,也成功实现了 “偷” 数据。但是主机后边插一根数据线,数据线再连接到一个大大的 NodeMCU 开发板上。实在太不优雅了!令我完全无法接受!
上淘宝看看有没有更简约的方案。似乎简单的 USB 转 TTL 通讯板 + ESP-01s 就能解决这个问题。果断买来换掉原方案。
然而,想象的很美好,这个方案却有一个致命问题,那就是通讯不稳定。导致主机的数据无法正确发送到单片机上。为此我还特地找来两台主机上分别实验了一下,其中一台能够正常通讯,另一台就一直失败。而旧方案相比之下就非常稳定,都能成功偷发数据。初步怀疑可能是新方案供电不稳定导致的,但是没有继续验证,如果有大佬懂得,麻烦告知一下,谢谢!
DIY 单片机#
既然现有方案无法满足我的需求,那只有一条路了!自己制作一个小巧玲珑,性能稳定的单片机。像我这样的萌新,直接开干,那肯定是不可能的了,还是得上开源硬件平台看看有没有大佬已经做过类似的项目。成功仿造一个,不就成了么!
usb-esp8266 - 嘉立创 EDA 开源硬件平台 (oshwhub.com)
感谢 moguiliue 大佬开源的项目,直接打板,开干!
大佬的方案确实可以!成品能够稳定运行,完美满足我的需求。不过过程中发现原设计 USB 公头位置的 PCB 会有干涉问题(不知道是不是我买的元器件不对🤦)。每套主板前端都要把干涉的位置用锉刀磨掉,才能焊上 USB 头。有点费力
而且这个方案只能满足最基本的数据通讯,没有将其他 GPIO 口引出,导致后续无法外接传感器或者显示屏。虽然优雅,但可玩性又差点意思。怎么办?
DIY 单片机 2.0#
既要优雅,又要能扩展,不如参考大佬的思路,自己再从头设计一版!
自己从头设计的开发板,将原有 CH340G 的方案改为 CH340C,省下外围晶振电路的空间,增加一个 4pin 母座用于引出 I2C 通讯。由于原设计的走线和布局很难改动了,只能重构整体。目前进度是已打板,但还未制作。希望等材料到了之后,这块自己第一次从头设计的单片机能成功运行!
2023/4/23 update:#
今天终于把自己第一次设计的单片机做出来了,一切运行正常,开心~