改进版代码的github地址如下,读取并记录到本地文件。https://github.com/hanjintao1996/jy61-/tree/master

如有帮助请在github点赞,感激不尽。

#define IOBEGIN 22 
#define IOEND 53               //定义初始化的IO口
// the setup function runs once when you press reset or power the board
void setup() {
    Serial.begin(9600);         //初始化端口
    Serial.print("Ready");
    for(int i=IOBEGIN;i<=IOEND;i++)
    {  
        
        pinMode(i,OUTPUT);
    } 
}
 
// the loop function runs over and over again forever
void loop() {
  if(Serial.available()){
   char ch = Serial.read();        //读取串口
   Serial.print(ch);
   switch(ch){                     //根据传入信息判断工作模式
   case'1':
   digitalWrite(22,HIGH);
   digitalWrite(23,HIGH);
   digitalWrite(24,HIGH);
   digitalWrite(25,HIGH);
   digitalWrite(26,HIGH);
   digitalWrite(27,HIGH);
   break;
   case'2':
   digitalWrite(22,LOW);
   digitalWrite(23,LOW);
   digitalWrite(24,LOW);
   digitalWrite(25,LOW);
   digitalWrite(26,LOW);
   digitalWrite(27,LOW);
   break;
}}}


因为之前用原始的方法进行数据的读取,导致在出现丢包之类的情况发生的时候会出现程序错误,在实验室师兄的帮助下,改写了之前的程序,具体情况参见注释:

import serial

ACCData=[0.0]*8
GYROData=[0.0]*8
AngleData=[0.0]*8         #定义三个数组,分别存储加速度角速度与角度的值

FrameState = 0            #通过0x后面的值判断属于哪一种情况
Bytenum = 0               #读取到这一段的第几位
CheckSum = 0              #求和校验位         

def DueData(inputdata):   #新增的核心程序,对读取的数据进行划分,各自读到对应的数组里
    global  FrameState    #在局部修改全局变量,要进行global的定义
    global  Bytenum
    global  CheckSum
    for data in inputdata:  #在输入的数据进行遍历
        if FrameState==0:   #当未确定状态的时候,进入以下判断
            if data==0x55 and Bytenum==0: #0x55位于第一位时候,开始读取数据,增大bytenum
                CheckSum=data
                Bytenum=1
                continue
            elif data==0x51 and Bytenum==1:#在byte不为0 且 识别到 0x51 的时候,改变frame
                CheckSum+=data
                FrameState=1
                Bytenum=2
            elif data==0x52 and Bytenum==1: #同理
                CheckSum+=data
                FrameState=2
                Bytenum=2
            elif data==0x53 and Bytenum==1:
                CheckSum+=data
                FrameState=3
                Bytenum=2
        elif FrameState==1: # acc    #已确定数据代表加速度
            if Bytenum<10:            # 读取8个数据
                ACCData[Bytenum-2]=data # 从0开始
                CheckSum+=data
                Bytenum+=1
            else:
                if data == (CheckSum&0xff):  #假如校验位正确
                    print(get_acc(ACCData))
                CheckSum=0                  #各数据归零,进行新的循环判断
                Bytenum=0
                FrameState=0
        elif FrameState==2: # gyro
            if Bytenum<10:
                GYROData[Bytenum-2]=data
                CheckSum+=data
                Bytenum+=1
            else:
                if data == (CheckSum&0xff):
                    print(get_gyro(GYROData))
                CheckSum=0
                Bytenum=0
                FrameState=0
        elif FrameState==3: # angle
            if Bytenum<10:
                AngleData[Bytenum-2]=data
                CheckSum+=data
                Bytenum+=1
            else:
                if data == (CheckSum&0xff):
                    print(get_angle(AngleData))
                CheckSum=0
                Bytenum=0
                FrameState=0


def get_acc(datahex):  #加速度
    axl = datahex[0]                                        
    axh = datahex[1]
    ayl = datahex[2]                                        
    ayh = datahex[3]
    azl = datahex[4]                                        
    azh = datahex[5]
    
    k_acc = 16

    acc_x = (axh << 8 | axl) / 32768 * k_acc
    acc_y = (ayh << 8 | ayl) / 32768 * k_acc
    acc_z = (azh << 8 | azl) / 32768 * k_acc
    if acc_x >= k_acc:
        acc_x -= 2 * k_acc
    if acc_y >= k_acc:
        acc_y -= 2 * k_acc
    if acc_z >= k_acc:
        acc_z-= 2 * k_acc
    
    return acc_x,acc_y,acc_z


def get_gyro(datahex):                                          #陀螺仪
    wxl = datahex[0]                                        
    wxh = datahex[1]
    wyl = datahex[2]                                        
    wyh = datahex[3]
    wzl = datahex[4]                                        
    wzh = datahex[5]
    k_gyro = 2000

    gyro_x = (wxh << 8 | wxl) / 32768 * k_gyro
    gyro_y = (wyh << 8 | wyl) / 32768 * k_gyro
    gyro_z = (wzh << 8 | wzl) / 32768 * k_gyro
    if gyro_x >= k_gyro:
        gyro_x -= 2 * k_gyro
    if gyro_y >= k_gyro:
        gyro_y -= 2 * k_gyro
    if gyro_z >=k_gyro:
        gyro_z-= 2 * k_gyro
    return gyro_x,gyro_y,gyro_z


def get_angle(datahex):                                 #角度
    rxl = datahex[0]                                        
    rxh = datahex[1]
    ryl = datahex[2]                                        
    ryh = datahex[3]
    rzl = datahex[4]                                        
    rzh = datahex[5]
    k_angle = 180

    angle_x = (rxh << 8 | rxl) / 32768 * k_angle
    angle_y = (ryh << 8 | ryl) / 32768 * k_angle
    angle_z = (rzh << 8 | rzl) / 32768 * k_angle
    if angle_x >= k_angle:
        angle_x -= 2 * k_angle
    if angle_y >= k_angle:
        angle_y -= 2 * k_angle
    if angle_z >=k_angle:
        angle_z-= 2 * k_angle

    return angle_x,angle_y,angle_z
 
 
if __name__=='__main__':  #主函数
    ser = serial.Serial("com8", 115200, timeout=0.5)  # 打开端口,改到循环外
    print(ser.is_open)
    while(1):
        #datahex = (ser.read(33).hex()) #之前转换成了字符串,一位变成了两位
        datahex = ser.read(33)       #不用hex()转化,直接用read读取的即是16进制
        DueData(datahex)            #调用程序进行处理

主要设计到数据读取的格式问题,进制问题,以及如何找到头数据,如何利用校验位。

另外,shift + tab可以往前缩进

#define IOBEGIN 22 
#define IOEND 53               //定义初始化的IO口
// the setup function runs once when you press reset or power the board
void setup() {
    Serial.begin(9600);         //初始化端口
    Serial.print("Ready");
    for(int i=IOBEGIN;i<=IOEND;i++)
    {  
        
        pinMode(i,OUTPUT);
    } 
}
 
// the loop function runs over and over again forever
void loop() {
  if(Serial.available()){
   char ch = Serial.read();        //读取串口
   Serial.print(ch);
   switch(ch){                     //根据传入信息判断工作模式
   case'1':
   digitalWrite(22,HIGH);
   digitalWrite(24,HIGH);
   break;
   case'2':
   digitalWrite(22,LOW);
   digitalWrite(24,LOW);
   break;
}}}
import serial
import time
import easygui

ACCData=[0.0]*8
GYROData=[0.0]*8
AngleData=[0.0]*8

FrameState = 0
Bytenum = 0
CheckSum = 0

shakedegree = 0

def DueData(inputdata):
    global  FrameState
    global  Bytenum
    global  CheckSum
    for data in inputdata:
        if FrameState==0:
            if data==0x55 and Bytenum==0:
                CheckSum=data
                Bytenum=1
                continue
            elif data==0x51 and Bytenum==1:
                CheckSum+=data
                FrameState=1
                Bytenum=2
            elif data==0x52 and Bytenum==1:
                CheckSum+=data
                FrameState=2
                Bytenum=2
            elif data==0x53 and Bytenum==1:
                CheckSum+=data
                FrameState=3
                Bytenum=2
        elif FrameState==1: # acc
            if Bytenum<10:
                ACCData[Bytenum-2]=data
                CheckSum+=data
                Bytenum+=1
            else:
                if data == (CheckSum&0xff):
                    #print(get_acc(ACCData))
                    accvalue = get_acc(ACCData)
                    return accvalue 
                CheckSum=0
                Bytenum=0
                FrameState=0
        elif FrameState==2: # gyro
            if Bytenum<10:
                GYROData[Bytenum-2]=data
                CheckSum+=data
                Bytenum+=1
            else:
                if data == (CheckSum&0xff):
                    pass
                    #print(get_gyro(GYROData))
                CheckSum=0
                Bytenum=0
                FrameState=0
        elif FrameState==3: # angle
            if Bytenum<10:
                AngleData[Bytenum-2]=data
                CheckSum+=data
                Bytenum+=1
            else:
                if data == (CheckSum&0xff):
                    pass#print(get_angle(AngleData))
                CheckSum=0
                Bytenum=0
                FrameState=0


def get_acc(datahex):  #加速度
    axl = datahex[0]                                        
    axh = datahex[1]
    ayl = datahex[2]                                        
    ayh = datahex[3]
    azl = datahex[4]                                        
    azh = datahex[5]
    
    k_acc = 16

    acc_x = (axh << 8 | axl) / 32768 * k_acc
    acc_y = (ayh << 8 | ayl) / 32768 * k_acc
    acc_z = (azh << 8 | azl) / 32768 * k_acc
    if acc_x >= k_acc:
        acc_x -= 2 * k_acc
    if acc_y >= k_acc:
        acc_y -= 2 * k_acc
    if acc_z >= k_acc:
        acc_z-= 2 * k_acc
    
    acc = [acc_x,acc_y,acc_z]
    return acc


def get_gyro(datahex):                                          #陀螺仪
    wxl = datahex[0]                                        
    wxh = datahex[1]
    wyl = datahex[2]                                        
    wyh = datahex[3]
    wzl = datahex[4]                                        
    wzh = datahex[5]
    k_gyro = 2000

    gyro_x = (wxh << 8 | wxl) / 32768 * k_gyro
    gyro_y = (wyh << 8 | wyl) / 32768 * k_gyro
    gyro_z = (wzh << 8 | wzl) / 32768 * k_gyro
    if gyro_x >= k_gyro:
        gyro_x -= 2 * k_gyro
    if gyro_y >= k_gyro:
        gyro_y -= 2 * k_gyro
    if gyro_z >=k_gyro:
        gyro_z-= 2 * k_gyro
    return gyro_x,gyro_y,gyro_z


def get_angle(datahex):                                 #角度
    rxl = datahex[0]                                        
    rxh = datahex[1]
    ryl = datahex[2]                                        
    ryh = datahex[3]
    rzl = datahex[4]                                        
    rzh = datahex[5]
    k_angle = 180

    angle_x = (rxh << 8 | rxl) / 32768 * k_angle
    angle_y = (ryh << 8 | ryl) / 32768 * k_angle
    angle_z = (rzh << 8 | rzl) / 32768 * k_angle
    if angle_x >= k_angle:
        angle_x -= 2 * k_angle
    if angle_y >= k_angle:
        angle_y -= 2 * k_angle
    if angle_z >=k_angle:
        angle_z-= 2 * k_angle

    return angle_x,angle_y,angle_z
 
def shakecharge(self):                #震颤判断函数
    ifshake = 0           #震颤次数
    ifshake_0 =0          #是否归零
    limit_a1 = 0.5
    limit_a2 = 0.8
    limit_a3 = 1.2        #震动分级
    interval_a = 5        #更新间隔
    acc_fre[0] = acc_fre[0] + 1 #重要!不能用变量,要用list
    global shakedegree
    shakedegree= shakedegree - 0.1    #十次平稳后切断
    print(acc_fre[0])
    if acc_fre[0] % interval_a == 0:  #采样
        acc_old[0] = acc[0]
        acc_old[1] = acc[1]
        acc_old[2] = acc[2]
    if acc_fre[0] % (interval_a * 10) == 0: #重置
        if ifshake == ifshake_0:           #如果没更新
            ifshake = ifshake_0 = 0
            print('——————重置!')
        else:                              #更新归零阈值
            ifshake_0 = ifshake
            print('******更新! ')
    else:
        pass
 
    if acc_fre[0] > interval_a*2 and (abs(acc[0] - acc_old[0]) > limit_a3 or acc[1] - acc_old[1] > limit_a3 or acc[2] - acc_old[2] > limit_a3) :
        print("===重度震颤!!!!!")   #LED灯亮
        shakedegree = 1
        #time.sleep(1)
        demo = b"1"
        ser1.write(demo)
        s = ser1.read(1)
        print(s)
    elif acc_fre[0] > interval_a*2 and (abs(acc[0] - acc_old[0]) > limit_a2 or acc[1] - acc_old[1] > limit_a2 or acc[2] - acc_old[2] > limit_a2):
        print("===中度震颤!!!!!")
        shakedegree = 1
        demo2 = b"1"
        ser1.write(demo2)
        #time.sleep(1)
        s = ser1.read(1)
        print(s)
        ifshake = 0
 
    elif acc_fre[0] > interval_a*2 and (abs(acc[0] - acc_old[0]) > limit_a1 or acc[1] - acc_old[1] > limit_a1 or acc[2] - acc_old[2] > limit_a1):
        print("===轻度震颤!!!!!")
        shakedegree = 1
        demo3 = b"1"
        ser1.write(demo3)
        #time.sleep(1)
        s = ser1.read(1)
        print(s)
        ifshake = 0
    else:
        shakedegree = shakedegree - 0.5
        print(shakedegree)
        if shakedegree < 0:
            demo4 = b"2"
            ser1.write(demo4)

if __name__=='__main__':
    ser1 = serial.Serial("com9", 9600)  # 打开Arduino端口
    #ser = serial.Serial("com8", 115200)  # 打开端口,改到循环外,避免一直开闭串口
    print(ser1.is_open)
    demo3 = b"1"
    ser1.write(demo3)
    acc_old = [0,0,0]
    acc_fre = [1]
    
    while(1):
        ser = serial.Serial("com8", 115200)  # 打开端口,放在循环内,可以避免连接不畅导致掉线
        datahex = ser.read(33)
        acc = DueData(datahex)
        if acc:
            print(acc)
            shakecharge(acc)
        #print(acc_fre)
        ser.close()
        time.sleep(0.2)