در قسمت 41 از آموزش آردوینو به بررسی راهاندازی LEDهای توانبالا و تنظیم رنگ یک LED پرداختیم. در این قسمت قصد داریم درباره کنترل تعداد زیادی LED رنگی و ترتیبدهی چند LED: ایجاد یک نمودار میلهای (Bar Graph) صحبت کنیم.
فرض کنید میخواهید تنها با استفاده از یک پایهی دیجیتال، رنگ تعداد زیادی LED را کنترل کنید.
در این روش از LEDهای RGB هوشمند استفاده میشود؛ این LEDها یک کنترلکنندهی کوچک درون خود دارند که امکان کنترل تعداد زیادی LED را تنها از طریق یک پایهی دیجیتال فراهم میکند. این کد نمونه با استفاده از کتابخانهی Adafruit NeoPixels (که از طریق Arduino Library Manager قابلنصب است)، رنگ LEDها را بر اساس مقدار خواندهشده از یک پایهی آنالوگ تغییر میدهد. شکل 1 نحوهی اتصال یک حلقهی NeoPixel و یک پتانسیومتر را برای کنترل رنگ نشان میدهد.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/* * SimplePixel sketch * LED color changes with sensor value */ #include <Adafruit_NeoPixel.h> const int sensorPin = A0; // analog pin for sensor const int ledPin = 6; // the pin the LED strip is connected to const int count = 8; // how many LEDs in the strip // declare LED strip Adafruit_NeoPixel leds = Adafruit_NeoPixel(count, ledPin, NEO_GRB + NEO_KHZ800); void setup() { leds.begin(); // initialize LED strip for (int i = 0; i < count; i++) { leds.setPixelColor(i, leds.Color(0,0,0)); // turn each LED off } leds.show(); // refresh the strip with the new pixel values (all off) } void loop() { static unsigned int last_reading = -1; int reading = analogRead(sensorPin); if (reading != last_reading) { // If the value has changed // Map the analog reading to the color range of the NeoPixel unsigned int mappedSensorReading = map(reading, 0, 1023, 0, 65535); // Update the pixels with a slight delay to create a sweeping effect for (int i = 0; i < count; i++) { leds.setPixelColor(i, leds.gamma32( leds.ColorHSV(mappedSensorReading, 255, 128))); leds.show(); delay(25); } last_reading = reading; } } |

شکل 1: اتصال یک حلقه NeoPixel
اگر از یک برد ۳٫۳ ولتی استفاده میکنید، لازم است هم پتانسیومتر و هم سیم مثبت نئوپیکسل را به ۳٫۳ ولت وصل کنید، نه ۵ ولت.
این اسکچ یک stick، نوار یا گروهی از نئوپیکسلهای زنجیرهای Adafruit را که شامل هشت LED RGB هستند، راهاندازی میکند. اگر تعداد LEDهای متفاوتی وصل کردهاید، میتوانید مقدار متغیر numOfLeds را تغییر دهید، اما در نظر داشته باشید که هر LED ممکن است تا ۶۰ میلیآمپر مصرف کند (اگر روی نور سفید با حداکثر روشنایی تنظیم شده باشد). یک پورت USB میتواند تا حدود هشت LED را تغذیه کند، اما برای تعداد بیشتر باید کانکتورهای تغذیهٔ نوار LED را به یک منبع تغذیهٔ ۵ ولت با جریان بالاتر وصل کنید؛ البته باید زمین (GND) منبع تغذیه را به زمین آردوینو هم متصل کنید.
اگر از یک برد ۳٫۳ ولتی استفاده میکنید، نباید نئوپیکسلها را با ولتاژی بیشتر از ۳٫۷ ولت تغذیه کنید (مثل باتری لیتیوم-پلیمر)، زیرا نئوپیکسلها به سیگنال دادهای نیاز دارند که نزدیک به ولتاژ تغذیهٔ آنها باشد. هنگام استفاده از یک منبع تغذیهٔ خارجی، باید یک خازن ۱۰۰۰ میکروفاراد را بین پینهای مثبت و منفی منبع تغذیه وصل کنید تا از پیکسلها محافظت شود (به پلاریته خازن توجه کنید و مطمئن شوید که آن را درست وصل میکنید).
متغیر leds با این کد تعریف شده است:
|
1 |
Adafruit_NeoPixel leds = Adafruit_NeoPixel(count, ledPin, NEO_GRB + NEO_KHZ800); |
این کد یک ساختار حافظه ایجاد میکند تا رنگ هر LED را ذخیره کند و با نوار LED ارتباط برقرار کند. شما باید تعداد LEDهای نوار (count)، پینی که خط داده به آن وصل شده (ledPin) و نوع نوار LED مورداستفاده خود را مشخص کنید (در این مثال: NEO_GRB + NEO_KHZ800.) لازم است داکیومنت کتابخانه و نوار خود را بررسی کنید تا ببینید آیا به تنظیمات متفاوتی نیاز دارید یا نه، اما هیچ ضرری ندارد که همه گزینههای موجود در کتابخانه را امتحان کنید تا یکی را پیدا کنید که درست کار میکند.
برای تعیین رنگ یک LED خاص، از روش led.setPixelColor استفاده میکنید. باید شماره LED موردنظر را مشخص کنید (شمارهها از ۰ برای اولین LED شروع میشوند) و رنگ دلخواه را تعیین کنید. برای ارسال دادهها به LEDها باید led.show را فراخوانی کنید. میتوانید مقدار چند LED را قبل از فراخوانی led.show تغییر دهید تا همه با هم تغییر کنند. مقادیری که تغییر نکردهاند، در تنظیمات قبلی خود باقی میمانند. هنگام ایجاد شیء Adafruit_NeoPixel، همه مقادیر به ۰ مقداردهی اولیه میشوند.
کتابخانه NeoPixel شامل تابعی برای تبدیل hue به مقدار RGB است: ColorHSV. پارامتر اول رنگ (hue)، پارامتر دوم شدت رنگ (saturation) و پارامتر سوم روشنایی (brightness) است. تابع gamma32 روی خروجی ColorHSV اعمال میشود تا تفاوت بین نحوه نمایش رنگها توسط کامپیوتر و نحوه درک آنها توسط چشم انسان جبران شود.
هر LED یا «پیکسل» دارای اتصالهایی برای ورودی و خروجی داده، تغذیه و زمین است. آردوینو ورودی داده اولین پیکسل را کنترل میکند و خروجی داده آن به ورودی داده پیکسل بعدی در زنجیره متصل میشود. شما میتوانید پیکسلها را بهصورت جداگانه یا به شکل نوارهایی که از قبل به هم متصل شدهاند، خریداری کنید.
نوارهای LED قدیمی از تراشه WS2811 استفاده میکردند. بعد از آن نسخههای مختلف دیگری مانند WS2812 ،WS2812B و APA102 عرضه شدند. اگر LEDهای شما توسط کتابخانه Adafruit پشتیبانی نمیشوند، میتوانید از کتابخانه FastLED استفاده کنید. بردهای Teensy 3.x و بالاتر که با آردوینو سازگار هستند، میتوانند هشت نوار LED را روی پینهای مختلف کنترل کنند و با ترکیبی از سختافزار و نرمافزار پرسرعت، امکان ایجاد انیمیشنهای بسیار باکیفیت را فراهم میکنند.
LEDها بهصورت تکتک موجود هستند، اما روی نوارهای انعطافپذیر در رولها نیز عرضه میشوند و با فاصلههای مختلف بین LEDها مشخص میشوند (معمولاً بهصورت LED بر متر یا فوت). شرکت Adafruit انواع مختلفی از فرمفاکتورهای PCB تولید میکند، از جمله حلقههای LED، نوارهای کوتاه و پنلها که تحت برند NeoPixel عرضه میشوند.
راهنمای Adafruit NeoPixel Uber شامل:
کتابخانه Teensy که تصاویر خوبی از نحوه سیمکشی برای منبع تغذیه با تعداد زیاد LEDها دارد و همچنین یک برنامه Processing که دادهها را از ویدئو استخراج میکند تا بتوانید آنها را به کد اضافه کرده و ویدئو را روی نوارهای LED نمایش دهید.
فرض کنید میخواهید یک نمودار میلهای LED داشته باشید که تعداد LEDهای روشن شده متناسب با یک مقدار در برنامه شما یا مقداری که از یک سنسور خوانده میشود، باشد. میتوانید LEDها را همانطور که قسمتهای قبل توضیح داده شد، وصل کنید (اگر میخواهید LEDهای بیشتری داشته باشید، از پینهای اضافی استفاده کنید). شکل 2 شش LED را نشان میدهد که به پینهای متوالی متصل شدهاند.

شکل 2: شش LED با کاتدهای متصل به پینهای آردوینو
این اسکچ یک سری از LEDها را روشن میکند، بهطوری که تعداد LEDهای روشن شده متناسب با مقدار یک سنسور است که به یک پورت ورودی آنالوگ متصل شده است:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/* * Bargraph sketch * * Turns on a series of LEDs proportional to a value of an analog sensor. * Six LEDs are controlled but you can change the number of LEDs by changing * the value of NbrLEDs and adding the pins to the ledPins array */ const int NbrLEDs = 6; const int ledPins[] = { 2, 3, 4, 5, 6, 7 }; const int analogInPin = A0; // Analog input pin connected to variable resistor // Swap values of the following two #defines if cathodes are connected to Gnd #define LED_ON LOW #define LED_OFF HIGH int sensorValue = 0; // value read from the sensor int ledLevel = 0; // sensor value converted into LED 'bars' void setup() { for (int led = 0; led < NbrLEDs; led++) { pinMode(ledPins[led], OUTPUT); // make all the LED pins outputs } } void loop() { sensorValue = analogRead(analogInPin); // read the analog in value ledLevel = map(sensorValue, 10, 1023, 0, NbrLEDs); // map to the number of LEDs for (int led = 0; led < NbrLEDs; led++) { if (led < ledLevel) { digitalWrite(ledPins[led], LED_ON); // turn on pins below the level } else { digitalWrite(ledPins[led], LED_OFF); // turn off pins higher than the level } } |
پینهایی که به LEDها متصل هستند، در آرایه ledPins نگهداری میشوند. برای تغییر تعداد LEDها، میتوانید المانهایی به این آرایه اضافه یا حذف کنید، اما مطمئن شوید که مقدار متغیر NbrLEDs با تعداد المانهای آرایه برابر باشد که باید با تعداد پینها همخوانی داشته باشد. میتوانید به کامپایلر اجازه دهید مقدار NbrLEDs را برای شما محاسبه کند، با جایگزینکردن این کد:
|
1 |
const int NbrLEDs = 6; |
با این کد:
|
1 |
const int NbrLEDs = sizeof(ledPins) / sizeof(ledPins[0]); |
تابع sizeof اندازه (تعداد بایتها) یک متغیر را برمیگرداند—در اینجا، تعداد بایتهای موجود در آرایه ledPins. ازآنجاکه این آرایه شامل اعداد صحیح است (هر عنصر دو بایت)، تعداد کل بایتهای آرایه بر اندازه یک عنصر (sizeof(ledPins[0])) تقسیم میشود و این مقدار، تعداد عناصر آرایه را به دست میدهد.
تابع map در آردوینو برای محاسبه تعداد LEDهایی استفاده میشود که باید روشن شوند، بهصورت متناسب با مقدار سنسور. کد برای هر LED حلقه میزند و آن را روشن میکند اگر مقدار متناسب سنسور بزرگتر از شماره LED باشد.
برای مثال: اگر مقدار سنسور کمتر از ۱۰ باشد، هیچ LEDی روشن نمیشود؛ اگر مقدار سنسور نصف مقدار ماکزیمم باشد، نصف LEDها روشن میشوند. در حالت ایدهآل، پتانسیومتر در کمترین تنظیم مقدار صفر را برمیگرداند، اما در دنیای واقعی ممکن است کمی تغییر داشته باشد. وقتی سنسور به بیشترین مقدار میرسد، همه LEDها روشن میشوند. اگر مشاهده کردید آخرین LED هنگام حداکثر مقدار پتانسیومتر چشمک میزند، میتوانید مقدار دوم تابع map را از ۱۰۲۳ به حدود ۱۰۰۰ کاهش دهید.
شکل 2 نشان میدهد که همه آندها به هم متصل شدهاند که به آن Common Anode گفته میشود و کاتدها به پینها وصل هستند؛ در این حالت، پین باید LOW باشد تا LED روشن شود.
اگر LEDها بهگونهای باشند که آندها به پینها متصل باشند و کاتدها به هم متصل شده باشند که به آن Common Cathode گفته میشود، LED وقتی روشن میشود که پین HIGH شود.
در این اسکچ، از نامهای ثابت LED_ON و LED_OFF استفاده شده تا انتخاب بین اتصال Common Anode یا Common Cathode راحت باشد. برای تغییر برنامه به حالت Common Cathode، کافی است مقادیر این ثابتها را بهصورت زیر جابهجا کنید:
|
1 2 |
const bool LED_ON = HIGH; // HIGH is on when using common cathode connection const bool LED_OFF = LOW; |
ممکن است بخواهید سرعت کاهش نور LEDها را کند کنید؛ مثلاً برای شبیهسازی حرکت نشانگر یک volume meter. در اینجا یک نسخهٔ تغییریافته از اسکچ آمده است که وقتی سطح کاهش مییابد، میلههای LED را بهآرامی خاموش میکند:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/* * LED bar graph - decay version */ const int ledPins[] = {2, 3, 4, 5, 6, 7}; const int NbrLEDs = sizeof(ledPins) / sizeof(ledPins[0]); const int analogInPin = A0; // Analog input pin connected to variable resistor const int decay = 10; // increasing this reduces decay rate of storedValue // Swap values of the following two #defines if cathodes are connected to Gnd #define LED_ON LOW #define LED_OFF HIGH // the stored (decaying) sensor value int storedValue = 0; void setup() { for (int led = 0; led < NbrLEDs; led++) { pinMode(ledPins[led], OUTPUT); // make all the LED pins outputs } } void loop() { int sensorValue = analogRead(analogInPin); // read the analog in value storedValue = max(sensorValue, storedValue); // use sensor value if higher int ledLevel = map(storedValue, 10, 1023, 0, NbrLEDs);// map to number of LEDs for (int led = 0; led < NbrLEDs; led++) { if (led < ledLevel ) { digitalWrite(ledPins[led], LED_ON); // turn on pins less than the level } else { digitalWrite(ledPins[led], LED_OFF); // turn off pins higher // than the level } } storedValue = storedValue - decay; // decay the value delay(10); // wait 10 ms before next loop } |
کاهش نور (Decay) با خطی که از تابع max استفاده میکند مدیریت میشود. این تابع بالاترین مقدار بین مقدار سنسور و مقدار ذخیرهشده کاهشیافته را برمیگرداند. اگر مقدار سنسور بیشتر از مقدار کاهشیافته باشد، این مقدار در storedValue ذخیره میشود. در غیر این صورت، سطح storedValue در هر بار اجرای حلقه، به اندازه ثابت decay کاهش مییابد (که توسط تابع delay روی ۱۰ میلیثانیه تنظیم شده است). افزایش مقدار ثابت decay باعث میشود زمان لازم برای خاموششدن کامل LEDها کمتر شود.
میتوانید این نمودار میلهای را با استفاده از NeoPixel هم پیادهسازی کنید. کد مربوط به این کار بهصورت زیر خواهد بود:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/* * PixelBarGraph.ino * Sensor value determines how many LEDs to light */ #include <Adafruit_NeoPixel.h> const int sensorPin = A0; // analog pin for sensor const int ledsPin = 2; // the pin the LED strip is connected to const int numOfLeds = 16; // how many LEDs in the strip //used to automatically map sensor values const int minReading = 0; const int maxReading = 1023; //declare LED strip Adafruit_NeoPixel leds = Adafruit_NeoPixel(numOfLeds, ledsPin, NEO_GRB + NEO_KHZ800); void setup() { leds.begin(); //initialize led strip leds.setBrightness(25); } void loop() { int sensorReading = analogRead(A0); int nbrLedsToLight = map(sensorReading, minReading, maxReading, 0, numOfLeds); for (int i = 0; i < numOfLeds; i++) { if ( i < nbrLedsToLight) leds.setPixelColor(i, leds.Color(0, 0, 255)); // blue else leds.setPixelColor(i, leds.Color(0, 255, 0)); // green } leds.show(); } |
من کاپیتان آردوینو، اسمم میلاده و اینجا هستم تا تجربیاتم در رابطه با آردوینو رو با شما به اشتراک بزارم!
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.