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矩形效果