Plataforma de painel solar de rastreamento de luz servo-controlada
Componentes e suprimentos
| | × | 4 | |
| Adafruit Flora RGB Neopixel LEDs - Pacote de 4 | | × | 1 | |
| SparkFun Botão de pressão 12 mm | | × | 2 | |
| | × | 1 | |
| | × | 1 | |
| RobotGeek Servo do robô de 180 graus | | × | 2 | |
| | × | 6 | |
| | × | 1 | |
| | × | 2 | |
| painel solar (80 mm x 80 mm) | | × | 1 | |
Aplicativos e serviços online
| | |
| Microsoft Excel para documentação e notas | | |
Sobre este projeto
Esta é outra implementação do uso de dois servos de 180 graus e quatro foto-resistores para ser capaz de rastrear um pequeno painel solar para se alinhar à área de maior intensidade de luz.
Os motores fazem pequenos movimentos para tentar apontar o painel solar para a luz mais forte.
Há também um LED multicolorido para indicar se o sistema está habilitado ou não. E dois botões de pressão para habilitar / desabilitar os motores.
Existem algumas rotinas que podem ser usadas para mover os motores para as posições comandadas. Os comandos são via interface de porta serial e uma série de códigos / comandos numéricos que podem ser enviados para o Arduino Uno.
Os comandos de movimento independentes são programados de forma a fornecer movimentos (um pouco) suaves em vez de comandos de posição imediatos que fazem com que o mecanismo mecânico se mova violentamente.
Código
- código do segundo trimestre
Q2 código Arduino
// Scott Mangiacotti // Tucson, Arizona, EUA // Maio de 2018 // 2º trimestre // Versão 2.0 # inclui // Constantsint const GIVE_BACK_TIME =125; // Constantes para inputsint const I_RED_BUTTON_PIN =4; int const I_GREEN_BUTTON_PIN =2; int const I_LDR1_PIN =A3; // ponto superior esquerdo const I_LDR2_PIN =A2; // canto superior direito const I_LDR3_PIN =A1; // inferior esquerdoint const I_LDR4_PIN =A0; // canto inferior direito // Constantes para outputsint 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; // Variáveis globais falsebool gRunning =false;; bool gVerboseDiagMode =false; Servo gServoTwist; int gServoTwistPositionCommand; // positionbool comandado gServoTwistMoveIP; // mover em andamentoServo gServoTilt; bool gServoTiltMoveIP; // movimento em andamentoint gServoTiltPositionCommand; // positionint comandado gLDR1; int gLDR2; int gLDR3; int gLDR4; // Executa oncevoid setup () {// Abra uma porta serial Serial.begin (9600); // Configurar entradas digitais pinMode (I_RED_BUTTON_PIN, INPUT); pinMode (I_GREEN_BUTTON_PIN, INPUT); // Configura as saídas digitais pinMode (O_RED_LED_PIN, OUTPUT); pinMode (O_GREEN_LED_PIN, OUTPUT); pinMode (O_BLUE_LED_PIN, OUTPUT); // Executa a rotina de inicialização startup ();} // Executa o loop continuamentevoid () {// Processamento de recebimento de mensagem da porta serial if (Serial.available ()> 0) {int iControlCode; iControlCode =Serial.parseInt (); processSerialMessage (iControlCode); } // Ler botão verde int iGreenButton; iGreenButton =digitalRead (I_GREEN_BUTTON_PIN); if (iGreenButton ==HIGH &&gRunning ==false) {enableTracking (); gTrackToLightEnabled =true; } // Lê o botão vermelho int iRedButton; iRedButton =digitalRead (I_RED_BUTTON_PIN); if (iRedButton ==HIGH &&gRunning ==true) {disableTracking (); } // Lê toda a instrumentação em variáveis globais readPhotoResistors (); averageTopTwoSensors (); averageBottomTwoSensors (); // Ajuste as posições dos servos de acordo com a luz nos fotorresistores if (gRunning ==true) {if (gTrackToLightEnabled ==true) {// Faça pequenos movimentos de servos com base nos níveis de luz dos fotorresistores trackToLightSensors (); } else {// Faça pequenos movimentos com base nos comandos do usuário na porta serial. Evita movimentos de alta velocidade no mecanismo smoothMoveTwist (); smoothMoveTilt (); }} // Atrasa um pouco de tempo atrás (GIVE_BACK_TIME);} // Liga servo trackingvoid enableTracking () {// Define variáveis globais para que outras partes do programa saibam que os motores estão prontos para rodar gRunning =true; // Anexar aos servo motores gServoTwist.attach (O_TWIST_SERVO_PIN); gServoTilt.attach (O_TILT_SERVO_PIN); // Liga o LED verde e apaga o LED vermelho digitalWrite (O_GREEN_LED_PIN, HIGH); digitalWrite (O_RED_LED_PIN, LOW); // Publicar resultados Serial.println ("servos enabled");} // Desativar servo trackingvoid disableTracking () {gRunning =false; gTrackToLightEnabled =false; // Separar dos servo motores gServoTwist.detach (); gServoTilt.detach (); // Limpa o comando de movimentação e as variáveis em processo (IP) de movimentação gServoTwistPositionCommand =gServoTwist.read (); gServoTwistMoveIP =false; // Limpe o comando de movimento e mova as variáveis em processo (IP) gServoTiltPositionCommand =gServoTilt.read (); gServoTiltMoveIP =false; // Liga o LED vermelho, apaga o LED verde digitalWrite (O_RED_LED_PIN, HIGH); digitalWrite (O_GREEN_LED_PIN, LOW); // Publicar resultados Serial.println ("servos disabled");} // Rastreie até a luz com base nos valores do fotossensorvoid trackToLightSensors () {float fTop; float fBottom; float fLeft; float fRight; int iTwistMoveCommand; int iTiltMoveCommand; int iMoveAmount; // Inicializar // A variável abaixo determina quantos graus de movimento potencial para ambos os servos // por varredura do programa. Este número em combinação com a constante global // chamada 'GIVE_BACK_TIME' determina o quão agressivo os movimentos serão. iMoveAmount =5; // Obtenha as posições atuais do servo iTwistMoveCommand =gServoTwist.read (); iTiltMoveCommand =gServoTilt.read (); // Obter médias fTop =averageTopTwoSensors (); fBottom =averageBottomTwoSensors (); fLeft =averageLeftTwoSensors (); fRight =averageRightTwoSensors (); // Calcula o movimento de torção if (fLeft> fRight) {// Move positivo iTwistMoveCommand + =iMoveAmount; } else if (fRight> fLeft) {// Mover iTwistMoveCommand negativo - =iMoveAmount; } else {// Mesmo. não se mova} // Calcula o movimento de inclinação if (fTop>
fBottom) {// Move positivo iTiltMoveCommand + =iMoveAmount; } else if (fBottom> fTop) {// Mover iTiltMoveCommand negativo - =iMoveAmount; } else {// Mesmo. não se mova} // Comando de movimento do servo de verificação de limites if (iTwistMoveCommand <0) {iTwistMoveCommand =0; } if (iTwistMoveCommand> 179) {iTwistMoveCommand =179; } // Comando de movimento do servo de verificação de limites if (iTiltMoveCommand <45) {iTiltMoveCommand =45; } se (iTiltMoveCommand> 135) {iTiltMoveCommand =135; } // Executa movimentos gServoTwist.write (iTwistMoveCommand); gServoTilt.write (iTiltMoveCommand); // Publicar resultados if (gVerboseDiagMode ==true) {Serial.println ("tl, tr, bl, br, média superior, média inferior, média esquerda, média direita, movimento de torção, movimento de inclinação:"); 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); }} // lê os valores do fotorresistor em variáveis globaisvoid readPhotoResistors () {// Os valores vêm em escala 0-1024 gLDR1 =analogRead (I_LDR1_PIN); gLDR2 =analogRead (I_LDR2_PIN); gLDR3 =analogRead (I_LDR3_PIN); gLDR4 =analogRead (I_LDR4_PIN);} // Quando os servos são comandados para uma posição, eles se movem em uma velocidade rápida.//Muito rápido afetará potencialmente a estrutura mecânica que mantém e move // o painel solar e a plataforma do sensor de luz. Essa rotina recebe um "comando de movimento" // e faz pequenos movimentos incrementais até que o servo esteja na posição desejada.// Esta rotina é para o servo motor de torção montado na base smoothMoveTwist () {int iCurrentPos; int iMoveAmountPerScan; int iNewMoveCommand; // Defina a quantidade de movimento por varredura em graus. // Combinação desta variável e const global 'GIVE_BACK_TIME' determina a velocidade geral de movimento iMoveAmountPerScan =1; // Determina a posição atual iCurrentPos =gServoTwist.read (); // Estamos em posição? if (iCurrentPos ==gServoTwistPositionCommand) {gServoTwistMoveIP =false; Retorna; } else {gServoTwistMoveIP =true; } // Comece onde estamos atualmente em iNewMoveCommand =iCurrentPos; // Determinar a quantidade de movimentação if (iCurrentPos 179) {iNewMoveCommand =179; } // Mover gServoTwist.write (iNewMoveCommand); // Publicar resultados if (gVerboseDiagMode ==true) {// todo:Serial.print ("Movimento de torção do servo (este movimento, total):"); Serial.print (iNewMoveCommand); Serial.print (","); Serial.println (gServoTwistPositionCommand); }} // Quando os servos são comandados para uma posição, eles se movem em uma velocidade rápida .//Muito rápido afetará potencialmente a estrutura mecânica que mantém e move // o painel solar e a plataforma do sensor de luz. Esta rotina recebe um "comando de movimento" // e faz pequenos movimentos incrementais até que o servo esteja na posição desejada. int iMoveAmountPerScan; int iNewMoveCommand; // Defina a quantidade de movimento por varredura em graus. // Combinação desta variável e const global 'GIVE_BACK_TIME' determina a velocidade geral de movimento iMoveAmountPerScan =1; // Determina a posição atual iCurrentPos =gServoTilt.read (); // Estamos em posição? if (iCurrentPos ==gServoTiltPositionCommand) {gServoTiltMoveIP =false; Retorna; } else {gServoTiltMoveIP =true; } // Comece onde estamos atualmente em iNewMoveCommand =iCurrentPos; // Determinar a quantidade de movimentação if (iCurrentPos 179) {iNewMoveCommand =179; } // Mover gServoTilt.write (iNewMoveCommand); // Publicar resultados if (gVerboseDiagMode ==true) {// todo:Serial.print ("Movimento do servo de inclinação (este movimento, total):"); Serial.print (iNewMoveCommand); Serial.print (","); Serial.println (gServoTiltPositionCommand); }} // Pegue a média matemática dos dois LDR no topo do panelfloat averageTopTwoSensors () {float fAvg; // Math fAvg =(gLDR1 + gLDR2) / 2.0; return fAvg;} // Pega a média matemática dos dois LDR na parte inferior do panelfloat averageBottomTwoSensors () {float fAvg; // Math fAvg =(gLDR3 + gLDR4) / 2.0; return fAvg;} // Pega a média matemática dos dois LDR à esquerda do panelfloat averageLeftTwoSensors () {float fAvg; // Math fAvg =(gLDR1 + gLDR3) / 2.0; return fAvg;} // Pega a média matemática dos dois LDR à direita do panelfloat averageRightTwoSensors () {float fAvg; // Math fAvg =(gLDR2 + gLDR4) / 2.0; return fAvg;} // Processar mensagens recebidas da interface da porta serial // Parâmetro de entrada iControlCode é o valor recebido da porta serial a ser processado // Os primeiros dois dígitos são o comando de controle, os três restantes são o valor para processvoid processSerialMessage (int iControlCode) {int iControlCommand; int iControlValue; // Calcula o comando e o valor iControlCommand =iControlCode / 1000; iControlValue =iControlCode% 1000; // Reportar comando e valor Serial.print ("código de controle:"); Serial.println (iControlCode); Serial.print ("comando de controle:"); Serial.println (iControlCommand); Serial.print ("valor de controle:"); Serial.println (iControlValue); // Categoria de comando diverso if (iControlCommand ==10) {if (iControlValue ==0) {gVerboseDiagMode =true; digitalWrite (O_BLUE_LED_PIN, HIGH); Serial.println ("modo de diagnóstico iniciado"); } else if (iControlValue ==1) {gVerboseDiagMode =false; digitalWrite (O_BLUE_LED_PIN, LOW); Serial.println ("modo de diagnóstico interrompido"); } else if (iControlValue ==2) {reportProductInfo (); } else if (iControlValue ==3) {// LED vermelho no digitalWrite (O_RED_LED_PIN, HIGH); Serial.println ("led vermelho aceso"); } else if (iControlValue ==4) {// LED vermelho desligado digitalWrite (O_RED_LED_PIN, LOW); Serial.println ("led vermelho apagado"); } else if (iControlValue ==5) {// LED verde no digitalWrite (O_GREEN_LED_PIN, HIGH); Serial.println ("led verde aceso"); } else if (iControlValue ==6) {// LED verde apagado digitalWrite (O_GREEN_LED_PIN, LOW); Serial.println ("led verde apagado"); } else if (iControlValue ==7) {// LED azul no digitalWrite (O_BLUE_LED_PIN, HIGH); Serial.println ("led azul aceso"); } else if (iControlValue ==8) {// LED azul desligado digitalWrite (O_BLUE_LED_PIN, LOW); Serial.println ("led azul apagado"); } else if (iControlValue ==9) {// Exibir valor LDR1 Serial.print ("valor LDR1:"); Serial.println (gLDR1); } else if (iControlValue ==10) {// Exibir valor LDR2 Serial.print ("valor LDR2:"); Serial.println (gLDR2); } else if (iControlValue ==11) {// Exibir valor LDR3 Serial.print ("valor LDR3:"); Serial.println (gLDR3); } else if (iControlValue ==12) {// Exibir valor LDR4 Serial.print ("valor LDR4:"); Serial.println (gLDR4); } else if (iControlValue ==13) {// Ativar o modo de rastreamento enableTracking (); } else if (iControlValue ==14) {// Desativa o modo de rastreamento disableTracking (); } else if (iControlValue ==19) {if (gRunning ==true &&gServoTwistMoveIP ==false &&gServoTiltMoveIP ==false) {gServoTwistPositionCommand =90; gServoTiltPositionCommand =90; Serial.println ("servos de torção e inclinação comandados a 90 graus"); }} 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 light source disabled"); } else {Serial.print ("valor de controle inválido:"); Serial.println (iControlValue); }} // Categoria do comando Servo1 (torção) if (iControlCommand ==11) {if (iControlValue> =0 &&iControlValue <=179) {// Mova o servo1 para a posição if (gRunning ==true &&gServoTwistMoveIP ==false) { gServoTwistPositionCommand =iControlValue; gServoTwistMoveIP =true; Serial.print ("Mover comando servo de torção:"); Serial.println (gServoTwistPositionCommand); }} else {Serial.print ("valor de controle inválido:"); Serial.println (iControlValue); }} // Categoria do comando Servo2 (inclinação) if (iControlCommand ==12) {if (iControlValue> =0 &&iControlValue <=179) {// Mova servo2 para a posição // Mova servo1 para a posição if (gRunning ==true &&gServoTiltMoveIP ==false) {gServoTiltPositionCommand =iControlValue; gServoTiltMoveIP =true; Serial.print ("Mover comando servo de inclinação:"); Serial.println (gServoTiltPositionCommand); } else {Serial.print ("servo de inclinação não habilitado ou movimento em andamento,"); Serial.print (gRunning); Serial.print (","); Serial.println (gServoTiltMoveIP); }} else {Serial.print ("valor de controle inválido:"); Serial.println (iControlValue); }} // Fim da string de solicitação Serial.println ("-----");} // Executar uma sequência de etapas para funções de autoteste, habilitar servos e inserir o modevoid de rastreamento de luz startup () {int iDelay; // Inicializar iDelay =500; // Exibir informações do aplicativo reportProductInfo (); atraso (iDelay); // Liga o LED vermelho processSerialMessage (10003); atraso (iDelay); // Desligue o LED vermelho, ligue o LED verde processSerialMessage (10004); processSerialMessage (10005); atraso (iDelay); // Desligue o LED verde, ligue o LED azul processSerialMessage (10006); processSerialMessage (10007); atraso (iDelay); // Desliga o LED azul, exibe os valores do resistor fotográfico (todos os quatro) processSerialMessage (10008); processSerialMessage (10009); processSerialMessage (10010); processSerialMessage (10011); processSerialMessage (10012); atraso (iDelay); // Habilita servos enableTracking (); atraso (iDelay); // Mova os servos para a posição inicial processSerialMessage (10019); atraso (iDelay); // Desabilita servos disableTracking (); // Diga adeus Serial.println ("seqüência de inicialização concluída");} // Envie informações do produto para o portvoid serial reportProductInfo () {// Relate o produto e outras informações para a porta serial Serial.println ("q versão 2" ); Serial.println ("tucson, arizona usa"); Serial.println ("maio de 2018"); Serial.print ("checksum"); Serial.println ("58BA-D969-2F82-08FD-2078-2777-396D-E1AA");}
Peças personalizadas e gabinetes
q2_assembly_details_RCbi893qzA.zip Esquemas
q2_schematic_TVp7kakwNa.fzz