亲,“电路城”已合并升级到更全、更大、更强的「新与非网」。点击查看「新与非网」

本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

基于物联网(IoT)的太阳能跟踪器

发布时间:2021-05-29
分享到:

基于物联网(IoT)的太阳能跟踪器

发布时间:2021-05-29
分享到:

该太阳跟踪器使用LDR传感器,并通过自动旋转来跟踪太阳的位置,也可以由用户通过IoT(物联网)应用程序的仪表板手动旋转。

系统首先通过LDR传感器检测太阳位置(光照强度),然后将数据发送到控制器(Arduino Mega开发板)。然后,控制器处理这些数据,并命令伺服电机(SM1和SM2)保持PV板朝着太阳旋转,生成的PV电压,电流,温度和湿度值也通过关联的传感器发送到Arduino。

与Arduino一起安装并允许其连接到Internet的以太网屏蔽将把由Arduino获取和/或处理的数据发送到云(Web服务器)。最后,太阳能跟踪器数据(包括LDR传感器,PV功率,温度和湿度)通过预先创建的小部件实时显示在IoT监视应用程序中。IoT监视应用程序是使用Cayenne myDevices平台设计的。一旦用户从其计算机或智能手机连接到Internet,他就可以在IoT应用程序的仪表板中可视化其关联的小部件中的所有太阳能跟踪器数据。因此,用户拥有与光伏面板的环境和性能相关的必要数据。此外,在手动模式下,伺服电机将从仪表板中与其关联的小部件获取角度方向。因此,用户可以控制他的系统以寻求最佳环境条件并从PV面板中提取最大能量。

(基于lot的太阳跟踪器系统的示意图)

硬件设计:

该太阳能跟踪器由一个PV面板,两个伺服电机,四个LDR传感器,一个分压器电路,一个温湿度传感器,一个Led和Arduino Mega板组成。

(基于lot的太阳能跟踪器的电子电路)

光伏面板:

  • 尺寸:115毫米x 85毫米
  • 输出功率:1.6 W(可产生6 V的电压)

伺服电机:

用于驱动太阳能跟踪器,由Arduino板通过PWM引脚5和6进行控制。左右(L-R)伺服电机(MG996R)在垂直轴(东/西)上旋转太阳跟踪器,而上下(U-D)伺服电机(SG90)在水平轴(南/北)上旋转太阳跟踪器。

LDR传感器:

固定在面板的四个角上,用于感测太阳的位置,LDR传感器通过A0-A3之间的模拟引脚连接到Arduino。LDR传感器是电阻器,其电阻值随入射在其表面上的光强度的增加而减小。

LDR传感器被设计为分压器电路,分压器输出电压由Arduino Mega微控制器从模拟值转换为0到1023之间的数字值。微控制器的转换器(ADC)以10位编码。LDR传感器电路中的串联电阻值为330Ω。

DHT22传感器:

DHT22内有一个热敏电阻和一个电容式湿度传感器,用于测量温度和相对湿度,其温度范围为-40至80°C,精度<±0.5°C,其湿度范围为0至100%,精度为±2%(最大±5%)。该传感器使用一根信号线将数据传输到Arduino(数字引脚2),并用两条线供电。

PV电压和电流通过分压器电路测量,该分压器电路还充当负载,由两个10Ω电阻串联组成。分频器电路输出连接到Arduino的模拟引脚A4。此外,连接到数字引脚3的LED在系统电路中反映太阳能跟踪器的模式状态(手动或自动)。

Arduino Mega板:

带有ATmega2560微控制器的Arduino Mega板,用作与Arduino以太网屏蔽以及监控平台交互的嵌入式控制器。TheEthernet防护板必须安装在Arduino板上,必须通过RJ45电缆与Wi-Fi路由器(或PC)连接。该以太网防护板基于Wiznet W5100以太网芯片,该芯片可提供用于TCP和UDP协议的网络(IP)堆栈。

(Arduino和以太网屏蔽之间的硬件接口)

软件设计:

Arduino IDE:

Arduino是具有易于使用的硬件和软件的开源电子原型平台。Arduino平台提供了集成开发环境(IDE),其中包括对C和C ++编程语言的支持。这项工作中使用的Arduino板由IDE进行编程,该IDE用作代码编辑器,程序代码可以通过USB电缆从其中上传到微控制器,来实现基于IoT的太阳能跟踪器的所有软件要求。

myDevices Cayenne:

MyDevices是一家提供物联网解决方案的公司,它为物联网提供了一个端到端的平台。在该项目中,将重点介绍myDevices的解决方案之一Cayenne。该工具允许开发人员、设计师和工程师构建物联网的原型。Cayenne使用消息QueuingTelemetry传输(MQTT)协议将任何设备与Cayennecloud连接起来。连接后,用户可以通过创建的小部件将数据从设备发送和接收到Cayenne仪表板。

MQTT是基于TCP/IP协议的发布-订阅消息传递协议。publish-subscribe方法使用一个负责向客户机传递消息的消息代理。MQTT是用于向Cayenne cloud、由Cayenne控制的设备发送信息的API。此连接中的消息代理是云,它管理发送和接收数据的不同客户端(传感器和执行器)。

要在Cayenne中使用MQTT,我们需要使用Cayenne库。对于Arduino,可以从IDE的库管理器安装CayenneMQTT库。为了对基于Cayenne IoT平台的IoT应用程序进行编程,将利用预定义的功能。

如,为了在配备以太网模块的Cayenne cloud和Arduino Mega之间建立连接,调用Cayenne MQTT Ethernet库,在该库中声明应从Cayenne仪表板获取的身份验证信息(用户名、密码和客户端ID)。然后,在程序的设置部分,调用Cayenne.begin()函数来建立与Cayenne dashboard的连接。

  • 对于每个执行器,创建一个函数,其中包含一个介于0和31之间的整数参数,必要时称为CAYENNE IN(虚拟通道)
  • 对于每个传感器,创建一个整数,即参数介于0和31之间的函数,该函数必要时被称为CAYENNE\u OUT(虚拟\u通道)

程序的循环部分,调用预定义的函数Cayenne.loop(),该函数本身调用函数Cayenne\u OUT和Cayenne\u In。

虚拟通道顾名思义是一个物理上不存在的通道,它以可视化或命令小部件为特征。它允许它们与相应的传感器或执行器连接。

嵌入式软件设计:

嵌入式软件是将嵌入到Arduino Mega中的组件,以在以太网模块和Cayenne云之间进行交互,其设计如下:

(i)基于IoT的太阳能跟踪器具有两种功能模式:手动和自动。在Cayenne仪表板中创建的按钮具有在两种模式之间切换的作用。处于非活动状态时,将选择手动模式,反之则选择自动模式。此外,在Arduino代码中建立了一个函数,该函数允许恢复按钮的状态,系统电路中的LED反映此开关的状态。

为了让控制器知道所选的工作模式,只需要测试连接LED的引脚的状态即可。如,如果LED状态为低电平,则控制器将调用手动模式功能来执行,否则,控制器将调用自动功能。

(ii)如果选择了手动模式,则用户可以直接控制伺服电动机的位置,以通过LR伺服电动机将PV面板从东向西定向,或者通过UD伺服电动机将光伏板从南向北定向。该控件由IoT应用程序仪表板上的伺服电动机的关联小部件完成。

在此模式下,控制器调用Cayenne.loop()函数,该函数本身将调用所有函数CAYENNE_IN,包括与伺服电动机相关的那些函数来执行。该Cayenne.loop()函数也将调用所有功能CAYENNE_OUT,连接到传感器,执行。与LDR传感器,PV电流,电压和功率,温度和湿度有关的数据将被发送到服务器,以便可以在IoT应用程序的关联小部件中对其进行可视化。

(iii)如果选择自动模式,将执行图4所示的算法。该算法从读取LDR传感器返回的模拟值开始。然后,它处理这些数据以命令伺服电机将PV面板移向太阳位置。考虑到基于垂直轴的太阳能跟踪器的运动,比较左侧两个LDR和右侧两个LDR的平均值,如果左侧接收更多的光,则PV面板将沿该方向移动(顺时针)通过LR伺服电机。当差值结果介于-10和10之间时,后者将停止。此范围用于稳定控制器并减少伺服电机的功耗。否则,如果正确的一组LDR接收到更多的光,PV面板将通过LR伺服电机沿该方向(逆时针)移动,并将继续旋转,直到差值结果在[-10,10]范围内。基于水平轴的太阳能跟踪器移动使用相同的方法,其中比较顶部的两个LDR和底部的两个LDR的平均值。

与自动模式一样,控制器还将调用Cayenne.loop()函数将太阳能跟踪器数据发送到IoT应用程序。

(太阳能跟踪器自动模式的流程图)

物联网监控应用程序的开发:

(i)与Cayenne IoT平台的硬件接口

将硬件(包括传感器和执行器)与IoT平台连接,需:

  • 创建帐户后登录Cayenne myDevice网站,如(a)
  • 单击Cayenne API中的“自备物品”,如(b)

  • 从Crete App复制MQTT凭证(用户名,密码和客户端ID),将它们粘贴到Arduino源代码中
  • 成功编译并将全部代码上传到Arduino Mega之后,在Arduino IDE中打开Serial Monitor以获取Cayenne日志打印件(图1)
  • 设备上线并连接到Cayenne后,图1将自动更新,将在在线仪表板上看到设备,如图3

(图1、MQTT凭证和Cayenne的设备连接)

(图2)

 

(图3、设备设置)

  • 连接传感器和执行器,即创建其小部件,单击“添加新…”,选择“设备/小部件”,然后单击“自定义小部件”(通道号必须与代码中的相同),单击“添加小部件”将其添加到设备的仪表板上。为所有传感器选择了“值”小部件,“按钮”小部件用于模式切换,用于伺服电机的“ Slider”小部件。

(自定义小部件)

  • 设计的IoT应用程序,用于监控太阳能跟踪器数据。建立与太阳能跟踪器系统的连接后,可以在其关联的小部件上显示传感器数据,可以从切换按钮选择跟踪模式(自动或手动),并通过其小部件控制伺服电机的角度。传感器数据也可以通过修改其设置中的表示类型,或者仅通过单击小部件上方的图形图标来以图形形式获得。

(太阳能跟踪器系统的物联网监控应用)

警报创建:

监视系统中最重要的标准之一是它具有发送通知警报的功能,为发生与其所监视的设备有关的事件时可及时通知用户。为此,利用Cayenne的功能之一向物联网应用程序添加了警报,可以在其中对应用程序进行预编程,以发送通知警报(SMS,电子邮件或两者)或执行指定的操作。

如,如图所示,将创建一个温度警报,以便在监视的温度达到阈值时向用户(或收件人)发送电子邮件通知。要创建警报,请单击“添加新的。 ..”并选择“触发器”,然后设置事件及其动作,最后单击“保存”将其添加到仪表板。

(温度警报配置)

原型:

该图展示了处于分离和组装状态的太阳能跟踪器原型。它由PV面板,-R和UD伺服电机以及LDR传感器组成。面板的一侧固定在U-Dservomotor上,另一侧固定在轴承上,以确保太阳能跟踪器绕水平轴旋转时具有更好的柔韧性。组件安装在LR伺服电机上。LDR传感器固定在中空圆柱体内面板的四个角上。如果面板不垂直于太阳,则最少有一个LDR将被周围圆柱体引起的阴影覆盖。因此,光强度会有所不同。最佳方向是所有LDR传感器的光强度均相等时。

(处于分离和组装状态的太阳能跟踪器原型)

(基于LOT的太阳跟踪器原型)

视频演示:

附件:

/***************************************************************
 PROJECT: IoT based solar tracker system / the embedded software
 Aboubakr El Hammoumi/ aboubakr.elhammoumi@usmba.ac.ma
***************************************************************/

#define CAYENNE_PRINT Serial
#include <CayenneMQTTEthernet.h>    //CayenneMQTT图书馆
#include <Servo.h>                  //伺服电机库
#include <DHT.h>                    //DHT图书馆 
#define DHTTYPE DHT22
#define DHTPIN 2
DHT dht(DHTPIN,DHTTYPE);

//MQTT凭据
char username[]="498d2d00-afe2-11ea-883c-638d8ce4c23d";
char password[]="ab4a8f92d94033c01f6e18ce1d8a84d8c304c9c4";
char clientID[]="17798a40-b968-11ea-93bf-d33a96695544";

Servo servo_x;                   //升降伺服电机
int servoh = 0;
int servohLimitHigh = 170;     
int servohLimitLow = 10;       

Servo servo_z;                   //左右伺服电机
int servov = 0; 
int servovLimitHigh = 170;
int servovLimitLow = 10;

int topl,topr,botl,botr;
int threshold_value=10;        
float Vout;

void setup()
{ Serial.begin(9600);
  Cayenne.begin(username, password, clientID);
  servo_x.attach(5);
  servo_z.attach(6);
  dht.begin();
  pinMode(3,OUTPUT);
  digitalWrite(3,LOW); 
}

void loop()
{ topr= analogRead(A2);       
  topl= analogRead(A3);         
  botl= analogRead(A4);         
  botr= analogRead(A5);        
  Vout=(analogRead(A1) * 5.0) / 1023;
  Serial.println(" Manual-mode");
  Cayenne.loop();
  
  if (digitalRead(3)==HIGH){
    Serial.println(" Automatic-mode");
    servoh = servo_x.read();
    servov = servo_z.read();
    int avgtop = (topr + topl) / 2;     
    int avgbot = (botr + botl) / 2;   
    int avgright = (topr + botr) / 2;   
    int avgleft = (topl + botl) / 2;    
    int diffhori= avgtop - avgbot;      
    int diffverti= avgleft - avgright;    
    
    /*按水平轴跟踪*/ 
    if (abs(diffhori) <= threshold_value)
    {
     servo_x.write(servoh);            //停止伺服升降
    }else {
       if (diffhori > threshold_value)
          { Serial.println(" x - 2 ");
          servo_x.write(servoh -2);    //顺时针旋转CW
          if (servoh > servohLimitHigh)
          {
           servoh = servohLimitHigh;
          }
          delay(10);
          }else {
           servo_x.write(servoh +2);   //CCW
           if (servoh < servohLimitLow)
           {
           servoh = servohLimitLow;
           }
           delay(10);
           }
      }      
    /*按纵轴跟踪*/ 
    if (abs(diffverti) <= threshold_value)
    {     
     servo_z.write(servov);       //停止左右伺服
    }else{
       if (diffverti > threshold_value)
       { 
       servo_z.write(servov -2);  //CW
       if (servov > servovLimitHigh) 
       { 
       servov = servovLimitHigh;
       }
       delay(10);
       }else{ 
        servo_z.write(servov +2);  //CCW
        if (servov < servovLimitLow) 
        {
        servov = servovLimitLow;
        }
        delay(10);
        }
     }
  }
}
// Cayenne Functions
CAYENNE_IN(8){
  int value = getValue.asInt();
  CAYENNE_LOG("Channel %d, pin %d, value %d", 8, 3, value);
  digitalWrite(3,value);
}
CAYENNE_IN(7){ //升降伺服电机
  if (digitalRead(3)==HIGH){ //自动模式
  }
  else{ //手动模式
  servo_x.write(getValue.asDouble() * 180);
  }
}
CAYENNE_IN(6){ //左右伺服电机
  if (digitalRead(3)==HIGH){
  }  
  else{
  servo_z.write(getValue.asDouble() * 180);
  }
}

CAYENNE_OUT(0) { //当前
  float current = Vout/10;
  Cayenne.virtualWrite(0, current);
  Serial.print("Current: ");
  Serial.println(current);
}
CAYENNE_OUT(1) { //电压
  float voltage = Vout * 2;
  Cayenne.virtualWrite(1, voltage);
  Serial.print("Voltage: ");
  Serial.println(voltage);
}
CAYENNE_OUT(2){ //LDR Top-right
  Cayenne.virtualWrite(2, topr);
}
CAYENNE_OUT(3){ //LDR Top-left
  Cayenne.virtualWrite(3,topl);
}
CAYENNE_OUT(4){ //LDR Bot-left
  Cayenne.virtualWrite(4,botl);
}
CAYENNE_OUT(5){ //LDR Bot-right
  Cayenne.virtualWrite(5,botr);
}
CAYENNE_OUT(10) { //Power
  float power = (Vout * 2 * Vout)/10 ;
  Cayenne.virtualWrite(10, power);
  Serial.print("Power: ");
  Serial.println(power);
}
CAYENNE_OUT(11){ //温度
  float t = dht.readTemperature();
  //int chk = dht.read(DHT11PIN);
  Cayenne.virtualWrite(11, t, TYPE_TEMPERATURE, UNIT_CELSIUS);
  Serial.print("temperature: ");
  Serial.println(t);
}
CAYENNE_OUT(12){ //Huidity
  float h = dht.readHumidity();
  //int chk = dht.read(DHT11PIN);
  Cayenne.virtualWrite(12, h);
  Serial.print("  humidity: ");
  Serial.println(h);
}

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论