ایجاد کلاس دسته Nunchuk در آردوینو

Ratings
(0)

 

 رابط کاربری کلاس Nunchuk ( و قسمت اصلی اجرای آن) به صورت زیر است:

#ifndef __NUNCHUK_H__
#define __NUNCHUK_H__
#define NUNCHUK_BUFFER_SIZE 6 

class Nunchuk {
public:
  void initialize();
  bool update();
  
  int joystick_x() const { return _buffer[0]; }
  int joystick_y() const { return _buffer[1]; }

  int x_acceleration() const {
    return ((int)(_buffer[2]) << 2) | ((_buffer[5] >> 2) & 0x03);
  }
  
  int y_acceleration() const {
    return ((int)(_buffer[3]) << 2) | ((_buffer[5] >> 4) & 0x03);
  }
  
  int z_acceleration() const {
    return ((int)(_buffer[4]) << 2) | ((_buffer[5] >> 6) & 0x03);
  }
  bool z_button() const { return !(_buffer[5] & 0x01); }
  bool c_button() const { return !(_buffer[5] & 0x02); }
  
private:
  void request_data();
  char decode_byte(const char);
  
  unsigned char _buffer[NUNCHUK_BUFFER_SIZE]; 
};

#endif

 برای دانلود فایل حاوی کدهای بالا اینجا کلیک کنید. این فایل در بسته ی دانلودی، در آدرس زیر قرار دارد:

Tinkering/NunchukDemo/nunchuk.h

 همه ی آنچه که برای استفاده از یک دسته ی بازی Nunchuk در آردوینو نیاز داریم، در این کلاس کوچک ++C وجود دارد. این کلاس از مکانیزم جلوگیری از دوبار اضافه شدن(double-include prevention mechanism) استفاده می کند: این کلاس ابتدا بررسی می کند که آیا قبلاً  یک ماکروی پیش پردازنده(preprocessor macro) به نام __NUNCHUK_H__ با استفاده از #ifndef  تعریف شده است یا نه. اگر مورد مذکور از قبل تعریف نشده باشد، ما آن را تعریف می کنیم و به ادامه ی کدهای کلاس Nunchuk می پردازیم. در غیر این صورت، پیش پردازنده(preprocessor) این اعلان را نادیده می گیرد؛ و ما با امنیت کامل، این فایل header را بیش از یک بار در اپلیکیشن(برنامه) خود اضافه(include) نمی کنیم.

 در خط 3، یک ثابت(constant) ایجاد کرده ایم، که از آن  برای نگهداری سایز یک آرایه، استفاده می کنیم.  ما به آرایه ی مذکور، برای ذخیره ی داده هایی که دسته ی Nunchuk برمی گرداند، نیاز داریم. این آرایه در خط 31 تعریف شده است و در اینجا، ما به جای استفاده از کلمه ی کلیدی const، از پیش پردازنده(preprocessor) استفاده می کنیم؛ زیرا ثابت های آرایه ای در زبان ++C باید به هنگام کامپایل، شناخته شده باشند.

پس از خط 3، تعریف اصلی کلاس Nunchuk شروع می شود. در خط 7، برای شروع کردن(initiate)  کانال ارتباطی بین آردوینو و دسته ی Nunchuk باید یک بار متد initialize  را فراخوانی کنیم. سپس هر موقع که ما می خواهیم کلاس Nunchuk داده های جدید را ارسال کند، متد update  را در خط 8 فراخوانی می کنیم. به زودی نحوه ی اجرای این دو متد را مشاهده خواهید کرد.

برای دریافت تمام خصوصیت هایی(attributes) که دسته ی Nunchuk برمی گرداند، چند متد عمومی(public) داریم که به این شرح هستند:

  • مختصات x و y جوی استیک آنالوگ
  • حالت های دکمه(button states)
  • مقادیر x و y و z از شتاب سنج

همه ی این متدها، بر روی داده های خامی(raw data) عمل می کنند که در بافر(buffer) در خط 31 موجود است. اجرای این متدها  اغلب بدیهی است و تنها به یک خط کد نیاز دارد. فقط، مونتاژ مقادیر 10 بیتی شتاب سنج کمی پیچیده است( در صفحه 251، عملیات بیتی را مشاهده کنید).

در انتهای تعریف این کلاس در خطوط 28 و 29، دو متد helper محلی(private) مشاهده می کنید که نام های آنها به ترتیب request_data و decode_byte است. ما به این متدها برای اجرای مقدار دهی اولیه(implement the initialize) و آپدیت متدها نیاز داریم:

#include <Arduino.h>
#include <Wire.h>
#include "nunchuk.h"
#define NUNCHUK_DEVICE_ID 0x52

void Nunchuk::initialize() {
  Wire.begin(); 
  Wire.beginTransmission(NUNCHUK_DEVICE_ID);
  Wire.write((byte)0x40);
  Wire.write((byte)0x00);
  Wire.endTransmission();
  update();
}

bool Nunchuk::update() {
  delay(1);
  Wire.requestFrom(NUNCHUK_DEVICE_ID, NUNCHUK_BUFFER_SIZE);
  int byte_counter = 0;
  while (Wire.available() && byte_counter < NUNCHUK_BUFFER_SIZE)
    _buffer[byte_counter++] = decode_byte(Wire.read());
  request_data();
  return byte_counter == NUNCHUK_BUFFER_SIZE;
}

void Nunchuk::request_data() {
  Wire.beginTransmission(NUNCHUK_DEVICE_ID);
  Wire.write((byte)0x00);
  Wire.endTransmission();
}

char Nunchuk::decode_byte(const char b) {
  return (b ^ 0x17) + 0x17;
}

برای دانلود فایل کدهای بالا اینجا کلیک کنید. این کدها در آدرس زیر در بسته ی دانلودی قرار دارند:

Tinkering/NunchukDemo/nunchuk.cpp

 پس از اینکه ما تمام کتابخانه های مورد نیاز را اضافه(include) کردیم، ثابت NUNCHUK_DEVICE_ID را تعریف می کنیم. I2C یک پروتکل master/slave (ارباب/برده) است و در مورد ما، آردوینو master(ارباب) است و دسته ی Nunchuk نقش slave (برده) را بازی می کند.

دسته ی Nunchuk خودش را در گذرگاه داده(data bus) با استفاده از یک ID یعنی 0x52 ثبت می کند، بنابراین وقتی که به چیزی احتیاج داشتیم، می توانیم آن را مورد خطاب قرار دهیم. در متد initialize ما با ارسال یک handshake، اتصالی بین آردوینو و دسته ی Nunchuk برقرار می کنیم. در خط 7، ما متد begin از کلاس Wire را فراخوانی می کنیم، تا آردوینو بتواند به گذرگاه I2C بعنوان یک master(ارباب) متصل(join) شود. اگر ما به متد begin یک ID بدهیم، در گذرگاه(bus) به صورت یک slave(برده) با این ID متصل(join) می شود.

سپس ما یک انتقال جدید(new transmission)  به دستگاه برقرار می کنیم که توسط  NUNCHUCK_DEVICE_ID یعنی همان دسته ی Nunchuk شناسایی می شود. ما دو بایت 0x40 و 0x00 را به Nunchuk ارسال می کنیم و سپس به انتقال پایان می دهیم. تمام روش handshake همین بود، و اکنون ما می توانیم با فراخوانی متد update، از دسته ی Nunchuk بخواهیم تا وضعیت فعلی خود را به ما گزارش دهد. در تصویر زیر، ما پیامی که بین آردوینو و Nunchuk رد و بدل می شود را مشاهده می کنیم. 

 در متد update با استفاده از دستور delay برای یک میلی ثانیه وقفه ایجاد می کنیم تا همه چیز حل و فصل شود. سپس ما در خط 17، با فراخوانی متد Wire.requestFrom شش بایت را از دسته ی Nunchuk درخواست می کنیم. در حقیقت این کار بایت ها را برنمی گرداند، بلکه ما باید بایت ها را در یک حلقه(loop) بخوانیم  و بافر(buffer) خود را پر کنیم.

متد Wire.available تعداد بایت های در دسترس بر روی گذرگاه داده(data bus) را برمی گرداند و متد Wire.read بایت فعلی را برمی گرداند. ما نمی توانیم از بایت هایی که مستقیماً از دسته ی Nunchuk دریافت می کنیم را مورد استفاده قرار دهیم، زیرا این دسته آنها را مبهم(obfuscates them) می کند. اما رمزگشایی این اطلاعات ساده است، زیرا می توانیم از متد decode_byte استفاده کنیم. 

 در نهایت ما متد request_data را فراخوانی می کنیم تا به دسته ی Nunchuk بفهمانیم که داده های جدید را آماده کند. این متد، یک بایت تکی صفر را به Nunchuk منتقل می کند؛ که به این معنی است: شش بایت بعدی را آماده کن.

 قبل از اینکه ما به طور واقعی از کلاس Nunchuk خود در بخش بعدی استفاده کنیم، نگاهی به مستندات کتابخانه ی Wire بیاندازید.  برای این کار، از منوی IDE آردوینو، گزینه ی Help > Reference را انتخاب کنید و سپس بر روی لینک Libraries کلیک کنید.


 کاربردهای علمی با استفاده از تجهیزات Wii

به دلیل دقت تجهیزات Wii، و قیمت ارزان آنها، بیشتر دانشمندان، نسبت به دیگر وسایل گیم، از آنها استفاده می کنند. برخی از متخصصان آب شناسی، از آن برای اندازه گیری میزان تبخیر یک یک مقدار آب استفاده می کنند. برای اطلاعات بیشتر در این زمینه اینجا کلیک کنید. برای انجام این کار، ما معمولاً ما تجهیزاتی نیاز داریم که بیش از 500 دلار قیمت دارند.  برخی از دکترها در دانشگاه ملبورن نگاه ویژه ای به برد تعادل  Wii یا همان Wii Balance Board دارند، زیرا آنها به دنبال یک دستگاه ارزان برای بهبود بیماران سکته ی مغزی هستند. برای اطلاعات بیشتر، اینجا کلیک کنید.

{module کمک نقدی به نویسنده}

  • بازدید: 481

نوشتن دیدگاه

لطفا نظرات خود را بیان کنید. به سوالات در سریع ترین زمان پاسخ داده خواهد شد.اما به نکات زیر توجه کنید:
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.

ارسال