آموزش آردوینو

کاهش مصرف انرژی در برد های آردوینو (Sleep Mode)

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

در این مقاله به روش های کاهش مصرف برق در پروژه های آردوینو می پردازیم، برای نشان دادن این روش ها، یک پروژه آردوینو کم مصرف را می سازیم که دما و رطوبت را با سنسور DHT22 تشخیص می دهد و خوانش سنسور را در حافظه EEPROM ذخیره می کند.

اصلاحات سخت افزاری کاهش مصرف برق آردوینو

Arduino UNO یک برد فوق العاده است که به کاربران اجازه می دهد دستگاه های بی شماری را ایجاد و آزمایش کنند. با این حال، طراحی آن در راستای کاهش مصرف انرژی نیست. بنابراین اگر پروژه خود را با  منبع تغذیه 12 ولت اجرا می کنید، این برد بیش از 50 میلی آمپر جریان مصرف می کند. با کاهش ولتاژ به یک باتری 9 ولت، می توانید جریان مصرفی را به حدود 33 میلی آمپر کاهش دهید. با این سرعت مصرف انرژی باتری ها خیلی زود تخلیه میشود.

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

همچنین برق رسانی به دستگاه های متصل شده از طریق یک پورت I/O به شما این امکان را می دهد که دستگاه را در زمانی که از آن استفاده نمی کنید خاموش کنید. در پروژه مثال، ما قرار است برق سنسور را از طریق پایه های GPIO تامین کنیم و هر وقت نیاز بود برق را قطع کنیم. این کار باعث کاهش مصرف انرژی و افزایش عمر سنسور می شود.

با این حال، برخی از دستگاه‌ها را نمی‌توان در حالت بی‌کار خاموش کرد. برای مثال، اگر از کارت‌خوان SD استفاده می‌کنید، به شما اجازه نمی‌دهد آن را خاموش کنید و با استفاده از پین GPIO دوباره روشن کنید. علاوه بر این، برخی از دستگاه‌ها ساعت واقعی را دوست دارند و ماژول باید روشن بماند و باید از محدودیت جریان یک پورت ورودی/خروجی (تقریباً 40 میلی آمپر) آگاه باشید.

آردوینو UNO از یک تنظیم کننده ولتاژ خطی استفاده می کند که موثر است اما خیلی کارآمد نیست. از آنجایی که رگولاتور برق روی برد ناکارآمد است، دور زدن آن آسان تر می شود. یک رگولاتور خطی ولتاژ اضافی را می گیرد و آن را به عنوان گرما دفع می کند. بنابراین با اجرای آردوینو خود با یک باتری 9 ولت، رگولاتور اساساً 4 ولت اضافی را به گرما تبدیل می کند. این حدود 44 درصد از برق را هدر می دهد. اگر از منبع تغذیه 12 ولت استفاده کنید، انرژی تلف شده حتی بیشتر می شود.

دستگاه نشان داده شده در زیر یک مبدل 4.5-24 ولت DC به 5 ولت DC است که به طور قابل توجهی کارآمدتر از رگولاتور خطی مورد استفاده در UNO است. مدار باید با هر مبدل DC به DC باک که دارای خروجی 5 ولت یا 3.3 ولت است کار کند. این یک مزیت اضافی دارد زیرا می توانید با اتصال GND به پایه Enable (سیم زرد) خروجی برق را غیرفعال کنید.

مبدل 4.5-24 ولت DC به 5 ولت DC سیم مشکی GND مشترک و قرمز ولتاژ ورودی و سیم سبز ولتاژ خروجی است.

دور زدن رگولاتور ولتاژ پردازنده آردوینو با مبدل باک باعث کاهش جریان از 52 میلی آمپر به حدود 23 میلی آمپر می شود:

حذف رگولاتور ولتاژ برد آردوینو Uno

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

اصلاحات نرم افزار صرفه جویی در مصرف برق

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

در اینجا نتایج اضافه کردن کتابخانه آردوینو LowPower به برنامه Blink آورده شده است. نتایج زیر مربوط به UNO های آردوینو یکسانی است که با ولتاژ 12 ولت با استفاده از رگولاتور داخلی و 12 ولت روی مبدل باک کار می کنند:

جریان مصرفی بدون کتابخانه LowPower  جریان مصرفی با کتابخانه LowPower 
12 ولت با استفاده از تنظیم کننده ولتاژ داخلی = 50 میلی آمپر 12 ولت با استفاده از تنظیم کننده ولتاژ داخلی = 45 میلی آمپر
مبدل باک 5 ولت = 27 میلی آمپر مبدل باک 5 ولت = 25 میلی آمپر
مبدل باک 3.3 ولت = 10 میلی آمپر مبدل باک 3.3 ولت = 8 میلی آمپر

نحوه استفاده از کتابخانه LowPower آردوینو

برای نشان دادن قابلیت های صرفه جویی در مصرف انرژی، برنامه Blink اصلاح شد و دو تابع delay() را با توابع کتابخانه LowPower جایگزین کردیم. ما در حقیقت delay() را با LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF); جایگزین کرده ایم.

همچنین اگر در مورد این مطلب سوالی داشتید در انتهای صفحه در قسمت نظرات بپرسید
#include <LowPower.h>
void setup() {
   pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  
  LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);                    
  digitalWrite(LED_BUILTIN, LOW);    
  LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);               
}

آرگومان اول، SLEEP_2S، پردازنده را به مدت دو ثانیه در حالت Sleep قرار می دهد. برای آزاد کردن پردازنده، سیگنال PWM روی یک ساعت خارجی ایجاد می‌شود که غیرفعال می‌شود و عملکرد ADC را خاموش می‌کند و باعث صرفه‌جویی در مصرف انرژی می‌شود. تایمر (BOT) که برای اطمینان از تامین ولتاژ مناسب استفاده می شود، نیز به طور موقت غیرفعال است.

مدت زمان خواب را می توان بر روی 15 میلی ثانیه، 30 میلی ثانیه، 60 میلی ثانیه، 120 میلی ثانیه، 250 میلی ثانیه، 500 میلی ثانیه، 1 ثانیه، 2 ثانیه، 4 ثانیه یا 8 ثانیه تنظیم کرد. روش هایی برای افزایش مدت زمان خواب بیش از 8 ثانیه وجود دارد که در ادامه این مقاله نشان داده شده است.

روش های متعدد دیگری برای کنترل مصرف انرژی توسط ATmega328P وجود دارد.برای سادگی، از روش LowPower.powerDown() استفاده می کنیم.

محاسبه دما و رطوبت کم مصرف در آردوینو

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

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

  • آردوینو Uno، آردوینو نانو یا مینی
  • سنسور دما و رطوبت DHT11 یا DHT22
  • AT24C256 EEPROM
  • ماژول ساعت بیدرنگ DS3231
  • مبدل کاهنده 5 ولت
  • مقاومت 10K
  • برد بورد
  • سیم های جامپر

AT24C256 از پیش برنامه ریزی شده از کارخانه با آدرس هگزادسیمال 0x50 ارائه می شود. هنگامی که همه قطعات را در اختیار داشتید، همه چیز را مثل این نمودار سیم کشی به هم وصل کنید:

محاسبه دما و رطوبت کم مصرف در آردوینوهمانطور که گفته شد، ما از یک حافظه فقط خواندنی قابل برنامه ریزی (EEPROM) برای ذخیره داده های حسگر DHT22 استفاده می کنیم. در روش دیگر، می توانیم از کارت خوان SD استفاده کنیم. با این حال، یک کارت خوان SD تقریباً 30 میلی آمپر نیاز دارد و انرژی بیشتری نسبت به کل پروژه را مصرف میکند. EEPROM بهترین گزینه برای ذخیره سازی داده ها در مکان های دور است. آنها کوچک و قابل اعتماد هستند و هنگام نوشتن روی آن کمتر از 3 میلی آمپر مصرف می کنند. داده های ذخیره شده روی آن غیرفرار هستند، به این معنی که پس از قطع برق قابل بازیابی هستند.

ما به سه برنامه جداگانه آردوینو نیاز داریم .برنامه اول برای نوشتن اطلاعات سنسور در EEPROM استفاده می شود. برنامه دوم برای خواندن داده های سنسور از EEPROM و برنامه سوم برای حذف داده های سنسور از EEPROM استفاده می شود.

کد نوشتن داده های حسگر

#include <DHT.h>
#include <LowPower.h>
#include <Wire.h>
#include <EEPROM.h>
#include <RTClib.h>
RTC_DS1307 rtc;
#define Led 13
#define DHTPIN 5      
#define DHTTYPE DHT22   
DHT dht(DHTPIN, DHTTYPE);
int address = 0;
void setup() {
  Serial.begin(9600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  } 
  //برای تنظیم تاریخ از کامنت در بیاورید و سپس دوباره کامنت و کامپایل کنید
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  if (!rtc.isrunning()) {
    Serial.println("RTC Not running!");
  }
  dht.begin();
  Wire.begin();
} 

void loop() {
  delay(500);
  DateTime now = rtc.now();
  float h = dht.readHumidity();
  delay(500);
  float t = dht.readTemperature();
  delay(500);
  float f = dht.readTemperature(true); 
  delay(500);   
  EEPROM.update(address, (now.month())); 
  address++; 
  delay(500);
  EEPROM.update(address,(now.day()));   
  address++; 
  delay(500);
  EEPROM.update(address,(now.hour()));  
  address++; 
  delay(500);
  EEPROM.update(address,(now.minute())); 
  address++; 
  delay(500);
  EEPROM.update(address,h); 
  address++;
  delay(500);
  EEPROM.update(address,f);             
  address++;   
  delay(500);
  Serial.print("Humidity:" );
  Serial.println(h);
  Serial.print("Temperature:");
  Serial.println(f);
  Serial.print("Time ");
  Serial.print(now.hour());  
  Serial.print(":");
  Serial.println(now.minute());
  delay(1000);
  for (int i = 0; i < 100; i++) {   
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
  }
}

عبارات #include کتابخانه های حسگر DHT مورد نیاز، کتابخانه LowPower، Wire.h، ماژول EEPROM و کتابخانه ساعت واقعی را فراخوانی می کند.

در تابع setup() پورت سریال فعال می شود و عملکرد ساعت واقعی تایید می شود. به خط //rtc.adjust(DateTime(F(DATE), F(TIME))) توجه کنید. برای تنظیم RTC با ساعتی که رایانه شما از آن استفاده می کند استفاده می شود. باید یک بار آنکامنت شود و سپس برای تنظیم ساعت آپلود شود. پس از تنظیم مجدد ساعت، این خط را دوباره کامنت کنید و کد را دوباره کامپایل کنید.

در تابع loop() بعد از delay()، اولین دستورالعمل دریافت زمان از RTC فراخوانی تابع rtc.how() است. سپس دما و رطوبت را میخوانیم و در دو متغیر t و h ذخیره میکنیم.

آدرس متغیری که در ابتدا به عنوان int با مقدار “0” اعلام شده است برای آدرس دادن به اولین مکان ذخیره سازی در آدرس EEPROM 0 استفاده می شود. تابع برای نوشتن در حافظه  EEPROM.update(address,(value)  است. استفاده از EEPROM.update باعث میشود فقط در صورتی بنویسد که داده ها با آنچه قبلاً در آن آدرس نوشته شده بود متفاوت باشد. این از نوشتن همان داده ها در مکان قبلی جلوگیری می کند؛ اگر داده ها تغییر نکرده اند، آن را بازنویسی نمیکند. زیرا سلول های حافظه را می توان تقریباً 100000 بار نوشت.

پس از نوشتن در اولین آدرس “0”، آدرس افزایش می یابد و مقدار بعدی را می توان در آدرس “1” نوشت. توجه کنید که ما دقیقاً 6 تکه داده برای هر نمونه می نویسیم.

تابع LowPower به حداکثر هشت ثانیه محدود میشود. ما یک حلقه با 100 بار تکرار LowPower تنظیم کردیم که کمی بیش از 13 دقیقه به ما تأخیر می‌دهد. زمان‌ها را می‌توان افزایش یا کاهش داد.

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

#include <EEPROM.h>
int i = 0;
int address = 0;
byte value;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
  }
}
void loop() {
  value = EEPROM.read(address);
  while (value > 1) {
    for (i = 0; i < 6; i++) {                 
      Serial.print("Date-");
      Serial.print(value);                     
      Serial.print("/");
      address++;
      value = EEPROM.read(address);
      delay(50);
      Serial.println(value);                   
      address++;
      value = EEPROM.read(address);
      delay(50);
      Serial.print("Hours:");
      Serial.print(value);                
      address++;
      value = EEPROM.read(address);
      delay(50);
      Serial.print(" Minutes:");
      Serial.println(value);
      address++;
      value = EEPROM.read(address);
      delay(50);
      Serial.print("Humidity:");
      Serial.print(value);
      Serial.println("%");
      address++;
      value = EEPROM.read(address);
      delay(50);
      Serial.print("Temperature:");
      Serial.print(value);
      Serial.println(" Degrees Fahrenheit");
      address++;
      Serial.println("\n");
      break;
    }
    break;
  }
}

خواندن داده های سنسور بسیار ساده است. تابعی که برای وارد کردن داده ها استفاده می شد، EEPROM.update() بود. اکنون، از تابع EEPROM.read() استفاده می کنیم تا داده ها را بخوانیم. ما تک به تک آدرس های مورد نیازمان را میخوانیم تا بفهمیم دما و رطوبت چقدر بوده است. حلقه for طوری پیکربندی شده که شش رکورد را بخواند.

اسکرین شات از خروجی

کد پاک کردن داده از EEPROM آردوینو

#include <EEPROM.h>

void setup() {
  // تعیین پین به عنوان خروجی
  pinMode(13, OUTPUT);
  
  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  // روشن کردن ال ای دی بعد از اتمام
  digitalWrite(13, HIGH);
}

void loop() {
   
}

این برنامه تمام داده های ذخیره شده در EEPROM را پاک می کند در نهایت LED روشن می شود تا نشان دهد EEPROM کاملاً پاک شده است. این برنامه را قبل از شروع هر نمونه برداری جدید اجرا کنید.

از خواندن متشکریم و اگر در مورد چیزی سوالی دارید، حتماً نظر خود را در زیر بنویسید!

4.5/5 - (2 امتیاز)

برای دریافت مطالب جدید کانال تلگرام یا پیج اینستاگرام آیرنکس را دنبال کنید.
تصویر از محمد رحیمی

محمد رحیمی

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

2 نظر

  1. رضا گفت:

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

    1. محمد رحیمی گفت:

      سلام عزیز
      ممنون از اطلاع رسانیتون اصلاح شد

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

نشانی ایمیل شما منتشر نخواهد شد.