مركبة فضائية تتجاوز العقبات باستخدام ليتل بيتس (LittleBits)

المقدمة

تخطي العقبات

 

يحاول العلماء استكشاف الكواكب في مجموعتنا الشمسية، و تساعدهم مركبات فضائية خاصة في التنقل على سطح الكوكب و حتى لا تصطدم المركبة بالعقبات أو صخور الكوكب يمكن تحسس العقبات التي قد تواجة المركبة و تجنبها أثناء سير المركبة، ستتعلم كيفية جعل المركبة الفضائية تتجاوز العقبات بعد استشعارها باستخدام الليتل بيتس و حساس القرب

المواد والأدوات

حتى تتمكن من تجميع المركبة الفضائية تحتاج من مجموعة مستكشف الفضاء ليتل بيتس (little bits Space Rover Inventor Kit):

cartoon-littlebits-rover-body

1× قالب كرتوني رقم (4)

cartoon-littlebits-rover-body

1× قالب كرتوني رقم (1)

استخدام مركز التحكم لتصنيع العربة الجوالة باستخدام ليتل بيتس

1× مركز التحكم

محرك تيار مستمر لـ العربة الجوالة باستخدام ليتل بيتس

2× محرك تيار مستمر

العجلة الكروية لـ العربة الجوالة باستخدام ليتل بيتس

1× عجلة كروية

المركبة الفضائية

2× عجلات

littlebits-rover-body

1× حامل البطارية

cable-littlebits-rover-body

1× سلك البطارية

استخدام البطارية لتصنيع العربة الجوالة باستخدام ليتل بيتس

1× بطارية

المركبة الفضائية

1× منفذ الطاقة

حساس الاقتراب

1X حساس الاقتراب

مصفوفة ضوئية

1Xصف من وحدات الإضاءة

مصدر صوت

1Xمصدر صوت

توصيل الدائرة

يمكن أن توصل قطع ليتل بيتس  بسهولة و بدون لحام لبناء الدائرة بالخطوات التالية

وصل منفذ الطاقة مع أسلاك التوصيل

تخطي العقبات

وصل السلك الأول مع مركز التحكم

توصيل الدائرة

وصل السلك الثاني معليتل بيتس حساس الاقتراب

توصيل الدائرة

باستخدام سلك توصيل قم بالتوصل بين حساس الاقتراب و مصدر الصوت

توصيل الدائرة

باستخدام سلك توصيل قم بالتوصيل بين مصدر الصوت وقطعة صف من وحدات الإضاءة

توصيل الدائرة أخيرا قم بتوصيل محركا التيار المستمر مع وحدة مركز التحكم

توصيل الدائرة

يمكن من خلال وحدة التحكم بالمحرك تحديد اتجاه الدوران للمحرك:

ccw عكس عقارب الساعة 

Cw مع عقارب الساعة

Var متغير يمكن أن تكون مع أو عكس عقارب الساعة

محرك

تجميع مكونات المركبة الفضائية

يتكون جسم المركبة الفضائية التي  تتجاوز العقبات من جزئين الأول تًثبت عليه جميع مكونات المركبة الفضائية

الجزء الثاني تُثبت عليه وحدة صف الإضاءة

مركبة فضائية

ابدأ خطوات تجميع الجزء الأول كالتالي :

 اطو الخطوط المتقطعة في القالب الكرتوني الموفر في حقيبة ليتل بيتس  (1) ثم فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-rover-body

اطو الخطوط المتصلة في القالب الكرتوني (1) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-rover-body

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى آخر رقم بالقالب الكرتوني.

match-littlebits-rover-body

littlebits-rover-body-match-face

المركبة الفضائية ليتل بيتس

littlebits-rover-body

littlebits-rover-body

طي القطع لـ العربة الجوالة باستخدام ليتل بيتس

ليتل بيتس

ابدأ خطوات تجميع الجزء الثاني كالتالي :

 اطو الخطوط المتصلة في القالب الكرتوني متوفر في حقيبة  ليتل بيتس (4) فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.littlebits-rover-body

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى آخر رقم بالقالب الكرتوني، واغلقها بإحكام.

ليتل بيتس

ليتل بيتس

littlebits-rover-body

تبيث قطع ليتل بيتس على هيكل المركبة الفضائية:

ثبت اللوحة في هيكل عربة الفضاء.

ليتل بيتس

ثبت البطارية في المربع المخصص للبطارية

ثبت العجلة الكروية و محركا التيار المستمر في الفتحة السفلية لهيكل عربة الفضاء، كما هو ظاهر.

تثبيت القطع

 ثبت جميع قطع ليتل بيتس كما هو ظاهر بالصورة

تخطي العقبات

أصبحت  المركبة الفضائية  التي تتجاوز العقبات باستخدام ليتل بيتس جاهزة




برمجة لعبة تخطي الحواجز باستخدام الاردوينو

مقدمة

تقوم فكرة لعبة تخطي الحواجز على السرعة والتركيز في إيصال الشخصيّة الرئيسيّة إلى مستويات أعلى وذلك من خلال تحريكها باتجاهات مختلفة لتفادي العقبات في هذا الدرس ستتعلم كيفية برمجة لعبة تخطي الحواجز باستخدام الاردوينو.

تخطي الحواجز

المواد والأدوات

arduino-game-by-lcd

1× اردوينو اونو

arduino-game-by-lcd

1× سلك الاردوينو

arduino-game-by-lcd

1× لوحة تجارب – حجم كبير

تخطي الحواجز

 شاشة كرستالية (LCD 2×16 )

تخطي الحواجز

1× مقاومة متغيرة

تخطي الحواجز

 حزمة أسلاك توصيل (ذكر- ذكر)

تخطي الحواجز

1× مقاومة 220 Ω

تخطي الحواجز

مفتاح تحكم

اردوينو

1× 40 رأس دبوس

توصيل الدائرة

لمعرفة المزيد حول الشاشة الكرستالية يمكنك الرجوع للدرس التحكم بالشاشة الكرستالية LCD

لابد من تلحيم المنافذ مع الشاشة الكرستالية، للمزيد حول اللحام يمكنك الرجوع للدرس تعلم كيفية التلحيم – تلحيم القطع باللوحة الإلكترونية

تخطي الحواجز

الكود البرمجي

ارفع كود لعبة تخطي الحواجز إلى لوحة الاردوينو.

#include <LiquidCrystal.h>
#define PIN_BUTTON 2
#define PIN_AUTOPLAY 1
#define PIN_READWRITE 10
#define PIN_CONTRAST 12

#define SPRITE_RUN1 1
#define SPRITE_RUN2 2
#define SPRITE_JUMP 3
#define SPRITE_JUMP_UPPER '.' // Use the '.' character for the head
#define SPRITE_JUMP_LOWER 4
#define SPRITE_TERRAIN_EMPTY ' ' // User the ' ' character
#define SPRITE_TERRAIN_SOLID 5
#define SPRITE_TERRAIN_SOLID_RIGHT 6
#define SPRITE_TERRAIN_SOLID_LEFT 7

#define HERO_HORIZONTAL_POSITION 1 // Horizontal position of hero on screen
#define TERRAIN_WIDTH 16
#define TERRAIN_EMPTY 0
#define TERRAIN_LOWER_BLOCK 1
#define TERRAIN_UPPER_BLOCK 2

#define HERO_POSITION_OFF 0 // Hero is invisible
#define HERO_POSITION_RUN_LOWER_1 1 // Hero is running on lower row (pose 1)
#define HERO_POSITION_RUN_LOWER_2 2 // (pose 2)

#define HERO_POSITION_JUMP_1 3 // Starting a jump
#define HERO_POSITION_JUMP_2 4 // Half-way up
#define HERO_POSITION_JUMP_3 5 // Jump is on upper row
#define HERO_POSITION_JUMP_4 6 // Jump is on upper row
#define HERO_POSITION_JUMP_5 7 // Jump is on upper row
#define HERO_POSITION_JUMP_6 8 // Jump is on upper row
#define HERO_POSITION_JUMP_7 9 // Half-way down
#define HERO_POSITION_JUMP_8 10 // About to land

#define HERO_POSITION_RUN_UPPER_1 11 // Hero is running on upper row (pose 1)
#define HERO_POSITION_RUN_UPPER_2 12 // (pose 2)

LiquidCrystal lcd(11, 9, 6, 5, 4, 3);
static char terrainUpper[TERRAIN_WIDTH + 1];
static char terrainLower[TERRAIN_WIDTH + 1];
static bool buttonPushed = false;
void initializeGraphics(){
static byte graphics[] = {
// Run position 1
B01100,
B01100,
B00000,
B01110,
B11100,
B01100,
B11010,
B10011,
// Run position 2
B01100,
B01100,
B00000,
B01100,
B01100,
B01100,
B01100,
B01110,
// Jump
B01100,
B01100,
B00000,
B11110,
B01101,
B11111,
B10000,
B00000,
// Jump lower
B11110,
B01101,
B11111,
B10000,
B00000,
B00000,
B00000,
B00000,
// Ground
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
// Ground right
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
// Ground left
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
};
int i;
// Skip using character 0, this allows lcd.print() to be used to
// quickly draw multiple characters
for (i = 0; i < 7; ++i) {
lcd.createChar(i + 1, &graphics[i * 8]);
} for (i = 0; i < TERRAIN_WIDTH; ++i) {
terrainUpper[i] = SPRITE_TERRAIN_EMPTY;
terrainLower[i] = SPRITE_TERRAIN_EMPTY;
} } // Slide the terrain to the left in half-character increments
// void advanceTerrain(char* terrain, byte newTerrain){ for (int i = 0; i < TERRAIN_WIDTH; ++i) { char current = terrain[i]; char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1]; switch (current){ case SPRITE_TERRAIN_EMPTY: terrain[i] = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT : SPRITE_TERRAIN_EMPTY; break; case SPRITE_TERRAIN_SOLID: terrain[i] = (next == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT : SPRITE_TERRAIN_SOLID; break; case SPRITE_TERRAIN_SOLID_RIGHT: terrain[i] = SPRITE_TERRAIN_SOLID; break; case SPRITE_TERRAIN_SOLID_LEFT: terrain[i] = SPRITE_TERRAIN_EMPTY; break; } } } bool drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) { bool collide = false; char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION]; char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION]; byte upper, lower; switch (position) { case HERO_POSITION_OFF: upper = lower = SPRITE_TERRAIN_EMPTY; break; case HERO_POSITION_RUN_LOWER_1: upper = SPRITE_TERRAIN_EMPTY; lower = SPRITE_RUN1; break; case HERO_POSITION_RUN_LOWER_2: upper = SPRITE_TERRAIN_EMPTY; lower = SPRITE_RUN2; break; case HERO_POSITION_JUMP_1: case HERO_POSITION_JUMP_8: upper = SPRITE_TERRAIN_EMPTY; lower = SPRITE_JUMP; break; case HERO_POSITION_JUMP_2: case HERO_POSITION_JUMP_7: upper = SPRITE_JUMP_UPPER; lower = SPRITE_JUMP_LOWER; break; case HERO_POSITION_JUMP_3: case HERO_POSITION_JUMP_4: case HERO_POSITION_JUMP_5: case HERO_POSITION_JUMP_6: upper = SPRITE_JUMP; lower = SPRITE_TERRAIN_EMPTY; break; case HERO_POSITION_RUN_UPPER_1: upper = SPRITE_RUN1; lower = SPRITE_TERRAIN_EMPTY; break; case HERO_POSITION_RUN_UPPER_2: upper = SPRITE_RUN2; lower = SPRITE_TERRAIN_EMPTY; break; } if (upper != ' ') { terrainUpper[HERO_HORIZONTAL_POSITION] = upper; collide = (upperSave == SPRITE_TERRAIN_EMPTY) ? false : true; } if (lower != ' ') { terrainLower[HERO_HORIZONTAL_POSITION] = lower; collide |= (lowerSave == SPRITE_TERRAIN_EMPTY) ? false : true; } byte digits = (score > 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 1; // Draw the scene terrainUpper[TERRAIN_WIDTH] = '\0'; terrainLower[TERRAIN_WIDTH] = '\0'; char temp = terrainUpper[16-digits]; terrainUpper[16-digits] = '\0'; lcd.setCursor(0,0); lcd.print(terrainUpper); terrainUpper[16-digits] = temp; lcd.setCursor(0,1); lcd.print(terrainLower); lcd.setCursor(16 - digits,0); lcd.print(score); terrainUpper[HERO_HORIZONTAL_POSITION] = upperSave; terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave; return collide; } // Handle the button push as an interrupt void buttonPush() { buttonPushed = true; } void setup(){ pinMode(PIN_READWRITE, OUTPUT); digitalWrite(PIN_READWRITE, LOW); pinMode(PIN_CONTRAST, OUTPUT); digitalWrite(PIN_CONTRAST, LOW); pinMode(PIN_BUTTON, INPUT);
digitalWrite(PIN_BUTTON, HIGH);
pinMode(PIN_AUTOPLAY, OUTPUT);
digitalWrite(PIN_AUTOPLAY, HIGH); // Digital pin 2 maps to interrupt 0
attachInterrupt(0/*PIN_BUTTON*/, buttonPush, FALLING); initializeGraphics(); lcd.begin(16, 2);
} void loop(){ static byte heroPos = HERO_POSITION_RUN_LOWER_1;
static byte newTerrainType = TERRAIN_EMPTY;
static byte newTerrainDuration = 1;
static bool playing = false;
static bool blink = false;
static unsigned int distance = 0; if (!playing) { drawHero((blink) ? HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3);
if (blink) {
lcd.setCursor(0,0);
lcd.print("Press Start"); } delay(250); blink = !blink;
if (buttonPushed) {
initializeGraphics();
heroPos = HERO_POSITION_RUN_LOWER_1;
playing = true;
buttonPushed = false;
distance = 0; } return; } // Shift the terrain to the left advanceTerrain(terrainLower, newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY);
advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); // Make new terrain to enter on the right
if (--newTerrainDuration == 0) { if (newTerrainType == TERRAIN_EMPTY) {
newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK;
newTerrainDuration = 2 + random(10);
} else { newTerrainType = TERRAIN_EMPTY;
newTerrainDuration = 10 + random(10); } } if (buttonPushed) { if (heroPos <= HERO_POSITION_RUN_LOWER_2) heroPos = HERO_POSITION_JUMP_1;
buttonPushed = false;
} if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 3)) { playing = false; // The hero collided with something. Too bad.
} else { if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos == HERO_POSITION_JUMP_8) {
heroPos = HERO_POSITION_RUN_LOWER_1;
} else if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <= HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] != SPRITE_TERRAIN_EMPTY) {
heroPos = HERO_POSITION_RUN_UPPER_1; } else if (heroPos >= HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] == SPRITE_TERRAIN_EMPTY) {
heroPos = HERO_POSITION_JUMP_5; } else if (heroPos == HERO_POSITION_RUN_UPPER_2) {

heroPos = HERO_POSITION_RUN_UPPER_1;
} else { ++heroPos; } ++distance; digitalWrite(PIN_AUTOPLAY, terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW); }
delay(100); }

شرح الكود البرمجي

هذا السطر يستدعي مكتبة الشاشة الكرستالية.

نستطيع تحميلها بتتبع المسار التالي:

Sketch > Include libraries > Manage libraries

ثم نكتب بخانة البحث Liquid crystal by Arduino

ثم نضغط على Install.

#include <LiquidCrystal.h>

هذا السطر يوضح منفذ الاردوينو الذي ستستخدمه لربط مفتاح التحكم في هذا المشروع.

#define PIN_BUTTON 2

هذه الأسطر تعرّف المتغيرات التي سنستخدمها لرسم العقبات في اللعبة وتحديد مسارها.

#define SPRITE_RUN1 1
#define SPRITE_RUN2 2
#define SPRITE_JUMP 3
#define SPRITE_JUMP_UPPER '.' // Use the '.' character for the head
#define SPRITE_JUMP_LOWER 4
#define SPRITE_TERRAIN_EMPTY ' ' // User the ' ' character
#define SPRITE_TERRAIN_SOLID 5
#define SPRITE_TERRAIN_SOLID_RIGHT 6
#define SPRITE_TERRAIN_SOLID_LEFT 7

هذه الأسطر تعرّف المتغيرات التي سنستخدمها لرسم الشخصية وتحديد مسارها.

#define HERO_HORIZONTAL_POSITION 1 // Horizontal position of hero on screen
#define TERRAIN_WIDTH 16
#define TERRAIN_EMPTY 0
#define TERRAIN_LOWER_BLOCK 1
#define TERRAIN_UPPER_BLOCK 2

#define HERO_POSITION_OFF 0 // Hero is invisible
#define HERO_POSITION_RUN_LOWER_1 1 // Hero is running on lower row (pose 1)
#define HERO_POSITION_RUN_LOWER_2 2 // (pose 2)

#define HERO_POSITION_JUMP_1 3 // Starting a jump
#define HERO_POSITION_JUMP_2 4 // Half-way up
#define HERO_POSITION_JUMP_3 5 // Jump is on upper row
#define HERO_POSITION_JUMP_4 6 // Jump is on upper row
#define HERO_POSITION_JUMP_5 7 // Jump is on upper row
#define HERO_POSITION_JUMP_6 8 // Jump is on upper row
#define HERO_POSITION_JUMP_7 9 // Half-way down
#define HERO_POSITION_JUMP_8 10 // About to land

#define HERO_POSITION_RUN_UPPER_1 11 // Hero is running on upper row (pose 1)
#define HERO_POSITION_RUN_UPPER_2 12 // (pose 2)

بعد ذلك عرّفنا المتغيرات الخاصة بالشاشة الكرستالية.

LiquidCrystal lcd(11, 9, 6, 5, 4, 3);

في دالة ()void initializeGraphics يتم توضيح الرسومات المستخدمة لرسم العقبات في كل اتجاه.

void initializeGraphics(){
static byte graphics[] = {
// Run position 1
B01100,
B01100,
B00000,
B01110,
B11100,
B01100,
B11010,
B10011,
// Run position 2
B01100,
B01100,
B00000,
B01100,
B01100,
B01100,
B01100,
B01110,
// Jump
B01100,
B01100,
B00000,
B11110,
B01101,
B11111,
B10000,
B00000,
// Jump lower
B11110,
B01101,
B11111,
B10000,
B00000,
B00000,
B00000,
B00000,
// Ground
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
// Ground right
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
B00011,
// Ground left
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
B11000,
};

هذه الأسطر تجعل العقبات تظهر بشكل مستمر طوال اللعبة.

int i;
// Skip using character 0, this allows lcd.print() to be used to
// quickly draw multiple characters
for (i = 0; i < 7; ++i) {
lcd.createChar(i + 1, &graphics[i * 8]);
}
for (i = 0; i < TERRAIN_WIDTH; ++i) {
terrainUpper[i] = SPRITE_TERRAIN_EMPTY;
terrainLower[i] = SPRITE_TERRAIN_EMPTY;
}
}

هنا يتم التحكم بحجم العقبات فحجمها ليس ثابتًا في اللعبة.

void advanceTerrain(char* terrain, byte newTerrain){
for (int i = 0; i < TERRAIN_WIDTH; ++i) {
char current = terrain[i];
char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1];
switch (current){
case SPRITE_TERRAIN_EMPTY:
terrain[i] = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT : SPRITE_TERRAIN_EMPTY;
break;
case SPRITE_TERRAIN_SOLID:
terrain[i] = (next == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT : SPRITE_TERRAIN_SOLID;
break;
case SPRITE_TERRAIN_SOLID_RIGHT:
terrain[i] = SPRITE_TERRAIN_SOLID;
break;
case SPRITE_TERRAIN_SOLID_LEFT:
terrain[i] = SPRITE_TERRAIN_EMPTY;
break;
}
}
}

هذه الأسطر توضح طريقة رسم الشخصية الرئيسية وطريقة تحركها للأعلى أو للأسفل.

bool drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) {
bool collide = false;
char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION];
char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION];
byte upper, lower;
switch (position) {
case HERO_POSITION_OFF:
upper = lower = SPRITE_TERRAIN_EMPTY;
break;
case HERO_POSITION_RUN_LOWER_1:
upper = SPRITE_TERRAIN_EMPTY;
lower = SPRITE_RUN1;
break;
case HERO_POSITION_RUN_LOWER_2:
upper = SPRITE_TERRAIN_EMPTY;
lower = SPRITE_RUN2;
break;
case HERO_POSITION_JUMP_1:
case HERO_POSITION_JUMP_8:
upper = SPRITE_TERRAIN_EMPTY;
lower = SPRITE_JUMP;
break;
case HERO_POSITION_JUMP_2:
case HERO_POSITION_JUMP_7:
upper = SPRITE_JUMP_UPPER;
lower = SPRITE_JUMP_LOWER;

break;
case HERO_POSITION_JUMP_3:
case HERO_POSITION_JUMP_4:
case HERO_POSITION_JUMP_5:
case HERO_POSITION_JUMP_6:
upper = SPRITE_JUMP;
lower = SPRITE_TERRAIN_EMPTY;
break;
case HERO_POSITION_RUN_UPPER_1:
upper = SPRITE_RUN1;
lower = SPRITE_TERRAIN_EMPTY;
break;
case HERO_POSITION_RUN_UPPER_2:
upper = SPRITE_RUN2;
lower = SPRITE_TERRAIN_EMPTY;
break;
}

يتم تمثيل المشهد طوال اللعبة بحيث تظهر العقبات بأشكال مختلفة وتتحرك من اليمين لليسار والشخصية ثابتة في موضعها ما لم يحركها اللاعب.

سيكون هناك عدّاد (نقاط) يعمل بشكل تصاعدي على الشاشة.

// Draw the scene
terrainUpper[TERRAIN_WIDTH] = '\0';
terrainLower[TERRAIN_WIDTH] = '\0';
char temp = terrainUpper[16-digits];
terrainUpper[16-digits] = '\0';
lcd.setCursor(0,0);
lcd.print(terrainUpper);
terrainUpper[16-digits] = temp;
lcd.setCursor(0,1);
lcd.print(terrainLower);
lcd.setCursor(16 - digits,0);
lcd.print(score);
terrainUpper[HERO_HORIZONTAL_POSITION] = upperSave;
terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave;
return collide;
}

في حالة الضغط على الزر سيتم تحريك الشخصية للأعلى لتفادي العقبات.

// Handle the button push as an interrupt
void buttonPush() {
buttonPushed = true;
}

في الدالة ()void setup تتم تهيئة العقبات والشخصية على الشاشة.

وربط الزر مع حركة الشخصية.

void setup(){
pinMode(PIN_READWRITE, OUTPUT);
digitalWrite(PIN_READWRITE, LOW);
pinMode(PIN_CONTRAST, OUTPUT);
digitalWrite(PIN_CONTRAST, LOW);
pinMode(PIN_BUTTON, INPUT);
digitalWrite(PIN_BUTTON, HIGH);
pinMode(PIN_AUTOPLAY, OUTPUT);
digitalWrite(PIN_AUTOPLAY, HIGH);
// Digital pin 2 maps to interrupt 0
attachInterrupt(0/*PIN_BUTTON*/, buttonPush, FALLING);
initializeGraphics();
lcd.begin(16, 2);
}

في الدالة ()void loop يتم عرض العقبات على الشاشة وتحديد مدة زمنية لكل عقبة بعدها تختفي وتظهر في مكان آخر بحجم آخر.

والشخصية سوف تظهر بحالة سكون ما لم يقوم اللاعب بضغط زر التحكم لتحريكها للأعلى.

وسيكون هناك عدّاد (نقاط) يعمل بشكل تصاعدي على يمين الشاشة إذا حدث تلامس بين الشخصية والعقبات سيتوقف العدّاد وتنتهي اللعبة.

يمكنك البدء من جديد من خلال الضغط على زر التحكم.

void loop(){
static byte heroPos = HERO_POSITION_RUN_LOWER_1;
static byte newTerrainType = TERRAIN_EMPTY;
static byte newTerrainDuration = 1;
static bool playing = false;
static bool blink = false;
static unsigned int distance = 0;
if (!playing) {
drawHero((blink) ? HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3);
if (blink) {
lcd.setCursor(0,0);
lcd.print("Press Start");
}
delay(250);
blink = !blink;
if (buttonPushed) {
initializeGraphics();
heroPos = HERO_POSITION_RUN_LOWER_1;
playing = true;
buttonPushed = false;
distance = 0;
}
return;
}
// Shift the terrain to the left
advanceTerrain(terrainLower, newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY);
advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY);
// Make new terrain to enter on the right
if (--newTerrainDuration == 0) {
if (newTerrainType == TERRAIN_EMPTY) {
newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK;
newTerrainDuration = 2 + random(10);
} else {
newTerrainType = TERRAIN_EMPTY;
newTerrainDuration = 10 + random(10);
}
}
if (buttonPushed) {
if (heroPos <= HERO_POSITION_RUN_LOWER_2) heroPos = HERO_POSITION_JUMP_1;
buttonPushed = false;
}
if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 3)) {
playing = false; // The hero collided with something. Too bad.
} else {
if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos == HERO_POSITION_JUMP_8) {
heroPos = HERO_POSITION_RUN_LOWER_1;
} else if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <= HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] != SPRITE_TERRAIN_EMPTY) {
heroPos = HERO_POSITION_RUN_UPPER_1;
} else if (heroPos >= HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] == SPRITE_TERRAIN_EMPTY) {
heroPos = HERO_POSITION_JUMP_5;

} else if (heroPos == HERO_POSITION_RUN_UPPER_2) {

heroPos = HERO_POSITION_RUN_UPPER_1;
} else {

++heroPos;

}

++distance;
digitalWrite(PIN_AUTOPLAY, terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW);
}

delay(100);
}




جرافة باستخدام ليتل بيتس (LittleBits)

مقدمة

تستخدم الجرافة لدفع كميات كبيرة من التربة أو الرمل أو الثلج أو الأنقاض أو البضائع يمكن العثور عليها في المناجم والمزارع والقواعد العسكرية والمصاع سوف تتعلم في هذا الدرس تجميع هيكل الجرافة باستخدام ليتل بيتس..

الجرافة

المواد والأدوات من ليتل بيتس

حتى تتمكن من تجميع الجرافة تحتاج من مجموعة مستكشف الفضاء ليتل بيتس (little bits Space Rover Inventor Kit):

littlebits-cargo-carrier

1× قالب كرتوني رقم (4)

الجرافة

 1×  قالب كرتوني رقم (2)

littlebits-cargo-carrier

1× قالب كرتوني رقم (1)

الجرافة

1× قالب كرتوني رقم (8)

الجرافة1× قالب كرتوني رقم (9)

littlebits-robot-arm

 1×  ذراع تحكم
littlebits-cargo-carrier

1× مركز التحكم

littlebits-cargo-carrier

2× محرك تيار مستمر

الجرافة

 1×  محرك السيرڤو

littlebits-cargo-carrier

1× عجلة كروية

الجرافة

2× عجلات

الجرافة

1× حامل البطارية

littlebits-cargo-carrier

1× سلك البطارية

littlebits-cargo-carrier

1× بطارية

الجرافة

1× منفذ الطاقة

littlebits-robot-arm

 1×  محور

littlebits-robot-arm

 1× وصلة محور

الجرافة

1× ربطات قابلة للإلتواء

(اختياري)

توصيل الدائرة

تحتوي مجموعة ليتل بيتس على بطارية ومنفذ الطاقة اللذان يعتبران مسؤولان عن تزويد دائرتك بالطاقة اللازمة لتشغيلها.

ادخل البطارية في حامل البطارية، ثم وصل سلك البطارية مع البطارية.

littlebits-cargo-carrier

اربط سلك البطارية مع منفذ الطاقة.

littlebits-cargo-carrier

وصل السلك مع منفذ الطاقة، وفي الطرف الآخر اضف مركز التحكم.

يمكن أيضًا أن يعمل كمكبر صوت لتشغيل المؤثرات الصوتية.

الجرافة

محرك التيار المستمر يقوم بتدوير المحور حسب القيمة التي يتلقاها، كلما زادت القيمة زادت سرعة دوران المحرك.

littlebits-cargo-carrier

لا تدر المحرك بيديك؛ فذلك قد يؤدي إلى تلفه.

littlebits-cargo-carrier

وصل محرك التيار المستمر الأول مع المخرج الأول، ومحرك التيار المستمر الثاني مع المخرج الثالث في مركز التحكم.

littlebits-cargo-carrier

محرك

يمكن من خلال وحدة التحكم بالمحرك تحديد اتجاه الدوران للمحرك:

ccw عكس عقارب الساعة

Cw مع عقارب الساعة

Var متغير يمكن أن تكون مع أو عكس عقارب الساعة

حرك المفتاح في كلا محركين التيار المستمر لوضع var في المنتصف.

المركبة الفضائية ليتل بيتس

اضف محرك السيرڤو في المخرج الثاني لمركز التحكم.

محرك السيرڤو الأول يدور حسب الزوايا التي يتم إدخالها له.

littlebits-cargo-carrier

شغل المفتاح الموجود على محرك السيرڤو.

الجرافة

تجميع مكونات الجرافة

 اطو الخطوط المتصلة في القالب الكرتوني (4) فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.littlebits-cargo-carrier

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى آخر رقم بالقالب الكرتوني، واغلقها بإحكام.

littlebits-cargo-carrier

الجرافة

littlebits-cargo-carrier

 اطو الخطوط المتقطعة في القالب الكرتوني (1) ثم فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-cargo-carrier

اطو الخطوط المتصلة في القالب الكرتوني (1) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-cargo-carrier

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى آخر رقم بالقالب الكرتوني.

littlebits-cargo-carrier

الجرافة

littlebits-cargo-carrier

littlebits-cargo-carrier

littlebits-cargo-carrier

الجرافة

اطو الخطوط المتقطعة في القالب الكرتوني (5) فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

الجرافة

اطو الخطوط المتصلة في القالب الكرتوني (5) فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

الجرافة

اطو الخطوط المتقطعة في القالب الكرتوني (8) فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-cargo-carrier

اطو الخطوط المتصلة في القالب الكرتوني (8) فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

الجرافة

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى الشكل الموجود على اليسار.

الجرافة الجرافة

ادخل ذراع التحكم في الفتحة الموجودة في القالب الكرتوني رقم (8).

الجرافة

اطو الخطوط المتقطعة في القالب الكرتوني (9) فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

الجرافة

اطو الخطوط المتصلة في القالب الكرتوني (9) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-cargo-carrier

اطو الخطوط المتصلة في القالب الكرتوني (2) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-cargo-carrier

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل للرقم (7)، ادخل وصلة التثبيت رقم (8) مع المنفذ المقابل (8) حينها ستصل للشكل النهائي الموجود على اليسار.

littlebits-cargo-carrier littlebits-cargo-carrier

ادخل وصلة المحور بالمحور.

littlebits-cargo-carrier

ادخل أحد أطراف المحور أسفل القالب الكرتوني (2) الذي يسمى رأس العجلة.

الجرافة

تثبيت مكونات الجرافة:

ثبت اللوحة في هيكل عربة الفضاء.

الجرافة

ثبت العجلة الكروية في الفتحة السفلية لهيكل العربة كما هو ظاهر.

littlebits-cargo-carrier

ثبت البطارية في المستطيل، كما هو ظاهر.

littlebits-cargo-carrier

ثبت محركا التيار المستمر في الفتحات السفلية لهيكل العربة، كما هو ظاهر.

littlebits-cargo-carrier

ثبت مركز التحكم، منفذ الطاقة والمتحكم لكلا محركا التيار المستمر على اللوحة، كما هو ظاهر.littlebits-cargo-carrier

ثبت وصلة المحور على الهيكل.

خطوة اختيارية: استخدم ربطات قابلة للإلتواء؛ لتجعلها أكثر ثباتًا.

ذراع الروبوت ليتل بيتس

خطوة اختيارية: استخدم ربطات قابلة للإلتواء؛ لتثبيت وصلة المحور على الهيكل.

ذراع الروبوت ليتل بيتس

ثبت محرك السيرڤو على اللوحة.

littlebits-space-hammer

ثبت ذراع التحكم الموجودة في القالب الكرتوني رقم (8) على محرك السيرڤو.

littlebits-cargo-carrier

ثبت العجلتين على محركا التيار المستمر.الجرافة

ثبت القالب الكرتوني (9) على القالب الكرتوني (4).

الجرافة

ثبت القالب الكرتوني (4) على هيكل العربة.

الجرافة

 بعد تركيب كل مكونات ليتل بيتس يمكنك تشغيل الجرافة من خلال المفتاح الموجود في منفذ الطاقة.

تشغيل العربة الجوالة باستخدام ليتل بيتس

افحص مجددًا تركيب النظام لترى انه متوافق مع الصور.

تأكد من تشغيل وحدة مزود الطاقة

وتأكد أن الجرافة تسير وتجرف الأجسام المقابلة لها.

تذكر فصل وحدة مزود الطاقة عند الانتهاء من استخدام النظام.

 

 




المركبة الفضائية باستخدام ليتل بيتس (LittleBits)

مقدمة

يحاول العلماء استكشاف الكواكب في مجموعتنا الشمسية، ولذلك يحتاجون إلى المركبة الفضائية في هذا الدرس ستتعلم كيفية عمل مشروع المركبة الفضائية باستخدام ليتل بيتس

 تصنيع العربة الجوالة باستخدام ليتل بيتس

المواد والأدوات من ليتل بيتس

حتى تتمكن من تجميع المركبة الفضائية تحتاج من مجموعة مستكشف الفضاء ليتل بيتس (little bits Space Rover Inventor Kit):

cartoon-littlebits-rover-body

1× قالب كرتوني رقم (4)

cartoon-littlebits-rover-body

1× قالب كرتوني رقم (1)

solar-littlebits-rover-body

1× قالب كرتون رقم (5) – لوحة الطاقة الشمسية

استخدام مركز التحكم لتصنيع العربة الجوالة باستخدام ليتل بيتس

1× مركز التحكم

محرك تيار مستمر لـ العربة الجوالة باستخدام ليتل بيتس

2× محرك تيار مستمر

العجلة الكروية لـ العربة الجوالة باستخدام ليتل بيتس

1× عجلة كروية

المركبة الفضائية

2× عجلات

littlebits-rover-body

1× حامل البطارية

cable-littlebits-rover-body

1× سلك البطارية

استخدام البطارية لتصنيع العربة الجوالة باستخدام ليتل بيتس

1× بطارية

المركبة الفضائية

1× منفذ الطاقة

توصيل الدائرة

تحتوي مجموعة ليتل بيتس على بطارية ومنفذ الطاقة اللذان يعتبران مسؤولان عن تزويد دائرتك بالطاقة اللازمة لتشغيلها.

ادخل البطارية في حامل البطارية، ثم وصل سلك البطارية مع البطارية.

المركبة الفضائية ليتل بيتس

اربط سلك البطارية مع منفذ الطاقة.

المركبة الفضائية ليتل بيتس

وصل السلك مع منفذ الطاقة، وفي الطرف الآخر اضف مركز التحكم.

يمكن أيضًا أن يعمل كمكبر صوت لتشغيل المؤثرات الصوتية.

littlebits-rover-body

محرك التيار المستمر يقوم بتدوير المحور حسب القيمة التي يتلقاها، كلما زادت القيمة زادت سرعة دوران المحرك.

المركبة الفضائية ليتل بيتس

لا تدر المحرك بيديك؛ فذلك قد يؤدي إلى تلفه.

instruction-littlebits-rover-body

وصل محرك التيار المستمر الأول مع المخرج الأول، ومحرك التيار المستمر الثاني مع المخرج الثالث في مركز التحكم.

تثبيت المحرك لـ العربة الجوالة باستخدام ليتل بيتس

محرك

يمكن من خلال وحدة التحكم بالمحرك تحديد اتجاه الدوران للمحرك:

ccw عكس عقارب الساعة 

Cw مع عقارب الساعة

Var متغير يمكن أن تكون مع أو عكس عقارب الساعة

حرك المفتاح في كلا محركين التيار المستمر لوضع var في المنتصف.

المركبة الفضائية ليتل بيتس

تجميع مكونات المركبة الفضائية

 اطو الخطوط المتصلة في القالب الكرتوني (4) فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.littlebits-rover-body

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى آخر رقم بالقالب الكرتوني، واغلقها بإحكام.

المركبة الفضائية ليتل بيتس

بعد الطي القطع لـ العربة الجوالة باستخدام ليتل بيتس

littlebits-rover-body

 اطو الخطوط المتقطعة في القالب الكرتوني (1) ثم فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-rover-body

اطو الخطوط المتصلة في القالب الكرتوني (1) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-rover-body

طبق الأوجه التي لها نفس الرقم (1) مع (1) وهكذا حتى تصل إلى آخر رقم بالقالب الكرتوني.

match-littlebits-rover-body

littlebits-rover-body-match-face

المركبة الفضائية ليتل بيتس

littlebits-rover-body

littlebits-rover-body

طي القطع لـ العربة الجوالة باستخدام ليتل بيتس

اطو الخطوط المتقطعة في القالب الكرتوني (5) فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

المركبة الفضائية ليتل بيتس

اطو الخطوط المتصلة في القالب الكرتوني (5) فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-rover-body

تبيث مكونات المركبة الفضائية:

ثبت اللوحة في هيكل عربة الفضاء.

Board-littlebits-rover-body

ثبت العجلة الكروية في الفتحة السفلية لهيكل عربة الفضاء، كما هو ظاهر.

ball-littlebits-rover-body

ثبت البطارية في المستطيل، كما هو ظاهر.

تثبيت البطارية لـ العربة الجوالة باستخدام ليتل بيتس

ثبت محركا التيار المستمر في الفتحات السفلية لهيكل المركبة الفضائية، كما هو ظاهر.

littlebits-rover-body-DC

ثبت مركز التحكم، منفذ الطاقة والمتحكم لكلا محركا التيار المستمر على اللوحة، كما هو ظاهر.

littlebits-rover-body

ثبت العجلتين على محركا التيار المستمر.

تثبيت العجلات لـ العربة الجوالة باستخدام ليتل بيتس

ثبت وصلات التثبيت الموجودة على لوحة الطاقة الشمسية في المنافذ الموجودة بالقالب الكرتوني (4).

littlebits-rover-body-solar

ثبت القالب الكرتوني (4) مع لوحة الطاقة الشمسية على هيكل عربة الفضاء.

littlebits-rover-body

 بعد تركيب كل مكونات ليتل بيتس يمكنك تشغيل عربة الفضاء من خلال المفتاح الموجود في منفذ الطاقة.

تشغيل العربة الجوالة باستخدام ليتل بيتس

افحص مجددًا تركيب النظام لترى انه متوافق مع الصور.

تأكد من تشغيل وحدة مزود الطاقة

وتأكد أن المركبة الفضائية تسير بدون توقف.

تذكر فصل وحدة مزود الطاقة عند الانتهاء من استخدام النظام.




التحكم بالحاسوب بحركة اليد بدلًا من الفأرة باستخدام الاردوينو

مقدمة

أصبحت التكنولوجيا الحديثة تسهل علينا حياتنا، وتجعلها أبسط ومن ضمن ما طوره الباحثون في التقنية هو التحكم بالأجهزة عن بعد عن طريق حركات اليد ويعد نهجًا جديدًا للتحكم والسيطرة عن طريق مطابقة الحركة، في هذا الدرس ستتعلم كيفية التحكم بالحاسوب بحركات اليد بدلًا من الفأرة وذلك باستخدام الاردوينو وحساس الموجات فوق الصوتية.

سوف تتمكن من برمجة الاردوينو مع حساس الموجات فوق الصوتية، بحيث يقوم بمهام كإيقاف الفيديو أو تقديم وترجيع الفيديو وكذلك مهام التحكم بالصوت.

arduino-python-gesture-control

المواد والأدوات

التحكم بالحاسوب بحركات اليد

اردوينو اونو

التحكم بالحاسوب بحركات اليد

1× سلك الاردوينو

التحكم بالحاسوب بحركات اليد

حزمة أسلاك توصيل (ذكر – أنثى)

التحكم بالحاسوب بحركات اليد

حساس المسافة (HC-SR04)

التحكم بالحاسوب بحركات اليد

1× شريط لاصق ذو وجهين

توصيل الدائرة

المفهوم بسيط جدًا سنضع حساسي الموجات فوق الصوتية أعلى شاشة الحاسوب وسنقوم بإدخال المسافة بين الشاشة ويدنا باستخدام الاردوينو، بناءً على هذه القيمة سنقوم بإجراءات معينة.

للمزيد حول حساس الموجات فوق الصوتية يمكنك الرجوع للدرس التالي حساب المسافة بإستخدام حساس الموجات فوق صوتية

arduino-python-gesture-control

تثبيت القطع على جهاز الحاسوب

قم بقص الشريط اللاصق لثلاث قطع صغيرة وثبتها على جهاز الحاسوب كما هو واضح بالصورة:

التحكم بالحاسوب بحركات اليد

ثبت الدائرة الكهربائية كما هو موضح:

التحكم بالحاسوب بحركات اليد

الكود البرمجي للتحقق من قراءة المدخلات

في البداية سنقوم برفع كود برمجي لمحاكاة مشروع التحكم بالحاسوب بحركات اليد بدلًا من الفأرة والتحقق من أن الحساس يعطي قراءات صحيحة، ويتم طباعة الأوامر على شاشة الاتصال التسلسلي

ارفع الكود التالي إلى لوحة الاردوينو عن طريق (IDE) وافتح شاشة الاتصال التسلسلي.

const int trigger1 = 2; //Trigger pin of 1st Sesnor
const int echo1 = 3; //Echo pin of 1st Sesnor
const int trigger2 = 4; //Trigger pin of 2nd Sesnor
const int echo2 = 5;//Echo pin of 2nd Sesnor long time_taken;
int dist,distL,distR; void setup() { Serial.begin(9600);
pinMode(trigger1, OUTPUT);  pinMode(echo1, INPUT); 
pinMode(trigger2, OUTPUT); 
pinMode(echo2, INPUT); 
} /*###Function to calculate distance###*/ void calculate_distance(int trigger, int echo) { digitalWrite(trigger, LOW); delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW); time_taken = pulseIn(echo, HIGH);
dist= time_taken*0.034/2;
if (dist>50)
dist = 50; } void loop() { //infinite loopy calculate_distance(trigger1,echo1); distL =dist; //get distance of left sensor
calculate_distance(trigger2,echo2);
distR =dist; //get distance of right sensor //Uncomment for debudding
/*Serial.print("L=");
Serial.println(distL); Serial.print("R="); Serial.println(distR);
*/ //Pause Modes -Hold
if ((distL >40 && distR>40) && (distL <50 && distR<50)) //Detect both hands
{Serial.println("Play/Pause"); delay (500);} calculate_distance(trigger1,echo1);
distL =dist;
calculate_distance(trigger2,echo2);
distR =dist; if ((distL >40 && distL<50) && (distR ==50)) //Detect Left Hand {Serial.println("Rewind"); delay (500);} if ((distR >40 && distR<50) && (distL ==50)) //Detect Right Hand {Serial.println("Forward"); delay (500);} //Control Modes
//Lock Left - Control Mode if (distL>=13 && distL<=17) {
  delay(100); //Hand Hold Time   calculate_distance(trigger1,echo1);
distL =dist;   if (distL>=13 && distL<=17) {     Serial.println("Left Locked");     while(distL<=40)     {
      calculate_distance(trigger1,echo1);
      distL =dist;
      if (distL<10) //Hand pushed in        {Serial.println ("Vup"); delay (300);}       if (distL>20) //Hand pulled out
      {Serial.println ("Vdown"); delay (300);} }
} } //Lock Right - Control Mode if (distR>=13 && distR<=17) {   delay(100); //Hand Hold Time   calculate_distance(trigger2,echo2);   distR =dist;
  if (distR>=13 && distR<=17)
{     Serial.println("Right Locked");
  while(distR<=40)
{       calculate_distance(trigger2,echo2);       distR =dist;       if (distR<10) //Right hand pushed in       {Serial.println ("Rewind"); delay (300);}       if (distR>20) //Right hand pulled out
      {Serial.println ("Forward"); delay (300);} }
}
} delay(200); }

شرح الكود البرمجي

عرفنا  المتغيرات اللازمة التي  يستخدمها كلا حساسي الموجات فوق الصوتية.

المخرج للحساس الأول (trigger1) والمدخل للحساس الأول (echo1).

المخرج للحساس الثاني (trigger2) والمدخل للحساس الثاني (echo2).

const int trigger1 = 2; //Trigger pin of 1st Sesnor
const int echo1 = 3; //Echo pin of 1st Sesnor
const int trigger2 = 4; //Trigger pin of 2nd Sesnor
const int echo2 = 5;//Echo pin of 2nd Sesnor long time_taken;
int dist,distL,distR; void setup() { Serial.begin(9600); 
pinMode(trigger1, OUTPUT);  pinMode(echo1, INPUT); 
pinMode(trigger2, OUTPUT); 
pinMode(echo2, INPUT); 
}.

عند تشغيل أي مقطع فيديو على مشغل الفيديو (VLC) أو اليوتيوب سيتم حساب المسافة بين كلا حساسي الموجات فوق الصوتية واليدين في كل مرة من خلال الدالة ()calculate_distance، وسيكون هناك عدة اجراءات بناء على تلك القراءات.

/*###Function to calculate distance###*/
void calculate_distance(int trigger, int echo)
{
digitalWrite(trigger, LOW);
delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW); time_taken = pulseIn(echo, HIGH);
dist= time_taken*0.034/2;
if (dist>50)
dist = 50; }

داخل دالة ()Loop، يتم التحقق من قيمة المسافة وعلى أساسها يتم الاختيار من بين الاجراءات.

نستخدم المتغير distL ويشير إلى مقدار المسافة بين حساس الموجات الصوتية و اليد الموجود باليسار

نستخدم المتغير distR ويشير إلى مقدار المسافة بين حساس الموجات الصوتية و اليد الموجود باليمين

calculate_distance(trigger1,echo1);
distL =dist; //get distance of left sensor

calculate_distance(trigger2,echo2);
distR =dist; //get distance of right sensor

بناء على المسافة (عند وضع كلتا اليدين على الحساسين في نفس الوقت وكانت المسافة أكبر من 40 وأصغر من 50) سيتوقف الفيديو وعند الرغبة بتشغيل الفيديو مرة أخرى يمكنك إرجاع كلتا يديك لكلا الحساسين.

if ((distL >40 && distR>40) && (distL <50 && distR<50)) //Detect both hands
{Serial.println("Play/Pause"); delay (500);}

بناء على المسافة (المسافة بين الحساس الأيسر واليد اليسرى أكبر من 40 وأقل من 50 والمسافة بين الحساس الأيمن واليد اليمنى تساوي 50)  سيتم ترجيع الفيديو للخلف.

بناء على المسافة (المسافة بين الحساس الأيمن واليد اليمنى أكبر من 40 وأقل من 50 والمسافة بين الحساس الأيسر واليد اليسرى تساوي 50)  سيتم تقديم الفيديو للامام.

if ((distL >40 && distL<50) && (distR ==50)) //Detect Left Hand
{Serial.println("Rewind"); delay (500);}

if ((distR >40 && distR<50) && (distL ==50)) //Detect Right Hand
{Serial.println("Forward"); delay (500);}

إذا كانت المسافة (المسافة بين الحساس الأيسر ويدك اليسرى أقل من 10) سيزيد حجم الصوت.

إذا كانت المسافة (المسافة بين الحساس الأيسر ويدك اليسرى أكبر من 20)  سينقص حجم الصوت.

//Lock Left - Control Mode
if (distL>=13 && distL<=17)
{
  delay(100); //Hand Hold Time
  calculate_distance(trigger1,echo1);
  distL =dist;
  if (distL>=13 && distL<=17)
  {
    Serial.println("Left Locked");
    while(distL<=40)
    {
      calculate_distance(trigger1,echo1);
      distL =dist;
      if (distL<10) //Hand pushed in 
      {Serial.println ("Vup"); delay (300);}
      if (distL>20) //Hand pulled out
      {Serial.println ("Vdown"); delay (300);}
    }
  }
}

إذا كانت المسافة (المسافة بين الحساس الأيمن ويدك اليمنى أقل من 10) سيتم ترجيع الفيديو للخلف.

إذا كانت المسافة (المسافة بين الحساس الأيمن ويدك اليمنى أكبر من 20)  سيتم تقديم الفيديو للأمام.

//Lock Right - Control Mode
if (distR>=13 && distR<=17)
{
  delay(100); //Hand Hold Time
  calculate_distance(trigger2,echo2);
 distR =dist;
if (distR>=13 && distR<=17)
{
Serial.println("Right Locked");
    while(distR<=40)
{
calculate_distance(trigger2,echo2);
 distR =dist;
 if (distR<10) //Right hand pushed in
 {Serial.println ("Rewind"); delay (300);}
 if (distR>20) //Right hand pulled out
 {Serial.println ("Forward"); delay (300);}
 }
}
}
delay(200);
}

تنصيب (Python IDLE) و (Pyserial)

1- تنصيب (Python IDLE)

تثبيت البايثون على نظام ويندوز سوا كان نظام تشغيل 32 بت أو 64 بت هو نفسه.

 انقر على الرابط التالي Python 3.9.2 وثبت البرنامج على جهاز الحاسوب.

حمّل نسخة 32 بت دائمًا مهما كان نظام التشغيل.

التحكم بالحاسوب

افتح ملف exe الذي تم تنزيله واتبع التعليمات لا تقم بتغيير المسار الذي يتم فيه تثبيت Python.

سيكون المسار C:\Program Files (x86)\Python39-32 بشكل افتراضي اتركه كما هو عليه.

التحكم بالحاسوب بحركات اليد

2- ضبط إعدادات لوحة الأوامر

بعد تنصيب البايثون على  جهازك، علينا اجراء التعديلات ليتم السماح بتنفيذ أوامره في شاشة الأوامر Command Prompt.

علينا اضافة مترجم اوامر البايثون إلى امتدادات الأوامر – PATH environment variable.
عليك الذهاب للوحة التحكم بويندوز واتباع المسار التالي:
Control Panel\System and Security\System
اختر من القائمة Advanced system setting:

التحكم بالحاسوب بحركات اليد

انقر على Environment variable:

التحكم بالحاسوب بحركات اليد

انقر على Path من قائمة System Variables.

arduino-python-gesture-control

انقر على New وأضف المسار التالي (أو المسار الذي قمت بتحميل البرنامج عليه):
C:\Program Files (x86)\Python39-32

 انقر على New مرة أخرى وضع مسار مجلد Scripts:

C:\Program Files (x86)\Python39-32\Scripts

التحكم بالحاسوب

بعد اتمامك للخطوات سيكتمل تنصيب البرنامج، يمكنك التحقق من وجوده وذلك بالبحث عنه مع قائمة البرامج Python IDLE.

3- تنصيب (Pyserial)

بعد ذلك علينا تنصيب Pyserial انقر على الرابط التالي وحمله على حاسوبك Pyserial 3.5 

التحكم بالحاسوب عن طريق التلويح

بعد تحميله فك الضغط عنه وانسخ المسار الذي يتواجد فيه ملف Pyserial.

انقر بالسهم اليمين على Command Prompt واختر من القائمة Run as administrator.

arduino-python-gesture-control

اكتب الأمر التالي وضع المسار الذي قمت بتحميل Pyserial فيه:

cd (Pyserial المسار لبرنامج)

حمل setup.py.

python setup.py install
4- تنصيب مكتبة (Pyautogui)

تركيب وحدة Pyautogui للويندوز:

تأكد من أن جهاز الحاسوب متصل بالإنترنت واتبع الخطوات أدناه:

الخطوة 1: افتح صفحة الأوامر بويندوز Windows prompt وقم بتغيير المسار إلى المجلد الذي قمت بتثبيت به البايثون.

cd C:\Program Files (x86)\Python39-32

الخطوة 2: داخل مسار بايثون، سنقوم بترقية Pip وهي أداة في البايثون تساعدنا على تثبيت وحدات البايثون بسهولة استخدم الأمر التالي لترقيتها.

pip install –-upgrade pip

 الخطوة 3: ثبت وحدة Pyautogui.

pip install pyautogui

  الكود البرمجي (بايثون)

افتح برنامج IDLE (Python 3.9 32-bit) من قائمة File اختر New File والصق الكود البرمجي التالي.

التحكم بالحاسوب بحركات اليد

ارفع الكود البرمجي للوحة الاردوينو من قائمة Run انقر على Run module.

import serial #Serial imported for Serial communication
import time #Required to use delay functions
import pyautogui
ArduinoSerial = serial.Serial('com18',9600) #Create Serial port object called arduinoSerialData
time.sleep(2) #wait for 2 seconds for the communication to get established
while 1:
    incoming = str (ArduinoSerial.readline()) #read the serial data and print it as line
    print (incoming)
    if 'Play/Pause' in incoming:
        pyautogui.typewrite(['space'], 0.2)
    if 'Rewind' in incoming:
        pyautogui.hotkey('ctrl', 'left')  
    if 'Forward' in incoming:
        pyautogui.hotkey('ctrl', 'right') 
    if 'Vup' in incoming:         pyautogui.hotkey('ctrl', 'down')     if 'Vdown' in incoming:       pyautogui.hotkey('ctrl', 'up')
  incoming = "";

شرح الكود البرمجي

افتح صفحة جديدة في IDLE Python وقم باستدعاء المكتبات المطلوبة pyautogui, serial python و time.

import serial #Serial imported for Serial communication
import time #Required to use delay functions
import pyautogui

حدد المنفذ COM المستخدم في الاتصال مع الاردوينو.
(هذا سطر قابل للتغيير بناء على نوع المنفذ الذي ستستخدمه في المشروع يمكنك تعيينه عن طريق برنامج اردوينو IDE من قائمة Port).

ArduinoSerial = serial.Serial('com18',9600) #Create Serial port object called arduinoSerialData 
time.sleep(2) #wait for 2 seconds for the communication to get established

 في هذا السطر تتم قراءة المسافة بين اليدين والحساس من المنفذ التسلسلي.

وعلى أساس تلك المسافة يتم تنفيذ الاجراءات وربطها مع اختصارات لوحة المفاتيح.

الاختصارات المستخدمة في هذا الدرس من مشغل VLC:

Space :ايقاف/تشغيل الملف

 Ctrl +  السهم يمين أو يسار: التقديم أو الترجيع دقيقة

Ctrl + السهم للأعلى والأسفل: رفع وخفض مستوي الصوت

while 1:
    incoming = str (ArduinoSerial.readline()) #read the serial data and print it as line
    print incoming
    
    if 'Play/Pause' in incoming:
        pyautogui.typewrite(['space'], 0.2)

    if 'Rewind' in incoming:
        pyautogui.hotkey('ctrl', 'left')  

    if 'Forward' in incoming:
        pyautogui.hotkey('ctrl', 'right') 

    if 'Vup' in incoming:
        pyautogui.hotkey('ctrl', 'down')
        
    if 'Vdown' in incoming:
        pyautogui.hotkey('ctrl', 'up')

ستلاحظ كقدرتك على التحكم بالحاسوب بحركات اليد بدلًا من الفأرة باستخدام الاردوينو يمكنك اختبار صحة الخطوات والاجراءات من خلال الصفحة المنبثقة بعد النقر على Run modul ستظهر  صفحة IDLE Shell.

التحكم بالحاسوب بحركات اليد

لا تنسى إيقاف مصدر الطاقة بعد الانتهاء من استخدام النظام.

 




تسجيل الدخول لنظام ويندوز باستخدام الاردوينو و (RFID)

 مقدمة

تساعد كلمة المرور لجهاز الحاسوب في الحفاظ على بياناتك وخصوصية جهازك، في هذا الدرس ستتعلم كيفية تسجيل الدخول لنظام ويندوز باستخدام الاردوينو وقارئ البطاقات في حال كنت لا ترغب في إدخال كلمة عند تسجيل الدخول.

arduino-unlock-computer-with-rfid

المواد والأدوات

الدخول لنظام ويندوز RFID

1× اردوينو اونو

الدخول لنظام ويندوز RFID

1× سلك الاردوينو

arduino-unlock-computer-with-rfid

حزمة أسلاك توصيل (ذكر – أنثى)

اردوينو

 أسلاك توصيل (ذكر-ذكر)

security-access-using-rfid-reader

قارئ البطاقة (RFID mfrc522)

توصيل الدائرة

وصل الدائرة كما هو موضح بالشكل:

arduino-unlock-computer-with-rfid

الدخول لنظام ويندوز RFID

لمعرفة المزيد حول بطاقة RFID يمكنك الرجوع للدرس RFID

الكود البرمجي

في البداية عليك تثبيت المكتبة الخاصة بقارئ البطاقات RFID انقر على الرابط التالي RFID-master وحملها على جهازك.

1- قراءة رمز البطاقة

حتى تتمكن من تسجيل الدخول لنظام ويندوز باستخدام الاردوينو و (RFID) ارفع الكود البرمجي التالي على لوحة الاردوينو.

#include <SPI.h>
#include <MFRC522.h> // RFID library
#define SS_PIN 10 //RX slave select
#define RST_PIN 9
int gled = 7; // optional
int rled = 4;// optional
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
String card_ID=""; //
String password="" ; // Change It To Your Windows / fb / any Account's Password String rfid="";// UID (unique Id Code Of Your Rfid Tag) void setup() { Serial.begin(9600); // Initialize serial communications with the PC SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(gled,OUTPUT);
pinMode(rled,OUTPUT);
} void loop() { //look for new card if ( ! mfrc522.PICC_IsNewCardPresent()) { return; }
if ( ! mfrc522.PICC_ReadCardSerial()) { return;//if read card serial(0) returns 1, the uid struct contians the ID of the read card. }
for (byte i = 0; i < mfrc522.uid.size; i++) { card_ID += mfrc522.uid.uidByte[i]; }
// Serial.println(card_ID); Serial.print(card_ID); delay(1000); card_ID=""; }

افتح شاشة الاتصال التسلسلي وضع البطاقة على قارئ البطاقات.

انسخ رمز البطاقة واحفظه في ملف ستحتاج إليه لاحقًا.

الدخول لنظام ويندوز RFID

2- رفع الكود البرمجي لنظام

قبل رفع الكود البرمجي إلى لوحة الاردوينو هناك أمور مهمة عليك العمل بها، اقرأ شرح الكود البرمجي.

uint8_t buf[8] = { 0 };
#include <SPI.h>
#include <MFRC522.h> // RFID library
#define SS_PIN 10 //RX slave select
#define RST_PIN 9
int gled = 7; // optional
int rled = 4;// optional
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
String card_ID=""; //
String password="" ; // Change It To Your Windows / fb / any Account's Password
String rfid="";// UID (unique Id Code Of Your Rfid Tag) void setup() { Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(gled,OUTPUT);
pinMode(rled,OUTPUT);
}
void loop() { //look for new card if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } if ( ! mfrc522.PICC_ReadCardSerial()) {
return;//if read card serial(0) returns 1, the uid struct contains the ID of the read card.
} for (byte i = 0; i < mfrc522.uid.size; i++) {
card_ID += mfrc522.uid.uidByte[i];
} // Serial.println(card_ID);
if(card_ID==rfid){digitalWrite(gled,HIGH);
typeLiteralString(password);
pressKey("enter"); releaseKey("enter");
digitalWrite(gled,LOW); delay(200);digitalWrite(gled,HIGH); delay(200);digitalWrite(gled,LOW);
} if(card_ID!=password){
digitalWrite(rled,HIGH); digitalWrite(rled,LOW); delay(200);digitalWrite(rled,HIGH); delay(200);digitalWrite(rled,LOW); } else{ goto cont;}
delay(1000);
cont:
delay(1000);
card_ID=""; } boolean isModifier(int keycode) {
boolean result = false;
if (keycode >= 224 && keycode <= 231) { // if the keycode is a modifier key
result = true;
} return result; } void pressModifier(String keyname) {
pressModifier(getKeycode(keyname));
} void pressModifier(int keycode) {
int modifiermask = 0;
if (isModifier(keycode)) { // if the keycode represents a modifier key modifiermask = getModifierMask(keycode);
buf[0] = buf[0] | modifiermask;
Serial.write(buf, 8); // Send key report
} } void releaseModifier(String keyname) {
releaseModifier(getKeycode(keyname));
} void releaseModifier(int keycode) {
int modifiermask = 0;
if (isModifier(keycode)) { // if the keycode represents a modifier key
modifiermask = getModifierMask(keycode);
buf[0] = buf[0] & (~modifiermask);
Serial.write(buf, 8); // Send key report
} } void releaseAllModifiers() {
buf[0] = B00000000;
Serial.write(buf, 8); // Send key report
} void pressKey(String keyname) {
pressKey(getKeycode(keyname));
} void pressKey(int keycode) { // TODO: cycle the 6 key spots in the report buffer instead of just using buf[2] each time. buf[2] = keycode;
Serial.write(buf, 8); // Send key report
} void releaseKey(String keyname) {
releaseKey(getKeycode(keyname));
} void releaseKey(int keycode) {
// find the keycode in the report buffer, then set it to zero.
int i=0;
for (i=2; i<8; i++) {
if (buf[i] == keycode) {
buf[i] = 0;
} } Serial.write(buf, 8); // Send key report
} void releaseAllKeys() {
int i=0;
for (i=2; i<8; i++) {
buf[i] = 0;
} Serial.write(buf, 8); // Send key report
} void pressSequenceOfKeys(const char * keySequence[], int numberOfKeys) {
// This function can be good for pressing a few keys while holding a modifier down for example.
int i = 0; for (i=0; i<numberOfKeys; i++) {
pressKey(keySequence[i]);
releaseKey(keySequence[i]);
} } void typeLiteralString(String string) {
char charArray[string.length()+1];
string.toCharArray(charArray, string.length()+1);
typeLiteralString(charArray, string.length());
} void typeLiteralString(char string[], int stringLength) { // stringLength is the length of the printable string without considering the null byte.
// This function will type the given string exactly as given, automatically pressing left_shift where necessary for capitals and symbols. // just in case: releaseAllKeys(); releaseAllModifiers(); boolean charNeedsShift = false; boolean shiftIsPressed = false; int i=0;
for (i=0; i<stringLength; i++) {
charNeedsShift = characterNeedsShift(string[i]);
if (charNeedsShift && !shiftIsPressed) {
pressModifier("left_shift");
shiftIsPressed = true;
} else if (!charNeedsShift && shiftIsPressed) {
releaseModifier("left_shift");
shiftIsPressed = false;
} pressKey(String(string[i])); // without converting the char in string[i] to a String, arduino would prefer the pressKey(int) function instead of the pressKey(String) function, casting the char to a keycode (int) instead of a keyname (String).
releaseKey(String(string[i])); // same as previous comment, but with releaseKey(). } releaseAllModifiers(); } boolean characterNeedsShift(char character) { int needsModifier = false; if ( // look up an ascii table and this will make sense.
(character >= 33 && character <= 38)
|| (character >= 40 && character <= 43)
|| (character == 58)
|| (character == 60)
|| (character >= 62 && character <= 90)
|| (character >= 94 && character <= 95)
|| (character >= 123 && character <= 126)
) { needsModifier = true;
} return needsModifier; } int getKeycode(String keyname) { String key = String(keyname); // Use a copy so that we don't mutate the user's String. Not sure if this is needed, but just in case. TODO: find out.
key.toLowerCase(); int keycode = 0; // keycode of zero means nothing pressed. // non-modifier keys
if (key == "a") { keycode = 4; }
else if (key == "b") { keycode = 5; }
else if (key == "c") { keycode = 6; }
else if (key == "d") { keycode = 7; }
else if (key == "e") { keycode = 8; }
else if (key == "f") { keycode = 9; }
else if (key == "g") { keycode = 10; }
else if (key == "h") { keycode = 11; }
else if (key == "i") { keycode = 12; }
else if (key == "j") { keycode = 13; }
else if (key == "k") { keycode = 14; }
else if (key == "l") { keycode = 15; }
else if (key == "m") { keycode = 16; }
else if (key == "n") { keycode = 17; } else if (key == "o") { keycode = 18; } else if (key == "p") { keycode = 19; }
else if (key == "q") { keycode = 20; }
else if (key == "r") { keycode = 21; }
else if (key == "s") { keycode = 22; }
else if (key == "t") { keycode = 23; }
else if (key == "u") { keycode = 24; }
else if (key == "v") { keycode = 25; } else if (key == "w") { keycode = 26; }
else if (key == "x") { keycode = 27; }
else if (key == "y") { keycode = 28; }
else if (key == "z") { keycode = 29; } else if (key == "1" || key == "!") { keycode = 30; }
else if (key == "2" || key == "@") { keycode = 31; }
else if (key == "3" || key == "#") { keycode = 32; } else if (key == "4" || key == "$") { keycode = 33; }
else if (key == "5" || key == "%") { keycode = 34; }
else if (key == "6" || key == "^") { keycode = 35; }
else if (key == "7" || key == "&") { keycode = 36; }
else if (key == "8" || key == "*") { keycode = 37; } else if (key == "9" || key == "(") { keycode = 38; } else if (key == "0" || key == ")") { keycode = 39; }
else if (key == "enter" || key == "return") { keycode = 40; }
else if (key == "escape" || key == "") { keycode = 41; }
else if (key == "backspace" || key == "") { keycode = 42; }
else if (key == "tab" || key == " ") { keycode = 43; }
else if (key == "space" || key == " ") { keycode = 44; } else if (key == "-" || key == "_") { keycode = 45; }
else if (key == "=" || key == "+") { keycode = 46; }
else if (key == "[" || key == "{") { keycode = 47; }
else if (key == "]" || key == "}") { keycode = 48; }
else if (key == "\\" || key == "|") { keycode = 49; } else if (key == ";" || key == ":") { keycode = 51; }
else if (key == "'" || key == "\"") { keycode = 52; } else if (key == "`" || key == "~") { keycode = 53; }
else if (key == "," || key == "<") { keycode = 54; }
else if (key == "." || key == ">") { keycode = 55; }
else if (key == "/" || key == "?") { keycode = 56; } // TODO: Fix these keycodes. V
else if (key == "capslock") { keycode = 58; } else if (key == "f1") { keycode = 59; }
else if (key == "f2") { keycode = 60; }
else if (key == "f3") { keycode = 61; }
else if (key == "f4") { keycode = 62; }
else if (key == "f5") { keycode = 63; }
else if (key == "f6") { keycode = 64; }
else if (key == "f7") { keycode = 65; }
else if (key == "f8") { keycode = 66; }
else if (key == "f9") { keycode = 67; }
else if (key == "f10") { keycode = 68; } else if (key == "f11") { keycode = 69; }
else if (key == "f12") { keycode = 70; } else if (key == "print_screen") { keycode = 70; }
else if (key == "scroll_lock") { keycode = 71; }
else if (key == "pause") { keycode = 72; } else if (key == "insert") { keycode = 73; }
else if (key == "home") { keycode = 74; } else if (key == "page_up") { keycode = 75; }
else if (key == "delete") { keycode = 76; }
else if (key == "end") { keycode = 77; }
else if (key == "page_down") { keycode = 78; } else if (key == "right_arrow") { keycode = 79; }
else if (key == "left_arrow") { keycode = 80; }
else if (key == "down_arrow") { keycode = 81; }
else if (key == "up_arrow") { keycode = 82; } else if (key == "numlock" || key == "clear") { keycode = 83; } //TODO: keypad and miscellaneous keys if you want them. // modifier keys. else if (key == "left_control") { keycode = 224; }
else if (key == "left_shift") { keycode = 225; }
else if (key == "left_alt") { keycode = 226; }
else if (key == "left_gui") { keycode = 227; } else if (key == "right_control") { keycode = 228; }
else if (key == "right_shift") { keycode = 229; }
else if (key == "right_alt") { keycode = 230; }
else if (key == "right_gui") { keycode = 231; } return keycode; }
int getModifierMask(String keyname) { return getModifierMask(getKeycode(keyname));
}
int getModifierMask(int keycode) { // return value of 0 means key is not a modifier.
int modifiermask = 0; // NOTE: these are not the usage keycodes like for other keys, but rather the bit masks.
if (keycode == 224) { modifiermask = B00000001; } // left ctrl
else if (keycode == 225) { modifiermask = B00000010; } // left shift
else if (keycode == 226) { modifiermask = B00000100; } // left alt
else if (keycode == 227) { modifiermask = B00001000; } // left gui
else if (keycode == 228) { modifiermask = B00010000; } // right ctrl
else if (keycode == 229) { modifiermask = B00100000; } // right shift
else if (keycode == 230) { modifiermask = B01000000; } // right alt
else if (keycode == 231) { modifiermask = B10000000; } // right gui return modifiermask;
}

شرح الكود البرمجي

في هذا السطر نستدعي مكتبة قارئ البطاقة RFID ومكتبة الاتصال المتزامن.

#include <SPI.h>
#include <MFRC522.h> // RFID library

هذه الأسطر توضح منافذ الاردوينو التي ستستخدمها للربط في هذا المشروع.

#define SS_PIN 10 //RX slave select
#define RST_PIN 9

بعد ذلك أعلنا عن المتغيرات اللازمة مثل المتغيرات الخاصة بقارئ البطاقة RFID.

int gled = 7; // optional
int rled = 4;// optional
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.

هذه الأسطر حساسة ومهمة.

السطر الأول: اتركه كما هو عليه فارغ.

السطر الثاني: اكتب كلمة المرور التي تستخدمها عند تسجيل دخولك لنظام ويندوز (كن منتبهًا لحالة الأحرف).

السطر الثالث: اكتب رقم ID للبطاقة.

String card_ID=""; //
String password="12345986" ; // Change It To Your Windows / fb / any Account's Password
String rfid="215177152200";// UID (unique Id Code Of Your Rfid Tag)

في الدالة ()setup يتم انشاء جسر تواصل تسلسلي بين الحاسوب وقارئ البطاقة وتهيئة قارئ البطاقة لتسجيل القيم.

void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
pinMode(gled,OUTPUT);
pinMode(rled,OUTPUT);

في الدالة ()loop يستبدل الرمز السابق للبطاقة بالرمز الجديد (رمز تسجيل الدخول لنظام ويندوز).

 تتم قراءة البيانات من قارئ البطاقة ويتم ارسالها إلى الاردوينو لمعالجة البيانات المدخلة.

سيختبر القارئ كل بطاقة يتم توجيهها له وسيمنع أي محاولات لدخول النظام غير مصرحة.

وسيعطي الصلاحية فقط لحامل البطاقة التي تحمل كلمة المرور لنظام ويندوز.

void loop() {}

يمكنك الآن رفع الكود البرمجي على لوحة الاردوينو بعد تعيين رمز البطاقة وكلمة المرور لنظام ويندوز.

وضع (DFU)

هو اختصار لكلمة (Device Firmware Update).

عند وضع الاردوينو بوضع DFU فلا يمكنك استخدام المنفذ التسلسلي USB مرة أخرى مع برنامج Arduino IDE.
وهنا يمكنك عمل ترقية باستخدام برامج أخرى مثل Flip.

بعد رفع الكود البرمجي لنظام تسجيل الدخول لنظام ويندوز باستخدام الاردوينو و RFID.

وصل سلك من GND إلى الرأس المشار إليه بالسهم لمدة ثانية أو ثانيتين ستبدأ لوحة الاردوينو بالوميض أزل السلك بعد انتهاء الوميض.

الدخول لنظام ويندوز RFID

عند الذهاب للمسار التالي:

Control panel > Hardware and Sound > Device Manager

ستلاحظ وجود جهاز جديد بهذا الاسم.

arduino-unlock-computer-with-rfid

يمكنك فصل سلك USB الموصل مع لوحة الاردوينو وإعادته مرة أخرى.

سيبدأ النظام بالعمل مباشرة يمكنك اختباره واختبار صحة خطواتك.

لا تنسَ فصل مصدر الطاقة بعد الانتهاء من استخدام النظام.

 




الطباعة على مصفوفة الإضاءة باستخدام ليتل بيتس (LittleBits)

مقدمة

 تُستخدم مصفوفة الإضاءة في أشياء كثيرة بحياتنا اليومية مثل جعلها وسيلة تعليمية أو يتم وضع فيها عبارات ترحيبية أو تحفيزية يمكنك أيضًا إضافة الرسومات التي تفضلها في هذا الدرس ستتعلم كيفية طباعة (Hello World) وتعني مرحبا بالعالم على مصفوفة الإضاءة باستخدام ليتل بيتس.

littlebits-hello-world

 المواد والأدوات من ليتل بيتس

حتى تتمكن من طباعة مرحبا بالعالم (Hello World) على مصفوفة الإضاءة تحتاج من مجموعة البرمجة سفيرو ليتل بيتس (Code kit by sphero little bits):

littlebits-hello-world

1× سلك (USB)

littlebits-hello-world

1× وحدة برمجة

littlebits-hello-world

1× ناقل الطاقة

1× ناقل التعليمات البرمجية

littlebits-hello-world

1× بطارية

1× مصفوفة الإضاءة

littlebits-hello-world

1× مفتاح

littlebits-hello-world

1× جهاز حاسوب

وحدة البرمجة

تقوم وحدة البرمجة بنفس عمل الدماغ البشري.

littlebits-hello-world

يوجد في وحدة البرمجة 3 منافذ مدخلات لتوصيل الحساسات مثل الصوت أو غيره من المدخلات على اليسار وثلاث منافذ مخرجات لتوصيل القطع مثل الضوء أو المحرك على اليمين، تقوم الوحدة بتحليل المدخلات بناء على المقطع البرمجي وتظهر النتائج على المخرجات.

littlebits-hello-world

توصيل الدائرة

وصل البطارية مع سلك (USB)، وفي الطرف الآخر اضف ناقل الطاقة.

littlebits-hello-world

وصل المفتاح مع ناقل الطاقة، كما هو ظاهر.

littlebits-hello-world

وصل الطرف الآخر للمفتاح مع المدخل الثاني لوحدة البرمجة.

littlebits-hello-world

وصل مصفوفة الإضاءة مع المخرج الأول لوحدة البرمجة.

littlebits-hello-world

 حرك المفتاح لـ Serial، يساعدك هذا الخيار على طباعة الصور والجمل على مصفوفة الإضاءة.

مصفوفة الإضاءة ليتل بيتس

عند تشغيل الطاقة فسيعمل المقطع البرمجي الافتراضي يمكنك تغيير المقطع البرمجي حتى تحصل على مخرجات مختلفة على مصفوفة الإضاءة.

littlebits-hello-world

وصل ناقل التعليمات البرمجية على جهاز الحاسوب وتصبح قطع ليتل بيتس جاهزة لمرحلة البرمجة.

يعمل ناقل التعليمات البرمجية على نقل المقطع البرمجي من جهاز الحاسوب إلى النظام.

littlebits-hello-world

تنصيب برنامج ليتل بيتس (Littlebits)

حتى تتمكن من تغيير البرمجة لابد من تحميل برنامج ليتل بيت كود بيت من الرابط التالي: LittleBits code kit اختر نوع نظام التشغيل المتوافق مع جهازك.

littlebits-hello-world

بعد اكتمال عملية التحميل اضغط على أيقونة البرنامج.

littlebits-hello-world

اختر (Only for me) ثم اضغط على (install).

install

بعد اكتمال عملية التنزيل اضغط على (finish).

المقطع البرمجي

افتح برنامج ليتل بيتس (Littlebits) تظهر لك هذه النافذة مباشرة اضغط على  (Open A blank canvas) حتى تبدأ بكتابة المقطع البرمجي.

littlebits-hello-world

ستظهر هذه النافذة مباشرة وتحتوي على عدة أقسام موضحة في الصورة التالية:

littlebits-hello-world

سنبدأ بكتابة المقطع البرمجي.

من قائمة (Timing) والتي تقوم بتحديد وقت معين لكل أمر برمجي اسحب الأمر (Wait for IN1 to be on) وتعني بأن ننتظر حتى يكون المدخل In1 فعّال وجاهز للعمل.

Wait for IN1 to be on

بعد افلات الأمر في منطقة التحكم نعدل المدخل ونختار من القائمة المدخل الثاني (IN2).

IN2

من قائمة (Text) والتي تخص طباعة النص بأشكالها المختلفة نسحب (Send scrolling text hello world to OUT1) والتي تعني ارسل الجملة أهلا بالعالم إلى المخرج 1.

Text

في هذا الدرس سنستخدم جملة مرحبا بالعالم (Hello World) يمكنك اختيار اي جملة ترغب بطباعتها على مصفوفة الإضاءة.

littlebits-hello-world

بعد كتابة الجملة اضغط على (Connect to your CODEBIT):

Connect to your CODEBIT

 اضغط على المفتاح الموجود في وحدة البرمجة: 

littlebits-hello-world

 بعد الضغط عليه، سوف يومض باللون الأخضر ويظهر في القائمة يمكنك اختياره بالضغط على (Connect) .

Connect

اضغط على (Upload) حتى تقوم برفع المقطع البرمجي:

Upload

الآن قد اكتمل بناء نظام الطباعة على مصفوفة الإضاءة لتشغيل النظام اضغط على الزر وستلاحظ أن جملة مرحبا بالعالم (Hello World) ستظهر على مصفوفة الإضاءة.

افحص مجددًا تركيب النظام لترى انه بمتوافق مع صور التركيب.

تأكد من تشغيل وحدة مزود الطاقة.

littlebits-hello-world

تذكر فصل وحدة مزود الطاقة عند الانتهاء من استخدام النظام.




حجب الإعلانات باستخدام الراسبيري باي وباي هول (Pi-hole)

مقدمة

في هذا الدرس ستتعلم كيف تستخدم الراسبيري باي وباي هول (Pi-hole) لحجب الإعلانات المزعجة؛ حتى لا تواجهك أو تواجه أبنائك أثناء استخدام الانترنت

راسبيري باي وباي هول

المواد والأدوات

حجب الإعلانات الراسبيري باي

 1× راسبيري باي

الراسبيري باي وباي هول

 1× كرت ذاكرة

الراسبيري باي وباي هول

 1× سلك (HDMI)

الراسبيري باي وباي هول

1× محول تيار (5V-2A)

Fan

1× مروحة الراسبيري باي

الراسبيري باي وباي هول

غطاء الراسبيري باي

raspberry-pi-hole-block-ads

1× سلك ايثرنت

تبريد المعالج

قد يتعرض معالج الراسبري باي إلى الحرارة الزائدة عند تشغيل برامج ثقيلة لفترات طويلة. فقد تقترب درجة الحرارة الداخلية للمعالج من 85 درجة مئوية، وسيؤدي ذلك أن يعمل الراسبيري باي على خفض تردد التشغيل أو إيقاف التشغيل تمامًا. ويمكن أن يؤثر ذلك سلبًا على أداء مشروعك. ومن هنا تأتي فائدة توفير أساليب لخفض حرارة المعالج لذلك ستحتاج إلى مروحة ومسرب حراري.

ثبت المسرب الحراري على وحدة (SOC) ووحدة (USB controller)

الراسبيري باي وباي هول

وصل السلك الأحمر لمروحة التبريد(الموجب) مع المنفذ رقم 4

وصل السلك الأسود لمروحة التبريد (السالب) مع المنفذ رقم 6

الراسبيري باي وباي هول

تصبح المروحة بهذا الشكل بعد تثبيتها.

المروحة والراسبيري باي

تثبيت وتكوين باي هول (Pi-hole)

أولًا، سوف تحتاج إلى تثبيت نظام الراسبيان على الراسبيري باي إذا لم تكن قد فعلت ذلك قم بالاطلاع على الدرس الأول نظام تشغيل الراسبيري باي

وبعد تثبيت النظام، يمكنك تهيئة النظام من خلال الرجوع  للدرس الثاني تهيئة نظام التشغيل

افتح الشاشة السوداء LXterminal للبدء باستخدام الراسبيري باي.

LXterminal

للبدء، سنقوم بإستخدام الـ Termial لتحديث الراسبيري باي إلى أحدث إصدار.

sudo apt-get update
sudo apt-get upgrade

أعد تشغيل الراسبيري باي.

reboot

في هذه الخطوة سيتم تثبيت باي هول (Pi-hole) من خلال الأمر التالي:

curl -sSL https://install.pi-hole.net | bash

سوف تبدأ عملية التحديث وتثبيت باي هول (Pi-hole).

تثبيت باي هول

عليك فقط اتباع الأوامر التي تظهر على الشاشة لتثبيت باي هول (Pi-hole) على الشاشة.

اختر الإعدادات الافتراضية دائمًا وانتظر حتى ينتهي الإعداد.

اضغط OK.

حجب الإعلانات الراسبيري باي وباي هول

اضغط OK.

حجب الإعلانات الراسبيري باي وباي هول

اضغط OK.

حجب الإعلانات الراسبيري باي وباي هول

اختر طريقة اتصال الراسبيري باي مع الانترنت

الخيار الأول: هل عن طريق سلك ايثرنت؟

الخيار الثاني: أم عن طريق شبكة لاسلكية؟

ثم انقر على Ok.

حجب الإعلانات الراسبيري باي وباي هول

لاختيار الإعدادات الافتراضية اضغط OK.

حجب الإعلانات الراسبيري باي وباي هول

اختر كافة الخيارات المتاحة لك؛ لكي يتم حجب الإعلانات من كافة المزودين لها ثم اضغط OK.

حجب الإعلانات الراسبيري باي وباي هول

اختر كل البروتكولات المتاحة ثم اضغط OK.

حجب الإعلانات الراسبيري باي وباي هول

هنا يطلب منك التأكد من عنوان الشبكة إذا كنت متأكد من رغبتك باستخدامه اضغط Yes.

raspberry-pi-hole-block-ads

تحميل خادم الويب اضغط على OK.

web server

استكمال التثبيت اضغط على OK.

Wep server & PHP

استكمال التثبيت اضغط على OK.

web server

اضغط على الخيار الأول لعرض كل شيء ثم Ok.

Show Everything

ستبدأ عملية تعريف وتحميل الحزمة سيأخذ عدة دقائق.

حجب الإعلانات الراسبيري باي وباي هول

عند اكتمال تعريف الحزمة سيتم إخطارك بذلك.

سيظهر لك عنوان الراسبيري باي IPv4 ستحتاج إليه في الخطوات القادمة.

انقر على OK.

raspberry-pi-hole-block-ads

ادخل الأمر التالي ثم ضع كلمة المرور التي يسهل عليك تذكرها.

pihole -a -p

إعدادات باي هول (Pi-hole)

افتح المتصفح الخاص بك وغيّر العنوان التالي إلى عنوان الراسبيري باي.

http://192.168.100.14/admin/

انقر على Login واكتب كلمة المرور التي عينتها مسبقًا.raspberry-pi-hole-block-ads

في Dashboard يتم عرض الإحصائيات والمواقع التي تم حجبها.

وفي أسفل الصفحة قائمة بأسماء الأجهزة التي تستخدم (Pi-hole) لحجب الإعلانات.

raspberry-pi-hole-block-adsraspberry-pi-hole-block-ads

ستظهر لك هذه الصفحة.

انقر على Settings.

الراسبيري باي وباي هول

انقر على DNS.

فعّل الخيارات الظاهرة بالصورة.

الراسبيري باي وباي هول

انزل أسفل الصفحة واكتب عنوان الشبكة الخاصة بك على سبيل المثال هنا ألياف بصرية بدء من العنوان 192.168.100.0.

ثم انقر على Save.

ثم انقر على DHCP.

وفعّل خيار DHCP server enabled.

ثم اكتب نطاق الشبكة.

وانقر على Save.
raspberry-pi-hole-block-ads

حدّث الصفحة.

 تغيير (DNS) على ويندوز

افتح “إعدادات الشبكة” على جهاز الكمبيوتر الخاص بك الذي يعمل بنظام ويندوز وتأكد من أنه متصل بالراوتر انتقل للمسار التالي:

انقر بالزر اليمين على قائمة ابدأ > اتصالات الشبكة > خصائص > تحرير.

اكتب عنوان الراسبيري باي بجانب Preferred DNS server.

اكتب عنوان الشبكة بدء من صفر على سبيل المثال 192.168.100.0 بجانب Alternate DNS server.

ثم انقر على حفظ.
raspberry-pi-hole-block-ads

 تغيير (DNS) على ماك

لتغيير DNS على ماك ، افتح “تفضيلات النظام”.

اضغط على مفتاح CMD + SPACE لإظهار البحث في spotlight واكتب System Preferences واضغط مفتاح الإدخال على النتيجة.

ابحث عن الشبكة من الخيارات وانقر نقرًا مزدوجًا لفتح إعدادات الشبكة.

Mac

سترى خادم DNS.

انقر على زر القفل في أسفل يسار النافذة.

سيطلب منك بيانات اعتماد تسجيل الدخول، أدخل التفاصيل الصحيحة، ثم انقر فوق خيارات متقدمة.

Mac

انقر فوق DNS وانقر فوق الزر + لإضافة إدخال DNS.

أدخل عنوان الراسبيري باي وانقر فوق موافق.

تم تكوين Pihole DNS الخاص بك الآن على جهاز كمبيوتر Mac.

Mac

 تغيير (DNS) على الايفون

الشبكات اللاسلكية > معلومات الشبكة > DNS > يدوي ثم اكتب عنوان الراسبيري باي واحفظ ذلك.

واحذف العناوين السابقة.

IPhone

IPhone

سيتم حجب الإعلانات مباشرة Yahoo.

  إذا أردت حجب إعلان معين أو موقع معين يمكنك إكمال الخطوات التالية.

WhiteList و BlackList

Whitelist يمكنك وضع فيها قائمة المواقع التي تريد حجب الإعلانات عنها فقط.

Blacklist يمكنك وضع فيها قائمة المواقع التي تريد حجبها بالكامل.

الراسبيري باي وباي هولأضف الرابط بهذا الشكل لقائمة BlackList.

www.اسم الموقع.com

على سبيل المثال هنا نريد حجب موقعwww.theguardian.com.
raspberry-pi-hole-block-ads

حدّث الصفحة.

ستلاحظ أن الموقع انحجب بالكامل.

raspberry-pi-hole-block-ads

المشاكل والإصلاحات

في بعض الأوقات قد تواجهك هذه الرسالة عند إدخال أسماء المواقع في BlackList و WhiteList.

raspberry-pi-hole-block-ads

ادخل الأمر التالي وسيتم حلّها مباشرة.

pihole -a -p

 لا تنسَ فصل مصدر الطاقة بعد الانتهاء من استخدام نظام حجب الإعلانات باستخدام الراسبيري باي وباي هول .




ترجمة شفرة مورس على الشاشة باستخدام الاردوينو

مقدمة

 تستخدم شفرة مورس قديمًا للتواصل بطريقة مشفرة، خاصة في الشؤون العسكرية والبرقيات الدولية ومحطات الراديو، في هذا الدرس ستتعلم إدخال الرموز المستخدمة في شفرة مورس عن طريق الأزرار وطباعتها على الشاشة الكرستالية باستخدام الاردوينو.

شفرة مورس

المواد والأدوات

الاردوينو يستخدم في حساس الغاز/ الدخان

1× اردوينو اونو

arduino-smoke-gas-sensor

1× سلك الاردوينو

arduino-smoke-gas-sensor

لوحة تجارب – حجم كبير

lcd

 شاشة كرستالية (LCD 2×16 )

شفرة مورس

1× مقاومة متغيرة

arduino-smoke-gas-sensor

 حزمة أسلاك توصيل (ذكر- ذكر)

arduino-unlock-computer-with-rfid

حزمة أسلاك توصيل (ذكر – أنثى)

arduino-smoke-gas-sensor

3× مقاومة 220 Ω

شفرة مورس

أزرار

شفرة

1× 40 رأس دبوس

شفرة مورس

هي نوع من الشفرات التي تستخدم في إرسال المعلومات التلغرافية باستخدام العناصر المتتابعة المكونة من النقطة والشرطة.

وتتم ترجمة شفرة مورس إلى حروف وأرقام ورموز أخرى.

arduino-morse-code-translator

توصيل الدائرة

لمعرفة المزيد حول الشاشة الكرستالية يمكنك الرجوع للدرس التحكم بالشاشة الكرستالية LCD

لابد من تلحيم المنافذ مع الشاشة الكرستالية، للمزيد حول اللحام يمكنك الرجوع للدرس تعلم كيفية التلحيم – تلحيم القطع باللوحة الإلكترونية

شفرة مورس

الكود البرمجي

#include <LiquidCrystal.h>
#define BUTTON1PIN 6
#define BUTTON2PIN 8
#define BUTTON3PIN 7
#define DISPLAY_NUMOFCOLUMNS 16
int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int Button1State = 0;
int Button1LastState = 0;
int Button2State = 0;
int Button2LastState = 0;
int Button3State = 0;
int Button3LastState = 0;
String tonesBuffer;
String text;
String expectedText;
String symbolsAlphabet[][2] =
{
{ ".-","A" },
{ "-...","B" },
{ "-.-.","C" },
{ "-..","D" },
{ ".","E" },
{ "..-.","F" },
{ "--.","G" },
{ "....","H" },
{ "..","I" },
{ ".---","J" },
{ "-.-","K" },
{ ".-..","L" },
{ "--","M" },
{ "-.","N" },
{ "---","O" },
{ ".--.","P" },
{ "--.-","Q" },
{ ".-.","R" },
{ "...","S" },
{ "-","T" },
{ "..-","U" },
{ "...-","V" },
{ ".--","W" },
{ "-..-","X" },
{ "-.--","Y" },
{ "--..","Z" },
{ ".----","1" },
{ "..---","2" },
{ "...--","3" },
{ "....-","4" },
{ ".....","5" },
{ "-....","6" },
{ "--...","7" },
{ "---..","8" },
{ "----.","9" },
{ "-----","0"}
};
char getToneFromButtonStates()
{
if (!Button1State && Button1LastState)
return '-';
if (!Button2State && Button2LastState)
return '.';
if (!Button3State && Button3LastState)
return ' ';
return (char)0;
}
char getSymbolFromBuffer()
{
if (tonesBuffer == "")
return ' ';
for (int i = 0; i < sizeof symbolsAlphabet / sizeof symbolsAlphabet[0]; i++)
if (tonesBuffer == symbolsAlphabet[i][0])
return symbolsAlphabet[i][1][0];
return (char)0; }
 void extractActionFromTonesBuffer() {
 if (tonesBuffer == "......")
 text.remove(text.length() - 1, 1);
 if (tonesBuffer == "------") text = ""; } 
void setup()
 { lcd.clear();
 lcd.begin(16,2);
 lcd.print("Morse");
 lcd.setCursor(0, 1); 
lcd.print("Code");
 pinMode(BUTTON1PIN, INPUT); 
pinMode(BUTTON2PIN, INPUT); 
pinMode(BUTTON3PIN, INPUT); }
 void loop() { 
Button1State = digitalRead(BUTTON1PIN);
 Button2State = digitalRead(BUTTON2PIN);
 Button3State = digitalRead(BUTTON3PIN);
 char tone = getToneFromButtonStates(); 
if (tone != (char)0) 
{ if (tone == ' ') 
{ char symbol = getSymbolFromBuffer(); 
if (symbol != (char)0) { text += symbol; 
if (text.length() > DISPLAY_NUMOFCOLUMNS) {
 text = (String)symbol; }
 } else { extractActionFromTonesBuffer(); } tonesBuffer = "";
 } else {
 tonesBuffer += tone;
 if (tonesBuffer.length() > DISPLAY_NUMOFCOLUMNS) 
{ tonesBuffer = (String)tone; 
} 
} lcd.clear();
 lcd.print(text);
 lcd.setCursor(0, 1); 
lcd.print(tonesBuffer); }
 Button1LastState = Button1State; 
Button2LastState = Button2State; 
Button3LastState = Button3State; }

شرح الكود البرمجي

هذا السطر يستدعي مكتبة الشاشة الكرستالية.

نستطيع تحميلها بتتبع المسار التالي:

Sketch > Include libraries > Manage libraries

ثم نكتب بخانة البحث Liquid crystal by Arduino

ثم نضغط على Install.

#include <LiquidCrystal.h>

هذه الأسطر توضح منافذ الاردوينو التي ستستخدمها للربط في هذا المشروع.

#define BUTTON1PIN 6
#define BUTTON2PIN 8
#define BUTTON3PIN 7
#define DISPLAY_NUMOFCOLUMNS 16

في هذه الأسطر قمنا بإنشاء متغيرات لتخزين الحالة الحالية والسابقة للأزرار؛ لضمان كتابة الضغطة مرة واحدة فقط عند الضغط على الزر.

int Button1State = 0;
int Button1LastState = 0;
int Button2State = 0;
int Button2LastState = 0;
int Button3State = 0;
int Button3LastState = 0;

أيضًا أنشئنا متغيرات لتخزين التسلسل الحالي للضغطات والرمز التابع لكل ضغطة، التسلسل الحالي إما نقطة أو شرطة.

ترجمة الرموز في شفرة مورس ستكون إما رقم أو حرف أو رموز خاصة.

String tonesBuffer;
String text;
String expectedText;

ومتغير symbolsAlphabet من نوع string تمت تهيئته ويحتوي على ترجمة الرموز وتم تخزينها على شكل مصفوفة ثنائية الأبعاد.

String symbolsAlphabet[][2] =
{
{ ".-","A" },
{ "-...","B" },
{ "-.-.","C" },
{ "-..","D" },
{ ".","E" },
{ "..-.","F" },
{ "--.","G" },
{ "....","H" },
{ "..","I" },
{ ".---","J" },
{ "-.-","K" },
{ ".-..","L" },
{ "--","M" },
{ "-.","N" },
{ "---","O" },
{ ".--.","P" },
{ "--.-","Q" },
{ ".-.","R" },
{ "...","S" },
{ "-","T" },
{ "..-","U" },
{ "...-","V" },
{ ".--","W" },
{ "-..-","X" },
{ "-.--","Y" },
{ "--..","Z" },
{ ".----","1" },
{ "..---","2" },
{ "...--","3" },
{ "....-","4" },
{ ".....","5" },
{ "-....","6" },
{ "--...","7" },
{ "---..","8" },
{ "----.","9" },
{ "-----","0"}
};

في دالة ()setup، التي ستبدأ عند بدء التشغيل، تتم تهيئة الشاشة وتشغيل الإضاءة الخلفية وطباعة النص “Morse code” هنا علينا تعريف المنافذ إلى مدخلات  للاتصال الرقمي باستخدام الأزرار.

void setup() {
clear.lcd();
lcd.begin(16,2);
lcd.print("Morse");
lcd.setCursor(0, 1);
lcd.print("Code");
pinMode(BUTTON1PIN, INPUT);
pinMode(BUTTON2PIN, INPUT);
pinMode(BUTTON3PIN, INPUT);
}

تبدأ دالة ()loop بقراءة حالات الأزرار واستدعاء دالة ()getToneFromButtonStates.

void loop() {
Button1State = digitalRead(BUTTON1PIN);
Button2State = digitalRead(BUTTON2PIN);
Button3State = digitalRead(BUTTON3PIN);
char tone = getToneFromButtonStates();

يتم تحليل الضغطة هنا، إذا كانت لا تحمل قيم بوضع Low (لم يضغط المستخدم على الزر) فلن يحدث شيء.

إذا كانت تحمل قيم (ضغط المستخدم على أي زر)، يأتي تحليل آخر، يتفرع البرنامج إلى قسم “تم الضغط على النقطة” وقسم ” “تم الضغط على الشرطة”.

if (tone != (char)0) {
        if (tone == ' ')
        {
        }
        else
       {
        }
        lcd.clear();
        lcd.print(text);
        lcd.setCursor(0, 1);
        lcd.print(tonesBuffer);
}
Button1LastState = Button1State;
Button2LastState = Button2State;
Button3LastState = Button3State;

تعمل الدالة ()getSymbolFromBuffer على إرجاع القراءات التي تم الحصول عليها من الازرار إذا ضغط المستخدم الزر الذي بالمنتصف سيتم إنهاء المخزن المؤقت وترجمة القيم.

إذا كان المخزن المؤقت فارغًا وتم الضغط على الزر الذي بالمنتصف فستفسر دالة ()getSymbolFromBuffer بأنه لا يوجد مخرجات لطباعتها على الشاشة.

إذا لم يكن المخزن المؤقت فارغًا، يتم البحث عن ترجمة الرموز المدخلة ويتم إرجاع ترجمة الرمز الذي تم العثور عليه.

إذا كان هناك رمز ولم يتم العثور على ترجمة الرمز، فسيتم إرجاع قيمة فارغة.

char getSymbolFromBuffer()
{
if (tonesBuffer == "")
return ' ';
for (int i = 0; i < sizeof symbolsAlphabet / sizeof symbolsAlphabet[0]; i++)
if (tonesBuffer == symbolsAlphabet[0])
return symbolsAlphabet[1][0];
return (char)0;
}

في هذه الدالة سيكون هناك رموز خاصة في شفرة مورس لها تفسير معين.

عند إدخال المستخدم 6 نقط متتابعة فذلك يعني أن المستخدم يريد حذف آخر حرف تمت كتابته.

عند إدخال المستخدم 6 شرطات متتابعة فذلك يعني أن المستخدم يريد حذف كامل النص المكتوب.

void extractActionFromTonesBuffer()
{
if (tonesBuffer == "......")
text.remove(text.length() - 1, 1);
if (tonesBuffer == "------")
text = "";
}

شفرة مورس

شفرة مورس

 

 

 




اصنع فانوس رمضان بنفسك

فانوس رمضان

يحتل شهر رمضان مكانه عظيمة في نفوس المسلمين، لما خصه الله بفضائل كثيرة، وقد اعتاد المسلمون على استقبال هذا الشهر بتزين الشوارع والبيوت بالإضاءة، ومن أبرز ما تعارف الناس على استخدامه في زينة رمضان هو الفوانيس، ومن  الملاحظ التنوع الكبير في أشكال وألوان وتراكيب الفوانيس، في هذا الدرس سنساعدك على صناعة فانوس رمضان مضيء يمكنك أن تضيفه لزينة رمضان في منزلك.

المواد والأدوات

شريط ليد

1Xشريط اضاءة

بطارية

1Xبطارية

حامل بطارية

1Xحامل بطارية

حساس الألوان (ألواح أكليريك)

 

1Xلوح أكليريك(3*150*150)

 

آلة تفريز

1Xألية التفريز(أو قاطع ليزر)

لحام

1Xكاوية لحام 

سلك توصيل

1Xأسلاك توصيل

سلك لحام

1Xسلك لحام 

هيكل الفانوس

في هذا الدرس صممنا هيكل الفانوس باستخدام أكليريك بسماكة 3 ملم يجب مراعاة السماكة المستخدمة عند التصميم، و اختانا اللون الأبيض يمكنك تحميل الهيكل من خلال الرابط

فانوس رمضان

ثم نقوم بتصبيت جميع أجزاء الفانوس ليظهر كما هو بالصورة

فانوس رمضان

اضاءة الفانوس

في قاعدة الفانوس ثبتنا الإضاءة و البطارية،

فانوس رمضان

فانوس رمضان

 




سلة مهملات ذكية باستخدام ليتل بيتس (LittleBits)

مقدمة

ستتعلم في هذا الدرس صناعة سلة المهملات الذكية باستخدام ليتل بيتس (LittleBits) باستخدام حساس الاقتراب ومحرك السيرفو في بناء سلة المهملات الذكية، بمجرد وضع المهملات تقوم السلة بإدخالها داخل الصندوق للتخلص من المهملات ومنع الجراثيم والبكتيريا من الانتقال ليد المستخدم.

سلة مهملات ليتل بيتس

المواد والأدوات من ليتل بيتس

حتى تتمكن من صناعة سلة المهملات الذكية تحتاج مجموعة (littleBits Base Inventor Kit) وحدات المبتكر ليتل بيتس:

أسلاك توصيل

3× سلك

littlebits-smart-trash

1× حامل البطارية

littlebits-smart-trash

1× سلك البطارية

بطارية

1× بطارية

littlebits-smart-trash

1× منفذ الطاقة

littlebits-smart-trash

1× مستشعر الإقتراب

قالب كرتوني

1× قالب كرتوني رقم (8)

littlebits-navagitor

1× قالب كرتوني رقم (9)

littlebits-navagitor

1× مفتاح تحكم

littlebits-navagitor

1× محرك السيرڤو

littlebits-navagitor

1× ذراع تحكم

توصيل الدائرة

تحتوي مجموعة ليتل بيتس (littlebits) على بطارية ومنفذ الطاقة اللذان يعتبران مسؤولان عن تزويد دائرتك بالطاقة اللازمة لتشغيلها.

ادخل البطارية في حامل البطارية، ثم وصل سلك البطارية مع البطارية.

تركيب البطارية

اربط سلك البطارية مع منفذ الطاقة.

littlebits-navigator

وصل السلك مع منفذ الطاقة، وفي الطرف الآخر اضف مستشعر الإقتراب.

littlebits-smart-trash

وصل السلك مع مستشعر الإقتراب، وفي الطرف الآخر نضيف مفتاح التحكم.

littlebits-smart-trash

وصل محرك السيرڤو مع مفتاح التحكم.

littlebits-smart-trash

شغل محرك السيرڤو من مفتاح التشغيل.

littlebits-smart-trash

تجميع مكونات سلة المهملات الذكية

 قم بطي الخطوط المتقطعة في القالب الكرتوني (8) ثم فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

بناء الهيكل

قم بطي الخطوط المتصلة في القالب الكرتوني (8) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

سلة مهملات ليتل بيتس

ادخل وصلات التثبيت 1 و 2 في المنفذين المقابلين 1 و 2 بإحكام، كما هو ظاهر.

سلة مهملات ليتل بيتس

طبق الأوجه التي لها نفس الرقم (3) مع (3) كرر ذلك حتى تصل إلى آخر رقم بالقالب الكرتوني وتحصل على شكل صندوق.

سلة مهملات ليتل بيتس

سلة مهملات ليتل بيتس

سلة مهملات Littlebits

ادخل اللوحة في الفتحة السوداء الموجودة بإحدى جوانب القالب الكرتوني.

سلة مهملات ليتل بيتس

قم بطي الخطوط المتقطعة في القالب الكرتوني (9) ثم فك الطي،كرر ذلك مع جميع الخطوط المتقطعة.

littlebits-smart-trash

قم بطي الخطوط المتصلة في القالب الكرتوني (9) ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة.

سلة مهملات Littlebits

طبق الأوجه التي لها نفس الرقم بدءًا من (1) حتى آخر رقم بالنموذج، واغلقها بإحكام.

littlebits-smart-trash

littlebits-smart-trash

ثبت منفذ الطاقة والبطارية على اللوحة خارج القالب الكرتوني (8).

منفذ الطاقة سلة المهملات الذكية ليتل بيتس

ثبت مفتاح التحكم، ومحرك السيرڤو في اللوحة داخل القالب الكرتوني (8).

littlebits-smart-trash

اسحب مفتاح التحكم للأعلى

سلة المهملات الذكية ليتل بيتس

نثبت ذراع التحكم على محرك السيرڤو.

littlebits-smart-trash

ثبت لاقط المهملات على ذراع التحكم.

لاقط المهملات سلة المهملات الذكية ليتل بيتس

ثبت حساس الإقتراب على الفتحات الموجودة على لاقط المهملات.

سلة مهملات Littlebits

اسحب مفتاح التحكم للمنتصف.

 سلة المهملات الذكية ليتل بيتس

اغلق الباب لسلة المهملات الذكية.

الباب سلة المهملات الذكية ليتل بيتس

 بعد تركيب كل مكونات ليتل بيتس يمكنك تشغيل سلة المهملات الذكية من خلال المفتاح الموجود في منفذ الطاقة.

الطاقة سلة المهملات الذكية ليتل بيتس

افحص مجددًا تركيب النظام لترى انه متوافق مع الصور.

تأكد من تشغيل وحدة مزود الطاقة

وتأكد أن سلة المهملات الذكية تلتقط المهملات بدون لمسها كرر ذلك حتى تتأكد من عملها بالشكل الصحيح.

سلة مهملات بدون لمس

تذكر فصل وحدة مزود الطاقة عند الانتهاء من استخدام النظام.




كاشف العقبات باستخدام ليتل بيتس (LittleBits)

مقدمة

يساعد كاشف العقبات على اكتشاف الأجسام والأشياء التي أمامه بدون لمسها يمكن استخدام النظام في مجالات كثيرة مثل مساعدة المكفوفين على معرفة العقبات التي أمامهم حتى لا يصطدمون بها . في درس هذا الدرس سنستخدم ليتل بيتس (LittleBits)، و نتعلم كيفية استخدام حساس القرب الذي يستكشف وجود الأجسام القريبة، و سيقوم النظام بإصدار طنين لتنبيه بوجود جسم قريب.

المقدمة

المواد والأدوات من ليتل بيتس

حتى تتمكن من صناعة كاشف العقبات تحتاج مجموعة (littleBits Base Inventor Kit) وحدات المبتكر ليتل بيتس:

littlebits-navigator

1× قالب الكرتوني رقم (4)

اسلاك توصيل

2× سلك

littlebits-navigator

1× حامل البطارية

littlebits-navigator

1× سلك البطارية

littlebits-navigator

1× بطارية

littlebits-navigator

1× منفذ الطاقة

littlebits-navigator

1× حساس القرب

مصدر صوت

1× مصدر صوت

littlebits-navigator

1× لوحة

littlebits-navigator

1× شريط لاصق

توصيل الدائرة

تحتوي مجموعة ليتل بيتس على بطارية و منفذ الطاقة اللذان يعتبران مسؤولان عن تزويد دائرتك بالطاقة اللازمة لتشغيلها.

ادخل البطارية في حامل البطارية، ثم وصل سلك البطارية مع البطارية.

الطاقة

اربط سلك البطارية مع منفذ الطاقة.

littlebits-navigator

وصل الطرف الأول للسلك مع منفذ الطاقة والطرف الثاني مع حساس القرب.

توصيل مصدر الصوت

استخدم السلك الثاني في التوصيل بين حساس القرب من طرف و مصدر الصوت من الطرف الثاني

littlebits-navigator

يقوم حساس القرب بالكشف عن الأجسام المقابلة له، ويقوم بإرسال الإشارات لمصدر الصوت.

مستكشف الأشياء ليتل بيتس

 

تجميع مكونات كاشف العقبات

 قم بطي الخطوط المتقطعة في القالب الكرتوني ثم فك الطي، كرر ذلك مع جميع الخطوط المتقطعة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-navigator

قم بطي الخطوط المتصلة في القالب الكرتوني ثم فك الطي، كرر ذلك مع جميع الخطوط المتصلة؛ حتى تصبح مرنة أثناء عملية التجميع.

littlebits-navigator

طبق الأوجه التي لها نفس الرقم (1) .

littlebits-navigator

ادخل وصلات التثبيت 2 و 3 في المنفذين المقابلين 2 و 3 بإحكام،.

littlebits-navigator

وبعد ذلك ادخل وصلات التثبيت 4 و 5 في المنفذين المقابلين 4 و 5 بإحكام،.

littlebits-navigator

ادخل وصلات التثبيت في المنفذين المقابلين.

littlebits-navigator

اطو الوجهين اللذان لهم نفس الرقم (6) وجهًا لوجه، .

littlebits-navigator

اسحب الجزء العلوي وادخله في المنفذ المقابل له.

littlebits-navigator

 ادخل اللوحة في الفتحة السفلية للقالب الكرتوني، بعد ذلك يصبح هيكل كاشف العقبات جاهزًا.

littlebits-navigator

تثبيت مكونات ليتل بيتس على كاشف العقبات:

ثبّت البطارية  في الموقع C.

littlebits-navigator

ومنفذ الطاقة  في الموقع A.

تركيب

وحساس القرب في الموقع B.

littlebits-navigator

ومصدر الصوت على اللوحة.

تثبيت البطارية

لجعل كاشف العقبات الخاص بك أكثر قوة، يمكنك وضع شريط لاصق على الطرفين.

تركيب

 بعد تركيب كل مكونات ليتل بيتس يمكنك تشغيل كاشف العقبات من خلال المفتاح الموجود في منفذ الطاقة.

littlebits-navigator

افحص مجددًا تركيب النظام تأكد من تشغيل وحدة مزود الطاقة

قرب الأداة إلى أحد العقبات المتواجدة حولك ولاحظ إصدار إنذار عند الاقتراب منها.

مستكشف

تذكر فصل وحدة مزود الطاقة عند الانتهاء من استخدام النظام.