Go Down

Topic: Aide - Solar Tracker (Read 452 times) previous topic - next topic

Charly4343

Bonjour à tous, après de nombreuses recherches je bloque toujours sur des servomoteurs que j'utilise pour un projet de suiveur solaire.

Mon projet est le suivant:

- Un panneau photovoltaïque (6V 160mA) est fixé sur un bras qui possède 2 articulations et 2 servomoteurs permettent des rotations autour de ces articulations. 4 photorésistances sont disposées aux coins du panneau photovoltaïque et je récupère les valeurs des photorésistances, je calcule des moyennes et je fais bouger le PV en conséquence, de manière à suivre la lumière.
 
- Le PV est câblé à l'Arduino de manière à lui envoyer la tension, le courant et la puissance produite (que je calcule) pour ensuite être affichés sur un écran LCD.

- J'ai prévu 2 modes : un mode automatique, qui utilise les 4 capteurs pour suivre automatiquement la lumière et un mode manuel, qui permet de faire bouger le panneau à l'aide d'un joystick.
Mon projet fonctionne globalement assez bien mais j'ai encore 2 soucis à régler pour le finaliser:

1°) Je n'arrive pas à définir de limites pour mes servomoteurs !
Le servomoteur du haut ne doit pas effectuer de rotation de 0° à 180° car vu mon câblage, ça risque d'abîmer le montage (de 0° à 75° serait suffisant).
J'ai essayé de définir des limites (cfr code : servoLimitHigh et servoLimitLow) mais ça ne bloque pas mon servo .. j'ai également essayé via la commande monservo.attach(pin, min, max) mais encore une fois, le servo n'a aucune limitation. Auriez-vous une idée de la source de ce problème ?

2°) Pour passer du mode automatique au mode manuel, j'ai prévu une condition en utilisant le bouton poussoir du joystick du genre :
if ( BP == HIGH )
 {
   routine du mode automatique
 }

else
 {
   routine du mode manuel
 }

Cfr code pour plus de compréhension. Mon soucis est que même lorsque j'appuie sur le joystick, rien ne se passe et ma boucle reste continuellement en mode automatique, je suis obligé de modifier la condition de test pour pouvoir rentrer dans le 'else' et tester le mode manuel.
Je me doute bien que le BP du joystick fonctionne comme un interrupteur qui s'ouvre ou se ferme en fonction de l'appui dessus, donc je comprends à ce niveau que mon code ne fonctionne pas, auriez-vous une solution à me suggérer ?

Voici des photos du montage et mon code :


Code: [Select]
#include <Servo.h>
#include <LiquidCrystal.h>

// Création de l'objet écran LCD
LiquidCrystal monEcran(12,11,5,4,3,2);

// Assignation des broches de la led RGB sur les entrées de l'Arduino
int redPin= 13;
int greenPin = 8;
int bluePin = 7;

void setColor(int redValue, int greenValue, int blueValue)
{
  analogWrite(redPin, redValue);
  analogWrite(greenPin, greenValue);
  analogWrite(bluePin, blueValue);
}

// Définition des servomoteurs
Servo servohori;
int servoh = 90;
int servohLimitHigh = 160;
int servohLimitLow = 20;

Servo servoverti;
int servov = 0;
int servovLimitHigh = 70;
int servovLimitLow = 0;

// Assignation des photorésistances sur les entrées de l'Arduino
int ldrtopl = 2; //top left LDR green
int ldrtopr = 1; //top right LDR yellow
int ldrbotl = 3; // bottom left LDR blue
int ldrbotr = 0; // bottom right LDR orange

// Définition des variables du joystick
int VRx = A5;
int VRy = A4;
int SW = 13;

int xPosition = 0;
int yPosition = 0;
int SW_state = 0;
int mapX = 0;
int mapY = 0;

//int test = 0; // variable test pour forcer de rentrer dans le else ... à retirer par la suite

 void setup ()
 {
 
  //on initialise la communication avec 16 colonnes et deux lignes pour le LCD
  monEcran.begin(16,2);

  // Valeurs de départ des servomoteurs
  servohori.attach(10);
  servohori.write(90);
  servoverti.attach(9);
  servoverti.write(0);
  delay(500);

  // Pins de l'Arduino en mode OUTPUT pour gérer les broches de la led RGB
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  // Pins de l'Arduino en INPUT pour le joystick
  pinMode(VRx, INPUT);
  pinMode(VRy, INPUT);
  pinMode(SW, INPUT_PULLUP);
 }

void loop()
{
 
  servoh = servohori.read();
  servov = servoverti.read();

    if(SW_state == HIGH)  // Mode automatique
    //if(test !=0)
  {
    monEcran.clear(); // on efface l'écran
    monEcran.print("Mode auto: P= 0W");
    monEcran.setCursor(0,1); //on passe à la ligne suivante
    monEcran.print("U= 0V et I= 0mA");
    setColor(0, 255, 0); // Led en couleur verte lors du mode automatique
 
    //Récupération des valeurs analogiques de chaque capteur
    int topl = analogRead(ldrtopl);
    int topr = analogRead(ldrtopr);
    int botl = analogRead(ldrbotl);
    int botr = analogRead(ldrbotr);
 
    // Calculs des moyennes
    int avgtop = (topl + topr) / 2; //moyenne des photorésistances du haut
    int avgbot = (botl + botr) / 2; //moyenne des photorésistances du bas
    int avgleft = (topl + botl) / 2; //moyenne des photorésistances de gauche
    int avgright = (topr + botr) / 2; //moyenne des photorésistances de droite
   
      if (avgbot < avgtop)
    {
      servoverti.write(servov +1);
      if (servov > servovLimitHigh)
        {
          servov = servovLimitHigh;
        }
       delay(10);
    }
  else if (avgtop < avgbot)
  {
    servoverti.write(servov -1);
    if (servov < servovLimitLow)
      {
        servov = servovLimitLow;
      }
    delay(10);
  }
  else
      {
        servoverti.write(servov);
      }
 
  if (avgright > avgleft)
    {
      servohori.write(servoh +1);
      if (servoh > servohLimitHigh)
        {
        servoh = servohLimitHigh;
        }
    delay(10);
    }
  else if (avgleft > avgright)
    {
      servohori.write(servoh -1);
      if (servoh < servohLimitLow)
        {
          servoh = servohLimitLow;
         }
    delay(10);
    }
  else
    {
      servohori.write(servoh);
    }
  delay(10);
 } 

else   // Mode manuel
     {
    monEcran.clear(); // on efface l'écran
    monEcran.print("Mode manu: P= 0W");
    monEcran.setCursor(0,1); //on passe à la ligne suivante
    monEcran.print("U= 0V I= 0mA");

    setColor(0, 255, 255); // Led RGB en mauve lors du mode manuel
 
    xPosition = analogRead(VRx);
    yPosition = analogRead(VRy);
    SW_state = digitalRead(SW);
    mapX = map(xPosition, 0, 1023, -512, 512);
    mapY = map(yPosition, 0, 1023, -512, 512);

    if (yPosition>550)
    {
      servoverti.write(servov -1);
    }
   
    if(yPosition<480)
    {
      servoverti.write(servov +1);
    }

    if (xPosition<480)
    {
      servohori.write(servoh +1);
    }
   
    if(xPosition>550)
    {
      servohori.write(servoh -1);
    }

    }
  delay(25);
  }

lesept

Dans tes tests, par exemple
Code: [Select]
    servoverti.write(servov -1);
    if (servov < servovLimitLow)
      {
        servov = servovLimitLow;
      }
tu bouges le servo puis tu testes si tu as dépassé la borne.
Tu devrais faire ça dans l'autre sens : tester si on atteint la borne, et si non bouger le servo. Par exemple :

Code: [Select]
    if (servov > servovLimitLow)
      {
        servov -=1;
        servoverti.write(servov);
      }

Pour le BP, tu devrais utiliser une variable d'état booléenne 'MODE_AUTO' qui change (true -- false) à chaque appui du bouton avec
Code: [Select]
MODE_AUTO != MODE_AUTO;
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

biggil

tu testes le bouton (SW_state) uniquement quand tu es en 'manuel', donc si tu passes en 'automatique', tu ne peux plus revenir en 'manuel'.

68tjs

#3
Mar 16, 2018, 08:52 am Last Edit: Mar 16, 2018, 08:54 am by 68tjs
Pour la hauteur du soleil un débatement entre 0 et 75 degrés est suffisant.
Par contre pour l'azimut, pour tirer pleinement partie du suiveur solaire de fin mars à fin septembre, il faudrait un servomoteur 270 degrés.

Charly4343

Merci pour votre aide,

J'ai modifié mon code et tout fonctionne bien maintenant !  :)

Go Up