亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

伺服控制的光跟踪太阳能电池板平台

组件和用品

光敏电阻
× 4
Adafruit Flora RGB Neopixel LED - 4 个装
或等效的 RBG 多色 LED
× 1
SparkFun 按钮开关 12mm
或等效的常开按钮
× 2
温度传感器
× 1
Arduino UNO
× 1
RobotGeek 180度机器人伺服
或等价物。我用的是双叶 S3003 舵机
× 2
电阻 10k ohm
× 6
电阻 221 ohm
我用的是 220 欧姆
× 1
电容 100 µF
× 2
太阳能电池板(80mm x 80mm)
可以在 Amazon.com 或同等网站上购买
× 1

必要的工具和机器

手工工具和一些小螺母和螺栓来制作支架
用于安装“扭曲”伺服电机的坚固底座。
我用了一小块木头
可弯曲的金属或小片刚性铝,可以制成一个“L”形支架
我用了大约。 3 毫米厚的铝,宽度不到 2 厘米
薄而可弯曲的金属形成一个支架来固定太阳能电池板平台并将其安装到“扭曲”伺服
我使用在五金店购买的薄钢带,通常用于将暖通空调管道固定在一起。已预先钻好安装孔以方便使用

应用和在线服务

Arduino IDE
用于文档和注释的 Microsoft Excel

关于这个项目

这是使用两个 180 度伺服器和四个光敏电阻器来跟踪小型太阳能电池板以对准光强度最大的区域的另一种实现方式。

电机进行小幅运动,尝试将太阳能电池板指向最亮的光线。

还有一个多色 LED 指示系统是否已启用。以及两个用于启用/禁用电机的按钮。

有一些程序可用于将电机移动到指定位置。命令是通过串口接口和一系列可以发送到Arduino Uno的数字代码/命令。

独立移动命令的编程方式提供(有点)平滑的运动,而不是导致机械机构剧烈运动的即时位置命令。

代码

  • 第二季度代码
Q2 代码Arduino
//Scott Mangiacotti//美国亚利桑那州图森//May 2018//Q2//Version 2.0#include //Constantsint const GIVE_BACK_TIME =125;//输入常量int const I_RED_BUTTON_PIN =4;int const I_GREEN_BUTTON_PIN =2; int const I_LDR1_PIN =A3; //top leftint const I_LDR2_PIN =A2; //右上角int const I_LDR3_PIN =A1; //bottom leftint const I_LDR4_PIN =A0; //右下角//输出常量int const O_RED_LED_PIN =9;int const O_GREEN_LED_PIN =11;int const O_BLUE_LED_PIN =10;int const O_TWIST_SERVO_PIN =5;int const O_TILT_SERVO_PIN =6;//全局变量bool gRunningToLightEnabled;bool false;bool gVerboseDiagMode =false;Servo gServoTwist;int gServoTwistPositionCommand; //命令positionbool gServoTwistMoveIP; //移动中Servo gServoTilt;bool gServoTiltMoveIP; // 移动中 gServoTiltPositionCommand; //命令位置int gLDR1;int gLDR2;int gLDR3;int gLDR4;//运行一次void setup() { //打开串口Serial.begin(9600); //设置数字输入 pinMode(I_RED_BUTTON_PIN, INPUT); pinMode(I_GREEN_BUTTON_PIN,输入); //设置数字输出 pinMode(O_RED_LED_PIN, OUTPUT); pinMode(O_GREEN_LED_PIN,输出); pinMode(O_BLUE_LED_PIN,输出); //运行启动例程startup();}//连续运行void loop(){ //串口消息接收处理 if (Serial.available()> 0) { int iControlCode; iControlCode =Serial.parseInt(); processSerialMessage(iControlCode); } //读取绿色按钮 int iGreenButton; iGreenButton =digitalRead(I_GREEN_BUTTON_PIN); if (iGreenButton ==HIGH &&gRunning ==false) { enableTracking(); gTrackToLightEnabled =true; } //读取红色按钮 int iRedButton; iRedButton =digitalRead(I_RED_BUTTON_PIN); if (iRedButton ==HIGH &&gRunning ==true) { disableTracking(); } //将所有检测读入全局变量 readPhotoResistors();平均TopTwoSensors(); averageBottomTwoSensors(); //根据光敏电阻上的光线调整伺服位置 if (gRunning ==true) { if (gTrackToLightEnabled ==true) { //根据光敏电阻的光线水平对伺服进行小幅移动 trackToLightSensors(); } else { //串口根据用户命令做小动作。避免机制上的高速移动 smoothMoveTwist();平滑移动倾斜(); } } //给一点时间延迟(GIVE_BACK_TIME);}//打开伺服跟踪void enableTracking(){ //设置全局变量,以便程序的其他部分知道电机已准备好运行 gRunning =true; //连接到伺服电机 gServoTwist.attach(O_TWIST_SERVO_PIN); gServoTilt.attach(O_TILT_SERVO_PIN); //打开绿色LED和关闭红色LED digitalWrite(O_GREEN_LED_PIN, HIGH);数字写入(O_RED_LED_PIN,低); //发布结果 Serial.println("servos enabled");}//关闭伺服跟踪void disableTracking(){ gRunning =false; gTrackToLightEnabled =false; //从伺服电机上分离 gServoTwist.detach(); gServoTilt.detach(); //清除移动命令并移动进程内(IP)变量 gServoTwistPositionCommand =gServoTwist.read(); gServoTwistMoveIP =false; //清除移动命令并移动进程内(IP)变量 gServoTiltPositionCommand =gServoTilt.read(); gServoTiltMoveIP =false; //打开红色LED,关闭绿色LED digitalWrite(O_RED_LED_PIN, HIGH);数字写入(O_GREEN_LED_PIN,低); //发布结果 Serial.println("servos disabled");}//根据光传感器值跟踪光线void trackToLightSensors(){ float fTop;浮动 fBottom;浮动左;浮动恐惧; int iTwistMoveCommand; int iTiltMoveCommand;内部 iMoveAmount; //Initialize //下面的变量决定了程序每次扫描时两个舵机的潜在运动度数。这个数字与全局常量 //named 'GIVE_BACK_TIME' 一起决定了移动的激进程度。 iMoveAmount =5; //获取当前舵机位置 iTwistMoveCommand =gServoTwist.read(); iTiltMoveCommand =gServoTilt.read(); //获取平均值 fTop =averageTopTwoSensors(); fBottom =averageBottomTwoSensors(); fLeft =averageLeftTwoSensors(); fRight =averageRightTwoSensors(); //计算扭曲移动 if (fLeft> fRight) { //正向移动 iTwistMoveCommand +=iMoveAmount; } else if (fRight> fLeft) { //移动负值 iTwistMoveCommand -=iMoveAmount; } else { //同上。不要移动 } //计算倾斜移动 if (fTop>
 fBottom) { //移动正 iTiltMoveCommand +=iMoveAmount; } else if (fBottom> fTop) { //移动负值 iTiltMoveCommand -=iMoveAmount; } else { //同上。不移动 } //边界检查扭曲伺服移动命令 if (iTwistMoveCommand <0) { iTwistMoveCommand =0; } if (iTwistMoveCommand> 179) { iTwistMoveCommand =179; } //边界检查倾斜伺服移动命令 if (iTiltMoveCommand <45) { iTiltMoveCommand =45; } if (iTiltMoveCommand> 135) { iTiltMoveCommand =135; } //执行移动 gServoTwist.write(iTwistMoveCommand); gServoTilt.write(iTiltMoveCommand); //发布结果 if (gVerboseDiagMode ==true) { Serial.println("tl, tr, bl, br, top avg, bottom avg, left avg, right avg, 扭曲移动,倾斜移动:"); Serial.print(gLDR1); Serial.print(", "); Serial.print(gLDR2); Serial.print(", "); Serial.print(gLDR3); Serial.print(", "); Serial.print(gLDR4); Serial.print(", "); Serial.print(fTop); Serial.print(", "); Serial.print(fBottom); Serial.print(", "); Serial.print(fLeft); Serial.print(", "); Serial.print(fRight); Serial.print(", "); Serial.print(iTwistMoveCommand); Serial.print(", "); Serial.println(iTiltMoveCommand); } }//将光敏电阻值读入全局变量void readPhotoResistors(){ //值按0-1024缩放gLDR1 =analogRead(I_LDR1_PIN); gLDR2 =模拟读取(I_LDR2_PIN); gLDR3 =模拟读取(I_LDR3_PIN); gLDR4 =analogRead(I_LDR4_PIN);}//当舵机被命令到一个位置时,它们会快速移动。//太快可能会影响支撑和移动的机械结构//太阳能电池板和光传感器平台。该例程采用“移动命令”//并进行小的增量移动,直到伺服处于所需位置。//该例程用于底座安装的扭转伺服电机void smoothMoveTwist(){ int iCurrentPos; int iMoveAmountPerScan; int iNewMoveCommand; //以度为单位设置每次扫描的移动量。 //这个变量和全局常量'GIVE_BACK_TIME'的组合决定整体移动速度 iMoveAmountPerScan =1; //确定当前位置 iCurrentPos =gServoTwist.read(); //我们到位了吗? if (iCurrentPos ==gServoTwistPositionCommand) { gServoTwistMoveIP =false;返回; } else { gServoTwistMoveIP =true; } //从我们当前所在的位置开始 iNewMoveCommand =iCurrentPos; //确定移动量 if (iCurrentPos  179) { iNewMoveCommand =179; } //移动gServoTwist.write(iNewMoveCommand); //发布结果 if (gVerboseDiagMode ==true) { //todo:Serial.print("Twist Serve move (this move, total):"); Serial.print(iNewMoveCommand); Serial.print(", "); Serial.println(gServoTwistPositionCommand); }}//当舵机被命令到一个位置时,它们会以很快的速度移动。//太快可能会影响支撑和移动//太阳能电池板和光传感器平台的机械结构。该例程采用“移动命令”//并进行小的增量移动,直到伺服处于所需位置。//该例程适用于安装在支架上的倾斜伺服电机void smoothMoveTilt(){ int iCurrentPos; int iMoveAmountPerScan; int iNewMoveCommand; //以度为单位设置每次扫描的移动量。 //这个变量和全局常量'GIVE_BACK_TIME'的组合决定整体移动速度 iMoveAmountPerScan =1; //确定当前位置 iCurrentPos =gServoTilt.read(); //我们到位了吗? if (iCurrentPos ==gServoTiltPositionCommand) { gServoTiltMoveIP =false;返回; } else { gServoTiltMoveIP =true; } //从我们当前所在的位置开始 iNewMoveCommand =iCurrentPos; //确定移动量 if (iCurrentPos  179) { iNewMoveCommand =179; } //移动gServoTilt.write(iNewMoveCommand); //发布结果 if (gVerboseDiagMode ==true) { //todo:Serial.print("倾斜伺服移动(这个移动,总计):"); Serial.print(iNewMoveCommand); Serial.print(", "); Serial.println(gServoTiltPositionCommand); }}//取面板顶部的两个LDR的数学平均值float averageTopTwoSensors(){ float fAvg; //数学fAvg =(gLDR1 + gLDR2) / 2.0; return fAvg;}//取面板底部的两个LDR的数学平均值float averageBottomTwoSensors(){ float fAvg; //数学fAvg =(gLDR3 + gLDR4) / 2.0; return fAvg;}//取panelfloat averageLeftTwoSensors()左边的两个LDR的数学平均值{ float fAvg; //数学fAvg =(gLDR1 + gLDR3) / 2.0; return fAvg;}//取面板右侧的两个LDR的数学平均值float averageRightTwoSensors(){ float fAvg; //数学fAvg =(gLDR2 + gLDR4) / 2.0; return fAvg;}//处理从串口接口接收到的消息//输入参数iControlCode为从待处理串口接收到的值//前两位为控制命令,后三位为要处理的值void processSerialMessage(int iControlCode){ int iControlCommand; int iControlValue; //计算命令和值 iControlCommand =iControlCode / 1000; iControlValue =iControlCode % 1000; //报告命令和值 Serial.print("control code:"); Serial.println(iControlCode); Serial.print("控制命令:"); Serial.println(iControlCommand); Serial.print("控制值:"); Serial.println(iControlValue); //杂项命令类别 if (iControlCommand ==10) { if (iControlValue ==0) { gVerboseDiagMode =true;数字写入(O_BLUE_LED_PIN,高); Serial.println("诊断模式启动"); } else if (iControlValue ==1) { gVerboseDiagMode =false;数字写入(O_BLUE_LED_PIN,低); Serial.println("诊断模式停止"); } else if (iControlValue ==2) { reportProductInfo(); } else if (iControlValue ==3) { //digitalWrite上的红色LED(O_RED_LED_PIN, HIGH); Serial.println("红灯亮"); } else if (iControlValue ==4) { //红色LED关闭digitalWrite(O_RED_LED_PIN, LOW); Serial.println("红灯灭"); } else if (iControlValue ==5) { //数字写入上的绿色 LED(O_GREEN_LED_PIN, HIGH); Serial.println("绿灯亮"); } else if (iControlValue ==6) { //绿色LED关闭digitalWrite(O_GREEN_LED_PIN, LOW); Serial.println("绿灯熄灭"); } else if (iControlValue ==7) { //digitalWrite 上的蓝色 LED(O_BLUE_LED_PIN, HIGH); Serial.println("蓝色指示灯亮"); } else if (iControlValue ==8) { //蓝色LED关闭digitalWrite(O_BLUE_LED_PIN, LOW); Serial.println("蓝灯灭"); } else if (iControlValue ==9) { //显示LDR1值Serial.print("LDR1 value:"); Serial.println(gLDR1); } else if (iControlValue ==10) { //显示LDR2值Serial.print("LDR2值:"); Serial.println(gLDR2); } else if (iControlValue ==11) { //显示LDR3值Serial.print("LDR3值:"); Serial.println(gLDR3); } else if (iControlValue ==12) { //显示LDR4值Serial.print("LDR4值:"); Serial.println(gLDR4); } else if (iControlValue ==13) { //开启追踪模式 enableTracking(); } else if (iControlValue ==14) { //关闭追踪模式 disableTracking(); } else if (iControlValue ==19) { if (gRunning ==true &&gServoTwistMoveIP ==false &&gServoTiltMoveIP ==false) { gServoTwistPositionCommand =90; gServoTiltPositionCommand =90; Serial.println("扭转和倾斜舵机命令到 90 度"); } } else if (iControlValue ==21) { if (gRunning ==true) { gTrackToLightEnabled =true; Serial.println("跟踪到光源启用"); } } else if (iControlValue ==22) { gTrackToLightEnabled =false; Serial.println("跟踪到光源已禁用"); } else { Serial.print("无效控制值:"); Serial.println(iControlValue); } } //Servo1 (twist) 命令类别 if (iControlCommand ==11) { if (iControlValue>=0 &&iControlValue <=179) { //移动舵机1到位置 if (gRunning ==true &&gServoTwistMoveIP ==false) { gServoTwistPositionCommand =iControlValue; gServoTwistMoveIP =true; Serial.print("移动扭转伺服命令:"); Serial.println(gServoTwistPositionCommand); } } else { Serial.print("无效控制值:"); Serial.println(iControlValue); } } //Servo2(倾斜)命令类别 if (iControlCommand ==12) { if (iControlValue>=0 &&iControlValue <=179) { //移动伺服2到位置 //移动伺服1到位置 if (gRunning ==true &&gServoTiltMoveIP ==false) { gServoTiltPositionCommand =iControlValue; gServoTiltMoveIP =真; Serial.print("移动倾斜伺服命令:"); Serial.println(gServoTiltPositionCommand); } else { Serial.print("倾斜伺服未启用或正在移动,"); Serial.print(gRunning); Serial.print(", "); Serial.println(gServoTiltMoveIP); } } else { Serial.print("无效控制值:"); Serial.println(iControlValue); } } //End of request string Serial.println("-----");}//运行一系列步骤来自检功能,启用舵机并进入光跟踪模式void startup(){ int iDelay; //初始化iDelay =500; //显示应用信息 reportProductInfo();延迟(iDelay); //打开红色LED processSerialMessage(10003);延迟(iDelay); //关闭红色LED,打开绿色LED processSerialMessage(10004); processSerialMessage(10005);延迟(iDelay); //关闭绿色LED,开启蓝色LED processSerialMessage(10006); processSerialMessage(10007);延迟(iDelay); //关闭蓝色LED,显示光敏电阻值(所有四个) processSerialMessage(10008); processSerialMessage(10009); processSerialMessage(10010); processSerialMessage(10011); processSerialMessage(10012);延迟(iDelay); //启用舵机 enableTracking();延迟(iDelay); //移动舵机到原位 processSerialMessage(10019);延迟(iDelay); //禁用舵机 disableTracking(); //说再见Serial.println("启动序列完成");}//发送产品信息到串口void reportProductInfo(){ //上报产品等信息到串口Serial.println("q version 2" ); Serial.println("图森,美国亚利桑那州"); Serial.println("2018 年 5 月"); Serial.print("校验和"); Serial.println("58BA-D969-2F82-08FD-2078-2777-396D-E1AA");}

定制零件和外壳

q2_assembly_details_RCbi893qzA.zip

示意图

q2_schematic_TVp7kakwNa.fzz

制造工艺

  1. 太阳能供暖系统
  2. 太阳能电池
  3. 使用 Arduino 的太阳能电池板实时数据采集
  4. 智能百叶窗
  5. 基于物联网 (IoT) 的太阳能跟踪器
  6. SmartPostBox
  7. 具有自动和手动模式的双轴太阳能跟踪器面板
  8. 太阳能电池板太阳追踪器 - 手机充电器
  9. UltrasonicEyes
  10. 了解太阳能
  11. 太阳能电池板:质量问题和关键控制点
  12. 太阳能电池板制造过程:太阳能电池板是如何制造的?