lunes, 1 de abril de 2019

NORBA STATION 1: captación de energía solar fotovoltaica

Un grupo de alumnos de 4º de ESO están desarrollando un sistema para captar energía solar, almacenarla y posteriormente usarla, el cual debe disponer de un mecanismo que permita orientarse automáticamente para maximizar la obtención de energía. Para la realización del mismo se utilizarán una placa solar policristalina, cuatro fotorresistencias, dos servomotores y una placa arduino de control, así como otros componentes básicos tales como resistencias, cableado, protoboard, pegamento, y materiales reciclados en general. Además, con vistas a probar el rendimiento del sistema, se utilizarán también voltímetros, amperímetros y baterías, entre otros elementos.

Placa solar fotovoltaica
Fotorresistencia
Servomotor
Previa a la creación del sistema, el cual aún no está finalizado, se ha realizado un estudio preliminar de los distintos componentes a utilizar. Para ello se ha empleado, como en otros proyectos, el simulador proporcionado por Tinkercad. Posteriormente se ha dividido el proyecto en tres partes bien diferenciadas:
  1. Sub-sistema motor para el movimiento de la placa solar, el cual consta de dos servomotores que permiten dotar al mismo de dos grados de libertad (giro de 360 grados sobre una superficie horizontal, y giro de unos 170 grados en el plano vertical), y de distintas estructuras conectadas a los mismos capaces de sujetar la placa y moverla de forma eficiente.
    Un primer esbozo de la estructura de este subsistema se ha realizado mediante el software de diseño CAD de Tinkercad.
    Diseño CAD del sistema motor.
    Basándose en ese diseño, posteriormente se ha realizado un primer prototipo del mismo usando materiales reciclados, el cual aún está en fase de revisión y mejora.
    Alumnos 4º ESO con su primer prototipo del sub-sistema motor.
    Sub-sistema motor del captador de energía solar en detalle.
    Para probar este sub-sistema se ha utilizado una placa Arduino y una serie de interruptores para la realización del movimiento de forma manual, mediante un diseño y un software de control muy parecido al utilizado para la construcción del primer NORBA JOINT o "Brazo Robot" del proyecto NorbaSky.
    Circuito creado para probar manualmente el movimiento de los dos servomotores.
    Completando el circuito de control manual mediante interruptores y Arduino.

    Sistema motor, aún sin placa solar, moviéndose mediante interruptores y Arduino.
    (Actualización febrero 2019). Los alumnos han creado un segundo prototipo para el sub-sistema motor, mucho más refinado, usando también materiales reciclados. Esta nueva mejora soluciona algunos problemas del primer prototipo tales como la "rotación invertida de la base" cuando la placa rotaba, añadiendo una base de granito reciclado procedente de escombros de una obra. También se ha añadido un "segundo eje de sujección" para la placa, la cual se desprendía frecuentemente del motor debido a su peso. No obstante, esta solución es provisional y puede ser mejorada.
    Segundo prototipo del sistema motor con mejoras importantes.
    Alumnos de 4º de ESO mostrando las mejoras del segundo prototipo.
    Segundo prototipo del sistema motor montado, pero no conectado a la circuitería de control.
    Probando funcionamiento del nuevo subsistema motor conectado a la circuitería de control.
    Además de las nuevas mejoras del prototipo físico de este nuevo sistema, se han realizado también importantes mejoras en el software de control, inicialmente casi idéntico al del primer NorbaJoint, destinadas a la optimización energética. Hasta el momento, el sistema estaba constantemente actualizando la posición de los motores, aunque los cambios de orientación fueran mínimos o incluso nulos. Esto suponía una vibración constante de los servos y un consumo eléctrico constante. Ahora se han introducido unas modificaciones tales que hacen que solamente se activen los servomotores cuando se detecta un cambio significativo de los ángulos de inclinación de los mismos, ahora mismo debidos únicamente a la pulsación de los botones de control y más adelante debidos a la información recibida del sistema de localización de luz.
    #include <Servo.h> 
    
    //Patillas control servos
    #define PinSERVO1 6
    #define PinSERVO2 5
    
    //Interruptores de control 
    #define BotonSube1 13
    #define BotonBaja1 7
    #define BotonSube2 12
    #define BotonBaja2 8
    
    //Angulos máximos y minimos de cada servo
    #define MAX1 180
    #define MIN1 0
    #define MAX2 125
    #define MIN2 55
    
    Servo Servo1, Servo2; //2 objetos servo, uno por motor
    int angulo1=(MIN1+MAX1)/2, angulo2=(MIN2+MAX2)/2, mover=0;
    
    void setup() {
      Servo1.attach(PinSERVO1);  // Asocia patilla PinSERVO1 a motor Servo1
      Servo2.attach(PinSERVO2);  // Asocia patilla PinSERVO2 a motor Servo2
      pinMode(BotonSube1,INPUT);
      pinMode(BotonBaja1,INPUT);
      pinMode(BotonSube2,INPUT);
      pinMode(BotonBaja2,INPUT);
      Servo1.write(angulo1); //Le dice a Servo1 (base) que gire a angulo1
      Servo2.write(angulo2); //Le dice a Servo2 (placa) que se incline a angulo2
      delay(500);
      }
    
    void loop() {
      if (digitalRead(BotonSube1)&&(angulo1<MAX1)){angulo1++; mover=1;}
      if (digitalRead(BotonSube2)&&(angulo2<MAX2)){angulo2++; mover=1;}
      if (digitalRead(BotonBaja1)&&(angulo1>MIN1)){angulo1--; mover=1;}
      if (digitalRead(BotonBaja2)&&(angulo2>MIN2)){angulo2--; mover=1;} 
      if (mover==1){ //Solo se manda mover al servo cuando se modifican angulos
          Servo1.write(angulo1);
          Servo2.write(angulo2); 
          delay(20);
          mover=0;
          }
      }
    
Código de control del Sistema de Motor .







  • (Actualización abril 2019) Sub-sistema de localización de luz, el cual consta de dos pares de fotorresistencias colocadas perpendicularmente una de la otra, formando todas ellas un ángulo de 45º con la placa solar. Estos componentes informarán acerca de la luz recibida. Con esta configuración, las cuatro fotorresistencias deberían recibir la misma cantidad de luz cuando la placa solar fotovoltaica se posicionase perpendicularmente a la fuente de luz (situación óptima).
    Para probar este sistema, se han creadon varios circuitos a partir de las citadas fotoresistencias además de varios leds como indicadores del punto de origen de la luz. Hemos tenido muchos problemas para conseguir que este sistema funcionase correctamente, ya que las LDR no se comportaban igual ante la misma luz, se producían numerosos ruidos esporádicos en las lecturas, los ángulos de incidencia de la luz sobre las mismas no afectaban a su comportamiento tanto como hubiéramos deseado, retardos en las lecturas, histiéresis,... Para más detalle, hemos creado una entrada en el blog en la que hemos explicado todos los problemas encontrados y cómo los hemos ido solucionando.
    Sistema de información de inclinación óptima de las cuatro fotorresistencias.
    #define VArr A2 //Lila
    #define HIzq A0 //Blanco
    #define VAba A1 //Gris
    #define HDer A3 //Azul
    
    #define HLedIzq 13 //Blanco
    #define HLedDer 10 //Azul
    #define VLedArr 11 //Lila
    #define VLedAba 12 //Gris
    
    #define BotonCalibrado 7
    
    
    #define NivelesCalibrado 2
    
    #define PesoNuevoMinMax 90
    #define PesoViejoMinMax 10
    
    
    long int MinLuz[4]={1024,1024,1024,1024};  //Valor inicial a corregir en calibrado
    long int MaxLuz[4]={0,0,0,0};              //Valor inicial a corregir en calibrado
    
    
    int foto_res[4]={HIzq,VAba,VArr,HDer};
    
    void setup() {
      long int luz;
      char cadena[20];
      
      Serial.begin(9600);
      for (int x=0;x<4;x++){ 
        pinMode(foto_res[x], INPUT); 
        };
      pinMode(BotonCalibrado,INPUT);
     
      
      //Proceso de calibrado, buscando luz máxima y mínima  
      while (digitalRead(BotonCalibrado)==LOW) { //Calibrado hasta pulsar botón
        Serial.println("");
        Serial.print(dtostrf((float)millis()/1000, 6, 1, cadena));
        for (int x=0;x<4;x++) {  
            luz=analogRead(foto_res[x]); 
            MinLuz[x]=(luz<MinLuz[x]?(luz*PesoNuevoMinMax+MinLuz[x]*PesoViejoMinMax)/100:MinLuz[x]); 
            MaxLuz[x]=(luz>MaxLuz[x]?(luz*PesoNuevoMinMax+MaxLuz[x]*PesoViejoMinMax)/100:MaxLuz[x]);
            Serial.print("----(LDR"+String(x)+":"+String(luz)+"("+String(map(luz,(int)MinLuz[x],(int)MaxLuz[x],0,NivelesCalibrado))+")  m:"+String(MinLuz[x])+" M:"+String(MaxLuz[x])+")");
            delay(10);
            }
        }
    }
    
    
    void loop() {
      int v[4];
      
      for (int x=0;x<4;x++) { v[x]=0; }
      for (int cont=0;cont<20;cont++){
          for (int x=0;x<4;x++) { 
              v[x]=v[x]+analogRead(foto_res[x]);
              }
          delay(20);
          }    
      for (int x=0;x<4;x++) { 
          v[x]=map(v[x]/20,MinLuz[x],MaxLuz[x],0,NivelesCalibrado); 
          }
      Serial.print( " Izq:"+String(v[0])+
                      " Der:"+String(v[3])+
                      " Arr:"+String(v[2])+
                      " Aba:"+String(v[1]));
      
      digitalWrite(HLedIzq, (v[0]>v[3]));  
      if (v[0]>v[3]) {Serial.print(" Torcer a izquierda.");} //VIzq>VDer
      
      digitalWrite(HLedDer, (v[3]>v[0]));  
      if (v[3]>v[0]) {Serial.print(" Torcer a derecha.");}  //VDer>Vizq
      
      digitalWrite(VLedArr, (v[1]>v[2]));  
      if (v[1]>v[2]) {Serial.print(" Torcer a abajo.");}    //HAba>HArr
      
      digitalWrite(VLedAba, (v[2]>v[1]));  
      if (v[2]>v[1]) {Serial.print(" Torcer a arriba.");}   //HArr>HAba
      Serial.println("");
    
      delay(100); 
    }
    
    
    Código de control del Sistema de Información de Orientación Optima.
  • Sistema completo incluyendo el "sub-sistema de localización de luz", el "sub-sistema motor" y el software de procesamiento que transforma la información procedente del primero en actuaciones sobre el segundo. En nuestro diseño definitivo hemos utilizado unos servos de 9V alimentados por pilas de 9V, pero cuyo rendimiento caía en cuanto el voltaje bajaba minimamente. Para evitar el arruinarnos en pilas, finalmente nos decantamos por usar como alimentación un transformador de 12V de un router viejo. Por lo pronto, no hemos quemado los motores que están demostrando funcionar bastante bien. Pero por si acaso, incluimos una pequeña resistencia en el circuito para evitar problemas. 

  • Esquema hardware del sistema de completo de la placa solar autoorientable de forma autónoma.
    Construcción del sistema completo de captación de energía solar incluyendo los subsistemas de localización de fuente de luz y motor (vista 1).
    Construcción del sistema completo de captación de energía solar incluyendo los subsistemas de localización de fuente de luz y motor (vista 2).
     
    Sistema de captación de luz auto-orientable en funcionamiento, probándose con una linterna.
     
    #include <Servo.h>
    #define VArr A2 //Lila      ver
    #define HIzq A0 //Amarillo  ama
    #define VAba A1 //Gris      nar
    #define HDer A3 //Azul      azu
    
    #define NivelesCalibrado 2
    
    #define PesoNuevoMinMax 90 //Porcentaje aplicado a nuevo máximo o mínimo
    #define PesoViejoMinMax 10 //Porcentaje aplicado a viejo máximo o mínimo
    #define BotonCalibrado 7
    
    //Patillas control servos 
    #define PinSERVO1 6     //Servo Izquierda-derecha
    #define PinSERVO2 5     //Servo Arriba-Abajo
     
     
    //Angulos máximos y minimos de cada servo 
    #define MAX1 180
    #define MIN1 0
    #define MAX2 170
    #define MIN2 10
    
    
    Servo Servo1, Servo2; //2 objetos servo, uno por motor
    int angulo1=(MIN1+MAX1)/2, angulo2=(MIN2+MAX2)/2, mover=0;
    
    
    long int MinLuz[4]={1024,1024,1024,1024};  //Valor inicial a corregir en calibrado
    long int MaxLuz[4]={0,0,0,0};              //Valor inicial a corregir en calibrado
    
    int foto_res[4]={HIzq,VAba,VArr,HDer};
    void setup() {
      long int luz;  
      char cadena[20];
      
      Serial.begin(9600); 
     
      for (int x=0;x<4;x++){ 
        pinMode(foto_res[x], INPUT); 
        };
      pinMode(BotonCalibrado,INPUT);
     
      Servo1.attach(PinSERVO1);  // Asocia patilla PinSERVO1 a motor Servo1 Izq-Der
      Servo2.attach(PinSERVO2);  // Asocia patilla PinSERVO2 a motor Servo2 Arr-Aba
      Servo1.write(angulo1);     //Le dice a Servo1 (base) que gire a angulo1
      delay(500);
      Servo2.write(angulo2);     //Le dice a Servo2 (placa) que se incline a angulo2
      delay(500);  
     
      //Proceso de calibrado, buscando luz máxima y mínima   
      while (digitalRead(BotonCalibrado)==LOW) { //Calibrar hasta pulsar botón
        Serial.println("");
        Serial.print(dtostrf((float)millis()/1000, 6, 1, cadena)); 
        for (int x=0;x<4;x++) {  
            luz=analogRead(foto_res[x]); 
            MinLuz[x]=(luz<MinLuz[x]?(luz*PesoNuevoMinMax+MinLuz[x]*PesoViejoMinMax)/100:MinLuz[x]); 
            MaxLuz[x]=(luz>MaxLuz[x]?(luz*PesoNuevoMinMax+MaxLuz[x]*PesoViejoMinMax)/100:MaxLuz[x]);
            Serial.print("----(LDR"+String(x)+":"+String(luz)+"("+String(map(luz,(int)MinLuz[x],(int)MaxLuz[x],0,NivelesCalibrado))+")  m:"+String(MinLuz[x])+" M:"+String(MaxLuz[x])+")");        }
            } 
      }
    
    
    void loop() {
      int v[4];  
      for (int x=0;x<4;x++) { v[x]=0; }
      for (int cont=0;cont<20;cont++){
          for (int x=0;x<4;x++) { 
              v[x]=v[x]+analogRead(foto_res[x]);
              }
          }  
      for (int x=0;x<4;x++) { 
          v[x]=map(v[x]/20,MinLuz[x],MaxLuz[x],0,NivelesCalibrado); 
          }      
      Serial.print( " Izq:"+String(v[0])+
                    " Der:"+String(v[3])+
                    " Arr:"+String(v[2])+
                    " Aba:"+String(v[1]));                  
     
      // Moviendo a la izquierda (a la derecha si la placa está por el otro lado (angulo2>90)
      if (v[0]>v[3]  && (abs(v[3]-v[0])<=5) && angulo1<MAX1) { 
           //La parte de "abs" evita que por error de calibrado o hardware se mueva bruscamente el sistema
           Serial.print(" Torcer a izquierda. de "+String(angulo1)+" hasta "); 
           angulo1=angulo1+((angulo2<90)?1:-1); //90º es horizontal. Por debajo de 90, girar al oeste es a la izq. Pero por encima de 90, girar al oeste es la der
           Serial.print(String(angulo1)+". "); 
           mover=1;
           } //VIzq>VDer 
     
       // Moviendo a la derecha (a la izquierda si la placa está por el otro lado (angulo2>90) 
      if (v[3]>v[0] && (abs(v[3]-v[0])<=5) && angulo1>MIN1) { 
           //La parte de "abs" evita que por error de calibrado o hardware se mueva bruscamente el sistema 
           Serial.print(" Torcer a derecha de "+String(angulo1)+" hasta "); 
           angulo1=angulo1-((angulo2<90)?1:-1); //90º es horizontal. Por debajo de 90, girar al este es a la der. Pero por encima de 90, girar al este es la izq
           mover=1;
           Serial.print(String(angulo1)+". "); 
           }  //VDer>Vizq 
     
      // Moviendo hacia arriba 
      if (v[1]>v[2]  && (abs(v[1]-v[2])<=5) && angulo2<MAX2) {  
           //La parte de "abs" evita que por error de calibrado o hardware se mueva bruscamente el sistema
           Serial.print(" Torcer a abajo. de "+String(angulo2)+" hasta "); 
           mover=1;
           angulo2+=1;
           Serial.print(String(angulo2)+". ");
           }    //HAba>HArr 
     
      // Moviendo hacia abajo
      if (v[2]>v[1]  && (abs(v[1]-v[2])<=5) && angulo2>MIN2) {  
           //La parte de "abs" evita que por error de calibrado o hardware se mueva bruscamente el sistema
           Serial.print(" Torcer a arroba. de "+String(angulo2)+" hasta "); 
           mover=1;
           angulo2-=1;
           Serial.print(String(angulo2)+". "); 
           }   //HArr>HAba
     
      if (mover==1){ //Solo se manda mover al servo cuando se modifican angulos
          Servo1.write(angulo1);
          Servo2.write(angulo2); 
          mover=0;
          } 
     
      Serial.println(""); 
    }
    Código de control del sistema de captación de luz auto-orientable: azul (motor), naranja (orientación), amarillo (salida información por serie).

    No hay comentarios: