esp8266+OLED屏显示cube水平旋转效果

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了esp8266+OLED屏显示cube水平旋转效果相关的知识,希望对你有一定的参考价值。

esp8266+OLED屏显示cube水平旋转效果

  • 代码:

#include "SH1106Wire.h" //1.3寸用这个
//#include "SSD1306Wire.h"    //0.96寸用这个
#include "OLEDDisplayUi.h"

#if defined(ESP8266)    //OLED引脚定义
const int SDA_PIN = D2; //对应nodemcu接D5或者D1,,wemosD1mini的D2
const int SDC_PIN = D1; //对应nodemcu接D6或者D2,,wemosD1mini的D5
#else
const int SDA_PIN = D1; //对应nodemcu接D5或者D1
const int SCL = D2;     //对应nodemcu接D6或者D2
#endif

const int I2C_DISPLAY_ADDRESS = 0x3c;                      //I2c地址默认

SH1106Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); // 1.3寸用这个
//SSD1306Wire     display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);   // 0.96寸用这个

 OLEDDisplayUi ui     ( &display );

 typedef struct Vertex{
  int location[3];
}MyVertex;

typedef struct Edge{
  char connection[2];
}MyEdge;

typedef struct Object{
  int numv;
  int nume;
  MyVertex* v;
  MyEdge* e;
  float quat[4];
  float offset[3];
}MyObject;


static MyVertex mp[] ={{-20,-20,-20},{-20,20,-20},{20,20,-20},{20,-20,-20},{-20,-20,20},{-20,20,20},{20,20,20},{20,-20,20}};

static MyEdge me[] ={{0, 1}, {1, 2},{2, 3},{3, 0}, {4, 5},{5, 6},{6, 7},{7, 4},{0, 4},{1, 5},{2, 6},{3, 7}};
MyObject  obj = {8, 12, mp, me,{1,0,0,0},{0,0,0}};

void oledcube(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);


float* matconv(float* a,float b[3][3]){//计算矩阵乘法
  float res[3];
  for(int i=0;i<3;i++)
    res[i]=b[i][0]*a[0]+b[i][1]*a[1]+b[i][2]*a[2];
  for(int i=0;i<3;i++)a[i]=res[i];
  return a;
}

void rotate(float* obj,float x,float y,float z){//旋转该向量
  x/=PI;y/=PI;z/=PI;
  float rz[3][3]={{cos(z),-sin(z),0},{sin(z),cos(z),0},{0,0,1}};
  float ry[3][3]={{1,0,0},{0,cos(y),-sin(y)},{0,sin(y),cos(y)}};
  float rx[3][3]={{cos(x),0,sin(x)},{0,1,0},{-sin(x),0,cos(x)}};
  matconv(matconv(matconv(obj,rz),ry),rx);
}

 FrameCallback frames[] = {oledcube}; //
//页面数量,图形绘制回调函数数组,

const int numberOfFrames = 1; // 显示16屏内容信息

void setup()   {
  Serial.begin(9600);
  display.init();
  display.clear();
  display.display();
  //    display.flipScreenVertically(); //屏幕翻转
  // display.mirrorScreen();//使用分光棱镜显示需要用到此函数
  display.setContrast(240); //屏幕亮度
  delay(1000);
 ui.setTargetFPS(80);                   //刷新频率
  ui.disableAllIndicators();             //不显示页码小点。
 ui.enableAutoTransition();
  ui.setFrameAnimation(SLIDE_LEFT);           //切屏方向
  ui.setAutoTransitionForwards();//设置自动过渡方向,
  ui.setFrames(frames, numberOfFrames);       // 设置框架和显示屏幕内容数
  ui.setTimePerFrame(5000);                   //设置切换时间
  ui.setTimePerTransition(500);//设置转场大约所需要时间
  // ui.setOverlays(overlays, numberOfOverlays); //设置覆盖的画面数  
  ui.init();// UI负责初始化显示
 
  moveObject(obj,64,32,0);
  renderObject(obj);

}
 
static float qdelta[4]={0.999847695f,0,0.0174524f,0};
static float qview[4]={0.99144486f,0.13052619f,0,0};
static float qtemp[4];
void loop()
{
  int remainingTimeBudget = ui.update(); //剩余时间预算
  if (remainingTimeBudget > 0)
  {
    //你可以在这里工作如果你低于你的时间预算。
    delay(remainingTimeBudget);
  }

}
void oledcube(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y){
     qproduct(qdelta,obj.quat,qtemp);  
  rotateObject(obj,qtemp);
  display->clear();
  renderObject(obj);
display->display();
  delay(10);
}
 
void moveObject(MyObject &mo, float x, float y, float z) {
  mo.offset[0]=x;
  mo.offset[1]=y;
  mo.offset[2]=z;
}
 
void rotateObject(MyObject &mo, float* q) {
  mo.quat[0]=q[0];
  mo.quat[1]=q[1];
  mo.quat[2]=q[2];
  mo.quat[3]=q[3];
}
 
void renderObject(MyObject &mo) {
  MyVertex* mv=new MyVertex[mo.numv];
 
  qproduct(qview,mo.quat,qtemp);
  qnormalized(qtemp);
 
  for (int i = 0; i < mo.numv; i++) {
    iqRot(qtemp,mo.v[i].location,mv[i].location);
    mv[i].location[0] += mo.offset[0];
    mv[i].location[1] += mo.offset[1];
    mv[i].location[2] += mo.offset[2];
  }
 
  for (int i = 0; i < mo.nume; i++) {
    int p1 = mo.e[i].connection[0];
    int p2 = mo.e[i].connection[1];
  display.drawLine(mv[p1].location[0], mv[p1].location[1], mv[p2].location[0], mv[p2].location[1]);
  }
  delete mv;
}
 
float iqRot(float q[],int v[],int result[]){
  float prod[4];
  prod[0] =  - q[1] * v[0] - q[2] * v[1] - q[3] * v[2];
  prod[1] = q[0] * v[0] + q[2] * v[2] - q[3] * v[1];
  prod[2] = q[0] * v[1] - q[1] * v[2] + q[3] * v[0];
  prod[3] = q[0] * v[2] + q[1] * v[1] - q[2] * v[0];
 
  result[0] = -prod[0] * q[1] + prod[1] * q[0] - prod[2] * q[3] + prod[3] * q[2];
  result[1] = -prod[0] * q[2] + prod[1] * q[3] + prod[2] * q[0] - prod[3] * q[1];
  result[2] = -prod[0] * q[3] - prod[1] * q[2] + prod[2] * q[1] + prod[3] * q[0];
}
 
void qproduct(const float* p, const float* q, float* qr) {
  qr[0] = p[0] * q[0] - p[1] * q[1] - p[2] * q[2] - p[3] * q[3];
  qr[1] = p[0] * q[1] + p[1] * q[0] + p[2] * q[3] - p[3] * q[2];
  qr[2] = p[0] * q[2] - p[1] * q[3] + p[2] * q[0] + p[3] * q[1];
  qr[3] = p[0] * q[3] + p[1] * q[2] - p[2] * q[1] + p[3] * q[0];
}
 
void qnormalized(float* q) {
  float invnorm;
  invnorm = fastinvsqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
  if (invnorm < 100000000) {
    q[0] *= invnorm;
    q[1] *= invnorm;
    q[2] *= invnorm;
    q[3] *= invnorm;
  } else {
    q[0] = 1;
    q[1] = 0;
    q[2] = 0;
    q[3] = 0;
  }
}
float fastinvsqrt(float x) {
  float halfx = 0.5f * x;
  float y = x;
  long i = *(long*)&y;
  i = 0x5f3759df - (i>>1);
  y = *(float*)&i;
  y = y * (1.5f - (halfx * y ## 利用MPU6050 + OLED屏显示cube3D矩形效果

OLED_I2C_3D_Cube for ESP8266

ESP8266嵌套Cube3D旋转动画(嵌套)

ESP8266 + 0.96“ I2C OLED双色屏显示

ESP8266 + oled I2C屏幕动态雪花效果显示实例程序

ESP8266 NodeMCU驱动OLED屏(SSD1306,4PIN,IIC)