Banc de vision et convoyeur

Banc de vision piloté

Fait par :

  • BOUDAOUDI Aissame
  • ANDERHUBER Tom

Objectif

L’objectif de ce projet est de réaliser un banc de vision et convoyeur pour pouvoir scanner des pièces en 3D et repérer les défauts existants. En utilisant un tapis avec un moteur pas à pas, des boutons pour gérer le tapis, des rubans de leds, un capteur de détection de pièces, une caméra et finalement un arduino UNO qui va nous permettre de lier tous ces éléments afin de les faire fonctionner.

Fonctionnement

Une caméra avec leds sur un banc de vision

Nous plaçons une pièce sur le convoyeur, cette pièce est éclairer par des leds afin d’avoir un reflet, une fois que la pièce est détecté par le capteur infrarouge, la caméra de vision prend une photo et analyse la pièce afin de vérifier la pièce et ainsi voir si cette dernière est conforme (présence d’un défaut ou non)

Afin de programmer tout cela nous utiliseront un Arduino UNO, ce dernier vas nous permettre de faire fonctionner les boutons poussoirs, le capteur infrarouge, le moteur du banc de vision et les bandeaux leds

Nous allons également utiliser anaconda afin de réaliser une liaison série qui vas nous permettre de contrôler le programme à distance via un ordinateur.

Nous avons décidé d’utiliser deux boutons et un switch.

Un bouton va gérer la fonction marche/arrêt du tapis, un deuxième bouton est pour l’instant libre, il ne fait rien, on l’a installé pour pouvoir le coder et programmer. Le switch va gérer le sens du tapis, en changeant la position du Switch on change le sens de rotation du tapis.

Partie électrique

Schéma de câblage

(Fichier disponible sur la plateforme ED campus )

  • On peut voir qu’on utilise un différentielle afin de protéger l’installation d’un défaut de tension, et couper la tension en cas de problème.

En ce qui concerne le matériel utilisé :

  • Arduino UNO
  • COnvertisseur 230V en 24V, 12V, et 5V
  • Différentielle merlin gerin multi 9 DPN vigi
  • Carte de commande Micrositch driver
  • Deux bouton, un switch
  • Un capteur de détection de pièces
  • Un Tapis avec moteur pas à pas

Plaque électronique

Partie code

On a fourni la code complet dans un fichier « ino » sur la plateforme EDCampus

Pour la partie code du projet, on a utilisé le logiciel arduino , et le langage C++ pour pouvoir donner des instructions bien précises à l’arduino et pouvoir le piloter aussi à distance en utilisant un ordinateur.

Le point de plus qui change cette année en comparant les deux projets celui de l’année dernière et l’actuel en tout ce qui est code c’est l’utilisation du TIMER, on va utiliser un Timer pour pouvoir gérer le tapis au lieu de le faire rouler avec des pas et des temporisations qui n’est pas pratique.

Bibliothèques

Pour pouvoir gérer les Leds, on utilisera une bibliothèque spécifique aux types des Leds utilisés « Adafruit_Neopixel » qu’on va intégrer dans notre code: #include <Adafruit_Neopixel.h>.

Ensuite On va créer quatre variables qu’on va utiliser pour configurer cette bibliothèque, on a choisi LED1_COUNT, LED1_PIN, LED2_COUNT et LED2_PIN, dont le rôle est de choisir un pin pour chaque ruban de leds et une autre qui va compter les leds de chaque ruban. On choisit après chaque ruban et on affecte ces variables au ruban.

//Bilbliothèque des Leds
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(LED1_COUNT, LED1_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(LED2_COUNT, LED2_PIN, NEO_GRB + NEO_KHZ800);

Définition des Pins

On a définit les Pins de l’Arduino comme suit :

  • Pin 1 du Switch : 7
  • Pin 2 du Switch : 8
  • Pin du premier bouton : 2
  • Pin du deuxième bouton : 13
  • Pin du timer : 9
  • Pin qui gère le sens du tapis : 5
  • Pin pour alimenter le tapis : 6
  • Pin du premier ruban des leds : 3
  • Pin du deuxième ruban des leds : 4
  • Premier Pin de la caméra : 10
  • Deuxième Pin de la caméra : 11
//Définition des Pins
# define Switch_1 7
# define Switch_2 8
# define Entree_Bouton 2
# define Entree_Bouton2 13
# define OC1a_Timer 9
# define Sens_Tapis 5
# define Alim_Tapis 6

//led pin
#define LED1_PIN  3
#define LED1_COUNT  25
#define LED2_PIN  4
#define LED2_COUNT  25

//camera pins
#define CAM1_PIN 10
#define CAM2_PIN 11

Déclaration des varaiables globales

Pour pouvoir gérer les Leds on a créé les variables suivantes : br1, br2, r1, r2, g1, g2, b1, b2, rg1_1, rg1_2, rg2_1, rg2_2. PB1_state et PB2_state pour savoir si le bouton est appuyé ou relâché.

numChars est une variable qui va nous servir dans la liaison série pour pouvoir envoyer ou recevoir un nombre limité de caractères, et receivedChars est un tableau qui va contenir les caractères envoyés ou reçu. newData est juste un booléen qui est égal soit à 0 ou 1 et qui dépend de la réception du caractère (reçu ou non). Par défaut on lu affecte la valeur 0 ( ou False.)

Ensuite passons aux variables qu’on va utiliser pour gérer nos boutons :

– lastbottonstat est la variable qui va nous informer du dernier événement appliqué sur le bouton

– currentbottonstat est l’état actuel du bouton

–  tapistat est l’état du tapis s’il est en marche ou pas.

//Déclaration variables globales

//vriables leds
int br1, br2, r1, r2, g1, g2, b1, b2, rg1_1, rg1_2, rg2_1, rg2_2;
 
int PB1_state, PB2_state; //variables boutons


const byte numChars = 200;
char receivedChars[numChars];
boolean newData = false;



//variables boutons
bool lastbottonstat=LOW;
bool currentbottonstat=LOW;
bool tapistat=LOW;

On commence notre code finalement en initialiisant la liaison en série, on va choisir une vitesse de 9600 bauds avec un délai de 300 ms, et on va mettre cette inialisation dans la fonction void setup comme suit :

Serial.begin(9600); //Liaison en série
delay(300);

Et juste après, on initialise aussi le TIMER 1 de l’arduino Uno en choisisant une fréquence d’échentillonnage de 16 MHz.

TCCR1B = 0x18; // 0001 1000, Disable Timer Clock 
TCCR1A = 0xA2; // 1010 0010

ICR1 = 1400;
OCR1A = (int) (ICR1 * 0.25);
OCR1B = (int) (ICR1 * 0.50);
TCNT1=0x0;

TCCR1B |= 1; // Prescale=1, Enable Timer Clock

Toujours dans la fonction setup, on passe à l’étape de choix de Pins. Après déclarer et affecter les Pins à des variables précis, on choisit le mode de chaque Pin.

//Choix des Pins
  pinMode(Switch_1,INPUT_PULLUP);
  pinMode(Switch_2,INPUT_PULLUP);
  pinMode(Entree_Bouton,INPUT_PULLUP);
  pinMode(Entree_Bouton2,INPUT_PULLUP);
  pinMode(OC1a_Timer, OUTPUT);  // OC1a
  pinMode(Alim_Tapis,OUTPUT);
  pinMode(Sens_Tapis,OUTPUT);
  digitalWrite(Sens_Tapis,HIGH);
  digitalWrite(Alim_Tapis,LOW);
  digitalWrite(Entree_Bouton,HIGH);
  digitalWrite(Entree_Bouton2,HIGH);
  digitalWrite(Switch_1,HIGH);
  digitalWrite(Switch_2,HIGH);

Ensuite, on configure les leds à une valeur par défaut, pour pouvoir s’activer et afficher au moins une couleur au démarrage et quand on change pas la valeur du degré soir du bleu, rouge ou vert de chaque ruban. les variables sont décrites comme suit:

  • br1/2 est le degré de luminosité des rubans
  • r1/2 est la valeur de la couleur rouge
  • b1/2 est la valeur de la couleur bleu
  • g1/2 est la valeur de la couleur verte
  • rg1-1/2 est le nombre des leds dans chaque ruban
//Configuration des Leds
  br1 = 100;
    r1 = 255;
    g1 = 255;
    b1 = 255;
    rg1_1 = 0;
    rg1_2 = LED1_COUNT-1;
    strip1.begin();
    strip1.show();

    br2 = 100;
    r2 = 255;
    g2 = 255;
    b2 = 255;
    rg2_1 = 0;
    rg2_2 = LED2_COUNT-1;
    strip2.begin();
    strip2.show();


Fonctions utilisés

recvWithStartEndMarkers()

Cette fonction sert à recevoir des caractères en utilisant la liaison en série . Après vérifier qu’il n’y a pas de nouveaux Data qui arrive on recois les caratères et on les place dans notre tableau receivedChar sinon on patiente.

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

ProcessNewData()

La fonction ProcessNewData sert à lire le caractères reçus. Si la valeur de newData est égale à 1 on lis les caratère reçus, si c’est

  • « Go » = Le tapis marche
  • « NoGo »: Le tapis s’arrête
  • « RightLeft » : le tapis tourne de droite à gauche
  • « LeftRight » : le tapis tourne au sens inverse de gauche à droite
  • « V » en indiquant un chiffre après: La vitesse du tapis change avec la valeur écrite après la chaîne de carctère V
  • « Led1_Go » : Lance le premier ruban de leds
  • « Led2_Go »: lance le deuxième ruban de leds
void ProcessNewData() {
    if (newData == true) {
    
        //Serial.print("The received data is :: ");
        //Serial.println(receivedChars);

        if (strcmp(receivedChars, "Go") == 0 || strcmp(receivedChars, "NoGo") == 0)
        {
            if (strcmp(receivedChars, "Go") == 0) 
              StartStopMotor(HIGH);
            else
              StartStopMotor(LOW);
        }
        if (strcmp(receivedChars, "RightLeft") == 0 || strcmp(receivedChars, "LeftRight") == 0)
        {
            if (strcmp(receivedChars, "RightLeft") == 0) 
              Direction(HIGH);
            else
              Direction(LOW);
        }
        
//##############
      if (strcmp(receivedChars, "V") == 0)
        {
           ICR1=receivedChars[1]-30*1000+receivedChars[2]-30*100+receivedChars[3]-30*10+receivedChars[4]-30;
           
        }
  

//################
        
        if (strcmp(receivedChars, "Vitesse") == 0)
        {
          Vitesse(ICR1);
        }
        else
        {
          char * pch;
          pch = strtok(receivedChars,",");
          while (pch != NULL)
          {
            
            if(strcmp(pch, "R1") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                r1 = atoi(pch);
                //strip1.fill(strip1.Color(r1, g1, b1), rg1_1, rg1_2);
              }
            }
  
            else if(strcmp(pch, "R2") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                r2 = atoi(pch);
                //strip2.fill(strip2.Color(r2, g2, b2), rg2_1, rg2_2);
              }
            }
  
            else if(strcmp(pch, "G1") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                g1 = atoi(pch);
                //strip1.fill(strip1.Color(r1, g1, b1), rg1_1, rg1_2);
              }
            }
            else if(strcmp(pch, "G2") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                g2 = atoi(pch);
                //strip2.fill(strip2.Color(r2, g2, b2), rg2_1, rg2_2);
              }
            }
            else if(strcmp(pch, "B1") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                b1 = atoi(pch);
                //strip1.fill(strip1.Color(r1, g1, b1), rg1_1, rg1_2);
              }
            }
            else if(strcmp(pch, "B2") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                b2 = atoi(pch);
                //strip2.fill(strip2.Color(r2, g2, b2), rg2_1, rg2_2);
              }
            }
            else if(strcmp(pch, "Br1") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                br1 = atoi(pch);
                strip1.setBrightness(br1);
                //strip1.fill(strip1.Color(r1, g1, b1), rg1_1, rg1_2);
              }
            }
            else if(strcmp(pch, "Br2") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                br2 = atoi(pch);
                strip2.setBrightness(br2);
                //strip2.fill(strip2.Color(r2, g2, b2), rg2_1, rg2_2);
              }
            }
            else if(strcmp(pch, "Rg1") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                rg1_1 = atoi(pch);
                pch = strtok (NULL, ",");
                if (pch != NULL)
                {
                  rg1_2 = atoi(pch);
                  strip1.fill(strip1.Color(r1, g1, b1), rg1_1, rg1_2);
                }
              }
            }
            else if(strcmp(pch, "Rg2") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                rg2_1 = atoi(pch);
                pch = strtok (NULL, ",");
                if (pch != NULL)
                {
                  rg2_2 = atoi(pch);
                  strip2.fill(strip2.Color(r2, g2, b2), rg2_1, rg2_2);
                }
              }
            }
            else if(strcmp(pch, "LED1_go") == 0)
            {
              strip1.show();
            }
            else if(strcmp(pch, "LED2_go") == 0)
            {
              strip2.show();
            }
            else if(strcmp(pch, "Sp") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                Sp = atoi(pch);
              }
            }
            else if(strcmp(pch, "Dr") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                Dr = atoi(pch);
              }
            }
            else if(strcmp(pch, "NbSteps") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                NbSteps = atoi(pch);
              }
            }
            else if(strcmp(pch, "Ret") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                Ret = atoi(pch);
              }
            }
            else if(strcmp(pch, "TrigPas1") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                TrigSteps1 = atoi(pch);
              }
            }
            else if(strcmp(pch, "TrigPas2") == 0)
            {
              pch = strtok (NULL, ",");
              if (pch != NULL)
              {
                TrigSteps2 = atoi(pch);



                
              }
            }
          
            pch = strtok (NULL, ",");
          }
        }
        
        newData = false; 
    }
}

StartMotor()

StartMotor() est la fonction principale qui lance et arrête le moteur du tapis. En utilisant les variables « currentbottonstat » et « lastbottonstat » on peut savoir si le bouton a été relâché pour pouvoir arrêter, puis faire fonctionner le tapis.

Si l’état actuel du bouton est différent de l’état précédent on alimente le tapis et on le fait tourner sinon on l’arrête et bien sûr après avoir vérifié si le tapis tourne déjà ou pas.

La variable tapistat permet de vérifier si le tapis tourne ou pas, si tapistat est à la valeur HIGH on arrête le tapis sinon on le fait tourner.

void StartMotor(){
     
    //Utilisation du bouton STOP/Marche
    currentbottonstat = digitalRead(Entree_Bouton);
     if (digitalRead(Entree_Bouton) == HIGH){
        if ( currentbottonstat != lastbottonstat )
          {
                if ( currentbottonstat == HIGH )
                {
       
                    if ( tapistat == LOW ) 
                        {
                        digitalWrite(Alim_Tapis, HIGH);
                        tapistat = HIGH;
                        }
                    else          
                    {
                      digitalWrite(Alim_Tapis, LOW);
                      tapistat = LOW;
                     }
                  }
                  else
                  {
                      if ( tapistat == HIGH ) 
                      {
                        digitalWrite(6, LOW);
                        tapistat = LOW;
                      }
                      else          
                      {
                        digitalWrite(6, HIGH);
                        tapistat = HIGH;
                      }
                   }
            }
       }
        if (digitalRead(Entree_Bouton) == LOW) 
        {  
          if ( currentbottonstat != lastbottonstat )
          {
              if ( currentbottonstat == HIGH )
              {
                  if ( tapistat == LOW ) 
                  {
                      digitalWrite(6, HIGH);
                      tapistat = HIGH;
                  }
                  else 
                  {
                      digitalWrite(6, LOW);
                      tapistat = LOW;
                  }
                }
                else
                {
                    if ( tapistat == HIGH ) 
                    {
                      digitalWrite(6, LOW);
                      tapistat = LOW;
                    }
                    else          
                    {
                      digitalWrite(6, HIGH);
                      tapistat = HIGH;
                    }
                 }
            }
          }
    lastbottonstat = currentbottonstat;
          if (digitalRead(Switch_1) == HIGH)
        {
            digitalWrite(Sens_Tapis, LOW);
        }
        if (digitalRead(Switch_2) == HIGH)
        {
            digitalWrite(Sens_Tapis, HIGH);
        }
}

Direction()

void Direction(bool RightLeft){
  digitalWrite(Sens_Tapis, RightLeft);
  }
 

StartStopMotor()

void StartStopMotor(bool GoNoGo){
  digitalWrite(Alim_Tapis, GoNoGo);
}

Vitesse()

void Vitesse(int vit){
  digitalWrite(ICR1, vit);
}

Fonction Principale

void loop() {
    recvWithStartEndMarkers(); //Données données par l'utilisateur
    ProcessNewData(); 
    
    StartMotor();
}

Contrôle du banc de vision avec du Python

Finalement pour pouvoir contrôler le banc de vision en utilisant un ordinateur, il faut être obligatoirement connecté à l’Arduino en utilisant un câble USB, et on va utiliser dy python et le logiciel Anaconda.

On lance Anaconda, et on a utilisé Spyder comme éditeur de texte pour lancer notre programme. Le programme écrit en python nous permet de gérer les leds et le moteur du tapis en utilisant les commandes qu’on a intégré dans nos fonctions. Le bout de code qui nous permet de faire cela est le suivant :

if serial_arduino is not None:

    serial_arduino.write(('<Br1,255,B1,255,G1,255,R1,255,Rg1,0,12>').encode())
    serial_arduino.write(('<LED1_go>').encode())

    serial_arduino.write(('<Br2,255,B2,255,G2,255,R2,255,Rg2,0,12>').encode())
    serial_arduino.write(('<LED2_go>').encode())


    serial_arduino.write(('<Sp,300>').encode())
    sleep(1)
    serial_arduino.write(('<Dr,0>').encode())
    serial_arduino.write(('<NbSteps,50000,TrigSteps1,500,TrigSteps2,500>').encode())

    #sleep(1)
    #serial_arduino.write(('<Go>').encode())
    #sleep(1)
    #erial_arduino.write(('<NbSteps,1500>').encode())
    #sleep(1)

Caméra

Nous utiliseront une Caméra In-Sight D900 ainsi que le logiciel Insight Explorer afin de traiter les images renvoyées par la caméra, et pour pouvoir lire les défauts détectés.

Partie Structure

On un banc qui a été fait par les étudiants de l’année précédante, avec des plaques en couleur noir ayant pour but d’absorber la lumière, et des barres métalliques pour tenir le matériel qui sera installé dessus. On a aussi une plaque de bois bien rigide, qu’on a utilisé pour poser le tapis dessus, et coller l’alimentation, la carte commande et l’arduino au-dessous.

Carte électronique

Ensuite on a le convoyeur qui lui permet de déplacer les pièces , il s’agit d’un tapis mis en rotation par un moteur .

Et la structure qui vas accueillir ces 2 éléments ainsi que les le supports leds.

Cependant la plaque ne dispose pas d’une protection électrique certifié IP2X. On a protégé la partie alimentation avec un boitier qu’on a installé en utilisant des pièces magnétiques pour pouvoir le détacher facilement, mais il faut l’installer définitivement sans pouvoir le détacher, et protéger la partie Arduino et commande.

Résultats

  • Code Fonctionnel
  • Câblage installation terminé
  • Liaison série réussie

Travail à finir

  • Installer la caméra de vision afin de rendre le système opérationnel
  • Mettre en place une protection IP2X afin de protéger l’installation (un boitier fermé que l’on ne peux ouvrir qu’a l’aide d’un outil )
  • Améliorer le câblage de l’installation

Problèmes rencontrés

  • Problème de code parce que c’est a première fois qu’in utilise ce type de logiciel et on code en langage arduino
  • Problème de liaison série et les commandes à envoyer pour pouvoir le contrôler
  • Problème de protection IP2X , parce qu’il y avait pas assez de matériel et de temps pour pouvoir bien protéger le banc
  • Problème de câblage, parce que on a pas prévu des longs câbles pour les leds
  • Prôblème de gestion de temps et d’organisaton

Codes sources


Tracker Solaire

Réalisation d’un système « Tracker Solaire »

Apprenti : Pierre SIMON

Enseignants : Frédéric STEGER – Christophe CUDEL

SYNAPTEC

PROJET GEII : Etudes et Réalisations

Année 2021 – 2022   

Sommaire 

I. Projet de GEII

1. Introduction

2. Présentation du cahier des charges

3. Evolution du projet

a. Choix du matériel

b. Carte de commande moteur et de gestion (autonomie/secteur)

c. Carte principale CI

d. Programmation ZELIO

II. Utilisation et démontage 

III. Conclusion

IV. Annexe

 

I. Projet de GEII 

1.     Introduction  

Au courant de mon année 2021-2022, nous avons choisi un projet en Etudes et Réalisations. J’avais choisi le « Tracker Solaire » en binôme avec un second étudiant de génie électrique et deux étudiants de génie mécanique pour la partie mécanique.

Illustration 1 : Coffret électrique

Nous nous intéressons donc à l’implantation d’un coffret (voir illustration 1) électrique comprenant les batteries et la carte de gestion de la motorisation, sur le pilier du panneau solaire.

Illustration 2 : Photorésistance séparées par un T

Pour déterminer la position du soleil, le « Tracker » devait s’orienter grâce à l’information de luminosité transmise par des photorésistances (voir illustration 2) séparées par un T pour une orientation d’angles de 120 degrés chacune. Cependant, de nombreux désavantages pour déterminer la position du Soleil quand la météo ne le permet pas : vérification par temps clair, par temps couvert, exposition au gel, à la pluie, au dépôt de résidus (poussière, mousse, etc…) …

Différentes approches pour vérifier ces problèmes peuvent être mises en place. Dans le cas du temps clair, il faut effectuer une mesure au luxmètre entre les différents niveaux d’éclairement (coin le plus éloigner de la position du Soleil, et le plus proche). Essais avec des tubes pour concentrer le point de mesure suivant les parties du ciel.

Pour ce qui est du cas du temps couvert, effectuer des essais similaires pour déterminer la position du Soleil (épais nuage, brouillard) si elle s’avère déterminable. J’ai donc remarqué une uniformisation de l’intensité lumineuse par temps couvert, ce qui rend l’orientation compliquée pour l’obtention d’un rendement maximal (les photorésistance sont sensibles à l’intensité lumineuse en Lux, et non à la puissance surfacique). Déterminer la puissance surfacique à différents angles d’inclinaisons, lors de ciel voilé, pour contrôler si le tracking avec module logique permet réellement de maintenir un meilleur rendement, comparé au tracking en lecture directe (photorésistances).

Dans le cas du gel des cellules de positionnement, il faut intégrer un chauffage permettant d’éviter de fausser la position par réfraction lumineuse ou perte de précision.

Le problème posé par la pluie peut s’apparenter à celui du gel, une solution similaire s’impose.

Le dépôt de résidus de différentes natures oblige un entretien régulier des cellules de positionnement.

Malheureusement, l’étudiant de génie électrique n’est pas revenu à la seconde alternance. J’ai alors discuté avec mon maître d’apprentissage, pour effectuer mon projet d’entreprise en adéquation avec le projet de GEII. Les professeurs m’avaient dit que le tracker solaire avait été démarré il y a 5 ans, mais que, soit la partie électrique n’était pas faite, soit il s’agissait de la partie mécanique. J’ai commencé à réfléchir à une réalisation utile et ludique d’une maquette entièrement réalisée au sein de mon entreprise : SYNAPTEC.

J’ai utilisé différents logiciel pour réaliser mon projet :

  • Zélio Soft V5.3 pour la programmation du module logique ZELIO
  • Target 3000 pour schémas électronique et CAO
  • Galaad et Percival pour la réalisation des circuits imprimés FAO

2. Présentation du cahier des charges

Après avoir relevé les différents soucis liés au suivi du Soleil en lecture directe (voir illustration 2 de l’introduction), j’ai décidé de prendre un module logique ZELIO de la marque « SCHNEIDER Electric ». En effet, ce module logique intègre un bloque fonction permettant de fournir une orientation AZIMUT et une ELEVATION en fonction des coordonnées GPS du site d’implantation et du fuseau horaire. C’est donc beaucoup plus pratique, peu importe la météo et l’environnement.

Les professeurs d’encadrement du projet en GEII m’ont demandé d’une part, de mettre à l’horizontal le panneau photovoltaïque si le vent devenait violent, ainsi que d’économiser l’énergie du système via un cycle de fonctionnement périodique d’environ 30 min.

Ces deux conditions primordiales m’ont amené à penser un cahier des charges relativement complexe. J’ai réfléchi à comment gérer un réveil uniquement lorsqu’il fait jour puis périodique pendant la journée, ainsi qu’une mise à l’horizontal du système lorsqu’il y a du vent, peu importe s’il fait jour ou nuit. J’en ai conclu que mon module logique seul ne pourrait en aucun cas gérer ces deux gros points. J’avais deux solutions en tête : utilisation d’un microcontrôleur ou création d’une carte électronique. J’ai alors choisi la seconde solution car elle m’a permis de me familiariser avec la logique électronique et les différents logiciels qu’on utilise, pour la machine de gravure de carte électronique.

3.     Evolution du projet

a.       Choix du matériel

Pour le choix et la gestion des orientations, mon système a besoin de précision pour le positionnement des moteurs sur les axes AZIMUT et ELEVATION je me suis donc tourné vers une extension SR3XT43BD car elle possède 2 entrées analogiques 10 Bits (soit 1024 points) contrairement aux entrées analogiques classiques qui ne comprennent que 8 Bits (256 points).

Pour le module logique ZELIO (voir illustration 3), je me suis tourné vers le SR3B262BD car il possède des sorties transistorisées. Ces sorties sont utiles pour la rapidité d’exécution et de fermeture du contact qui commande la marche des moteurs.

Le module logique SR3B262BD fonctionne sous 24V, il possède 10 entrées et 10 sorties ToR (24V) + 6 entrées analogiques 8 Bits (0-10V) :

5 entrées ToR :

  • Un fin de course sur l’orientation AZIMUT (position NORD)
  • Un fin de course sur l’orientation ELEVATION (position ARRIERE)
  • Un fin de course sur l’orientation ELEVATION (position AVANT/RANGEMENT)
  • Une entrée mode TEMPETE (envoyé depuis une carte externe CI)
  • Une entrée mode REGLAGE (définis par un interrupteur)

3 entrées analogiques 8 Bits (0 à 255 points) :

  • Courant moteur azimut (gérer le blocage moteur envoyé depuis carte externe CI)
  • Courant moteur élévation (gérer le blocage moteur envoyé depuis carte externe CI)
  • Ensoleillement (envoyé depuis carte externe CI)

5 sorties ToR :

  • Grande vitesse
  • Marche moteur AZIMUT
  • Inversion moteur AZIMUT
  • Marche moteur ELEVATION
  • Inversion moteur ELEVATION
  • Défaut(s)
  • Ordre de SOMMEIL (en fin de cycle)

Le module logique possède un écran, pratique pour les messages de défauts, ainsi que 4 boutons programmables. L’extension analogique 2 entrées analogiques 10 Bits et 2 sorties analogiques 10 Bits (0-10V) :

2 entrées analogiques 10 Bits :

  • Recopie potentiomètre AZIMUT (envoyé depuis carte externe CI)
  • Recopie potentiomètre ELEVATION (envoyé depuis carte externe CI)

 Illustration 3 : Module logique Zélio + extension et alimentation 

Pour la maquette, j’ai fait le choix d’utiliser 6 cellules photoélectriques d’une tension de 6V chacune, montée sur le système pour me délivrer une tension de 12V et d’une puissance totale de 3 Watt (nominales). Une batterie de 12V et de 2.1 Ah (mon système au repos consomme 26 mA). Deux moteurs de 12V et 25 mA en fonctionnement normal. Une alimentation 230V~/24V= et de 1.2 A, avec un disjoncteur de 2A courbe C pour le branchement sur secteur. Pour la position, j’ai deux potentiomètres de 5 kOhms, et une photorésistance pour le réveil journalier.

b. Carte de commande moteur et de gestion (autonomie/secteur)

SYNAPTEC a acquis au courant de l’année 2020 une machine d’usinage pour la réalisation de carte électronique. J’ai alors pu profiter du nouveau système l’année dernière avec mon ancien projet. Cette année, je me suis attelé à une panoplie de carte électronique pour ce projet notamment celle permettant de gérer l’orientation du système sur deux axes et de gérer entre l’alimentation par secteur, ou l’alimentation par batterie (cellule photovoltaïque) en autonomie.

INTERFACE DE COMMANDE MOTEUR + GESTION ALIMENTATION : (voir annexe)

Illustration 4 : carte électronique.

Interface de commande des moteurs : Elle possède 8 bornes en bas de l’illustration 4 et 5 qui servent à l’alimentation en grande vitesse (12V), petite vitesse (4.5V). Les commandes du module logique : grande vitesse, marche azimut, inversion azimut, marche élévation et inversion élévation. La dernière borne c’est le 0V commun à tout le système.

Illustration 5 : Circuit imprimé gestion moteur/alim.

Les commandes de marche des moteurs actionnent des optocoupleurs prévus pour moduler le signal à l’approche du point, ou bien de le hacher, augmentant ainsi la précision et la vitesse d’exécution du système. Tout ceci est géré par le module logique et les fameuses sorties transistorisées.

En sortie, comme montré sur la carte imprimée (illustration 5) en bas à gauche, la carte actionne les moteurs d’élévations et d’azimut avec l’aide des sortie +/- ME et +/-MA.

Les sorties +M1 et 0V M1 permettent de mesurer le courant moteur qui est envoyé vers la carte principale, puis vers le module logique. Idem pour les sorties +M2 et 0V M2.

CIE et CIA sont les commandes d’inversion pour la marche moteur.

Sur l’illustration 5, nous pouvons observer en haut la gestion de l’alimentation entre secteur et autonomie : en effet, lorsqu’il y a de la tension (24V) aux bornes du 0V et du +24V, les 3 relais s’enclenche, mon système se retrouve alimenté par l’alimentation secteur 230V/24V. cependant, dans le cas contraire, les système est alimenté en 12V par la batterie. Un problème se pose, mon module logique ne fonctionne qu’en 24V. Au repos, les contacts des relais aiguillent le 12V des batterie vers un convertisseur externe à la carte (12V/24V) et le 24V est envoyé sur le ZELIO, lui permettant de continuer à fonctionner en autonomie. Voici pourquoi il y a un système de gestion d’alimentation.

Quand nous sommes sur secteur, la production des panneaux solaires est aiguillée sur la sortie E10 3W, pour observer sur une ampoule l’intensité de production (il s’agit d’une maquette). Lorsque nous sommes en autonomie, la production d’énergie des cellules est déviée vers la batterie.

c. Carte principale CI

TRACKER SOLAIRE : DESCRIPTIF DE LA CARTE ET SES FONCTIONS. (Voir annexe, pages 31 et 32)

Illustration 6 : Carte principal CI.

Tout d’abord, l’existence de cette carte réside en 2 points : la gestion du mode tempête et le réveil périodique durant la journée. En effet, cela ne peut être géré par le module logique, c’est donc via une pléiade de composants que j’ai pu concevoir un système répondant au cahier des charges (illustration 6).

Illustration 7 : Circuit imprimé principal CI.

Dans un premier temps, l’orientation des potentiomètres, la gestion du courant moteurs et l’ensoleillement via la photorésistance sont amplifiés via des amplificateurs opérationnels. J’ai pu appliquer certaines notions vues en cours et me perfectionner sur l’amplification de signaux mais également sur la gestion de seuil comme pour l’ensoleillement. Une fois amplifié, l’ensoleillement entre à nouveau dans un amplificateur opérationnel mais pour y être comparé à un seuil (environ 1000 Lux). Ce seuil a pour effet de m’indiquer, sans pour autant être perturbé par la moindre petite lumière durant la nuit, quand est-ce qu’il fait jour.

Les autres signaux simplement amplifiés tels que le courant de chaque moteurs est envoyé sur mes entrées analogiques 8 Bits du module logique, pour y être traiter. Il est vrai que l’amplification de mes signaux n’est pas présente juste pour appliquer des notions vues en cours, mais également car le signal entrant directement sur le ZELIO était trop faible…

Pour ce qui est de la gestion des potentiomètres, l’AZIMUT est géré vis-à-vis la résolution maximal : 0 à 10V est égal à 0 à 1023 points dans mon programme et correspond de 0 à 360 degrés de rotation. Ayant pour origine de la mesure le NORD (0 et 360 = NORD), 90° = EST, 180°=SUD et 240°=OUEST. Mes potentiomètres ont une plage de 0 à 340° équivalent à 0 à 5kOhms (plage morte de 20°). J’ai donc dû mettre en place une réduction sur ma tige AZIMUT pour que mes 0 à 340° potentiomètres conviennent à la mesure sur 0 à 360° de rotation.

Pour la gestion de l’ELEVATION, il s’agit d’une course maximale de rotation de 0 à 180°. J’ai alors ajusté mon 0 – 10V de lecture sur mon entrée ZELIO pour faire correspondre non pas de 0 à 340° mais bel et bien de 0 à 180°. Nous avons donc une résolution de traitement de 0 à 180° valant 0 à 1023 points. Tout cet ajustement est réalisé avec le bon pont diviseur sur l’entrée de l’amplificateur opérationnel.

Ce qu’il faut retenir : mes signaux apparaissant sur mes entrées (0-10V) 10 Bits de l’extension ZELIO et (0-10V) 8 Bits du ZELIO sont amplifiés pour correspondre à la plage maximale de traitement dans le programme (0-1023 pour 10 Bits et 0-255 pour 8 Bits). Ceci correspond aux bornes de gauche et en haut sur l’illustration 7.

En haut à droite nous avons une commande venant du ZELIO : le SOMMEIL. Cette commande arrive sur la bobine du bistable d’alimentation du ZELIO, elle permet de l’auto couper une fois son cycle de fonctionnement terminé.

Son cycle de REVEIL (Illustration 8) est, quant à lui, géré par la carte CI directement avec l’utilisation du seuil 1000 Lux lançant le mode JOUR. Le mode JOUR envoie une impulsion toute les 55 secondes, ou bien 30 min via le choix du switch entouré en vert sur l’illustration 6. Les 55 secondes correspondent au cycle de test, et les 30 min, au cycle de fonctionnement normal. L’impulsion périodique possible grâce à l’utilisation d’un NE555 monté en astable.

Illustration 8 : Synoptique système REVEIL

Sur la partie de droite (Illustration 7) nous retrouvons le contact d’alimentation du ZELIO, qui peut être court-circuité par le REVEIL en cas de VENT VIOLENT, laissant 30 secondes d’alimentation au module LOGIQUE pour effectuer sa mise en sécurité. Juste en dessous, il y a la borne reliée à l’entrée VENT du ZELIO qui lui indique ou non de mettre le système à l’horizontal. Cette dernière est remise à zéro s’il n’y a pas eu de Bourrasque de puis 55 secondes ou bien 30 min (en fonction de la position du switch). En bas à gauche nous retrouvons les différentes tensions d’alimentation permettant au système de fonctionner : 24V si alimentation sur secteur, dans le cas contraire nous entrons directement en 12V sur l’entrée +12V IN (gérée depuis la carte de gestion d’alimentation décrite plus haut).

Nous détectons une bourrasque grâce à un anémomètre électronique : Le montage entouré en bleu en annexe page 32 correspond à l’anémomètre en question. Le phénomène provient de la particularité des semis conducteurs qui est : 2 mV par °C. Nous nous retrouvons donc avec un transistor T1 monté en diode et non chauffé correspondant à la référence de température. Un second transistor T2 également monté en diode mais couplé thermiquement à un troisième transistor T3. T2 est réchauffé par T3 de quelques degrés supérieurs à la température actuelle. Si un déplacement d’air survient, T1 reste à sa température actuelle, cependant T2 qui était chauffé se voit perdre des calories. T3 est doc obligé de compenser cette perte de calories commandé par l’amplificateur opérationnel, ce qui a pour effet de faire varier le signal de ce dernier. Un second amplificateur permet de comparer ce signal à un seuil de vent qu’on a défini comme pouvant être dangereux à notre maquette. Il émet donc une impulsion à chaque bourrasque via un NE555 monté en monostable déclenchant ainsi le mode tempête (voir illustration 9).

Illustration 9 : Synoptique système TEMPETE.

En bref, si on souffle sur les 2 transistors T1 et T2 en même temps, symbolisant l’anémomètre, le système se met en mode tempête ! A noter (Illustration 8) qu’à chaque seuil atteint, le système de TEMPETE réinitialise le REVEIL pour prolonger la mise en sécurité. Si aucune bourrasque ne survient pendant le temps calibré (via le switch), le REVEIL du système annule le mode TEMPETE indiqué par le DEL bleue sur l’illustration 6.

                                               d.                Programmation ZELIO

TRACKER SOLAIRE : GESTION DE L’ORIENTATION.

Illustration 10 : Gestion du bloc TRACKING  

L’illustration 10 est la partie de gestion du bloc fonction donnant la position du soleil en temps réel. Pour se faire, il faut lui entrer les coordonnées GPS du lieu d’implantation sous forme décimal (conversion GSP de degré vers décimal), ainsi que le fuseau horaire en minute signé (+120 pour l’Alsace). Les valeurs brutes d’AZIMUT sont comprises entre -18000 et +18000 :           

0 (0°/360°) pour le NORD ;               

9000 (90°) pour l’EST ;                                        

+/-18000 (180°) pour le SUD ;          

-9000 (240°) pour l’OUEST.

Les valeurs d’ELEVATION sont comprises entre -9000 à + 9000 : +9000 (90°) pour le point le plus haut à l’horizontal, 0 (0°) pour l’horizon. Les valeurs négatives correspondent à la position du Soleil sous l’Horizon.

Une fois ces valeurs comprises, j’ai effectué des règles simples : notamment diviser directement par 10 pour pouvoir utiliser mes valeurs de mots correctement.

En effet, entre -18000 et +18000 il y a 36000 valeurs, mais 36000 valeurs je ne peux pas les traiter avec des octets signés… je divise donc chaque valeurs par 10 pour me ramener à -900 à +900 pour l’ELEVATION et -1800 à +1800 pour l’AZIMUT.

Pour l’ELEVATION, il me suffit d’appliquer une règle de trois : nous avons une cours totale de 0 à 180° soit 0 à 1023 points. Cependant, le bloc fonction ne va que jusqu’à 90° donc une cours de 0 à 511 points (la moitié). Je multiplie donc la sortie de ma division par un coefficient (GAIN) égal à 512/900. Une fois fait, je peux comparer ma donnée à mon entrée 10 Bits du potentiomètre d’ELEVATION.

J’effectue la même chose pour l’AZIMUT sans oublier que mon 0 à 1023 points se fait dans le sens Nord->Est->Sud->Ouest. Or, mon bloc sort une valeur perturbante : 0=NORD, 900=EST, 1800=SUD, -1800=SUD, -900=OUEST. Je dois donc arriver à gérer quand je suis entre 0 et 1800, et quand je suis entre -1800 et 0. J’effectue donc un multiplexage changeant entre l’avant ZENITH, et l’après ZENITH. Il suffit donc de distinguer deux règles à appliquer : entre 0 et 1800 je suis coté EST, je multiplie la sortie de la division par un coefficient (GAIN) égal à 512/1800. Pour la partie OUEST, entre -1800 et 0, il faut que j’additionne ma sortie avec 1800 pour me le ramener en positif. Puis j’applique le même coefficient mais avec un offset de 512 puisque nous avons déjà parcouru la moitié de la course avec le premier réglage.

TRACKER SOLAIRE : GESTION DE L’ORIENTATION avec COMPARAISON POTENTIOMETRE

Voici la dernière partie de la programmation, effectuée à ce jour. Les différents tests m’ont permis d’ajuster et d’affiner le réglage de l’approche de la position souhaitée.

Illustration 11 : Gestion de la motorisation AZIMUT

Les ronds entourés en rouges représentent d’une part, les blocs de comparaison entre la valeur du potentiomètre AZIMUT avec la gestion du bloc TRACKING vu plus haut, et l’action sur les sortie ToR de marche et inversion moteur AZIMUT. A +/- 35 points (soit environ +/-12.3 °), le système passe de grande à petite vitesse, quand il arrive dans une plage de 6 points (environ 2.1° soit +/- 1°) encadrant la valeur de stabilisation, le moteur se coupe.

Le rond vert correspond à la gestion du bloc TRACKING

TRACKER SOLAIRE : GESTION DE L’ORIENTATION avec COMPARAISON POTENTIOMETRE

Illustration 12 : Gestion de la motorisation ELEVATION

Le rond jaune sur l’illustration 11 correspond à la marche et l’inversion moteur ELEVATION. Le rond rouge sur l’illustration 12 correspond à la gestion d’avance avec précision pour l’ELEVATION. En effet, La grande vitesse n’est effective qu’au-delà de +/-120 points (+/-21°), en dessous de +/-40 points (+/-7°) j’applique un correcteur de type hacheur envoyant des impulsions pour stabiliser autour de +/-1 points (+/-0.17°). Ce correcteur me permet également d’être très précis et rapidement.

II. Utilisation et démontage 

TRACKER SOLAIRE : Mise en route du système

Dans cette partie il faut se référer à l’illustration 1 ci-dessous, je vais expliquer comment utiliser le système Tracker Solaire. Tout d’abord, il faut s’assurer du choix de l’alimentation, si on veut être en autonomie, ou sur secteur. Pour ce faire, si on veut une alimentation par secteur il suffit de brancher la fiche électrique sur une prise 230V alternatif, puis d’enclencher le disjoncteur C2. Sinon, il suffit d’actionner le levier rouge indiquant l’utilisation de la batterie (en vérifiant que les connecteurs de la batterie sont correctement fixés).

 Illustration 1 : Module logique Zélio + extension et alimentation 

Une fois cette première partie effectuée, nous pouvons passer au choix du fonctionnement, dans un premier temps, nous allons regarder les différents interrupteurs. Le premier en haut à droite permet de choisir si on veut être en mode AUTO sur la gestion du mode JOUR, ou si on veut avoir la main sur le mode JOUR/NUIT. Dans ce dernier cas, l’interrupteur en bas à gauche du pupitre permet le réglage forcé JOUR/NUIT. Si notre système doit être lancé pour de l’autonomie, mettre l’interrupteur en haut à gauche sur position photorésistance (un symbole est dessiné).  Pour être sûr d’être en AUTONOMIE, l’interrupteur en bas à droite doit être mis sur la position AUTO.

Maintenant, il faut regarder sur la carte principale CI (illustration 2 ci-dessous) la position du switch (55’’ ou 30’) :

Illustration 2 : Carte principal CI.

Le choix de cette position détermine le temps périodique de fonctionnement en journée pour régler l’orientation du panneau photovoltaïque. Le choix est donc de 55 secondes, ou de 30 minutes. Maintenant que vous avez mis en autonomie le système, il faut s’assurer qu’il n’y est aucun défaut symbolisé par la DEL rouge sur le pupitre (voir illustration 1) ou de message(s) affiché(s) sur l’écran du module logique ZELIO (voir illustration 1).

L’indicateur 0 à 10 (voir illustration 1) nous permet de visualiser l’intensité lumineuse via la petite cellule photoélectrique.

TRACKER SOLAIRE : Démontage pour déplacer le système

Pour pouvoir déplacer le système, il faut d’abord le mettre en position de rangement. Dans un premier temps, mettre l’interrupteur de mode AUTO/REGLAGE en position REGLAGE, puis appuyer sur le bouton 1 sous l’écran du ZELIO (voir illustration 1). Attendre que le système ne bouge plus et soit orienté plein SUD sur l’axe AZIMUT et que les cellules photovoltaïques doivent pointer vers l’horizon SUD. Une fois effectué, couper l’alimentation (disjoncteur C2 ou interrupteur Batterie).

Voici la position dans laquelle le système doit se trouver avant de couper l’alimentation.

Accéder au blocage du câble plat pour pouvoir le bouger.

Déloger le câble plat pour pouvoir le bouger complétement

Déconnecter le connecteur HE10 en délogeant les ailettes de blocage.

Soulever le plateau après avoir dévisser les écrous pour pouvoir extraire le câble plat.

Dégager délicatement le câble plat et fixé le avec les pièces de blocage permettant de maintenir les plis du câble HE10.

Positionner le plateau sur son support en polyester sur les deux guides filetés.

Fixer les écrous de blocage du plateau une fois positionné.

Voici le système une fois rangé. Effectuer le cheminement inverse pour le remontage.

       III.     Conclusion

Les étudiants qui reprendront ce projet pourront se baser sur le travail effectué dans la programmation du module logique. Remplacer les potentiomètres par des codeurs en 0-10 V permettrait de ne pas utiliser les amplificateurs opérationnels dédiés. En effet, l’usage des amplificateurs est principalement là pour ne pas avoir à débourser une grande somme dans des convertisseurs analogiques (la lecture directe sur les entrées ZELIO introduirait une erreur).

La carte principal CI peut être réutilisée pour le système de mise en marche, ainsi que le cycle de réveil (30 min, ou bien dessouder les résistances définies pour 30 min et refaire le calcul pour un autre temps ; ou bien encore placer un potentiomètre pour avoir le choix sur une plage). Il faudra certainement que les futurs étudiants se procurent un véritable anémomètre, ou bien adaptent les 3 transistors pour déporter le système sur le véritable panneau solaire.

Enfin, les étudiants pourront s’appuyer sur le travail effectue pour gérer la marche des moteurs, et adapter au système à mettre en place. Idem pour le gestion d’alimentation entre le secteur ou l’autonomie, et vérifier les règles pour la récupération des informations (signaux analogiques 0-10V) de courant moteur.

En annexe, il y les schémas électroniques des cartes d’interface, ainsi que les plans de fabrication de la maquette.

Les étudiants devront très certainement trouver un moyen d’inclure la carte principale et le module logique ZELIO dans un coffret dédié au système de Tracking.

IV. Annexe 

gestion partie tempête (avec anémomètre électronique)
recopie potentiomètres
partie réveil + alim AOP

PLAN DE CONCEPTION structure du système de suivis du SOLEIL

Bloc fonction REMISE A L’EST

code source :

Projet complet

ZELIO : https://iskia.fr/dl/zip_tracker_solaire_pierre_simon.zip