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:#
今天終於把自己第一次設計的單片機做出來了,一切運行正常,開心~