Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Servogesteuerte, lichtnachführende Solarpanel-Plattform

Komponenten und Verbrauchsmaterialien

Fotowiderstand
× 4
Adafruit Flora RGB Neopixel LEDs - 4er Pack
oder gleichwertige mehrfarbige RBG-LED
× 1
SparkFun Drucktastenschalter 12 mm
oder gleichwertiger normalerweise offener Druckknopf
× 2
Temperatursensor
× 1
Arduino UNO
× 1
RobotGeek 180-Grad-Roboter-Servo
oder gleichwertig. Ich habe Futaba S3003 Servos verwendet
× 2
Widerstand 10k Ohm
× 6
Widerstand 221 Ohm
Ich habe 220 Ohm verwendet
× 1
Kondensator 100 µF
× 2
Solarpanel (80 mm x 80 mm)
kann auf Amazon.com oder gleichwertig gekauft werden
× 1

Notwendige Werkzeuge und Maschinen

Handwerkzeuge und ein paar kleine Schrauben und Muttern zur Herstellung der Halterung
Solide Basis zur Montage des "Twist"-Servomotors.
Ich habe einen kleinen Holzblock verwendet
Biegbares Metall oder kleine Bleche aus starrem Aluminium, die zu . geformt werden können eine "L"-förmige Klammer
Ich habe ca. 3 mm dickes Aluminium das knapp 2 cm breit ist
Dünnes, biegsames Metall als Halterung für die Solarpanel-Plattform und montieren Sie es am "Twist"-Servo
Ich habe dünne Stahlbänder verwendet, die im Baumarkt gekauft wurden und normalerweise zum Zusammenhalten von HLK-Kanälen verwendet werden. Hat zur Vereinfachung vorgebohrte Befestigungslöcher

Apps und Onlinedienste

Arduino-IDE
Microsoft Excel für Dokumentation und Notizen

Über dieses Projekt

Dies ist eine weitere Implementierung der Verwendung von zwei 180-Grad-Servos und vier Fotowiderständen, um ein kleines Solarpanel zu verfolgen, um es auf den Bereich mit der höchsten Lichtintensität auszurichten.

Die Motoren machen kleine Bewegungen, um zu versuchen, das Solarpanel auf das hellste Licht auszurichten.

Es gibt auch eine mehrfarbige LED, die anzeigt, ob das System aktiviert ist oder nicht. Und zwei Druckknöpfe zum Aktivieren/Deaktivieren der Motoren.

Es gibt einige Routinen, die zum Bewegen der Motoren in befohlene Positionen verwendet werden können. Die Befehle erfolgen über die serielle Schnittstelle und eine Reihe von numerischen Codes/Befehlen, die an das Arduino Uno gesendet werden können.

Die unabhängigen Bewegungsbefehle sind so programmiert, dass sie (etwas) sanfte Bewegungen anstelle von sofortigen Positionsbefehlen liefern, die eine heftige Bewegung des mechanischen Mechanismus verursachen.

Code

  • Q2-Code
Q2-CodeArduino
//Scott Mangiacotti//Tucson, Arizona USA//Mai 2018//Q2//Version 2.0#include //Konstantenint const GIVE_BACK_TIME =125;//Konstanten für Eingängeint const I_RED_BUTTON_PIN =4;int const I_GREEN_BUTTON_PIN =2;int const I_LDR1_PIN =A3; //oben linksint const I_LDR2_PIN =A2; //oben rechtsint const I_LDR3_PIN =A1; //unten linksint const I_LDR4_PIN =A0; //unten rechts//Konstanten für Ausgabenint 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;//ToLight=falseEnbool gunning =falseEnbool gunning =false;bool gVerboseDiagMode =false;Servo gServoTwist;int gServoTwistPositionCommand; //befohlene Positionbool gServoTwistMoveIP; //Bewegung läuftServo gServoTilt;bool gServoTiltMoveIP; //Vorwärts bewegenint gServoTiltPositionCommand; // befohlene Positionint gLDR1;int gLDR2;int gLDR3;int gLDR4; //Führt einmalvoid setup () { // Öffnen Sie eine serielle Schnittstelle Serial.begin (9600); // Digitaleingänge einrichten PinMode (I_RED_BUTTON_PIN, INPUT); pinMode (I_GREEN_BUTTON_PIN, INPUT); // Digitale Ausgänge einrichten PinMode (O_RED_LED_PIN, OUTPUT); pinMode (O_GREEN_LED_PIN, AUSGANG); pinMode (O_BLUE_LED_PIN, AUSGANG); //Startroutine startup() ausführen;}//Führt kontinuierlichvoid loop(){ //Verarbeitung des Nachrichtenempfangs über serielle Schnittstelle if (Serial.available()> 0) { int iControlCode; iControlCode =Serial.parseInt(); processSerialMessage(iControlCode); } // Grüne Schaltfläche lesen int iGreenButton; iGreenButton =digitalRead (I_GREEN_BUTTON_PIN); if (iGreenButton ==HIGH &&gRunning ==false) { enableTracking(); gTrackToLightEnabled =true; } // Rote Schaltfläche lesen int iRedButton; iRedButton =digitalRead (I_RED_BUTTON_PIN); if (iRedButton ==HIGH &&gRunning ==true) {disableTracking(); } //Alle Instrumentierung in globale Variablen einlesen readPhotoResistors(); DurchschnittTopTwoSensors(); DurchschnittBottomTwoSensors(); // Servopositionen entsprechend dem Licht auf Fotowiderständen anpassen if (gRunning ==true) { if (gTrackToLightEnabled ==true) {//Machen Sie kleine Bewegungen von Servos basierend auf den Lichtwerten der Fotowiderstände trackToLightSensors (); aufrechtzuerhalten. Else { // Machen Sie kleine Bewegungen basierend auf Benutzerbefehlen am seriellen Port. Vermeidet Bewegungen mit hoher Geschwindigkeit auf dem Mechanismus smoothMoveTwist(); smoothMoveTilt(); } } // Geben Sie ein wenig Zeitverzögerung (GIVE_BACK_TIME);} // Schalten Sie das Servo-Tracking ein. // An die Servomotoren anhängen gServoTwist.attach (O_TWIST_SERVO_PIN); gServoTilt.attach(O_TILT_SERVO_PIN); // Grüne LED einschalten und rote LED ausschalten digitalWrite (O_GREEN_LED_PIN, HIGH); digitalWrite (O_RED_LED_PIN, LOW); // Ergebnisse posten Serial.println ("Servos aktiviert");} // Servo-Tracking deaktivierenvoid disableTracking () { gRunning =false; gTrackToLightEnabled =false; // Von Servomotoren trennen gServoTwist.detach (); gServoTilt.detach(); // Move-Befehl bereinigen und In-Process (IP)-Variablen verschieben gServoTwistPositionCommand =gServoTwist.read(); gServoTwistMoveIP =false; // Move-Befehl bereinigen und In-Process (IP)-Variablen verschieben gServoTiltPositionCommand =gServoTilt.read(); gServoTiltMoveIP =false; // Rote LED einschalten, grüne LED ausschalten digitalWrite (O_RED_LED_PIN, HIGH); digitalWrite (O_GREEN_LED_PIN, LOW); // Ergebnisse posten Serial.println ("Servos deaktiviert");} // Track to light basierend auf Photosensor-Wertenvoid trackToLightSensors () { float fTop; float fBottom; float fLinks; schweben fRight; int iTwistMoveCommand; int iTiltMoveCommand; int iMoveAmount; // Initialisieren // Die Variable unten bestimmt, wie viele Grad der möglichen Bewegung für beide Servos // pro Scan des Programms. Diese Zahl in Kombination mit der globalen Konstanten //mit dem Namen 'GIVE_BACK_TIME' bestimmt, wie aggressiv die Züge sein werden. iMoveAmount =5; // Aktuelle Servopositionen abrufen iTwistMoveCommand =gServoTwist.read (); iTiltMoveCommand =gServoTilt.read(); // Durchschnitte abrufen fTop =AverageTopTwoSensors (); fBottom =AverageBottomTwoSensors(); fLeft =AverageLeftTwoSensors(); fRight =AverageRightTwoSensors(); // Drehbewegung berechnen if (fLeft> fRight) { // Positive Bewegung bewegen iTwistMoveCommand +=iMoveAmount; aufrechtzuerhalten. Sonst if (fRight> fLeft) {//Verschieben negatives iTwistMoveCommand -=iMoveAmount; } else { //Dasselbe. nicht bewegen} // Neigungsbewegung berechnen if (fTop>
 fBottom) { // Positive Bewegung bewegen iTiltMoveCommand +=iMoveAmount; aufrechtzuerhalten. Sonst if (fBottom> fTop) {//Verschiebe negativen iTiltMoveCommand -=iMoveAmount; } else { //Dasselbe. nicht bewegen} // Grenzen überprüfen Twist Servo Bewegungsbefehl if (iTwistMoveCommand <0) { iTwistMoveCommand =0; } if (iTwistMoveCommand> 179) { iTwistMoveCommand =179; } // Grenzen prüfen Neigungsservo-Bewegungsbefehl if (iTiltMoveCommand <45) { iTiltMoveCommand =45; } if (iTiltMoveCommand> 135) { iTiltMoveCommand =135; } //Bewegungen ausführen gServoTwist.write(iTwistMoveCommand); gServoTilt.write(iTiltMoveCommand); // Ergebnisse posten if (gVerboseDiagMode ==true) {Serial.println ("tl, tr, bl, br, oberer Mittelwert, unterer Mittelwert, linker Mittelwert, rechter Mittelwert, Drehbewegung, Neigungsbewegung:"); 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); } } // Fotowiderstandswerte in globale Variablen lesenvoid readPhotoResistors () {//Werte werden skaliert 0-1024 gLDR1 =analogRead (I_LDR1_PIN); gLDR2 =analogRead(I_LDR2_PIN); gLDR3 =analogRead(I_LDR3_PIN); gLDR4 =analogRead(I_LDR4_PIN);} // Wenn die Servos in eine Position befohlen werden, bewegen sie sich mit hoher Geschwindigkeit. // Zu schnell wirkt sich möglicherweise auf die mechanische Struktur aus, die das Solarpanel und die Lichtsensorplattform hält und bewegt. Diese Routine nimmt einen "Bewegungsbefehl" // und führt kleine inkrementelle Bewegungen aus, bis sich der Servo an der gewünschten Position befindet. // Diese Routine ist für den an der Basis montierten Drehservomotorvoid smoothMoveTwist () { int iCurrentPos; int iMoveAmountPerScan; int iNewMoveCommand; // Bewegungsbetrag pro Scan in Grad einstellen. //Kombination dieser Variablen und globaler const 'GIVE_BACK_TIME' bestimmen die Gesamtbewegungsgeschwindigkeit iMoveAmountPerScan =1; // Aktuelle Position ermitteln iCurrentPos =gServoTwist.read(); //Sind wir in Position? if (iCurrentPos ==gServoTwistPositionCommand) { gServoTwistMoveIP =false; Rückkehr; } else { gServoTwistMoveIP =true; } // Beginnen Sie dort, wo wir uns gerade befinden iNewMoveCommand =iCurrentPos; //Bewegungsbetrag bestimmen if (iCurrentPos  179) { iNewMoveCommand =179; } // gServoTwist.write (iNewMoveCommand) verschieben; // Ergebnisse posten, wenn (gVerboseDiagMode ==true) {//todo:Serial.print ("Twist Servo Move (this move, total):"); Serial.print (iNewMoveCommand); Serial.print (", "); Serial.println (gServoTwistPositionCommand); }} // Wenn die Servos in eine Position befohlen werden, bewegen sie sich mit hoher Geschwindigkeit. // Zu schnell wirkt sich möglicherweise auf die mechanische Struktur aus, die das Solarpanel und die Lichtsensorplattform hält und bewegt. Diese Routine nimmt einen "Bewegungsbefehl" // und führt kleine inkrementelle Bewegungen aus, bis sich der Servo an der gewünschten Position befindet. // Diese Routine ist für den halterungsmontierten Kippservomotorvoid smoothMoveTilt () { int iCurrentPos; int iMoveAmountPerScan; int iNewMoveCommand; // Bewegungsbetrag pro Scan in Grad einstellen. //Kombination dieser Variablen und globaler const 'GIVE_BACK_TIME' bestimmen die Gesamtbewegungsgeschwindigkeit iMoveAmountPerScan =1; // Aktuelle Position ermitteln iCurrentPos =gServoTilt.read(); //Sind wir in Position? if (iCurrentPos ==gServoTiltPositionCommand) { gServoTiltMoveIP =false; Rückkehr; } else { gServoTiltMoveIP =true; } // Beginnen Sie dort, wo wir uns gerade befinden iNewMoveCommand =iCurrentPos; //Bewegungsbetrag bestimmen if (iCurrentPos  179) { iNewMoveCommand =179; } // gServoTilt.write (iNewMoveCommand) verschieben; // Ergebnisse posten, wenn (gVerboseDiagMode ==true) {//todo:Serial.print ( "Neigungsservobewegung (diese Bewegung, insgesamt):"); Serial.print (iNewMoveCommand); Serial.print (", "); Serial.println (gServoTiltPositionCommand); }} // Nehmen Sie den mathematischen Durchschnitt der beiden LDR am oberen Rand des Panelsfloat AverageTopTwoSensors () { float fAvg; // Mathe fAvg =(gLDR1 + gLDR2) / 2,0; return fAvg;} // Nehmen Sie den mathematischen Durchschnitt der beiden LDR am unteren Rand des Panelsfloat AverageBottomTwoSensors () { float fAvg; // Mathe fAvg =(gLDR3 + gLDR4) / 2,0; return fAvg;} // Den mathematischen Durchschnitt der beiden LDRs auf der linken Seite des Panels nehmenfloat AverageLeftTwoSensors() { float fAvg; // Mathe fAvg =(gLDR1 + gLDR3) / 2,0; return fAvg;} // Den mathematischen Durchschnitt der beiden LDRs rechts vom Panel nehmenfloat AverageRightTwoSensors() { float fAvg; //Mathe fAvg =(gLDR2 + gLDR4) / 2,0; return fAvg;}//Empfingene Nachrichten von der seriellen Schnittstelle verarbeiten//Eingabeparameter iControlCode ist der von der zu verarbeitenden seriellen Schnittstelle empfangene Wert//Die ersten beiden Ziffern sind der Steuerbefehl, die restlichen drei sind der Wert zur Verarbeitungvoid processSerialMessage(int iControlCode){ int iControlCommand; int iControlValue; //Befehl und Wert berechnen iControlCommand =iControlCode / 1000; iControlValue =iControlCode % 1000; // Befehl und Wert melden Serial.print ( "Steuercode:"); Serial.println (iControlCode); Serial.print ( "Steuerbefehl:"); Serial.println (iControlCommand); Serial.print("Kontrollwert:"); Serial.println (iControlValue); //Verschiedene Befehlskategorie if (iControlCommand ==10) { if (iControlValue ==0) { gVerboseDiagMode =true; digitalWrite (O_BLUE_LED_PIN, HIGH); Serial.println ( "Diagnosemodus gestartet"); aufrechtzuerhalten. Sonst if (iControlValue ==1) { gVerboseDiagMode =false; digitalWrite (O_BLUE_LED_PIN, LOW); Serial.println ( "Diagnosemodus gestoppt"); aufrechtzuerhalten. Sonst if (iControlValue ==2) { reportProductInfo(); aufrechtzuerhalten. Sonst if (iControlValue ==3) {//Rote LED auf digitalWrite (O_RED_LED_PIN, HIGH); Serial.println ("rote LED an"); aufrechtzuerhalten. Sonst if (iControlValue ==4) {//Rote LED aus digitalWrite (O_RED_LED_PIN, LOW); Serial.println ("rote LED aus"); aufrechtzuerhalten. Sonst if (iControlValue ==5) {//Grüne LED auf digitalWrite (O_GREEN_LED_PIN, HIGH); Serial.println ("grüne LED an"); aufrechtzuerhalten. Sonst if (iControlValue ==6) {//Grüne LED aus digitalWrite (O_GREEN_LED_PIN, LOW); Serial.println ("grüne LED aus"); aufrechtzuerhalten. Sonst if (iControlValue ==7) {// Blaue LED auf digitalWrite (O_BLUE_LED_PIN, HIGH); Serial.println ("blaue LED an"); aufrechtzuerhalten. Sonst if (iControlValue ==8) {// Blaue LED aus digitalWrite (O_BLUE_LED_PIN, LOW); Serial.println ("blaue LED aus"); aufrechtzuerhalten. Sonst if (iControlValue ==9) {// LDR1-Wert anzeigen Serial.print ("LDR1-Wert:"); Serial.println (gLDR1); aufrechtzuerhalten. Sonst if (iControlValue ==10) {// LDR2-Wert anzeigen Serial.print ("LDR2-Wert:"); Serial.println (gLDR2); aufrechtzuerhalten. Sonst if (iControlValue ==11) {// LDR3-Wert anzeigen Serial.print ("LDR3-Wert:"); Serial.println (gLDR3); aufrechtzuerhalten. Sonst if (iControlValue ==12) {// LDR4-Wert anzeigen Serial.print ("LDR4-Wert:"); Serial.println (gLDR4); aufrechtzuerhalten. Sonst if (iControlValue ==13) {//Tracking-Modus einschalten enableTracking(); aufrechtzuerhalten. Sonst if (iControlValue ==14) {// Tracking-Modus deaktivieren disableTracking (); } else if (iControlValue ==19) { if (gRunning ==true &&gServoTwistMoveIP ==false &&gServoTiltMoveIP ==false) { gServoTwistPositionCommand =90; gServoTiltPositionCommand =90; Serial.println ( "Twist- und Tilt-Servos auf 90 Grad befohlen"); } } else if (iControlValue ==21) { if (gRunning ==true) { gTrackToLightEnabled =true; Serial.println ("Track to light source enabled"); } } else if (iControlValue ==22) { gTrackToLightEnabled =false; Serial.println ("Track to Lichtquelle deaktiviert"); aufrechtzuerhalten. Else { Serial.print ( "ungültiger Kontrollwert:"); Serial.println (iControlValue); } } //Servo1 (Twist) Befehlskategorie if (iControlCommand ==11) { if (iControlValue>=0 &&iControlValue <=179) { //Servo1 in Position bewegen if (gRunning ==true &&gServoTwistMoveIP ==false) { gServoTwistPositionCommand =iControlValue; gServoTwistMoveIP =true; Serial.print ( "Move Twist Servo-Befehl:"); Serial.println (gServoTwistPositionCommand); } } else { Serial.print ( "ungültiger Kontrollwert:"); Serial.println (iControlValue); aufrechtzuerhalten. gServoTiltMoveIP ==false) { gServoTiltPositionCommand =iControlValue; gServoTiltMoveIP =true; Serial.print ("Bewegen Sie den Neigungsservobefehl:"); Serial.println (gServoTiltPositionCommand); aufrechtzuerhalten. Else {Serial.print("Neigungsservo nicht aktiviert oder Bewegung im Gange,"); Serial.print (gRunning); Serial.print (", "); Serial.println (gServoTiltMoveIP); } } else { Serial.print ( "ungültiger Kontrollwert:"); Serial.println (iControlValue); } } // Ende der Anforderungszeichenfolge Serial.println ("-----");} // Führen Sie eine Abfolge von Schritten zum Selbsttest der Funktionen aus, aktivieren Sie die Servos und geben Sie den Lichtverfolgungsmodusvoid startup () { Int iDelay; // iDelay initialisieren =500; // App-Infobericht anzeigenProductInfo(); Verzögerung (iDelay); // Rote LED einschalten processSerialMessage(10003); Verzögerung (iDelay); // Rote LED ausschalten, grüne LED einschalten processSerialMessage(10004); processSerialMessage(10005); Verzögerung (iDelay); // Grüne LED ausschalten, blaue LED einschalten processSerialMessage(10006); processSerialMessage(10007); Verzögerung (iDelay); // Blaue LED ausschalten, Fotowiderstandswerte anzeigen (alle vier) processSerialMessage (10008); processSerialMessage(10009); processSerialMessage(10010); processSerialMessage(10011); processSerialMessage(10012); Verzögerung (iDelay); // Servos aktivieren enableTracking (); Verzögerung (iDelay); // Servos in Ausgangsposition bewegen processSerialMessage (10019); Verzögerung (iDelay); // Servos deaktivieren disableTracking (); // Verabschieden Sie sich von Serial.println ("Startsequenz abgeschlossen");} // Produktinformationen an die serielle Schnittstelle sendenvoid reportProductInfo () { // Produkt- und andere Informationen an die serielle Schnittstelle melden Serial.println ("q Version 2" ); Serial.println ("Tucson, Arizona, USA"); Serial.println ("Mai 2018"); Serial.print ("Prüfsumme"); Serial.println("58BA-D969-2F82-08FD-2078-2777-396D-E1AA");}

Kundenspezifische Teile und Gehäuse

q2_assembly_details_RCbi893qzA.zip

Schaltpläne

q2_schematic_TVp7kakwNa.fzz

Herstellungsprozess

  1. Solarheizung
  2. Solarzelle
  3. Echtzeit-Datenerfassung von Solarmodulen mit Arduino
  4. Smart Blinds
  5. Internet der Dinge (IoT)-basierter Solartracker
  6. SmartPostBox
  7. Zweiachsiges Solartracker-Panel mit automatischem und manuellem Modus
  8. Solarenergie verstehen
  9. Solarpanel:Qualitätsprobleme und wichtige Kontrollpunkte
  10. Herstellungsprozess von Solarmodulen:Wie wird ein Solarmodul hergestellt?