آموزش Espآموزش ESP32آموزش اینترنت اشیاپروژه های Esp

سیستم مانیتورینگ مصرف انرژی با ESP32 (کنتور)

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

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

برای دستیابی به این هدف، از دستگاه های نظارت بر مصرف انرژی که به صورت گسترده در بازار موجود هستند، میتوان استفاده کرد. اما این دستگاه بسیار گران بوده و استفاده از نسخه آماده آن به معنی از دست دادن لذت یادگیری و تجربه جالب ساخت این سیستم است. در این مطلب، نحوه ساخت یک دستگاه نظارت بر مصرف انرژی با ESP32 و تعدادی از سنسورهای معمولی و دردسترس را می آموزیم.

کنتور مصرف انرژی هوشمند چگونه کار میکند؟

در ابتدا باید بدانیم که هدف اصلی ما آوردن داده ولتاژ و جریان به میکروکنترلر است. در این پروژه از ESP32 به عنوان میکروکنترلر استفاده میکنیم. ESP32 داده دریافتی از سنسورها را پردازش کرده و آن را به نمایشگر OLED ارسال میکند تا کاربر مصرف انرژی را مشاهده کند. به علاوه، برای تغذیه تمام قطعات از منبع تغذیه سوئیچینگ  HI-LINK 5V 3W استفاده میکنیم که 220 ولت متناوب را به 5 ولت DC تبدیل میکند.

حال بیایید درباره سنسورهایی که در این پروژه استفاده میشوند، صحبت کنیم.

  1. ماژول سنسور ولتاژ ZMPT101B : ZMPT101B یک سنسور مبدل ولتاژ ( اندازه گیری ولتاژ) است که ولتاژ را به صورت خطی کاهش داده و یک خروجی آنالوگ به کاربر میدهد. این سنسور همچنین ولتاژ ایزولاسیون تا 4000 ولت و ولتاژ کاری امن تا 1000ولت را تامین میکند.

ماژول سنسور ولتاژ ZMPT101B

با مشاهده شماتیک میتوان دریافت که خروجی مبدل ZMPT101B به تقویت کننده عملیاتی LC358N که خود دارای دو آپ امپ است فرستاده شده و پیک های ولتاژ تقویت میشوند.

  1. ماژول سنسور جریان ACS712 20A: تراشه ACS712 یک سنسور تشخیص جریان براساس اثر هال است. این سنسور دورن خود یک سنسور اثر هال دارد که تغییرات میدان مغناطیسی به هنگام عبور جریان را شناسایی میکند. این تغییرات به یک ولتاژ مناسب تبدیل شده و سپس به عنوان خروجی به کاربر داده میشود. شماتیک ماژول سنسور جریان نشان میدهد که این تراشه تمام اجزا لازم را درون خود داشته و برای کارکردن تنها به چند المان پسیو نیاز دارد.

ماژول سنسور جریان ACS712 20A

از میان 3 دسته موجود از این تراشه ( 5 آمپر، 20 آمپر و 30 آمپر) ما نسخه 20 آمپری را انتخاب میکنیم زیرا که این مدل درعین دارا بودن رزولوشن و وضوح کافی، میتواند تقریبا تمام نیازهای ما را در اندازه گیری ولتاژ تامین کند.

مدار اتصال دستگاه مانیتورینگ و نظارت بر مصرف انرژی

مدار اتصال دستگاه مانیتورینگ و نظارت بر مصرف انرژی

نمودار بالا، نشان میدهد که منبع تغذیه سوئیچینگ HI-LINK و ترمینال ورودی سنسور ولتاژ  ZMPT101B به صورت موازی به سیم های فاز و نول وصل شده اند درحالیکه ماژول سنسور جریان ACS712 با مجموعه ای از اتصالات به سیم فاز متصل است.

نمایشگر OLED از طریق پایه های I2C به میکروکنترلر و سنسور ولتاژ و جریان به ترتیب به پایه های 34 و 36(VP) متصل شده اند. این پایه ها با استفاده از مبدل 12 بیتی آنالوگ به دیجیتال ESP32 قادر به تبدیل داده آنالوگ به دیجیتال هستند.

تمامی اجزا با ولتاژ خروجی 5 ولت ماژول HI-LINK تغذیه میشوند. (ترمینال های Vo- و Vo+)

قطعات مورد نیاز برای ساخت کنتور مصرف برق هوشمند

  1. ماژول ESP32 WROOM 32D
  2. منبع تغذیه سوئیچینگ HI-LINK 5V 3W
  3. LED96 اینچی 64*128 I2C
  4. ماژول سنسور ولتاژ ZMPT101B
  5. ماژول سنسور جریان ACS712
  6. سوکت نری 3 پایه 220V AC
  7. سوکت مادگی 3 پایه 220V AC
  8. قاب یا محفظه چاپ سه بعدی

کد دستگاه مانیتورینگ مصرف انرژی

نصب کتابخانه های ضروری

اگر در مورد این مطلب سوالی دارید در قسمت نظرات بپرسید

با نصب دوکتابخانه Adafruit GFX و Adafruit SSD 1306 شروع میکنیم. برای اینکار کافی است در IDE آردوینو، از منو tools بر library manager کلیک کنید.

نام Adafruit GFX و Adafruit SSD 1306 را جست و جو کرده و با کلیک بر install به آسانی آن ها را نصب کنید.

حال باید کتابخانه های لازم برای ماژول سنسور ولتاژ و جریان را نصب کنیم. کد هر دو کتابخانه به هم شباهت دارند. کتابخانه های اصلی این دو سنسور را میتوانید بیابید. اما ما برای جبران این امر که از میکروکنترلر دیگری استفاده کردیم، تغییرات اندکی در این دو کتابخانه به وجود آوردیم تا آن ها را با مبدل 12 بیتی آنالوگ به دیجیتال ESP32 سازگار کنیم. پروسه نصب دو کتابخانه کاملا مشابه هم است. کافی است سراغ گنجینه کتابخانه های GitHub رفته، ابتدا بر روی منو بازشونده Code و سپس بر download zip کلیک کنید.

وقتی فایل زیپ دانلود شد، IDE آردوینو را باز کرده و از منو sketch روی Include Library و سپس Add Zip Library  کلیک کنید.

محل ذخیره فایل را پیدا کرده و روی open کلیک کنید.

IDE آردوینو کتابخانه را نصب خواهد کرد. میتوانید برای کتابخانه دیگر نیز همین مراحل را انجام دهید. وقتی کتابخانه ها نصب شدند، آن ها را در کد خود فراخوانی کنید.

#include "ZMPT101B.h"
#include "ACS712.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

دو کتابخانه Wire و SPI از پیش در IDE آردوینو نصب شده اند و برای کار کردن باس I2C نمایشگر OLED به آن ها نیاز داریم.

دستورات آماده سازی اولیه

نمونه هایی از سنسور ولتاژ و جریان تعریف کرده و آن ها را مقداردهی میکنیم.

ZMPT101B voltageSensor(34);
ACS712 currentSensor(ACS712_20A, 36);

در کنار آن، نمایشگر OLED را با کد زیر آماده کار میکنیم.

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

سپس چند متغیر سراسری که بعدا به آن ها نیاز پیدا خواهیم کرد را تعریف کرده و مقداردهی میکنیم.

float P=0;
float U=0;
float I=0;
long dt=0;
float CulmPwh=0;
float units=0;    
long changeScreen=0;
float lastSample=0;
unsigned long lasttime=0;
long ScreenSelect = 0;

تابع  Void setup

در تابع setup، نقطه صفر و حساسیت سنسورها را تعیین کرده و نمایشگر را راه اندازی میکنیم.

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

پروسه  کالیبراسیون باید برای سنسور ولتاژ و جریان به صورت جداگانه انجام بگیرد.

void setup()
{
  Serial.begin(9600);
  delay(100);
  voltageSensor.setSensitivity(0.0025);
  voltageSensor.setZeroPoint(2621);
  currentSensor.setZeroPoint(2943);
  currentSensor.setSensitivity(0.15);
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); }
  // Clear the buffer
  display.clearDisplay();
  display.display();
  //Caliberation Commands Need To Be Run On First Upload. 
  //CalibCurrent();
  //CalibVoltage();
}

تابع Void Loop

در تابع loop، تنها باید با استفاده از دستورات خوانش داده آنالوگ، داده را از سنسورها خوانده و آن را پس از یک تاخیر 500 میلی ثانیه ای به تابع نمایشگر ارسال کنیم. همچنین در این قسمت، توان لحظه ای و انرژی مصرفی محاسبه میشوند.

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

void loop()
{
  // To measure voltage/current we need to know the frequency of voltage/current
  // By default 50Hz is used, but you can specify desired frequency
  // as first argument to getVoltageAC and getCurrentAC() method, if necessary
  U = voltageSensor.getVoltageAC();
    if(U<55)
      {
        U=0;
        CulmPwh=0;
       }
  I = currentSensor.getCurrentAC();
  dt = micros()- lastSample;
    if(I<0.15)
      {
        I=0;
        CulmPwh=0;
      }
  // To calculate the power we need voltage multiplied by current
  P = U * I;
  CulmPwh = CulmPwh + P*(dt/3600);///uWh
  units= CulmPwh/1000;
  if(millis()-changeScreen>5000)
    {
      ScreenSelect+=1;
      changeScreen=millis();
    }
  if(millis()-lasttime>500)
    {
      if((ScreenSelect%4)==0)
      { displayVoltCurrent(); }//Volts and Current
      else if( (ScreenSelect%4)==1)
      { displayInstPower();   }//Instantaenous Power
      else if( (ScreenSelect%4)==2)
      { displayEnergy();      } //Energy
      else if( (ScreenSelect%4)==3)
      { displayUnits();       } //Units
    }
  lastSample=micros();
}

توابعی که توسط کاربر تعریف میشوند

همانطور که میتوان در کد بالا مشاهده کرد، از توابعی استفاده شده که در کتابخانه موجود نیستند.

CalibCurrent();

CalibVoltage();
displayVoltCurrent();
displayInstPower();
displayEnergy();
displayUnits();
displayCenter(String,Position);

این توابع از پیش در کتابخانه تعریف نشده اند و ما خودمان آن ها را نوشته ایم. از آن ها تنها برای ارسال داده به ماژول OLED و مرتب نگاه داشتن کد استفاده میکنیم. این توابع را میتوان در تابع loop قرار داد.

void displayVoltCurrent()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
void displayVoltCurrent()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(3);
  displayCenter(String(U)+"V",3);
  display.setTextSize(3);
  displayCenter(String(I)+"A",33);
  display.display();
  lasttime=millis();
}
void displayInstPower()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0,0);
  displayCenter("Power",3);
  display.setTextSize(3);
     if(P>1000)
      {
        displayCenter(String(P/1000)+"kW",30);
      }
    else
      {
        displayCenter(String(P)+"W",30);
      }
  display.display();
  lasttime=millis();
}
void displayEnergy()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
   if(CulmPwh>1000000000)
     {
        display.setTextSize(2);
        displayCenter("Energy kWh",3);
        display.setTextSize(3);     
        displayCenter(String(CulmPwh/1000000000),30);
     }
   else if(CulmPwh<1000000000 && CulmPwh>1000000)
     {
        display.setTextSize(2);
        displayCenter("Energy Wh",3);
        display.setTextSize(3);     
        displayCenter(String(CulmPwh/1000000),30);
     }
   else if(CulmPwh<1000000 && CulmPwh>1000)
     {
        display.setTextSize(2)
        displayCenter("Energy mWh",3);
        display.setTextSize(3);     
        displayCenter(String(CulmPwh/1000),30);
     }
   else
     {
        display.setTextSize(2);
        displayCenter("Energy uWh",3);
        display.setTextSize(3);     
        displayCenter(String(CulmPwh),30);
     }
  display.display();
  lasttime=millis();
 }
void displayUnits()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
    if(units>1000000)
      {
        display.setTextSize(2);
        displayCenter("Units",3);
        display.setTextSize(3);     
        displayCenter(String(units/1000000),30);
      }
    else if(units<1000000 && units>1000)
      {
        display.setTextSize(2);
        displayCenter("MilliUnits",3);
        display.setTextSize(3);     
        displayCenter(String(units/1000),30);
      }
  else
      {
        display.setTextSize(2);
        displayCenter("MicroUnits",3);
        display.setTextSize(3);     
        displayCenter(String(units),30);
      }
  display.display();
  lasttime=millis();
 }
void CalibCurrent()
{
  while(1)
  {
    currentSensor.calibrate(); 
    Serial.print("Zero Point Current :");
    Serial.println(currentSensor.getZeroPoint());
    display.clearDisplay();
    display.setTextColor(WHITE);
    display.setTextSize(1);
    display.setCursor(0,0);
    display.print("Current Zero Point :");
    display.setCursor(0,20);
    display.setTextSize(2);
    display.print(currentSensor.getZeroPoint());
    display.display();
    delay(500);
  }
}
void CalibVoltage()
{
  while(1)
  {
    voltageSensor.calibrate(); 
    Serial.print("Zero Point Voltage :");
    Serial.println(voltageSensor.getZeroPoint());
    display.clearDisplay();
    display.setTextColor(WHITE);
    display.setTextSize(1);
    display.setCursor(0,0);
    display.print("Voltage Zero Point :");
    display.setCursor(0,20);
    display.setTextSize(2);
    display.print(voltageSensor.getZeroPoint());
    display.display();
    delay(500);
  }
}
void displayCenter(String text, int line)
{
  int16_t x1;
  int16_t y1;
  uint16_t width;
  uint16_t height;
  display.getTextBounds(text, 0, 0, &x1, &y1, &width, &height);
  // display on horizontal center
  display.setCursor((SCREEN_WIDTH - width) / 2, line);
  display.println(text); // text to display
  display.display();
}

مونتاژ سیستم مانیتورینگ انرژیESP32  

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

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

از ویدیوی زیر، برای قرار دادن تمام اجزا در جای خود و رسیدن به یک ترکیب محکم و زیبا استفاده کنید.

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

در نهایت پروژه به این شکل درمی آید.

شکل نهایی پروژه

عملکرد سیستم مانیتورینگ انرژی با ESP32

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

موارد موجود در فایل : سورس کامل، فایل های سه بعدی و …

5 (1 نفر)

برای دریافت مطالب جدید کانال تلگرام یا پیج اینستاگرام ما را دنبال کنید.

محمد رحیمی

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

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *