ورکشاپ آموزشی - آیسی مدار
رفتن به محتوا

استند کارت فراری با آردوینو و سنسور التراسونیک

ابزار و گجت
۰ نظر
۵۹ نفر
کد ۴۳۰۵

توی دنیای الکترونیک همیشه قرار نیست دستگاه‌هایی بسازیم که کارمون رو راحت کنن؛ بعضی وقتا ساختن یه گجت که حسابی روی اعصاب بره، خیلی جذاب‌تره! پروژه‌ای که امروز تو تیم آیسی‌مدار براتون آماده کردیم، دقیقا همین مدلیه. یه جا کارتی هوشمند که وقتی دستت رو می‌بری سمتش تا یه کارت برداری، سریع کارت‌ها رو می‌کشه پایین و قایم می‌کنه.

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

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

قطعات موردنیاز

  • 2 عدد مقاومت 200 اهم
  • 2 عدد مقاومت 10 کیلواهم
  • ال‌ای‌دی قرمز
  • ال‌ای‌دی سبز
  • 2 عدد مقاومت نوری (فتوسل یا LDR)
  • سروو موتور
  • سنسور التراسونیک
  • 2 عدد برد آردوینو نانو (یا ترکیب یک نانو و یک اونو)
  • 3 عدد بردبورد
  • سیم‌های جامپر
  • پلتفرم پیستونی (دست‌ساز یا پرینت سه‌بعدی)
  • فنر پلاستیکی یا فلزی نرم
  • پایه نگهدارنده پیستون
  • پایه نگهدارنده موتور
  • بازوی متحرک برای سروو موتور
  • مقوا یا کارتن برای ساخت بدنه
  • فوم یا یونولیت برای پایه‌های تقویتی
  • کارت ویزیت یا تگ مقوایی
  • چسب حرارتی
  • کاتر و خط‌کش
مرحله ۱

ایده اصلی و طراحی مکانیزم حرکتی

مفهوم کلی پروژه

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

منطق کار سنسورها و موتور

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

تست و پروتوتایپ

برای شروع کار، اول مکانیزم فنر و پیستون رو با قطعات پلاستیکی و پرینت سه‌بعدی تست کردیم. این‌طوری تونستیم زاویه دقیق بازوی موتور و واکنش فنر رو به دست بیاریم. تو این مرحله فهمیدیم که اضافه کردن یه پیستون دوم (بدون فنر) و بلندتر کردن پایه‌ها می‌تونه حرکت رو خیلی نرم‌تر و متعادل‌تر کنه.

مرحله ۲

ساخت پایه و مونتاژ پلتفرم فنردار

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

ابعاد پایه اصلی رو حدود 15 در 30 سانتی‌متر در نظر گرفتیم. پایه پیستون دقیقا وسط این کفی قرار می‌گیره تا فضای کافی برای سیم‌کشی‌ها و بقیه قطعات الکترونیکی اطرافش باقی بمونه.

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

مرحله ۳

ساخت بدنه و سیم‌کشی سنسورهای گمراه‌کننده

حالا نوبت ساخت دیواره‌های 16 سانتی‌متری جعبه‌ست. یه بردبورد هم داخل جعبه می‌ذاریم تا سیم‌کشی سنسورهای فیک رو روش انجام بدیم. اول از همه روی دیواره جلویی دو تا سوراخ برای ال‌ای‌دی‌ها و روی دیواره‌های کناری هم دو تا سوراخ برای قرار دادن فتوسل‌ها ایجاد کن.

فتوسل‌ها و ال‌ای‌دی‌ها رو سر جای خودشون بذار و سیم‌کشی رو طبق نقشه پیش ببر. حواست باشه سیم‌هایی که قراره به برد اصلی وصل بشن رو فعلا به سمت عقب جعبه هدایت کن تا دست و پاگیر نشن.

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

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

مرحله ۴

سیم‌کشی مدار اصلی و راه‌اندازی آردوینو

وقتی دیواره‌های جعبه کامل شد و سیم‌ها رو بیرون آوردی، وقتشه که بردبورد اصلی رو به برد آردوینو متصل کنی. سیم‌کشی رو دقیقا مثل شماتیک بالا پیش ببر و به اتصال سیم‌های موتور و ارتباط بین دو تا بردبورد حسابی دقت کن.

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

Arduino
/* Main Arduino Code
Used to control LEDs, Photoresisor Sensors, Servo Motor
and to process signals received from the Ultrasonic sensor.
*/
#include <Servo.h>
// Define Sensor and Actuator Pins
const int AphotoPIN = A0;
const int BphotoPIN = A1;
const int RledPIN = 10;
const int GledPIN = 11;
const int AservoPIN = 5;
const int dataPIN = 12;
// Servo Motor Setup
Servo servoA;
int pos = 0;
// Sensor Data from Arduino Controlling Ultrasonic Sensor
int sensor_output = 0;
int DATA = 0;
// Variables for Misleading Sensors
int sensorValueA = 0; // Photoresistor Values
int sensorValueB = 0;
int dummyA = 0; // Target Value of Photoresistor
int dummyB = 0;
int dummyAhigh = 0; // Bounds on Acceptable Target Values
int dummyAlow = 0;
int dummyBhigh = 0;
int dummyBlow = 0;
boolean dummyAtest = false; // Test for Correct Photoresistor Value
boolean dummyBtest = false;
int seed = 0; // Random Sensor Variation
// Variables for Passive Animations
boolean passive_animation = false;
int passive_TIMER = 0;
int passive_SELECT = 0;
// Variables for when Motion is Detected
boolean motion_detected = false;
int trigger_length = 0;
boolean motion_active = false;
void setup() {
// Randomizer for Misleading Sensors and Passive Animations:
seed = analogRead(A2);
randomSeed(seed);
// Define Input/Output Pins:
pinMode(RledPIN, OUTPUT);
pinMode(GledPIN, OUTPUT);
pinMode(dataPIN, INPUT);
servoA.attach(AservoPIN);
// Move Motor to Starting Position:
servoA.write(95);
// Define Misleading Sensors Values:
dummyA = random(30, 70);
dummyB = random(30, 70);
dummyAlow = dummyA - 10;
dummyAhigh = dummyA + 10;
dummyBlow = dummyB - 10;
dummyBhigh = dummyB + 10;
// Serial.begin (9600); (For Troubleshooting)
// 'Warm Up' Delay for Proper Operation Confirmation:
delay(2500);
}
void loop() {
// Randomizer for Passive Animations:
seed = analogRead(A2);
randomSeed(seed);
// Check if a Passive Animation should be played (and which one):
if (passive_animation == true) {
if (passive_SELECT == 1) {
passive_1();
} else if (passive_SELECT == 2) {
passive_2();
}
}
/* When no motion is present, start a count down to a
Passive Animation Activation, after 15 seconds of no
motion, play a random Passive Animation: */
if (motion_detected == false) {
passive_TIMER += 1;
if (passive_TIMER == 300) {
passive_SELECT = random(1, 3);
passive_animation = true;
passive_TIMER = 0;
}
}
/* When Motion is detected: run Active Animation, start a
count up on how long motion is continuously detected and
reset the Passive Animation Timer: */
if (motion_detected == true) {
sensor_triggered();
trigger_length += 1;
passive_TIMER = 0;
/* Play small Animation if motion is continuously detected
for 10 seconds: */
if (trigger_length >= 200) {
servoA.write(75);
delay(500);
servoA.write(80);
trigger_length = 0;
}
// When motion is no longer detected, reset motor position:
} else if (motion_active == true) {
servoA.write(95);
motion_active = false;
}
/* Check Output from Arduino running Ultrasonic Sensor for a
signal indicating motion: */
sensor_output = digitalRead(dataPIN);
if(sensor_output == HIGH) {
motion_detected = true;
} else {
motion_detected = false;
}
/* Run Misleading Sensors Animation if no Motion is detected
and both sensors are inside their range: */
dummy_sensors();
if (motion_detected == false && passive_animation == false) {
if(dummyAtest == true && dummyBtest == true) {
servoA.write(75);
delay(750);
servoA.write(95);
delay(750);
servoA.write(75);
delay(750);
servoA.write(95);
delay(750);
}
}
delay(50); // Delay for Tick Speed (20 Ticks/Second)
}
// Activate Motor (Push Spring Down) when motion detected:
void sensor_triggered() {
servoA.write(75);
passive_TIMER = 0;
motion_active = true;
}
// Run Misleading Sensors:
void dummy_sensors() {
// Check and Remap (0-100) the Photoresistor Sensor Values:
sensorValueA = analogRead(AphotoPIN);
sensorValueB = analogRead(BphotoPIN);
sensorValueA = map(sensorValueA, 0, 700, 0, 100);
sensorValueB = map(sensorValueB, 0, 700, 0, 100);
constrain(sensorValueA, 0, 100);
constrain(sensorValueB, 0, 100);
/* Check if the Photoresistor Sensor Values are within the
desired range (turn LED on if that one is): */
if (sensorValueA >= dummyAlow && sensorValueA <= dummyAhigh) {
digitalWrite(RledPIN, HIGH);
dummyAtest = true;
} else {
digitalWrite(RledPIN, LOW);
dummyBtest = false;
}
if (sensorValueB >= dummyAlow && sensorValueB <= dummyBhigh) {
digitalWrite(GledPIN, HIGH);
dummyBtest = true;
} else {
digitalWrite(GledPIN, LOW);
dummyBtest = false;
}
}
// First Passive Animation (Drop, Wait, Lift Back Up):
void passive_1() {
if (passive_animation == true) {
for (int pos = 95; pos >= 75; pos -= 1) { // Push Lever Down
servoA.write(pos);
delay(20);
}
delay(1500); // Wait
for (int pos = 75; pos <= 95; pos += 1) { // Lift Lever
servoA.write(pos);
delay(20);
}
// Reset Passive Animation
passive_animation = false;
passive_SELECT = 0;
}
}
/* Second Passive Animation (Quick Drop, Wait, Slow Lift
Halfway, Wait, Lift Other Half) */
void passive_2() {
if (passive_animation == true) {
for (int pos = 95; pos >= 75; pos -= 1) { // Quick Push Lever Down
servoA.write(pos);
}
delay(2500); // Wait
for (int pos = 75; pos <= 85; pos += 1) { // Slowly Lift Lever Halfway
servoA.write(pos);
delay(50);
}
delay(2500); // Wait
for (int pos = 85; pos <= 95; pos += 1) { // Lift Lever Remain Distance
servoA.write(pos);
delay(20);
}
passive_animation = false;
passive_SELECT = 0;
}
}
مرحله ۵

نصب سنسور التراسونیک و اضافه کردن برد دوم

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

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

در نهایت کدهای زیر رو روی برد دوم آپلود کن تا مغز دوم دستگاه هم فعال بشه.

Arduino
/* Arduino Controlling Ultrasonic Sensor
Utilizing a second Arduino for the sensor pulses
allows each controller to focus on processing its tasks
more efficiently (the nanosecond delays in the ultrasonic
sensor code do no interfere with operations of the main code).
*/
// Sensor and Connector Pins
const int trigPIN = 10;
const int echoPIN = 5;
const int dataPIN = 8;
// Variables Used in Distance Calculation
float dur = 0;
float dist = 0;
void setup() {
// Sensor and Connector Pin Setup
pinMode(trigPIN, OUTPUT);
pinMode(echoPIN, INPUT);
pinMode(dataPIN, OUTPUT);
// Serial.begin(9600); (For Troubleshooting)
}
void loop() {
digitalWrite(trigPIN, LOW); // Reset the Sensors
delayMicroseconds(2);
digitalWrite(trigPIN, HIGH); // Send Ultrasonic Signal
delayMicroseconds(10);
digitalWrite(trigPIN, LOW); // Stop Ultrasonic Signal
dur = pulseIn(echoPIN, HIGH); // Log Time Till Signal Returns
dist = (dur*.0343)/2; // Compute Distance from Time
/* Send signal to Main Arduino if something
is detected within 30cm: */
if (dist <= 30 && dist >= 1) {
digitalWrite(dataPIN, HIGH);
} else {
digitalWrite(dataPIN, LOW);
}
delay(100);
// Serial.println(dist); (For Troubleshooting)
}
مرحله ۶

مونتاژ نهایی و تست مکانیزم

کار ساخت بدنه و سیم‌کشی‌ها دیگه تموم شده! یه بار دیگه تمام اتصالات رو از روی نقشه کامل چک کن که چیزی جا نمونده باشه. حالا دستگاه رو روشن کن.

نتیجه یه جعبه جادوییه که تا دستت به 30 سانتی‌متریش می‌رسه کارت‌ها رو قایم می‌کنه و وقتی دور می‌شی، با حرکات ریز حسابی دلبری می‌کنه.

مرحله ۷

جمع‌بندی چالش‌ها و تجربه‌های پروژه

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

چالش‌هایی که تو مسیر داشتیم:

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

ایده اولیه‌مون استفاده از دو تا موتور بود. اما چون ولتاژ خروجی آردوینو محدوده و نمی‌خواستیم منبع تغذیه خارجی اضافه کنیم، مجبور شدیم به همون یک سروو موتور بسنده کنیم.

به خاطر همین محدودیت، موتور رو گذاشتیم یک طرف و طرف دیگه رو داخل یه غلاف قرار دادیم تا مسیر حرکت پلتفرم فقط به صورت خطی باشه و کج نشه.

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

راه‌حل این بود که یه برد جداگانه فقط برای سنسور بذاریم تا داده‌ها رو پردازش کنه و نتیجه رو به صورت باینری (صفر و یک) به برد اصلی بفرسته.

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

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

نتیجه‌گیری:

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

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

در نهایت یاد گرفتیم که چطور با یه موتور ساده و حرکات کوچیک، می‌شه به یه شیء بی‌جان شخصیت داد و یه داستان تعاملی براش تعریف کرد.

امیدوارم تو هم از ساخت این جا کارتی فراری لذت برده باشی. حتما این پروژه رو بساز و بذار روی میزت تا واکنش دوستات رو وقتی می‌خوان کارت بردارن ببینی! اگه ایده‌ای برای خفن‌تر کردنش داری، حتما تو بخش کامنت‌های آیسی‌مدار برامون بنویس.

فایل‌های پیوست

INO main_system_code.ino
INO ultrasonic_sensor_code.ino

تو میتونی اولین سازنده باشی!

اگه پروژه رو ساختی به اشتراک بزار و اعتبار هدیه بگیر

این آموزش با استانداردهای اختصاصی آیسی‌مدار بازنویسی و بهینه‌سازی شده و تمامی حقوق انتشار آن متعلق به این مجموعه است و در صورت کپی یا بازنشر پیگرد قانونی خواهد داشت.

آموزش‌های مشابه

گفتگو‌های کاربران

هنوز نظری ثبت نشده؛ تو شروع کن!