陀螺仪3D上位机&&串口不能直接发送负数解决方法

由于接触陀螺仪比较长时间了,一直有一个念想,就是做一个自己的陀螺仪3D模型显示,功夫不负有心人,终于某个早晨在一个技术群里发现了有processing这个软件可以比较简单的实现(虽然之前也知道C#等这些传统意义上的上位机豪强可以实现,但总归有些生疏隔阂一般,再一个也是基于时间成本考虑)。于是乎花了一天的时间将这个3D模型做了出来,效果还不错,嘻嘻🤭~

 

视频链接:https://www.bilibili.com/video/BV11y4y1m7t1

 

image.png

 

在这期间遇到了一个问题,在学长的帮助下成功解决,现在来描述一下这个具体过程:

首先有些东西必须描述清楚:

  1. 陀螺仪得出来得角度是有正有负
  2. 串口每次只能发1byte,也就是8bits

 

 

问题

在这两个大前提下,问题就慢慢显露了出来。首先1byte最大能表示2^8=255,难道还要我陀螺仪转的角度不超过255°不成,那显然是byte太刁蛮了,你byte表示不了这么多关我陀螺仪什么事对吧。这里就是第一个问题,陀螺仪得角度超过255时导致byte溢出又直接回到0,试着想一下3D模型上转了200多度了再继续转直接给你回到到0度,就像向日葵跟着太阳自东向西,第二天一个猛回头从西边甩到东边,这谁受得了?

 

第二个问题也呼应了标题,串口不能发负数的问题。这里要来一波小定义:byte数据类型(字节型)用一个字节(byte)储存,可区别256个数字,取值范围:0-255。byte是0-255的 无符号类型,所以不能表示负数。这也就是为什么串口发送数据发不过去的原因了。在3D的现象就是顺时针模型跟着动,逆时针就不动了。

 

解决

直接上代码吧,有缘人就看着🆗,反正笔记也是我自己看🐕

 

arduino的代码:

#include <MPU6050_tockn.h>

#include <Wire.h>

MPU6050 mpu6050(Wire);

int inByte = 0;                           // incoming serial byte

int pit,rol,yaw;                          //角度值

int pit_h,rol_h,yaw_h;                    //角度高八位

int pit_l,rol_l,yaw_l;                    //角度低八位

int pit_flag=0,rol_flag=0,yaw_flag=0;     //角度正负标志位

void setup()

{

 Serial.begin(115200);

 Wire.begin();

 mpu6050.begin();

 mpu6050.calcGyroOffsets(true);

 establishContact();                     // send a byte to establish contact until Processing responds  

}

void loop()

{

   mpu6050.update();

   pit = mpu6050.getAngleX();

   rol = mpu6050.getAngleY();

   yaw = mpu6050.getAngleZ();

   

/**********************************/

   if(pit > 255-1){

     pit_h = 255;

     pit_l = pit - 255;

     pit_flag = 0;

     }

   else if(pit>0 && pit<=255-1){

     pit_h = pit;

     pit_l = 0;  

     pit_flag = 0;

     }

   else if(pit < -255+1){

     pit_h = abs(-255);

     pit_l = abs(pit + 255);

     pit_flag = 1;

     }

   else{

     pit_h = abs(pit);

     pit_l = 0;

     pit_flag = 1;

     }

     

/**********************************/

   if(rol > 255-1){

     rol_h = 255;

     rol_l = rol - 255;

     rol_flag = 0;

     }

   else if(rol>0 && rol<=255-1){

     rol_h = rol;

     rol_l = 0;  

     rol_flag = 0;

     }

   else if(rol < -255+1){

     rol_h = abs(-255);

     rol_l = abs(rol + 255);

     rol_flag = 1;

     }

   else{

     rol_h = abs(rol);

     rol_l = 0;

     rol_flag = 1;

     }

     

/**********************************/

    if(yaw > 255-1){

     yaw_h = 255;

     yaw_l = yaw - 255;

     yaw_flag = 0;

     }

    else if(yaw>0 && yaw<=255-1){

     yaw_h = yaw;

     yaw_l = 0;

     yaw_flag = 0;

     }

    else if(yaw<-255+1){

     yaw_h = abs(-255);

     yaw_l = abs(yaw + 255);

     yaw_flag = 1;

     }

    else{

     yaw_h = abs(yaw);

     yaw_l = 0;

     yaw_flag = 1;

     }

   

   Serial.write(pit_h);

   Serial.write(pit_l);

   Serial.write(rol_h);

   Serial.write(rol_l);  

   Serial.write(yaw_h);  

   Serial.write(yaw_l);

   Serial.write(pit_flag);  

   Serial.write(rol_flag);  

   Serial.write(yaw_flag);  

/**************这里注释的供调试时看数据用*******************/

/*

   Serial.print("pit:");

   Serial.print(pit);

   Serial.print("    rol:");

   Serial.print(rol);

   Serial.print("    yaw:");

   Serial.println(yaw);

*/

}

/***************与processing确认连接*********************/

void establishContact() {

while (Serial.available() <= 0) {

     Serial.write('A');   // send a capital A

     delay(20);

 }

}

 

 

processing的代码:

import processing.serial.*;

Serial myPort;  

int[] serialInArray = new int[9];

int serialCount = 0;

int pit,rol,yaw;

int pit_last,rol_last,yaw_last;

boolean firstContact = false;

void setup() {

 size(640, 360, P3D);

 noStroke();

 

 String portName = Serial.list()[0];

 myPort = new Serial(this, portName, 115200);

}

float i = 0,j = 0,k = 0;

void draw() {

 lights();

 background(0);

 float cameraY = height/2.0;

 float fov = 0.12 * PI/2;

 float cameraZ = cameraY / tan(fov / 2.0);

 float aspect = float(width)/float(height);

 

 perspective(fov, aspect, cameraZ/10.0, cameraZ*10.0);

 

 translate(width/2, height/2, 0);

 rotateX(-rol*(PI/180));

 rotateY(yaw*(PI/180));

 rotateZ(-pit*(PI/180));

 

 fill(50,205,50);

 box(80, 10, 40);

}

void serialEvent(Serial myPort) {

 // read a byte from the serial port:

 int inByte = myPort.read();

 if (firstContact == false) {

   if (inByte == 'A') {  

     myPort.clear();          

     firstContact = true;      

     myPort.write('A');    

   }  

 }  

 else {

   serialInArray[serialCount] = inByte;

   serialCount++;

   if (serialCount > 9-1 ) {

     if(serialInArray[6] == 0)

       pit = serialInArray[0] +serialInArray[1];

     else

       pit = -(serialInArray[0] +serialInArray[1]);

       

     if(serialInArray[7] == 0)

       rol = serialInArray[2] +serialInArray[3];

     else

       rol = -(serialInArray[2] +serialInArray[3]);  

     

     if(serialInArray[8] == 0)

       yaw = serialInArray[4] +serialInArray[5];

     else

       yaw = -(serialInArray[4] +serialInArray[5]) ;

     

     serialCount = 0;

   }

 }

}

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值