日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

移动端点对点获取WeMos D1上搭载的JY-901九轴振动加速度传感器加速度数据

發(fā)布時(shí)間:2023/12/29 编程问答 74 豆豆
生活随笔 收集整理的這篇文章主要介紹了 移动端点对点获取WeMos D1上搭载的JY-901九轴振动加速度传感器加速度数据 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 介紹

暑假里老師給布置了個(gè)任務(wù),希望能夠避開云端,使用移動(dòng)端來獲取 WeMos D1 上傳感器的數(shù)據(jù)。
那么這里大致的思路就是:

  • 通過串口獲取傳感器的數(shù)據(jù);
  • 在WeMos D1上開啟服務(wù)以供移動(dòng)端訪問
  • 編寫移動(dòng)端APP

2 系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)

2.1 系統(tǒng)整體架構(gòu)設(shè)計(jì)

本系統(tǒng)主要以WeMos D1為核心,在其上開啟Socket服務(wù),將通過串口獲得的傳感器數(shù)據(jù),提供給移動(dòng)端。

2.2 WeMos D1端

俗話說便宜沒好貨,WeMos D1這塊板子就符合這個(gè)道理,在博主拿到這塊板子和傳感器的時(shí)候,就發(fā)現(xiàn)了一個(gè)問題——板子的硬件串口就只有一個(gè),而且這個(gè)串口是另有用途的,所以不能用來獲取傳感器的數(shù)據(jù),因此在這里我們需要用到軟串口。所幸的是,在Arduino IDE這個(gè)編程環(huán)境中,已經(jīng)給我們提供了軟串口1的庫,我們只需要像硬件串口一樣對(duì)其他引腳進(jìn)行操作便可。對(duì)軟串口不懂的朋友,可以看下注釋1的鏈接。
這里博主選用了引腳0和引腳16來作為軟串口的RX和TX,如圖:

為了讓移動(dòng)端能夠點(diǎn)對(duì)點(diǎn)連接上WeMos D1,這里WeMos D1需要開啟AP模式,以使得移動(dòng)端連接其WiFi構(gòu)建局域網(wǎng)。
接著使用Arduino IDE中ESP8266的庫函數(shù)2來開啟Socket服務(wù)。不知道怎么開啟的,請(qǐng)看注釋2的鏈接。

2.3 移動(dòng)端

移動(dòng)端的構(gòu)建非常簡單,就是一個(gè)很普通的Socket客戶端。
其布局如圖所示:

因?yàn)橐苿?dòng)端博主還有其它用途,所以這個(gè)布局有點(diǎn)多余的功能,各位看客要寫的話,是不需要那么多的按鈕的。
這里IP和Port在代碼中已經(jīng)有默認(rèn)輸入,所以不輸入直接點(diǎn)擊采集數(shù)據(jù)即可。

3 代碼

3.1 獲取JY-901加速度數(shù)據(jù)

在購買JY-901九軸加速度傳感器時(shí),店家隨了一份傳感器資料過來,其中有一份用Arduino UNOR3獲取JY-901串口數(shù)據(jù)的代碼,該代碼使用Arduino IDE進(jìn)行編寫,首先看工程文件“JY901Serial.ino”:

#include <Wire.h> #include <JY901.h> /* Test on Uno R3. JY901 UnoR3 TX <---> 0(Rx) */ void setup() {Serial.begin(9600); }void loop() {//print received data. Data was received in serialEvent;Serial.print("Time:20");Serial.print(JY901.stcTime.ucYear);Serial.print("-");Serial.print(JY901.stcTime.ucMonth);Serial.print("-");Serial.print(JY901.stcTime.ucDay);Serial.print(" ");Serial.print(JY901.stcTime.ucHour);Serial.print(":");Serial.print(JY901.stcTime.ucMinute);Serial.print(":");Serial.println((float)JY901.stcTime.ucSecond+(float)JY901.stcTime.usMiliSecond/1000);Serial.print("Acc:");Serial.print((float)JY901.stcAcc.a[0]/32768*16);Serial.print(" ");Serial.print((float)JY901.stcAcc.a[1]/32768*16);Serial.print(" ");Serial.println((float)JY901.stcAcc.a[2]/32768*16);Serial.print("Gyro:");Serial.print((float)JY901.stcGyro.w[0]/32768*2000);Serial.print(" ");Serial.print((float)JY901.stcGyro.w[1]/32768*2000);Serial.print(" ");Serial.println((float)JY901.stcGyro.w[2]/32768*2000);Serial.print("Angle:");Serial.print((float)JY901.stcAngle.Angle[0]/32768*180);Serial.print(" ");Serial.print((float)JY901.stcAngle.Angle[1]/32768*180);Serial.print(" ");Serial.println((float)JY901.stcAngle.Angle[2]/32768*180);Serial.print("Mag:");Serial.print(JY901.stcMag.h[0]);Serial.print(" ");Serial.print(JY901.stcMag.h[1]);Serial.print(" ");Serial.println(JY901.stcMag.h[2]);Serial.print("Pressure:");Serial.print(JY901.stcPress.lPressure);Serial.print(" ");Serial.println((float)JY901.stcPress.lAltitude/100);Serial.print("DStatus:");Serial.print(JY901.stcDStatus.sDStatus[0]);Serial.print(" ");Serial.print(JY901.stcDStatus.sDStatus[1]);Serial.print(" ");Serial.print(JY901.stcDStatus.sDStatus[2]);Serial.print(" ");Serial.println(JY901.stcDStatus.sDStatus[3]);Serial.print("Longitude:");Serial.print(JY901.stcLonLat.lLon/10000000);Serial.print("Deg");Serial.print((double)(JY901.stcLonLat.lLon % 10000000)/1e5);Serial.print("m Lattitude:");Serial.print(JY901.stcLonLat.lLat/10000000);Serial.print("Deg");Serial.print((double)(JY901.stcLonLat.lLat % 10000000)/1e5);Serial.println("m");Serial.print("GPSHeight:");Serial.print((float)JY901.stcGPSV.sGPSHeight/10);Serial.print("m GPSYaw:");Serial.print((float)JY901.stcGPSV.sGPSYaw/10);Serial.print("Deg GPSV:");Serial.print((float)JY901.stcGPSV.lGPSVelocity/1000);Serial.println("km/h");Serial.println("");delay(500); } /* SerialEvent occurs whenever a new data comes in the hardware serial RX. This routine is run between each time loop() runs, so using delay inside loop can delay response. Multiple bytes of data may be available. */ void serialEvent() {while (Serial.available()) {JY901.CopeSerialData(Serial.read()); //Call JY901 data cope function} }

閱讀這么一個(gè)工程文件,第一步先看setup函數(shù),只有一個(gè)以波特率9600打開串口的操作,第二步看loop函數(shù),以本博客要獲取的加速度數(shù)據(jù)為例:

Serial.print("Acc:");Serial.print((float)JY901.stcAcc.a[0]/32768*16);Serial.print(" ");Serial.print((float)JY901.stcAcc.a[1]/32768*16);Serial.print(" ");Serial.println((float)JY901.stcAcc.a[2]/32768*16);

可看到loop函數(shù)中都是輸出對(duì)象JY901中數(shù)據(jù)的語句,由此推測JY901中存放的便是傳感器獲取到的數(shù)據(jù)。而后第三步看serialEvent函數(shù),這個(gè)函數(shù)的作用是獲取串口數(shù)據(jù),并用函數(shù)CopeSerialData對(duì)串口數(shù)據(jù)進(jìn)行處理并存入對(duì)象JY901中,注釋中也提到,serialEvent函數(shù)在loop函數(shù)循環(huán)時(shí),同步運(yùn)行。
下面是函數(shù)CopeSerialData源碼:

void CJY901 ::CopeSerialData(unsigned char ucData) {static unsigned char ucRxBuffer[250];static unsigned char ucRxCnt = 0; ucRxBuffer[ucRxCnt++]=ucData;if (ucRxBuffer[0]!=0x55) {ucRxCnt=0;return;}if (ucRxCnt<11) {return;}else{switch(ucRxBuffer[1]){case 0x50: memcpy(&stcTime,&ucRxBuffer[2],8);break;case 0x51: memcpy(&stcAcc,&ucRxBuffer[2],8);break;case 0x52: memcpy(&stcGyro,&ucRxBuffer[2],8);break;case 0x53: memcpy(&stcAngle,&ucRxBuffer[2],8);break;case 0x54: memcpy(&stcMag,&ucRxBuffer[2],8);break;case 0x55: memcpy(&stcDStatus,&ucRxBuffer[2],8);break;case 0x56: memcpy(&stcPress,&ucRxBuffer[2],8);break;case 0x57: memcpy(&stcLonLat,&ucRxBuffer[2],8);break;case 0x58: memcpy(&stcGPSV,&ucRxBuffer[2],8);break;}ucRxCnt=0;} }

因此只要能夠從串口讀到傳感器數(shù)據(jù),并用CopeSerialData函數(shù)對(duì)串口數(shù)據(jù)進(jìn)行處理,即可獲得需要的加速度數(shù)據(jù)。

3.2 在WeMos D1端啟動(dòng)服務(wù)

WeMos D1端代碼解釋請(qǐng)看注釋,代碼如下:

#include<ESP8266WiFi.h> #include<SoftwareSerial.h>#define AP_SSID "ESP8266WiFi" #define AP_PSW "88888888" #define SERVER_MAX 1IPAddress ip(192,168,4,22); IPAddress gateway(192,168,4,9); IPAddress subnet(255,255,255,0); SoftwareSerial mySerial(0,16);//軟串口定義,引腳0表示RX,引腳16表示TXWiFiServer server(8000);//定義socket服務(wù),端口8000 WiFiClient clients[SERVER_MAX];//管理與socket服務(wù)相連的客戶端 struct Acceleration {short acc[3];//因?yàn)橹恍枰铀俣葌鞲衅?#xff0c;所以不必如傳感器資料里一樣定義一個(gè)類,只需定義一個(gè)代表加速度的結(jié)構(gòu)體即可short Time; }acceleration;void setup() {mySerial.begin(9600);//開啟熱點(diǎn),移動(dòng)移動(dòng)端連接WiFi,與WeMos D1構(gòu)建局域網(wǎng)WiFi.mode(WIFI_AP);//修改模式為APWiFi.softAPConfig(ip, gateway, subnet);//設(shè)置AP相關(guān)網(wǎng)絡(luò)參數(shù)//啟動(dòng)socket服務(wù)server.begin();server.setNoDelay(true);//關(guān)閉小包合并包功能,不會(huì)延時(shí)發(fā)送數(shù)據(jù) }void loop() {uint8_t i;if(server.hasClient()){//如果有新客戶端連接,釋放客戶端列表中失效客戶端,并將新客戶端加入for(i=0;i<SERVER_MAX;i++){if(!clients[i]||!clients[i].connected()){if(clients[i]){clients[i].stop();}clients[i]=server.available();break;}}//若客戶端列表已滿,則拒絕新客戶端連接if(i==SERVER_MAX){WiFiClient _client=server.available();_client.stop();}}if(mySerial.available()){//讀取串口數(shù)據(jù),并使用CopeSerialData函數(shù)進(jìn)行處理if(CopeSerialData(mySerial.read())){//將獲取到的加速度數(shù)據(jù)經(jīng)過處理,通過socket發(fā)送給移動(dòng)端//在要發(fā)送的數(shù)據(jù)前后分別加上begin和end,以供移動(dòng)端更容易的識(shí)別數(shù)據(jù)頭尾char sbuf0[10]="begin ",sbuf1[10],sbuf2[10],sbuf3[10],sbuf4[10]="end\n";//將加速度類型由浮點(diǎn)型轉(zhuǎn)化為字符串dtostrf((float)acceleration.acc[0]/32768*16,2,2,sbuf1);dtostrf((float)acceleration.acc[1]/32768*16,2,2,sbuf2);dtostrf((float)acceleration.acc[2]/32768*16,2,2,sbuf3);//將加速度數(shù)據(jù)依次發(fā)送給每一個(gè)連接的客戶端for(i=0;i<SERVER_MAX;i++) {if(clients[i]&&clients[i].connected()) {clients[i].write(sbuf0, 6);clients[i].write(sbuf1, Judge(sbuf1));clients[i].write(sbuf2, Judge(sbuf2));clients[i].write(sbuf3, Judge(sbuf3));clients[i].write(sbuf4, 4);delay(1);}}}} }bool CopeSerialData(unsigned char ucData){static unsigned char ucRxBuffer[250];static unsigned char ucRxCnt = 0;ucRxBuffer[ucRxCnt++]=ucData;//JY-901傳感器規(guī)定有效數(shù)據(jù)由0x55開始if(ucRxBuffer[0]!=0x55){ucRxCnt = 0;return false;}//規(guī)定每11個(gè)數(shù)據(jù)為一次有效數(shù)據(jù)if(ucRxCnt<11){return false;}else{switch(ucRxBuffer[1]){//只需要加速度數(shù)據(jù),因此只需判斷0x51即可,若要獲取別的數(shù)據(jù),請(qǐng)看上面完整的CopeSerialData函數(shù)源碼case 0x51:memcpy(&acceleration,&ucRxBuffer[2],8);break;}ucRxCnt=0;return true;} }int Judge(char str[]){//計(jì)算socket連接中發(fā)送消息的長度,并在消息后面補(bǔ)上一個(gè)空格int len;for(len=0;len<10;len++){if(str[len]=='-'||(str[len]>='0'&&str[len]<='9')||str[len]=='.'){continue;}else{break;}}str[len]=' ';return len+1; }

3.3 移動(dòng)端獲取數(shù)據(jù)

移動(dòng)端最主要的就是一個(gè)socket連接問題,首先是socket建立:

protected void SocketConnect() {ip = inputIP.getText().toString();port = inputPort.getText().toString();//WeMos D1的IP地址和端口一開始就有默認(rèn)值,但也可由用戶自行輸入if (!IsIPPortLegal()) {Toast.makeText(MainActivity.this, "填寫不正確,已使用默認(rèn)IP和端口", Toast.LENGTH_SHORT).show();ip = "192.168.4.22";port = "8000";}//Android開發(fā)中socket連接必須要以線程的方式才可以進(jìn)行Thread thread = new Thread("Connect") {@Overridepublic void run() {super.run();if (!socketStatus) {try {socket = new Socket(ip, Integer.parseInt(port));if (socket != null) {//socket建立成功inputStream = socket.getInputStream();outputStream = socket.getOutputStream();//socketStatus是一個(gè)標(biāo)志,避免socket還未連接就用socket獲取數(shù)據(jù)的錯(cuò)誤socketStatus = true;}} catch (IOException e) {//socket建立失敗e.printStackTrace();}}}};thread.start(); }

接著就是利用socket獲取數(shù)據(jù):

protected void SocketGetData() {//同樣要新建一個(gè)線程Thread thread = new Thread("GetData") {@Overridepublic void run() {super.run();//判斷socket是否已經(jīng)連接while(!socketStatus){};if (socketStatus) {try {//獲取數(shù)據(jù)int len = 0;byte[] buf = new byte[1024];String tmp = "";int count = 0;while (getDataStatus && ((len = inputStream.read(buf)) != -1)) {String _tmp = new String(buf, 0, len);tmp += _tmp;count++;if (count == 10) {DealWithInputStream(tmp);count = 0;tmp = "";}}} catch (IOException e) {e.printStackTrace();}}}};thread.start(); }protected void DealWithInputStream(String tmp) {//按照與WeMos D1約定的格式,使用正則表達(dá)式提取加速度數(shù)據(jù),并存入文件dataCenter中Pattern pattern = Pattern.compile("begin .* end");Matcher matcher = pattern.matcher(tmp);FileOutputStream out = null;BufferedWriter writer = null;try {out = openFileOutput("dataCenter", Context.MODE_APPEND);writer = new BufferedWriter(new OutputStreamWriter(out));while (matcher.find()) {String _tmp = "" + System.currentTimeMillis() + " " + matcher.group() + (dataStatus ? " 1\r\n" : " 0\r\n");Log.d("tag", _tmp);writer.write(_tmp);}} catch (IOException e) {e.printStackTrace();} finally {try {if (writer != null) {writer.close();}} catch (IOException e) {e.printStackTrace();}} }

4 遇到的問題

  • 一開始使用Micropython寫的代碼,但是它沒有軟串口的庫,IIC有關(guān)的例子又少,沒看懂,后來換了C語言,用Arduino IDE編寫代碼,果然這種硬件有關(guān)的東西還是C語言好用啊。
  • 寫APP的時(shí)候,代碼明明沒錯(cuò),但是Socket卻總是建立失敗,而后排查問題發(fā)現(xiàn),是沒有獲取權(quán)限的問題。
  • 有天開機(jī)的時(shí)候電腦掛了【ps:神舟電腦傷不起…】,而后重裝電腦,將Android Studio重裝,導(dǎo)入之前的項(xiàng)目,發(fā)現(xiàn)怎么都運(yùn)行不了,谷歌了好久都沒解決,后來靈機(jī)一動(dòng),新建了個(gè)項(xiàng)目,把代碼復(fù)制粘貼進(jìn)去,運(yùn)行成功。
  • 在寫APP的時(shí)候數(shù)據(jù)持久化遇到了個(gè)問題,存下來的數(shù)據(jù)找不到了,谷歌后才知道是在data/data/包名/file文件夾下面
  • 暫時(shí)想不起別的問題了。
  • 各位看官有問題請(qǐng)留言。

  • 軟串口通信——SoftwareSerial庫的使用 ??

  • 博哥零基礎(chǔ)教你玩轉(zhuǎn)ESP8266 ??

  • 總結(jié)

    以上是生活随笔為你收集整理的移动端点对点获取WeMos D1上搭载的JY-901九轴振动加速度传感器加速度数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 性――交――性――乱a | 日本精品一区在线观看 | 911精品| 亚洲男女视频在线观看 | 26uuu精品一区二区 | 91青草视频 | 三上悠亚在线观看一区二区 | 好男人在线视频www 亚洲福利国产 | 少妇第一次交换又紧又爽 | 国产在线观看第一页 | 9久久精品 | 一区二区三区久久久久 | 欧美日韩卡一卡二 | 男女激情啪啪 | 欧美熟妇精品一区二区 | 日韩精品国产一区二区 | 中国 免费 av | 狠狠五月 | 色婷婷综合久久久久中文一区二区 | 国产成人免费视频网站 | 热逼视频| 91在线视频网址 | 国产91香蕉 | 欧美一级免费看 | 国产强伦人妻毛片 | 看一级黄色片 | 青青操国产视频 | 性高跟鞋xxxxhd人妖 | 国产日批视频在线观看 | 久久成人乱码欧美精品一区二区 | 黄色小说在线免费观看 | 在线免费黄色网址 | 麻豆精品一区二区三区 | 亚洲成熟毛多妇女av毛片 | 久久中文娱乐网 | 观看av| 少妇久久久久久被弄高潮 | 亚洲美女性视频 | 日本一区二区不卡视频 | av小说免费在线观看 | 羞辱极度绿帽vk | 国产婷婷在线观看 | 久草视频中文在线 | 熟睡人妻被讨厌的公侵犯 | www.五月婷婷.com | 97激情| 在线免费av网址 | 精品一区二区久久久久久久网站 | 国产a国产片国产 | 少妇人妻偷人精品无码视频 | 国产麻豆午夜三级精品 | 久久久久国产精品视频 | 久久久久久久久久久久国产精品 | 香蕉一级视频 | 国产精品久久久久久久久久免费 | 在线观看国产亚洲 | 中文字幕一区二区三区在线视频 | 精品亚洲永久免费精品 | 日本免费电影一区二区三区 | 中文字幕人成人乱码亚洲电影 | 国产精品无码av无码 | 成人精品一区二区三区电影黑人 | 国产资源在线视频 | 欧美人妖另类 | 国产精品666 | 丰满人妻综合一区二区三区 | 夜夜躁狠狠躁日日躁 | 日韩精品在线免费看 | 日韩欧美一区二区三区在线 | 亚洲网站视频 | 天堂综合网久久 | 欧美女优一区 | 女色综合 | 电车痴汉在线观看 | 国产精品igao视频 | 超碰免费成人 | xxxx 国产| 中文字幕爱爱 | 久久一级免费视频 | 男男成人高潮片免费网站 | 成人av一区二区在线观看 | 成人精品三级av在线看 | 肉色欧美久久久久久久免费看 | 欧美精品国产精品 | 华人永久免费 | 欧美成人一级片 | 91国偷自产一区二区三区老熟女 | 欧美日韩高清一区二区 国产亚洲免费看 | 国产一区二区观看 | 午夜福利理论片在线观看 | 岛国久久久| 爱爱小视频网站 | a国产 | 国产伦精品一区二区三区免.费 | 99re在线观看视频 | 黄色网页免费看 | 色妞视频| 黄p在线播放 | 欧美尹人 |