آردوینو آموزش آردوینو شتاب و ژایرو نمایشگر OLED پروژه های آردوینو

پروژه کنترل مدل ۳D در نمایشگر Oled با ماژول MPU6050 و برد آردوینو

نوشته شده توسط CiferTech

تا به امروز آموزش های متفاوتی با استفاده ماژول MPU6050 ژایرو منتشر شده، در این آموزش قصد داریم با استفاده از این ماژول پرکاربرد و همچنین نمایشگر Oled، یک مدل سه بعدی را کنترل کنیم با استفاده از تغییر مقادیر x, y که از ماژول ژایرو بدست می‌آید، وضعیت مدل تغییر می‌کند. به عبارتی جابجایی سه بعدی سنسور ژایرو به صورت تصویری روی نمایشگر OLED نمایان میشود. در این آموزش از برد آردوینو نانو به عنوان برد راه‌انداز استفاده خواهیم کرد. در ادامه این آموزش با مرجع تخصصی آردوینو به زبان فارسی، دیجی اسپارک همراه باشید.

خروجی ماژول MPU6050 روی نمایشگر OLED - دیجی اسپارک

 


ماژول MPU6050 ژایرو


حالا زمان این رسیده با سخت افزار اصلی این آموزش، یعنی MPU6050 بیشتر آشنا بشیم. Mpu6050 دارای یک شتاب سنج سه محوره و یک ژیروسکوپ سه محوره MEMS می‌باشد. دقت ماژول مبدل آنالوگ به دیجیتال ۱۲ بیت بوده و می‌تواند مقادیر X ، Y ، Z را در یک زمان اندازه گیری کند. بافر این ماژول از نوع FIFO با ظرفیت ۱۰۲۴ بایت می‌باشد. این ماژول به عنوان Slave به آردوینو توسط پایه‌های SCL و SDA متصل می‌شود. با استفاده از پردازشگر دیجیتال، ۴ خروجی برای دستیابی به دقت قابل توجه، در حرکت‌های کند و سریع در سنسور فراهم کرده است. با این روش کاربر می‌تواند بازه اندازه گیری را متناسب با شتاب یا سرعت تغییر دهد. به همین منظور در قسمت ژیروسکوپ سنسور چهار بازه ۲۵۰±، ۵۰۰±، ۱۰۰۰± و ۲۰۰۰± درجه بر ثانیه و در قسمت شتاب سنج سنسور چهار بازه ۲g، ±۴g، ±۸g، ±۱۶g± برای کاربر قابل انتخاب خواهد بود. توجه داشته باشید که ولتاژ کاری این ماژول ۳ الی ۵ ولت می‌باشد.

ماژول MPU6050 راه اندازی با آردوینو نانو - دیجی اسپارک

 


برد آردوینو Arduino


مجموعه برد های آردوینو از جمله برد های توسعه پرطرفدار بین مهندسین امبدد هستند که در مدل های مختلفی از جمله Micro ,  proMini , Nano , Uno و همچنین Mega قابل تهیه هستند، هسته مرکزی این برد های محبوب از سری AtMega328 می باشد. آردوینو پلتفرم سخت‌افزاری و نرم‌افزاری متن‌باز است. همان طور که قبل تر اشاره کردیم، پلتفرم آردوینو شامل یک میکروکنترلر تک‌بردی متن‌باز است که قسمت سخت‌افزار آردوینو را تشکیل می‌دهد. علاوه بر این، پلتفرم آردوینو یک نرم‌افزار آردوینو IDE که به منظور برنامه‌نویسی برای بردهای آردوینو طراحی شده‌است و یک بوت لودر نرم‌افزاری که بر روی میکروکنترلر بارگذاری می‌شود را در بر می‌گیرد.

 


ماژول نمایشگر Oled 1306


معمولا در پروژه های اینترنت اشیا و دیگر پروژه های امبدد از برای نمایش متن و مقادیر مختلف از نمایشگر های Oled استفاده می شود، این ماژول ها بدر انواع مختلق بسته به نوع ذرایور  اندازه یافت می شوند که یکی از پرطرفدار ترین آن ها SSD1306 می باشد، این نوع از Oled ها معمولا در اندازه های ۰٫۹۶ و ۱٫۳ اینچ ساخته می شوند همچنین پروتکل ارتباطی Oled ها I2C می باشد.

 


توضیح تکمیلی


در این آموزش اقدام به کنترل یک مکعب خواهیم کرد، در کد پروژه مکعب را طراحی می کنیم، به این صورت که زوایای مختلف را در کد تعریف و در شرط های برنامه به ازای تغییر مقادیر x, y تغییرات ظاهری مکعب را نیز مشخص خواهیم کرد. و در نهایت شکل معکب را در نمایشگر Oled چاپ می کنیم و تغییر زاویه ماژول MPU شاهد تغییر زوایای مکعب خواهیم بود.

پروژه راه اندازی ماژول MPU6050 با آردوینو نانو Nano و OLED - دیجی اسپارک

 


وسایل موردنیاز


ماژول MPU6050

برد آروینو نانو

نمایشگر Oled 0.96

وسایل لازم برای راه اندازی ماژول MPU6050 - دیجی اسپارک

 


نصب کتابخانه مورد نیاز


ابتدا در نرم افزار Arduino IDE اقدام به نصب کتابخانه مورد نیاز خواهیم‌کرد. مراحل زیر را دنبال کنید:

  1. این مسیر را دنبال کنید Sketch Include Library > Manage Libraries
  2. کلمه Adafruit SSD1306  را جستجو کنید.
  3. کتابخانه را نصب کنید.
  • سپس کلمه “GFX” را جستجو کنید و آن را نصب کنید.

 


تست و راه اندازی


در اولین مرحل اتصالات را طبق جدول و شماتیک زیر برقرار کنید، برای را‌ه‌اندازی قطعات استفاده شده در این آموزش از پروتکل I2C استفاده می‌کنیم، به این صورت که پین های SCL, SDA به پین های A4, A5 متصل خواهند شد.

اتصالات ماژول نمایشگر OLED به آردوینو - دیجی اسپارک

اتصالات ماژول MPU6050 به برد آردوینو - دیجی اسپارک

 

اتصالات پروژه راه اندازی ماژول MPU6050 با آردوینو نانو - دیجی اسپارک

 

خب بعد از برقراری اتصالات، نوبت به کد پروژه می‌رسد. در ادامه باهم قسمت های مهمی از این کد را بررسی خواهیم کرد. در چند خط اول کتابخانه های مورد نیاز را معرفی می‌کنیم.

#include <SPI.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Wire.h>

 

در این چند خط راه‌اندازی های اولیه برای دو ماژول استفاده شده را انجام خواهیم داد، برای مثال مشخص کردن I2C آدرس ها برای هر ماژول و همچنین متغیر های اولیه.

const int MPU=0x68;  
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define OLED_address  0x3c

 

اینجا دو متغیر تعریف کرده‌ایم که وظیفه آن ها پردازش خطوط مکعب است،این دلیل که در حرکت مکعب خطوط قبلی باید پاک، و خطوط جدید چاپ شوند.

int LinestoRender; 
int OldLinestoRender;

 

کد کامل پروژه راه اندازی ماژول MPU6050 با OLED و آردوینو نانو

#include <SPI.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Wire.h>

const int MPU=0x68;  
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define OLED_address  0x3c 

float xx,xy,xz;
float yx,yy,yz;
float zx,zy,zz;

float fact;

int Xan,Yan;

int Xoff;
int Yoff;
int Zoff;

struct Point3d
{
  int x;
  int y;
  int z;
};

struct Point2d
{
  int x;
  int y;
};



int LinestoRender; 
int OldLinestoRender; 

struct Line3d
{
  Point3d p0;
  Point3d p1;
};

struct Line2d
{
  Point2d p0;
  Point2d p1;
};

Line3d Lines[12];  //تعداد خطوط قابل پردازش
Line2d Render[12];
Line2d ORender[12];


void SetVars(void)
{
  float Xan2,Yan2,Zan2;
  float s1,s2,s3,c1,c2,c3;
  
  Xan2 = Xan / fact; // تبدیل مقادیر زاویه
  Yan2 = Yan / fact;
  
    
  s1 = sin(Yan2);
  s2 = sin(Xan2);
  
  c1 = cos(Yan2);
  c2 = cos(Xan2);

  xx = c1;
  xy = 0; 
  xz = -s1;

  yx = (s1 * s2);
  yy = c2;
  yz = (c1 * s2);

  zx = (s1 * c2);
  zy = -s2;
  zz = (c1 * c2);
}


void ProcessLine(struct Line2d *ret,struct Line3d vec)
{
  float zvt1;
  int xv1,yv1,zv1;

  float zvt2;
  int xv2,yv2,zv2;
  
  int rx1,ry1;
  int rx2,ry2;
 
  int x1;
  int y1;
  int z1;

  int x2;
  int y2;
  int z2;
  
  int Ok;
  
  x1=vec.p0.x;
  y1=vec.p0.y;
  z1=vec.p0.z;

  x2=vec.p1.x;
  y2=vec.p1.y;
  z2=vec.p1.z;

  Ok=0; // بطور پیشفرض ۰

  xv1 = (x1 * xx) + (y1 * xy) + (z1 * xz);
  yv1 = (x1 * yx) + (y1 * yy) + (z1 * yz);
  zv1 = (x1 * zx) + (y1 * zy) + (z1 * zz);

  zvt1 = zv1 - Zoff;


  if( zvt1 < -5){
    rx1 = 256 * (xv1 / zvt1) + Xoff;
    ry1 = 256 * (yv1 / zvt1) + Yoff;
    Ok=1; // ok we are alright for point 1.
  }
  
  
  xv2 = (x2 * xx) + (y2 * xy) + (z2 * xz);
  yv2 = (x2 * yx) + (y2 * yy) + (z2 * yz);
  zv2 = (x2 * zx) + (y2 * zy) + (z2 * zz);

  zvt2 = zv2 - Zoff;


  if( zvt2 < -5){
    rx2 = 256 * (xv2 / zvt2) + Xoff;
    ry2 = 256 * (yv2 / zvt2) + Yoff;
  } else
  {
    Ok=0;
  }
  
  if(Ok==1){
  ret->p0.x=rx1;
  ret->p0.y=ry1;

  ret->p1.x=rx2;
  ret->p1.y=ry2;
  }
}


void setup() {
 Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3c);  
  display.clearDisplay();   // پاک کردن صفحه 


Wire.begin();

  fact = 180 / 3.14159265358979323846264338327950; // برای تبدیل زاویه به رادیان
  
  Xoff = 60; // محل قرار گیری مکعب در محور x
  Yoff = 15; //  محل قرار گیری مکعب در محور y
  Zoff = 1300;   //اندازه مکعب


// Front Face.

  Lines[0].p0.x=-50;
  Lines[0].p0.y=-50;
  Lines[0].p0.z=50;
  Lines[0].p1.x=50;
  Lines[0].p1.y=-50;
  Lines[0].p1.z=50;

  Lines[1].p0.x=50;
  Lines[1].p0.y=-50;
  Lines[1].p0.z=50;
  Lines[1].p1.x=50;
  Lines[1].p1.y=50;
  Lines[1].p1.z=50;

  Lines[2].p0.x=50;
  Lines[2].p0.y=50;
  Lines[2].p0.z=50;
  Lines[2].p1.x=-50;
  Lines[2].p1.y=50;
  Lines[2].p1.z=50;

  Lines[3].p0.x=-50;
  Lines[3].p0.y=50;
  Lines[3].p0.z=50;
  Lines[3].p1.x=-50;
  Lines[3].p1.y=-50;
  Lines[3].p1.z=50;


//back face.

  Lines[4].p0.x=-50;
  Lines[4].p0.y=-50;
  Lines[4].p0.z=-50;
  Lines[4].p1.x=50;
  Lines[4].p1.y=-50;
  Lines[4].p1.z=-50;

  Lines[5].p0.x=50;
  Lines[5].p0.y=-50;
  Lines[5].p0.z=-50;
  Lines[5].p1.x=50;
  Lines[5].p1.y=50;
  Lines[5].p1.z=-50;

  Lines[6].p0.x=50;
  Lines[6].p0.y=50;
  Lines[6].p0.z=-50;
  Lines[6].p1.x=-50;
  Lines[6].p1.y=50;
  Lines[6].p1.z=-50;

  Lines[7].p0.x=-50;
  Lines[7].p0.y=50;
  Lines[7].p0.z=-50;
  Lines[7].p1.x=-50;
  Lines[7].p1.y=-50;
  Lines[7].p1.z=-50;

// چهار گوشه مکعب.

  Lines[8].p0.x=-50;
  Lines[8].p0.y=-50;
  Lines[8].p0.z=50;
  Lines[8].p1.x=-50;
  Lines[8].p1.y=-50;
  Lines[8].p1.z=-50;

  Lines[9].p0.x=50;
  Lines[9].p0.y=-50;
  Lines[9].p0.z=50;
  Lines[9].p1.x=50;
  Lines[9].p1.y=-50;
  Lines[9].p1.z=-50;

  Lines[10].p0.x=-50;
  Lines[10].p0.y=50;
  Lines[10].p0.z=50;
  Lines[10].p1.x=-50;
  Lines[10].p1.y=50;
  Lines[10].p1.z=-50;

  Lines[11].p0.x=50;
  Lines[11].p0.y=50;
  Lines[11].p0.z=50;
  Lines[11].p1.x=50;
  Lines[11].p1.y=50;
  Lines[11].p1.z=-50;

  LinestoRender=12;
  OldLinestoRender=LinestoRender;
 
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  
  Wire.write(0);     // 0 برای بیدار کردن ماژول
  Wire.endTransmission(true);
  
}
/***********************************************************************************************************************************/
void RenderImage( void)
{

 for (int i=0; i<OldLinestoRender; i++ )
  {
   display.drawLine(ORender[i].p0.x,ORender[i].p0.y,ORender[i].p1.x,ORender[i].p1.y, BLACK); // خطوط قدیمی
  }

    
  for (int i=0; i<LinestoRender; i++ )
  {
   display.drawLine(Render[i].p0.x,Render[i].p0.y,Render[i].p1.x,Render[i].p1.y, WHITE);
  }
  OldLinestoRender=LinestoRender;
  
  
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); 
  Wire.endTransmission(true);
  Wire.requestFrom(MPU,14,true);  
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  
  //delay(10);
}

void loop() {
  display.display();
  display.clearDisplay();   
 
  //برای چرخش مکعب
  int xOut=0;
  int yOut=0;
  
  xOut = map(AcX,-17000,17000,-50,50);
    yOut = map(AcY,-17000,17000,-50,50);
  
 Xan+=xOut;
 Yan+=yOut;
  

  Yan=Yan % 360;
  Xan=Xan % 360; 
  


  SetVars(); 
  for(int i=0; i<LinestoRender ; i++)
  {
    ORender[i]=Render[i]; 
    ProcessLine(&Render[i],Lines[i]); 
  }  
  
  RenderImage(); 
  
  
 
}

 

راه اندازی ماژول MPU6050 با نمایشگر OLED و برد آردوینو نانو Nano - دیجی اسپارک

 


جمع بندی


در این آموزش با استفاده از ماژول MPU6050 و همچنین برد آردوینو نانو و نمایشگر Oled توانستیم با استفاده از مقادیر بدست آمده از ماژول ژایرو یک مکعب ۳D را نسبت تغییرات در این مقادیر حرکت دهیم.

  • تنظیمات منوی tools در نرم افزار آردوینو نیز مانند تصویر زیر است.

 

چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریع‌ترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند می‌توانید از همین طریق اطلاع رسانی کنید.

 

در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی , از وبسایت دیجی اسپارک حمایت کنید.

 

درباره نویسنده

CiferTech

تبادل نظر و رفع عیب با ثبت دیدگاه

۲ دیدگاه

  • سلام و خسته نباشید ، بسیار بسیار زیاد از زحمات و ارائه مطالب شما سپاسگزارم ، پیشنهاد داشتم که لطفا در خصوص کد برنامه ها که اتفاقا قسمت مهم پروژه ها هستند نیز توضیحات بیشتری ارائه بفرمایید ، خصوصا در برخی جرئیات و ریزه کاری ها که میتونه راهنمای خوبی برای همه و برای اجرای پروژه های مشابه باشد . تشکر