Cours | Projets Divers https://www.electronique-mixte.fr Cours | Projets Divers Pour les Ingénieurs & Futurs Ingénieurs Sun, 22 Jan 2023 17:17:55 +0000 fr-FR hourly 1 https://wordpress.org/?v=6.1.1 https://www.electronique-mixte.fr/wp-content/uploads/2019/09/cropped-logo-electroniques-mixte-inverse-e1568788097129-32x32.png Cours | Projets Divers https://www.electronique-mixte.fr 32 32 GRAFCET | Arduino #26: Inverseur de source – Réseau de secours – Partie III https://www.electronique-mixte.fr/grafcet-arduino-26-inverseur-de-source-reseau-de-secours-partie-iii/ https://www.electronique-mixte.fr/grafcet-arduino-26-inverseur-de-source-reseau-de-secours-partie-iii/#respond Sun, 22 Jan 2023 16:58:15 +0000 https://www.electronique-mixte.fr/?p=20484 GRAFCET | Arduino #26: Inverseur de source – Réseau de secours – Partie III was first posted on janvier 22, 2023 at 4:58 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  1. Savoir comment ça marche l’inverseur réseau
  2. Savoir commander un inverseur réseau avec Arduino
  3. Savoir comment détecter la présence d’un réseau
  4. Savoir convertir une entrée analogique en entrée digitale
  5. Etc.

Voir le tuto pour plus de détails.

Grafcet des transitions

Grafect arduino

Programme Arduino

Un extrait du code est disponible ci-dessous. Vous pouvez consulter le tuto pour plus de détails. Les codes des projets seront accessibles gratuitement en ligne à la fin de la série et à la publication du livre.

Conversion des entrées

word Analog2LogiV1(word in, word seuil)
{
if (in>=seuil) return 1;
else return 0;
}

word Analog2LogiV2(word nn, int pinAx, word seuil)
{
float somme=0.0, vmoy=0.0;

switch (pinAx)
{
case 0:
for(word i=0;i<nn; i++)somme+=(float)analogRead(A0);
vmoy=somme/(float)nn;
//Serial.print(vmoy); Serial.print(",");
if((word)vmoy>=seuil) return 1;
else return 0; break;

case 1:
for(word i=0;i<nn; i++)somme+=(float)analogRead(A1);
vmoy=somme/(float)nn;
//Serial.print(vmoy);Serial.print(","); Serial.println((float)analogRead(A1));
if((word)vmoy>=seuil) return 1;
else return 0; break;

case 2:
for(word i=0;i<nn; i++)somme+=(float)analogRead(A2);
vmoy=somme/(float)nn;
if((word)vmoy>=seuil) return 1;
else return 0; break;

case 3:
for(word i=0;i<nn; i++)somme+=(float)analogRead(A3);
vmoy=somme/(float)nn;
if((word)vmoy>=seuil) return 1;
else return 0; break;

case 4:
for(word i=0;i<nn; i++)somme+=(float)analogRead(A4);
vmoy=somme/(float)nn;
if((word)vmoy>=seuil) return 1;
else return 0; break;

case 5:
for(word i=0;i<nn; i++)somme+=(float)analogRead(A5);
vmoy=somme/(float)nn;
if((word)vmoy>=seuil) return 1;
else return 0; break;


default:
return 0;
}
}

Initialisation des E/S

void InitStateIO(bool *Etapes, word numEtapes, word *Inputs,word numIn,  word *Outputs, word numOut)
{
// Désactivation des étapes
for(word i=0;i<numEtapes;i++)
Etapes[i]=false;

// Activation d'une ou plusieurs étapes par défaut
Etapes[0]=true;

// Initialisation des entrées
for(word i=0;i<numIn;i++)
Inputs[i]=false;

// Initialisation des sorties
for(word i=0;i<numOut;i++)
Outputs[i]=false;

// Init des pins des entrées
pinMode(2, INPUT); // Dcy - Inputs[0]
// PrinActif -A0- Inputs[1]
// SecActif -A1- Inputs[2]

// Init des pins des sorties
pinMode(3, OUTPUT); // PSec - Outputs[0]
pinMode(4, OUTPUT); // StartSec
pinMode(5, OUTPUT); // P
pinMode(6, OUTPUT); // S - Inputs[4]
}

Lecture des entrées

void GetInputs(word *Inputss)
{
// Entrées digitales
Inputss[0]=digitalRead(2); // D2
Inputss[1]=Analog2LogiV2(N,0,VSeuil); // A0
Inputss[2]=Analog2LogiV2(N,1,VSeuil); // A1
}

Programme Arduino

La série GRAFCET…


GRAFCET | Arduino #26: Inverseur de source – Réseau de secours – Partie III was first posted on janvier 22, 2023 at 4:58 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/grafcet-arduino-26-inverseur-de-source-reseau-de-secours-partie-iii/feed/ 0
GRAFCET | Arduino #25: Inverseur de source – Réseau de secours – Partie II https://www.electronique-mixte.fr/grafcet-arduino-25-inverseur-de-source-reseau-de-secours-partie-ii/ https://www.electronique-mixte.fr/grafcet-arduino-25-inverseur-de-source-reseau-de-secours-partie-ii/#respond Sat, 14 Jan 2023 17:43:26 +0000 https://www.electronique-mixte.fr/?p=20476 GRAFCET | Arduino #25: Inverseur de source – Réseau de secours – Partie II was first posted on janvier 14, 2023 at 5:43 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  1. Savoir comment ça marche l’inverseur réseau
  2. Savoir commander un inverseur réseau avec Arduino
  3. Savoir programmer deux grafcets asynchrones
  4. Savoir comment détecter la présence d’un réseau
  5. Etc.

Architecture Matérielle

Le schéma de principe de l’inverseur est illustré dans la figure ci-dessous. Il est constitué d’une alimentation principale (1) et celle de secours (2). Les deux chargeurs servent à détecter le niveau de la tension des deux sources. On peut utiliser un chargeur 3.3V ou 5V en fonction de la carte Arduino utilisée (5V (Méga, Nano, Mini) ou 3.3V (Due)). Les sorties des chargeurs sont branchées dans les pins A0 et A1 de la carte Arduino successivement. La résistance 10K permet d’avoir la mise à la masse du signal en cas d’absence de l’alimentation afin d’éviter d’avoir une entrée flottante et ainsi réduire les parasites comme indiqué dans la figure.

Projet Inverseur de source Réseau de secours Arduino - Architecture

Grafcet

Voir le tuto pour plus de détails.

La série GRAFCET…


GRAFCET | Arduino #25: Inverseur de source – Réseau de secours – Partie II was first posted on janvier 14, 2023 at 5:43 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/grafcet-arduino-25-inverseur-de-source-reseau-de-secours-partie-ii/feed/ 0
GRAFCET | Arduino #24: Inverseur de source – Réseau de secours – Partie I https://www.electronique-mixte.fr/grafcet-arduino-24-inverseur-de-source-reseau-de-secours-partie-i/ https://www.electronique-mixte.fr/grafcet-arduino-24-inverseur-de-source-reseau-de-secours-partie-i/#respond Mon, 02 Jan 2023 18:27:50 +0000 https://www.electronique-mixte.fr/?p=20462 GRAFCET | Arduino #24: Inverseur de source – Réseau de secours – Partie I was first posted on janvier 2, 2023 at 6:27 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  1. Savoir comment ça marche l’inverseur réseau
  2. Savoir commander un inverseur réseau avec Arduino
  3. Savoir programmer deux grafcets asynchrones
  4. Savoir comment détecter la présence d’un réseau
  5. Etc.

La série GRAFCET…

 

 

 


GRAFCET | Arduino #24: Inverseur de source – Réseau de secours – Partie I was first posted on janvier 2, 2023 at 6:27 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/grafcet-arduino-24-inverseur-de-source-reseau-de-secours-partie-i/feed/ 0
Projet Commande de l’Intensité LASER avec un Encodeur Rotatif https://www.electronique-mixte.fr/projet-commande-de-lintensite-laser-avec-un-encodeur-rotatif/ https://www.electronique-mixte.fr/projet-commande-de-lintensite-laser-avec-un-encodeur-rotatif/#respond Mon, 10 Oct 2022 13:32:25 +0000 https://www.electronique-mixte.fr/?p=20426 Projet Commande de l’Intensité LASER avec un Encodeur Rotatif was first posted on octobre 10, 2022 at 1:32 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Applications

  • Capteur de vitesse & sens de rotation (encodeur optique)
  • Capteur angulaire
  • Asservissement de l’angle
  • Commutateur électromécanique multipositions
  • Curseur/ Slider électronique
  • Potentiomètre électromécanique linéaire
  • Etc.

Principe de fonctionnement

Le tuto est une application directe de l’utilisation d’un encodeur rotatif comme potentiomètre linéaire numérique. En effet, l’encodeur permet d’ajuster l’intensité d’un laser d’une façon progressive et linéaire. L’objectif est d’incrémenter ou décrémenter la valeur du rapport cyclique d’un signal PWM sur  8-bits avec un pas constant. Le pas est défini par l’utilisateur dans le programme. La valeur du rapport cyclique peut varier entre 0 (0%) et 255(100%).

Voir le tuto pour plus de détails.

Code Arduino

#define clkPin    2
#define dtPin 3
#define swPin 4 // Bouton Poussoir (Reset)

#define outPWM 8
#define StepPWM 15
#define numPWM 255 // Niveaux PWM


int nReset=1;

void setup()
{
//Init
Serial.begin(19200);
pinMode(clkPin,INPUT);
pinMode(dtPin,INPUT);
pinMode(swPin,INPUT_PULLUP);

pinMode(outPWM,OUTPUT);
analogWrite(outPWM,0);
}

void loop()
{
// Lecture de l'encodeur
nReset=digitalRead(swPin);
int R=encodUpDown(clkPin, dtPin, numPWM, StepPWM, 200, nReset);

// Affichage (Test)
Serial.print(R); Serial.print("\t");
Serial.println(R);

// Mise à jour intensité
analogWrite(outPWM,R);
}

int encodUpDown(int clkpin, int dtpin, int rotmax,int stpwm, int delay_ms, int nrst)
{
static int rotVal = 0;
static bool clkState = LOW, clkLast = HIGH;

clkState = digitalRead(clkpin);
if ((clkLast == LOW) && (clkState == HIGH))
{
if (digitalRead(dtpin) == HIGH) // Down
{
rotVal-=stpwm;
if ( rotVal < 0) rotVal = 0;
}
else // Up
{
rotVal+=stpwm;
if ( rotVal >= rotmax)rotVal = rotmax;
}
delay(delay_ms);
}
clkLast = clkState;

// Init
if (nrst==0)
{
rotVal = 0;
clkState = LOW;
clkLast = HIGH;
}
return rotVal;
}

Projet Commande de l’Intensité LASER avec un Encodeur Rotatif was first posted on octobre 10, 2022 at 1:32 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-commande-de-lintensite-laser-avec-un-encodeur-rotatif/feed/ 0
Projet Encodeur Rotatif avec Arduino https://www.electronique-mixte.fr/projet-encodeur-rotatif-avec-arduino/ https://www.electronique-mixte.fr/projet-encodeur-rotatif-avec-arduino/#respond Sun, 09 Oct 2022 06:41:56 +0000 https://www.electronique-mixte.fr/?p=20416 Projet Encodeur Rotatif avec Arduino was first posted on octobre 9, 2022 at 6:41 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir le fonctionnement d’un encodeur rotatif
  • Savoir utiliser un encodeur
  • Savoir les caractéristiques d’un encodeur
  • Savoir les limites de l’encodeur
  • Etc.

Applications

Qu’est-ce qu’encodeur rotatif ?

Un encodeur rotatif est un dispositif électromécanique qui permet de savoir l’angle ainsi la direction de la rotation. Il est constitué d’un curseur tournant comme celui du potentiomètre, mais graduel. Le nombre de pas du curseur par tour caractérise la résolution de l’encodeur. L’encodeur ci-dessous est constitué de 10 pas (ou micro-tous) par tour complète du curseur.

Le module KY-040

Le module KY-040 est un exemple d’un encodeur rotatif. Il dispose de trois sorties TOR et 10 micro-pas. Un front descendant apparut dans la sortie CLK (horloge) au moment de la détection d’une transition dans le curseur dans un sens ou dans l’autre sens.  En parallèle, la sortie DT (direction) est positionnée en fonction du sens de rotation du curseur : DT=’0′ (Sens 1), DT=’1′ (Sens 2). Le module dispose aussi d’un bouton poussoir monté sur le curseur (il faut appuyer sur le curseur pour enclencher le bouton poussoir).

Encodeur rotatif arduino

Voir le tuto concernant la procédure de la lecture de ‘encodeur ainsi les défauts de ce type de l’encodeur.

Programme Arduino

Le code ci-dessous permet de lire la position de l’encodeur en utilisant la fonction getRot(). Le bouton poussoir est utilisé pour initialiser le compteur de rotation.

#define clkPin    2
#define dtPin 3
#define swPin 4 // Bouton Poussoir (Reset)
#define numPos 10 // de 0 à numPos-1


int nReset=1;

void setup()
{
//Init
Serial.begin(9600);
pinMode(clkPin,INPUT);
pinMode(dtPin,INPUT);
pinMode(swPin,INPUT_PULLUP);
}

void loop()
{
nReset=digitalRead(swPin);
int R=getRot(clkPin, dtPin, numPos,200, nReset);
Serial.print(R); Serial.print("\t");
Serial.println(R);
}

int getRot(int clkpin, int dtpin, int rotmax, int delay_ms, int nrst)
{
static int rotVal = 0;
static bool clkState = LOW, clkLast = HIGH;

clkState = digitalRead(clkpin);
if ((clkLast == LOW) && (clkState == HIGH))
{
if (digitalRead(dtpin) == HIGH) // Down
{
rotVal--;
if ( rotVal < 0) rotVal = rotmax-1;
}
else // Up
{
rotVal++;
if ( rotVal >= rotmax)rotVal = 0;
}
delay(delay_ms);
}
clkLast = clkState;

// Init
if (nrst==0)
{
rotVal = 0;
clkState = LOW;
clkLast = HIGH;
}
return rotVal;
}

Projet Encodeur Rotatif avec Arduino was first posted on octobre 9, 2022 at 6:41 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-encodeur-rotatif-avec-arduino/feed/ 0
Projet Tachymètre LASER avec Arduino https://www.electronique-mixte.fr/projet-tachymetre-laser-avec-arduino/ https://www.electronique-mixte.fr/projet-tachymetre-laser-avec-arduino/#respond Wed, 05 Oct 2022 05:55:46 +0000 https://www.electronique-mixte.fr/?p=20411 Projet Tachymètre LASER avec Arduino was first posted on octobre 5, 2022 at 5:55 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir le fonctionnement d’un tachymètre LASER  Tx/Rx
  • Savoir utiliser une photorésistance
  • Savoir les limites d’une photorésistance
  • Savoir utiliser un LASER comme capteur de vitesse
  • Etc.

Programme Arduino

#define     Seuil   600.0
void setup()
{
// ADC
analogReadResolution(12); // Ajustable <= 12 (4096 Niveaux)

// Affichage
Serial.begin(250000);
}

void loop()
{
// Lecture
float V1=(float)analogRead(A0);
V1=(V1*3.3/4095.0)*1000.0;
float V2=3300.0*(V1<Seuil);

// Affichage
Serial.print(V1); Serial.print("\t");
Serial.println(V2);
delay(10);
}

Projet Tachymètre LASER avec Arduino was first posted on octobre 5, 2022 at 5:55 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-tachymetre-laser-avec-arduino/feed/ 0
Analyse fréquentielle #7: Le fenêtrage – Implémentation avec Arduino https://www.electronique-mixte.fr/analyse-frequentielle-7-le-fenetrage-implementation-avec-arduino/ https://www.electronique-mixte.fr/analyse-frequentielle-7-le-fenetrage-implementation-avec-arduino/#respond Mon, 03 Oct 2022 07:09:30 +0000 https://www.electronique-mixte.fr/?p=20396 Analyse fréquentielle #7: Le fenêtrage – Implémentation avec Arduino was first posted on octobre 3, 2022 at 7:09 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir implémenter le fenêtrage avec Arduino
  • Savoir supprimer la composante DC d’un signal
  • Savoir la forme mathématique des fenêtres basiques
  • Comprendre la notion du fenêtrage
  • Savoir l’utilité du fenêtrage
  • Savoir les différents types des fenêtres
  • Introduire la carte Portenta H7
  • Savoir implémenter la DFT en C/Arduino
  • Test de la DFT sur Arduino Mega/Due
  • Analyse des performances temporelles du code sur Mega/Due
  • Analyse de la DFT d’un signal sinusoïdal
  • Analyse de la DFT d’une entrée réelle
  • Prendre consciente du problème du sur-échantillonnage
  • Etc.

Voir le tuto pour plus de détails

exemple Le fenêtrage Implémentation sur Arduino1

La fonction getData()

float getData(float *dataout,int nn, unsigned long ts_us, int analogpin, float gain, int noDC)

Nous avons optimisé la fonction getData() utilisée dans le tuto afin d’obtenir une mesure précise de la fréquence. Elle permet de lire un buffer de données de taille N dans un pin analogique. La fonction peut supprimer ou non la composante DC du signal, ainsi l’ajustement du gain du signal acquis. Elle retourne la valeur approchée de la fréquence d’échantillonnage ainsi le tableau des données. Ci-dessous la définition de la fonction.

float getData(float *dataout,int nn, unsigned long ts_us, int analogpin, float gain, int noDC)
{
// Lecture des données brutes
float ts_f=0.0;
unsigned long t11;
for(int i=0; i<nn; i++)
{
t11=micros();
dataout[i]=(float)analogRead(54+analogpin);
delayMicroseconds(ts_us);
ts_f+=(float)micros()-(float)t11;
}
ts_f=ts_f/(float)nn;

// Conversion en V
for(int i=0; i<nn; i++)
dataout[i]=gain*dataout[i]*3.3/4095.0;

// Suppression de la valeur DC
if(noDC==0)
{
float Vm=0.0;
for(int i=0; i<nn;i++) Vm+=dataout[i];
Vm/=(float)nn;
for(int i=0; i<nn;i++) dataout[i]=dataout[i]-Vm;
}
return 1E6/ts_f;
}

La fonction setWindow()

float setWindow(float *datain, float *dataout, int n, int type)

La fonction setWindow() permet d’appliquer une fenêtre à un buffer de données. Elle prend en entrée le buffer et sa taille, ainsi le type de la fenêtre :

  • Type=0: Fenêtre de Hann
  • Type=1: Fenêtre de Hamming
  • Type=2: Fenêtre de Blackman
  • Type=3: Fenêtre Gaussienne
  • Type=4: Fenêtre Sin²
  • Type=X: Sans Fenêtre

Les amplitudes sont corrigées par rapport à un coefficient constant. Ci-dessous la définition de la fonction.

float getData(float *dataout,int nn, unsigned long ts_us, int analogpin, float gain, int noDC)
{
// Lecture des données brutes
float ts_f=0.0;
unsigned long t11;
for(int i=0; i<nn; i++)
{
t11=micros();
dataout[i]=(float)analogRead(54+analogpin);
delayMicroseconds(ts_us);
ts_f+=(float)micros()-(float)t11;
}
ts_f=ts_f/(float)nn;

// Conversion en V
for(int i=0; i<nn; i++)
dataout[i]=gain*dataout[i]*3.3/4095.0;

// Suppression de la valeur DC
if(noDC==0)
{
float Vm=0.0;
for(int i=0; i<nn;i++) Vm+=dataout[i];
Vm/=(float)nn;
for(int i=0; i<nn;i++) dataout[i]=dataout[i]-Vm;
}
return 1E6/ts_f;
}




float setWindow(float *datain, float *dataout, int n, int type)
{
float Hi, t=0.0,t0=0.0, sig=0.0;
const float gain[6]={0.5581,0.5934,0.4765,0.6456,0.5581,1.0000};

switch(type)
{
//Fenêtre de Hann
case 0:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=0.5-0.5*cos(2.0*PI*t);
dataout[i]=Hi*datain[i];
}
return gain[type];

//Fenêtre de Hamming
case 1:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=0.54-0.46*cos(2.0*PI*t);
dataout[i]=Hi*datain[i];
}
return gain[type];

// Fenêtre de Blackman
case 2:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=0.42-0.5*cos(2.0*PI*t)+0.08*cos(4.0*PI*t);
dataout[i]=Hi*datain[i];
}
return gain[type];

//Fenêtre de Gauss
case 3:
for(int i=0;i<n; i++)
{
t=((float)i/float(n))-0.5;
t0=0.5;
sig=t0/2.0;
Hi=exp(-0.5*t*t/(sig*sig));
dataout[i]=Hi*datain[i];
}
return gain[type];

//Fenêtre sin²
case 4:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=sin(2.0*0.5*PI*t)*sin(2.0*0.5*PI*t); // sin(x)²=(1-cos(2x))/2
dataout[i]=Hi*datain[i];
}
return gain[type];

default:
for(int i=0;i<n; i++)
{
dataout[i]=datain[i];
}
return gain[5];
}
}

Programme Complet

#define squareOut   8       // Sortie Carrée

#define N 256 // Données N=2^n, TFD Nf=2^(n-1)
// Agit sur la Résolution fréquentielle!!!!!!!!
// df= Fs/N

#define Ts_us 100 // Ts=1/Fs: Approchée (voir le programme)
// Agit sur la fréquence MAX du spéctre!!!!!!!!
// FMXA = Fs/2
/*
Type=0: Fenêtre de Hann
Type=1: Fenêtre de Hamming
Type=2: Fenêtre de Blackman
Type=3: Fenêtre Gaussienne
Type=4: Fenêtre Sin²
Type=X: Sans Fenêtre
*/


bool State=false;
unsigned long T1=0, T2=0, T3=0;
float Ts=0.0, Fs=0.0;
float Data[N],Data1[N], Nfft=N>>1;
float dF=0.0;
float MaxIdMax[2]={0.0,0.0};
float Am, ReIm[2]={0.0,0.0};


const float q=1.0/4096.0;


void setup()
{
// ADC
analogReadResolution(12); // Ajustable <= 12 (4096 Niveaux)

// Sortie
analogWrite(squareOut,128); // 1 KHz

// Affichage
Serial.begin(250000);
}


void loop()
{
/*
* Analyse Temporelle des Fenêtres
*/

// 1.1 Lecture des données
Fs=getData(Data, N, Ts_us, 0, 1000.0,0);
//Serial.println(Fs); return;

// 1.2 Fenêtrage
int N0=6;
float Datai[N0][N], Coefs[N0];
for(int i=0;i<N0; i++)
Coefs[i]=setWindow(Data, Datai[i], N, i);

// 1.3 Visualisation
static bool state=false;
if(state==false)
{
Serial.println("");
for (int i=0;i<N;i++)
{
Serial.print(Datai[0][i]); Serial.print("\t");
Serial.print(Datai[1][i]); Serial.print("\t");
Serial.print(Datai[2][i]); Serial.print("\t");
Serial.print(Datai[3][i]); Serial.print("\t");
Serial.print(Datai[4][i]); Serial.print("\t");
Serial.println(Datai[5][i]);
}
Serial.println("");
state=!state;
}
return;



/*
* Analyse Fréquentielle des Fenêtres
*/

// 2.1 DFT
float RealFFT[N0][N], ImagFFT[N0][N];
for(int i=0;i<N0; i++)
dF=DFT(Datai[i], N, RealFFT[i], ImagFFT[i], Fs);

// 2.2 Affichage
/*
static bool state=false;
float A;
if(state==false)
{
Serial.println("");
for (int i=1;i<N>>1;i++)
{
Serial.print((i-1)*dF); Serial.print("\t");

A=sqrt(RealFFT[0][i]*RealFFT[0][i]+ImagFFT[0][i]*ImagFFT[0][i])/(float)N;
Serial.print(A/Coefs[0]); Serial.print("\t");

A=sqrt(RealFFT[1][i]*RealFFT[1][i]+ImagFFT[1][i]*ImagFFT[1][i])/(float)N;
Serial.print(A/Coefs[1]); Serial.print("\t");

A=sqrt(RealFFT[2][i]*RealFFT[2][i]+ImagFFT[2][i]*ImagFFT[2][i])/(float)N;
Serial.print(A/Coefs[2]); Serial.print("\t");

A=sqrt(RealFFT[3][i]*RealFFT[3][i]+ImagFFT[3][i]*ImagFFT[3][i])/(float)N;
Serial.print(A/Coefs[3]); Serial.print("\t");

A=sqrt(RealFFT[4][i]*RealFFT[4][i]+ImagFFT[4][i]*ImagFFT[4][i])/(float)N;
Serial.print(A/Coefs[4]); Serial.print("\t");

A=sqrt(RealFFT[5][i]*RealFFT[5][i]+ImagFFT[5][i]*ImagFFT[5][i])/(float)N;
Serial.println(A/Coefs[5]);
}
Serial.println("");
state=!state;
}
*/
}


float getData(float *dataout,int nn, unsigned long ts_us, int analogpin, float gain, int noDC)
{
// Lecture des données brutes
float ts_f=0.0;
unsigned long t11;
for(int i=0; i<nn; i++)
{
t11=micros();
dataout[i]=(float)analogRead(54+analogpin);
delayMicroseconds(ts_us);
ts_f+=(float)micros()-(float)t11;
}
ts_f=ts_f/(float)nn;

// Conversion en V
for(int i=0; i<nn; i++)
dataout[i]=gain*dataout[i]*3.3/4095.0;

// Suppression de la valeur DC
if(noDC==0)
{
float Vm=0.0;
for(int i=0; i<nn;i++) Vm+=dataout[i];
Vm/=(float)nn;
for(int i=0; i<nn;i++) dataout[i]=dataout[i]-Vm;
}
return 1E6/ts_f;
}

float setWindow(float *datain, float *dataout, int n, int type)
{
float Hi, t=0.0,t0=0.0, sig=0.0;
const float gain[6]={0.5581,0.5934,0.4765,0.6456,0.5581,1.0000};

switch(type)
{
//Fenêtre de Hann
case 0:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=0.5-0.5*cos(2.0*PI*t);
dataout[i]=Hi*datain[i];
}
return gain[type];

//Fenêtre de Hamming
case 1:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=0.54-0.46*cos(2.0*PI*t);
dataout[i]=Hi*datain[i];
}
return gain[type];

// Fenêtre de Blackman
case 2:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=0.42-0.5*cos(2.0*PI*t)+0.08*cos(4.0*PI*t);
dataout[i]=Hi*datain[i];
}
return gain[type];

//Fenêtre de Gauss
case 3:
for(int i=0;i<n; i++)
{
t=((float)i/float(n))-0.5;
t0=0.5;
sig=t0/2.0;
Hi=exp(-0.5*t*t/(sig*sig));
dataout[i]=Hi*datain[i];
}
return gain[type];

//Fenêtre sin²
case 4:
for(int i=0;i<n; i++)
{
t=(float)i/float(n);
Hi=sin(2.0*0.5*PI*t)*sin(2.0*0.5*PI*t); // sin(x)²=(1-cos(2x))/2
dataout[i]=Hi*datain[i];
}
return gain[type];

default:
for(int i=0;i<n; i++)
{
dataout[i]=datain[i];
}
return gain[5];
}
}

float DFT(float *data, int Ndata, float *real, float *imag, float fs)
{
int nfft=floor((float)Ndata/2.0);
float df=(fs/2.0)/(float)nfft;
float somme_r=0.0, somme_i=0.0;
float wt=0.0;

for (int i=0; i<nfft; i++)
{
for (int j=0; j<Ndata; j++)
{
wt=-2.0*PI*(float)i*(float)j/Ndata;
somme_r+=data[j]*cos(wt);
somme_i+=data[j]*sin(wt);
}
real[i]= somme_r; somme_r=0.0;
imag[i]= somme_i; somme_i=0.0;
}
return df;
}

Analyse fréquentielle #7: Le fenêtrage – Implémentation avec Arduino was first posted on octobre 3, 2022 at 7:09 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-7-le-fenetrage-implementation-avec-arduino/feed/ 0
Analyse fréquentielle #6: Le fenêtrage – Simulation https://www.electronique-mixte.fr/analyse-frequentielle-6-le-fenetrage-simulation/ https://www.electronique-mixte.fr/analyse-frequentielle-6-le-fenetrage-simulation/#respond Sat, 01 Oct 2022 15:07:43 +0000 https://www.electronique-mixte.fr/?p=20389 Analyse fréquentielle #6: Le fenêtrage – Simulation was first posted on octobre 1, 2022 at 3:07 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Comprendre la notion du fenêtrage
  • Savoir l’utilité du fenêtrage
  • Savoir les différents types des fenêtres
  • Introduire la carte Portenta H7
  • Savoir implémenter la DFT en C/Arduino
  • Test de la DFT sur Arduino Mega/Due
  • Analyse des performances temporelles du code sur Mega/Due
  • Analyse de la DFT d’un signal sinusoïdal
  • Analyse de la DFT d’une entrée réelle
  • Prendre consciente du problème du sur-échantillonnage
  • Etc.

Voir le tuto pour plus de détails

Programme Complet

clear all; close all; clc;


%% Analyse Temporelle

N=2^13;
f0=1;t0=1/f0;
t=linspace(0,(10+1/3)*t0,N);
ts=t(2)-t(1); fs=1/ts;
s_t=5*sin(2*pi*f0*t)+sin(2*pi*2*f0*t)+sin(2*pi*10*f0*t);

% Fenêtres de Hann
Hh(1,:)=hann(N); % Fenêtres de Hann
Hh(2,:)=blackman(N); % Fenêtre de Hamming
Hh(3,:)=hamming(N); % Fenêtre de Blackman
Hh(4,:)=gaussmf(t,[t(end)/5 t(end)/2]); % Fenêtre Gaussienne
ti=linspace(0,1,N);Hh(5,:)=sin(2*pi*0.5*ti).^2; % Fenêtre sin²

figure(1)
plot(t,Hh','lineWidth',2);xlim([t(1) t(end)]);grid on;
legend({'hann','blackman','hamming','Gauss','Sin²'},'fontsize',13);
% return;



%% Analyse Fréquentielle

% Fenêtrage
for i=1:5
s_tf(i,:)=s_t.*Hh(i,:);
end;
s_tf(6,:)=s_t;


% FFT
nfft=N;
for i=1:6
s_fm(i,:)=fft(s_tf(i,:), nfft);
end;
df=fs/N;
f=linspace(-fs/2-df,fs/2,nfft);

% Affichage
figure(2);
subplot(211);
plot(t,s_tf,'lineWidth',2); grid on; xlim([t(1) t(end)]);
legend({'hann','blackman','hamming','Gauss','Sin²','Sans Fenêtre'},'fontsize',13);

subplot(212);
plot(f,20*log10(fftshift(abs(s_fm)/(N))),'lineWidth',2); grid on;xlim([-20*f0 20*f0]);
legend({'hann','blackman','hamming','Gauss','Sin²','Sans Fenêtre'},'fontsize',13);

Analyse fréquentielle #6: Le fenêtrage – Simulation was first posted on octobre 1, 2022 at 3:07 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-6-le-fenetrage-simulation/feed/ 0
Capteur | Arduino #11: Touche Optique IR https://www.electronique-mixte.fr/capteur-arduino-11-touche-optique-ir/ https://www.electronique-mixte.fr/capteur-arduino-11-touche-optique-ir/#respond Sun, 25 Sep 2022 10:08:40 +0000 https://www.electronique-mixte.fr/?p=20381 Capteur | Arduino #11: Touche Optique IR was first posted on septembre 25, 2022 at 10:08 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF


 

Objectifs

  1. Savoir le fonctionnement d’une touche optique
  2. Savoir utiliser un détecteur IR
  3. Savoir filtrer un signal TOR avec Arduino
  4. Savoir régler le seuil de sensibilité
  5. Etc.

Voir le tuto pour plus de détails

Programme Arduino

void setup()
{
// ADC
analogReadResolution(12); // Ajustable <= 12 (4096 Niveaux)

// Affichage
Serial.begin(250000);
}

void loop()
{
// Lecture
float V1=(float)analogRead(A0);
V1=(V1*3.3/4095.0)*1000.0;
float V2=3000.0*(V1<1000.0);

// Affichage
Serial.print(V1); Serial.print("\t");
Serial.println(V2);
delay(25);
}

Capteur | Arduino #11: Touche Optique IR was first posted on septembre 25, 2022 at 10:08 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/capteur-arduino-11-touche-optique-ir/feed/ 0
Tachymètre Numérique #3: Mesure de la vitesse – Technique II https://www.electronique-mixte.fr/tachymetre-numerique-3-mesure-de-la-vitesse-technique-ii/ https://www.electronique-mixte.fr/tachymetre-numerique-3-mesure-de-la-vitesse-technique-ii/#respond Sat, 24 Sep 2022 11:04:06 +0000 https://www.electronique-mixte.fr/?p=20362 Tachymètre Numérique #3: Mesure de la vitesse – Technique II was first posted on septembre 24, 2022 at 11:04 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  1. Savoir l’importance du capteur à effet Hall
  2. Savoir utiliser un compteur de vitesse
  3. Savoir l’utilité du capteur de vitesse
  4. Savoir les caractéristiques du compteur
  5. Savoir mesurer la vitesse de rotation d’un moteur
  6. Savoir mesurer la fréquence d’un signal (deux méthodes)
  7. Savoir utiliser un tachymètre pour la mesure de la vitesse
  8. Savoir réduire l’erreur de la mesure
  9. Savoir mesurer la largeur d’une impulsion
  10. Etc.

Caractéristiques du compteur de vitesse

Compteur de vitesse

Le compteur de vitesse est similaire à un fréquencemètre numérique. Elle permet de mesurer la fréquence d’un signal TOR.  Il suffit de multiplier la fréquence par 60 pour en déduire la vitesse en tr/min (RPM). Le module contient un µC STM8S003F3 et un afficheur 4 digits. Ci-dessous les caractéristiques techniques de l’afficheur.

  • Modèle : CF5135C-Z
  • Microcontrôleur : STM8S003F3
  • Capteur de proximité : NJK-5002C
  • Type d’affichage : affichage LED
  • Couleur de l’écran : Bleu
  • Tension de travail : 8-24V DC
  • Courant : 30 ~ 200mA
  • Plage de mesure : 10-9999 rpm (0.16-166 Hz)
  • Précision : 0.1%
  • Taux de rafraîchissement de l’écran : >3 fois / s (3 Hz)
  • Dimensions de l’installation : 76 x 39mm
  • Dimensions : 79 x 32 x 42mm
  • Poids net: 108g

Voir le tuto pour un câblage correct (sans incident) de l’afficheur).

pinout afficheur de vitesse

Caractéristiques du capteur magnétique

Datasheet du capteur ICI. 

Programme Arduino

Le programme est identique à celui utilisé dans la partie 2 (voir le tuto pour plus de détails techniques).

#define squareOut   8             // Sortie Carrée
#define F0 984.0 // Valeur approchée de la fréquence


void setup()
{
// ADC
analogReadResolution(12); // Ajustable <= 12 (4096 Niveaux)

// Output
analogWrite(squareOut,128); // 0-255

// Input
pinMode(squareOut+1, INPUT);

// Affichage
Serial.begin(250000);
}

void loop()
{
//Serial.println(analogRead(A0)); delay(100); return; // TEST!!


// 1. Mesure via la fonction pulseIn()
/*
unsigned long T_l=pulseIn(squareOut+1, LOW);
unsigned long T_h=pulseIn(squareOut+1, HIGH);
Serial.print(1.0/((float)(T_l)*2.0*1E-6));Serial.print("\t");
Serial.print(1.0/((float)(T_h)*2.0*1E-6));Serial.print("\t");
//Serial.println(1.0/((float)(T_l+T_h)*1E-6));return;
Serial.print(1.0/((float)(T_l+T_h)*1E-6));Serial.print("\t");
*/

// 2. Mesure via la fonction getFreqHz()
int nn=1024; // Filtrage de la fréquence
float F=0.0; // Fréquence en Hz
int s_max=1000; // Seuil maximal
int s_min=100; // Seuil minimal
int Pin=0; // Pin A0, (1)A1, (2)A2, etc.

// Mesure de la fréquence (Pins Analogiques!!)
for(int i=0; i<nn; i++)F+=getFreqHz(Pin, s_max,s_min);
F=F/(float)nn;

// Affichage
Serial.println(F*60.0);
}


float getFreqHz(int Ai, int s_max, int s_min)
{
static long T_2=0, T_1=0;
static int ai_1=0, ai_2=0;
static float freq=0.0;

ai_1=analogRead(54+Ai);
if((ai_2-ai_1)>s_max)
{
T_2=micros()-T_1;
freq=1.0/((float)T_2*1E-6);
T_1=micros();
}
ai_2=ai_1;
return freq;
}

Tachymètre Numérique #3: Mesure de la vitesse – Technique II was first posted on septembre 24, 2022 at 11:04 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/tachymetre-numerique-3-mesure-de-la-vitesse-technique-ii/feed/ 0
Tachymètre Numérique #2: Mesure de la vitesse – Technique I https://www.electronique-mixte.fr/tachymetre-numerique-2-mesure-de-la-vitesse-technique-i/ https://www.electronique-mixte.fr/tachymetre-numerique-2-mesure-de-la-vitesse-technique-i/#respond Wed, 21 Sep 2022 08:49:26 +0000 https://www.electronique-mixte.fr/?p=20341 Tachymètre Numérique #2: Mesure de la vitesse – Technique I was first posted on septembre 21, 2022 at 8:49 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  1. Savoir mesurer la vitesse de rotation d’un moteur
  2. Savoir mesurer la fréquence d’un signal (deux méthodes)
  3. Savoir utiliser un tachymètre pour la mesure de la vitesse
  4. Savoir réduire l’erreur de la mesure
  5. Savoir mesurer la largeur d’une impulsion
  6. Etc.

Comment mesurer la vitesse de rotation ?

La mesure de la vitesse de rotation en (tr/min) est équivalente à la mesure de la fréquence de rotation en nombre de cycles par seconde (Hz). En effet,  60 tr/min est égale à 60 cycles/min=60 cycles/(60 secondes) = 1 Hz!  D’une autre façon, la vitesse de rotation en (tr/min) et 60 fois inférieure à la fréquence de rotation en (Hz). Par conséquence, la mesure de vitesse est réduit à la mesure de la fréquence de rotation. Dans ce tuto, on va aborder deux fonctions qui vont nous permettre la mesure de la fréquence d’un signal tout ou rien, en particulier un signal carré. La formule de la vitesse en tours par minute (rpm) en Hertz (Hz) est donnée par F=N/60. Avec :

  •   la fréquence en Hertz (Hz)
  •   la vitesse angulaire en tours par minute (rpm ou tr/min)

La fonction pulseIn()

La fonction pulseIn() comme son nom l’indique, elle permet de mesurer la largeur ou la durée d’une impulsion. Le type de l’impulsion peut être niveau bas ou niveau haut. Dans le cas d’un signal carré, les deux durées sont identiques. La fréquence est donc l’inverse de la somme des deux niveaux ou le double de l’un des deux. La fonction prend en entrée la numération du pin digital, le type du niveau ainsi le timeout (optionnel). Elle retourne la durée de l’impulsion en nombre de cycles en µS.  Par exemple, si la valeur du retour est égale à 1000, alors la durée réelle de l’impulsion est égale à 1000*10^(-6)=1 ms. Par conséquent, la fréquence est égale à 1/(2*1ms)=500 Hz. Le timeout par défaut est égal à 1 seconde s’il n’est pas spécifié.

La fonction peu uniquement mesurée la fréquence dans un pin digital. Du coup, il faut lui fournir un signal ayant des niveaux compatibles avec la carte (0-5V, 0-3.3V, etc.).  Ci-desosus la définiton de la fonction

 

pulseIn(pin, value)
pulseIn(pin, value, timeout)

 

Ci-dessous l’exemple du code utilisé pour la mesure de la fréquence du signal branché dans le pin squareOut+1 (voir le tuto pour plus de détails).

  unsigned long T_l=pulseIn(squareOut+1, LOW);
unsigned long T_h=pulseIn(squareOut+1, HIGH);
Serial.print(1.0/((float)(T_l)*2.0*1E-6));Serial.print("\t");
Serial.print(1.0/((float)(T_h)*2.0*1E-6));Serial.print("\t");
//Serial.println(1.0/((float)(T_l+T_h)*1E-6));return;
Serial.print(1.0/((float)(T_l+T_h)*1E-6));Serial.print("\t");

La fonction getFreqHz()

La fonction getFreqHz() est une fonction fait maison dédiée à la mesure directe de la fréquence d’un signal carré (ou non) branché dans un pin analogique. Elle est basée sur la fonction micros() pour la mesure du temps en µS. La fonction prend en entrée la numérotation du pin, anis le seuil maximale et le seuil minimal (non utilisé) de la détection. Si par exemple le signal branché dans le pin analogique varié entre 0 et 500. Alors, on peut définir un seuil maximal de l’ordre de la moitié de la dynamique (~250) afin de discriminer entre le niveau bas et le niveau haut réel du signal. Ensuite la fonction dérive le signal pour en extraire seulement le font montant (dérivée > seuil) ou le front descendant (dérivée <-seuil). De plus, un front est disponible par période. Par conséquent, on lance une temporisation T0=micros() à la détection du premier front, puis on mesure la fréquence au prochain front (F=1/(micros()-T0)), etc. Ci-dessous la définition de la fonction.

float getFreqHz(int Ai, int s_max, int s_min)
{
static long T_2=0, T_1=0;
static int ai_1=0, ai_2=0;
static float freq=0.0;

ai_1=analogRead(54+Ai);
if((ai_2-ai_1)>s_max)
{
T_2=micros()-T_1;
freq=1.0/((float)T_2*1E-6);
T_1=micros();
}
ai_2=ai_1;
return freq;
}

Attention : La fonction effectue une lecture du signal par appel. Alors, il faut faire des multiples appels qui garantissent la détection de la transition du signal et garantir une bonne résolution de la mesure. La mise à jour la fréquence ne s’effectuée qu’à la détection d’une transition. Il ne faut pas intégrer aussi les retards dans la boucle qui peuvent prolonger la durée de la détection et introduire des fausses mesures.

Programme complet

#define squareOut   8             // Sortie Carrée
#define F0 984.0 // Valeur approchée de la fréquence


void setup()
{
// ADC
analogReadResolution(12); // Ajustable <= 12 (4096 Niveaux)

// Output
analogWrite(squareOut,128); // 0-255

// Input
pinMode(squareOut+1, INPUT);

// Affichage
Serial.begin(250000);
}

void loop()
{
//Serial.println(analogRead(A0)); delay(100); return; // TEST!!


// 1. Mesure via la fonction pulseIn()
/*
unsigned long T_l=pulseIn(squareOut+1, LOW);
unsigned long T_h=pulseIn(squareOut+1, HIGH);
Serial.print(1.0/((float)(T_l)*2.0*1E-6));Serial.print("\t");
Serial.print(1.0/((float)(T_h)*2.0*1E-6));Serial.print("\t");
//Serial.println(1.0/((float)(T_l+T_h)*1E-6));return;
Serial.print(1.0/((float)(T_l+T_h)*1E-6));Serial.print("\t");
*/

// 2. Mesure via la fonction getFreqHz()
int nn=1024; // Filtrage de la fréquence
float F=0.0; // Fréquence en Hz
int s_max=1000; // Seuil maximal
int s_min=100; // Seuil minimal
int Pin=0; // Pin A0, (1)A1, (2)A2, etc.

// Mesure de la fréquence (Pins Analogiques!!)
for(int i=0; i<nn; i++)F+=getFreqHz(Pin, s_max,s_min);
F=F/(float)nn;

// Affichage
Serial.println(F*60.0);
}


float getFreqHz(int Ai, int s_max, int s_min)
{
static long T_2=0, T_1=0;
static int ai_1=0, ai_2=0;
static float freq=0.0;

ai_1=analogRead(54+Ai);
if((ai_2-ai_1)>s_max)
{
T_2=micros()-T_1;
freq=1.0/((float)T_2*1E-6);
T_1=micros();
}
ai_2=ai_1;
return freq;
}

N’oublier de nous laisser un commentaire 🙂


Tachymètre Numérique #2: Mesure de la vitesse – Technique I was first posted on septembre 21, 2022 at 8:49 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/tachymetre-numerique-2-mesure-de-la-vitesse-technique-i/feed/ 0
Tachymètre Numérique #1: Introduction du capteur https://www.electronique-mixte.fr/tachymetre-numerique-1-introduction-du-capteur/ https://www.electronique-mixte.fr/tachymetre-numerique-1-introduction-du-capteur/#respond Sun, 18 Sep 2022 17:16:35 +0000 https://www.electronique-mixte.fr/?p=20325 Tachymètre Numérique #1: Introduction du capteur was first posted on septembre 18, 2022 at 5:16 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Comment ça marche un Capteur à effet Hall ?

Leur principe est basé sur une découverte déjà ancienne. En 1879, le physicien américain Edwin Herbert Hall découvre que si l’on introduit un élément conducteur de courant dans un champ électromagnétique, il apparaît alors une force électromotrice proportionnelle au champ magnétique appliqué et au courant qui traverse le conducteur. C’est l’effet Hall. Un capteur à effet hall donne donc un signal lorsqu’il détecte un champ magnétique. La tension de Hall est alors amplifiée dans le capteur. Lire la suite…

Principe de fonctionnement

Capteur magnétique

Basé sur la découverte de l’effet Hall par Edwin H. Hall en 1879, c’est une conséquence de la loi de la force de Lorentz, qui stipule que lorsqu’une charge q se déplaçant à la vitesse v est sollicitée par un champ d’induction magnétique B, elle est soumise à une force F, perpendiculaire au champ électrique E, exprimée selon l’équation suivante, lire la suite…

 

 


Tachymètre Numérique #1: Introduction du capteur was first posted on septembre 18, 2022 at 5:16 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/tachymetre-numerique-1-introduction-du-capteur/feed/ 0
Analyse fréquentielle #5: Le fenêtrage – Introduction https://www.electronique-mixte.fr/analyse-frequentielle-5-le-fenetrage-introduction/ https://www.electronique-mixte.fr/analyse-frequentielle-5-le-fenetrage-introduction/#respond Wed, 14 Sep 2022 07:08:22 +0000 https://www.electronique-mixte.fr/?p=20301 Analyse fréquentielle #5: Le fenêtrage – Introduction was first posted on septembre 14, 2022 at 7:08 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Comprendre la notion du fenêtrage
  • Savoir l’utilité du fenêtrage
  • Introduire la carte Portenta H7
  • Savoir implémenter la DFT en C/Arduino
  • Test de la DFT sur Arduino Mega/Due
  • Analyse des performances temporelles du code sur Mega/Due
  • Analyse de la DFT d’un signal sinusoïdal
  • Analyse de la DFT d’une entrée réelle
  • Prendre consciente du problème du sur-échantillonnage
  • Etc.

Voir le tuto pour plus de détails

Qui ce que le fenêtrage ?

En traitement du signal, le fenêtrage est utilisé dès que l’on s’intéresse à un signal de longueur volontairement limitée. En effet, un signal réel ne peut qu’avoir une durée limitée dans le temps ; de plus, un calcul ne peut se faire que sur un nombre fini de points. Pour observer un signal sur une durée finie, on le multiplie par une fonction fenêtre d’observation (également appelée fenêtre de pondération ou d’apodisation). La plus simple est la fenêtre rectangulaire (ou porte), définie telle que, lire la suite…

les Fenêtres temporelles

À quoi sert le fenêtrage ?

Le fenêtrage est utile pour adoucir les transitions au début et la fin de la fenêtre d’acquisition. Pour objectif, d’avoir un spectre moins polluant en harmoniques (voir le tuto pour plus de détails). On verra dans la suite de la série des exemples des fenêtres en traitement du signal.


Analyse fréquentielle #5: Le fenêtrage – Introduction was first posted on septembre 14, 2022 at 7:08 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-5-le-fenetrage-introduction/feed/ 0
Analyse fréquentielle #4: Mesure  et suivi des harmoniques https://www.electronique-mixte.fr/analyse-frequentielle-4-mesure-et-suivi-des-harmoniques/ https://www.electronique-mixte.fr/analyse-frequentielle-4-mesure-et-suivi-des-harmoniques/#respond Wed, 14 Sep 2022 02:18:45 +0000 https://www.electronique-mixte.fr/?p=20295 Analyse fréquentielle #4: Mesure  et suivi des harmoniques was first posted on septembre 14, 2022 at 2:18 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir calculer l’amplitude d’une harmonique spécifique
  • Savoir implémenter la DFT en C/Arduino
  • Test de la DFT sur Arduino Mega/Due
  • Analyse des performances temporelles du code sur Mega/Due
  • Analyse de la DFT d’un signal sinusoïdal
  • Analyse de la DFT d’une entrée réelle
  • Prendre consciente du problème du sur-échantillonnage
  • Etc.

Voir le tuto pour plus de détails

Applications

  • Capteurs actifs (Tx, Rx)
  • Linéarité
  • THD
  • Mesure de la FT (Fonction de Transfert)
  • Contrôle non destructif
  • Etc.

Programme complet

Voir le tuto pour plus de détails

#define squareOut   8       // Sortie Carrée

#define N 128 // Données N=2^n, TFD Nf=2^(n-1)
// Agit sur la Résolution fréquentielle!!!!!!!!
// df= Fs/N

#define Ts_us 500 // Ts=1/Fs: Approchée (voir le programme)
// Agit sur la fréquence MAX du spéctre!!!!!!!!
// FMXA = Fs/2

bool State=false;
unsigned long T1=0, T2=0;
float Ts=0.0, Fs=0.0;
float Data[N], Nfft=N>>1;
float dF=0.0;
float RealFFT[N>>1], ImagFFT[N>>1], ModFFT[N>>1];
float MaxIdMax[2]={0.0,0.0};
float Am, ReIm[2]={0.0,0.0};
float sMoy=0.0;
int n=0;



const double q=1.0/4096.0;


void setup()
{
// Square Out - PWM (Due) - Non utilisée
/*
pinMode(squareOut, OUTPUT);
analogWriteResolution(12); // Ajustable <= 12 (4096 Niveaux)
analogWrite(squareOut, 2048); // Pins 2-13, 1000 Hz !!
*/

// ADC
analogReadResolution(12); // Ajustable <= 12 (4096 Niveaux)


// Affichage
Serial.begin(250000);
}

void loop()
{
// 1. Lecture des données
float A0_i=0.0,A1_i=0.0;
Ts=(float)Ts_us;
for(int i=0; i<N; i++)
{
T1=micros();
A0_i=(float)analogRead(A0)+(0.5*q*rand10());
A1_i=(float)analogRead(A1)+(0.5*q*rand10());
Data[i]=(A0_i-A1_i);
Data[i]*=3.3/4096.0;
delayMicroseconds(Ts_us);
Ts+=(float)micros()-(float)T1;
Ts=Ts/2.0;
//Serial.println(1000.0*Data[i]);
}
Fs=1E6/Ts;
//Serial.println(Fs); return;

// 2. Calcul du spectre
dF=DFT(Data, N, RealFFT, ImagFFT, Fs);

// Calcul du Module de la DFT
getModul(RealFFT, ImagFFT, ModFFT, N>>1);

// Extraction de la valeur Max
ModFFT[0]=0.0;getMax(ModFFT, N>>1, MaxIdMax);

// Affichage (f0)
//Serial.print(MaxIdMax[0]); Serial.print(" \t");
//Serial.print(MaxIdMax[1]); Serial.print(" \t");
Serial.println(MaxIdMax[1]*dF);
return;

// 3. Visualisation du spectre
static bool state=false;
if(state==false)
{
Serial.println("");
for (int i=0;i<(N>>1)-1;i++)
{
if (i!=0)
{
Serial.print(dF*(float)i); Serial.print("\t");
Serial.print(2.0*1000.0*ModFFT[i]/(float)N); Serial.print("\t");
Serial.println(1000*Data[2*i]);
}
else
{
Serial.print(dF*(float)i); Serial.print("\t");
Serial.print(1000.0*ModFFT[i]/(float)N); Serial.print("\t");
Serial.println(1000*Data[2*i]);
}
}
Serial.println("");
state=!state;
}
}

float DFT(float *data, int Ndata, float *real, float *imag, float fs)
{
int nfft=floor((float)Ndata/2.0);
float df=(fs/2.0)/(float)nfft;
float somme_r=0.0, somme_i=0.0;
float wt=0.0;

for (int i=0; i<nfft; i++)
{
for (int j=0; j<Ndata; j++)
{
wt=-2.0*PI*(float)i*(float)j/Ndata;
somme_r+=data[j]*cos(wt);
somme_i+=data[j]*sin(wt);
}
real[i]= somme_r; somme_r=0.0;
imag[i]= somme_i; somme_i=0.0;
}
return df;
}

float DFTn(float *data, int Ndata, float *realImag, int n, float fs)
{
int nfft=floor((float)Ndata/2.0);
float df=(fs/2.0)/(float)nfft;
float somme_r=0.0, somme_i=0.0;
float wt=0.0;

if (n>=nfft) return 0.0;

int i=n;
for (int j=0; j<Ndata; j++)
{
wt=-2.0*PI*(float)i*(float)j/(float)Ndata;
somme_r+=data[j]*cos(wt);
somme_i+=data[j]*sin(wt);
}
realImag[0]= somme_r;
realImag[1]= somme_i;
return df;
}

void getMax(float *datain, int n, float *maxid)
{
float maxe=datain[0];
float id=0;

for (int i=1;i<n; i++)
{
if (datain[i]>=maxe)
{
maxe=datain[i];
id=i;
}
}
maxid[0]=maxe;
maxid[1]=id;
}

void getModul(float *real, float *imag, float *modul, int n)
{
for (int i=0;i<n; i++)
modul[i]=sqrt((imag[i]*imag[i]) + (real[i]*real[i]));
}

double rand10(void)
{
double rn1=2.0*((random(1e10)/1e10)-0.5);
double rn2=2.0*((random(1e10)/1e10)-0.5);
double rn=tanh((rn1-rn2));

return rn;
}

N’oublie pas de nous laisser un commentaire 🙂


Analyse fréquentielle #4: Mesure  et suivi des harmoniques was first posted on septembre 14, 2022 at 2:18 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-4-mesure-et-suivi-des-harmoniques/feed/ 0
Analyse fréquentielle #3: Implémentation et Test de la DFT https://www.electronique-mixte.fr/analyse-frequentielle-3-implementation-et-test-de-la-dft/ https://www.electronique-mixte.fr/analyse-frequentielle-3-implementation-et-test-de-la-dft/#respond Sun, 04 Sep 2022 08:27:00 +0000 https://www.electronique-mixte.fr/?p=20274 Analyse fréquentielle #3: Implémentation et Test de la DFT was first posted on septembre 4, 2022 at 8:27 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir implémenter la DFT en C/Arduino
  • Test de la DFT sur Arduino Mega/Due
  • Analyse des performances temporelles du code sur Mega/Due
  • Analyse de la DFT d’un signal sinusoïdal
  • Analyse de la DFT d’une entrée réelle
  • Prendre consciente du problème du sur-échantillonnage
  • Savoir extraire les amplitudes de la DFT
  • Comprendre la notion de la fréquence
  • Savoir définir la fréquence d’échantillonnage
  • Savoir la formule de la transformée de Fourier discrète (DFT)
  • Comprendre la notion du spectre
  • Etc.

Voir le tuto pour plus de détails

Lecture des données

Données synthétiques

La première étape de l’analyse spectrale consiste à récolter les données d’un capteur ou ensemble des capteurs. Le choix de la résolution binaire  (Nb) du convertisseur A/N ainsi la fréquence maximale de la bande analogique est cruciale. On choisit le (Nb) en fonction du niveau du signal par rapport au bruit et la fréquence d’échantillonnage (Fs) en fonction de la rapidité du phénomène physique. La fréquence Fs permet de limiter la fenêtre d’observation du signal dans le domaine fréquentiel. En effet, on ne peut observer que les fréquences dans la plage [-Fs,2, Fs/2] environ. En pratique, on se limite aux à la bande 0 et Fs/2. Le pas dans le domaine fréquentiel (ou la résolution fréquentielle), elle est définie par le nombre d’échantillons (N). Elle est égale à Fs/N, autrement dit le nombre d’acquisitions (ou la fenêtre temporelle du signal). Ci-dessous l’exemple de synthèse d’un signal sinusoïdal.

...
float f0=10.0, t_i=0.0, ts=0.0;
float A0=1.0, DC=1.0;
for(int i=0; i<N; i++)
{
t_i=(float)i/(float)N;
Data[i]=DC + A0*sin(2.0*PI*f0*t_i); // + A0*sin(2.0*PI*0.5*f0*t_i)+ A0*sin(2.0*PI*(1.0/3.0)*f0*t_i); // DC, f0, f0/2
ts=(float)1.0/(float)N;
}
Fs=1/ts;
...

Données réelles

Le code ci-dessous permet de lire N échantillons de l’entrée A0. La période d’échantillonnage est défini par la variable Ts_us (nombre de cycles de 1 µs). Elle est ensuite remesurée afin d’obtenir une meilleure précision sur la mesure des harmoniques (voir le tuto pour plus de détails).

...
Ts=(float)Ts_us;
for(int i=0; i<N; i++)
{
T1=micros();
Data[i]=(float)analogRead(A0);
Data[i]*=5.0/1023.0;
delayMicroseconds(Ts_us);
Ts+=(float)(micros()-T1);
Ts=Ts/2.0;
}
Fs=1E6/Ts;
Serial.println(Fs);return;
...

Calcul de la DFT

float DFT(float *data, int Ndata, float *real, float *imag, float fs)

La DFT() retourne le spectre d’un signal. Elle prend en entrée trois paramètres :

  1. *data: Tableau contenant les données du signal de taille (N)
  2. Ndata: Nombre des échantillons du tableau (N)
  3. fs: la fréquence d’échardonnage en Hz

Elle retourne trois sorties :

  1. *real: tableau de la partie réelle du spectre de taille N/2
  2. *imag: tableau de la partie réelle du spectre de taille N/2
  3. float: la résolution fréquentielle

Programme complet

#define Sortie  8       // Non utilisée 
#define N 128 // Données N=2^n, TFD Nf=2^(n-1)
#define Ts_us 1000 // Ts=1/Fs: Approchée (voir le programme)

/*
* Objectifs:
* 1. Savoir implémenter la DFT
* 2. Test de la DFT avec un Sinus
* 3. Test de la DFT avec ADC (Données réelles)
* 4. Analyse de la vitesse Mega/Due
*/

bool State=false;
unsigned long T1=0, T2=0;
float Ts=0.0, Fs=0.0;
float Data[N], Nfft=N>>1;
float dF=0.0;
float RealFFT[N>>1], ImagFFT[N>>1];
float sMoy=0.0;
float Am, ReIm[2];
int n=0;

void setup()
{
// Affichage
Serial.begin(115200);
}

void loop()
{
// 1. Lecture des données/ Test de la DFT
/*
float f0=10.0, t_i=0.0, ts=0.0;
float A0=1.0, DC=1.0;
for(int i=0; i<N; i++)
{
t_i=(float)i/(float)N;
Data[i]=DC + A0*sin(2.0*PI*f0*t_i); // + A0*sin(2.0*PI*0.5*f0*t_i)+ A0*sin(2.0*PI*(1.0/3.0)*f0*t_i); // DC, f0, f0/2
ts=(float)1.0/(float)N;
}
Fs=1/ts;
*/

// 1. Lecture des données
Ts=(float)Ts_us;
for(int i=0; i<N; i++)
{
T1=micros();
Data[i]=(float)analogRead(A0);
Data[i]*=5.0/1023.0;
delayMicroseconds(Ts_us);
Ts+=(float)(micros()-T1);
Ts=Ts/2.0;
}
Fs=1E6/Ts;
//Serial.println(Fs);return;


// 2. Calcul de la FFT
T1=micros();
dF=DFT(Data, N, RealFFT, ImagFFT, Fs);
T2=micros()-T1;
Serial.print("Temps FFT(s): ");Serial.println((float)T2/1E6);
//Serial.print("Résolution Fréq(Hz): ");Serial.println(dF);
//return;

// 3. Afffichage
static bool state=false;
if(state==false)
{
for(int i=0; i<Nfft; i++)
{
if (i<Nfft-1)
{
float Amp=sqrt((RealFFT[i]*RealFFT[i])+ (ImagFFT[i]*ImagFFT[i]));

Serial.print((float)i*dF);Serial.print(" \t");
Serial.print((int)floor(1000.0*Amp/((float)N)));Serial.print(" \t"); //||DFT||/N(mV)
Serial.print(1000.0*Data[2*i+1]);Serial.print(" \t");
Serial.println("");
}
}
state=!state;
}

}


float DFT(float *data, int Ndata, float *real, float *imag, float fs)
{
int nfft=floor((float)Ndata/2.0);
float df=(fs/2.0)/(float)nfft;
float somme_r=0.0, somme_i=0.0;
float wt=0.0;

for (int i=0; i<nfft; i++)
{
for (int j=0; j<Ndata; j++)
{
wt=-2.0*PI*(float)i*(float)j/Ndata;
somme_r+=data[j]*cos(wt);
somme_i+=data[j]*sin(wt);
}
real[i]= somme_r; somme_r=0.0;
imag[i]= somme_i; somme_i=0.0;
}
return df;
}

On verra dans le prochain tuto comment suivre un ou plusieurs harmoniques du spectre.


Analyse fréquentielle #3: Implémentation et Test de la DFT was first posted on septembre 4, 2022 at 8:27 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-3-implementation-et-test-de-la-dft/feed/ 0
Analyse fréquentielle #2: Simulation de la DFT (Transformée de Fourier Discrète) https://www.electronique-mixte.fr/analyse-frequentielle-2-simulation-de-la-dft-transformee-de-fourier-discrete/ https://www.electronique-mixte.fr/analyse-frequentielle-2-simulation-de-la-dft-transformee-de-fourier-discrete/#respond Thu, 01 Sep 2022 13:45:58 +0000 https://www.electronique-mixte.fr/?p=20253 Analyse fréquentielle #2: Simulation de la DFT (Transformée de Fourier Discrète) was first posted on septembre 1, 2022 at 1:45 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir implémenter la DFT avec Matlab
  • Savoir exploiter le spectre d’un signal avec Matlab
  • Savoir extraire les amplitudes de la DFT
  • Comprendre la notion de la fréquence
  • Savoir la relation entre la fréquence et la longueur d’onde
  • Savoir définir la fréquence d’échantillonnage
  • Savoir la formule de la transformée de Fourier discrète (DFT)
  • Comprendre la notion du spectre
  • Etc.

Voir le tuto pour plus de détails

Analyse temporelle du signal (Code Matlab)

L’implémentation de la DFT (Digital Fourier Transform) consiste à implémenter l’équation ci-dessous.

formule transformée de fourrier descrete

Analyse fréquentielle - Signal temporel

%% Signal temporel 
N=2^12;
f0=1;t0=1/f0;
t=linspace(0,5*t0,N);
ts=t(2)-t(1); fs=1/ts;

s_0=1; % DC
s_1=2*sin(2*pi*f0*t); % f0
s_2=4*sin(2*pi*3*f0*t); % 3f0
s_3=6*sin(2*pi*7*f0*t); % 7f0
s_b=0*randn(1,N); % Bruit/Normal
s_t=s_0+s_1+s_2+s_3+s_b; % Signal

% Affichage
figure(1);
subplot(211);
plot(t,s_1,'r-o','LineWidth',2); hold on; grid on;
plot(t,s_2,'m-o','LineWidth',2);
plot(t,s_3,'k-o','LineWidth',2);
xlabel('Temps(s)','fontsize',13);
xlim([0 2*t0]);
ylabel('Amplitude(V)','fontsize',13);
legend({'s_1(t), f_0','s_2(t), 3f_0','s_3(t), 7f_0'},'fontsize',13);
set(gca,'color','none');

subplot(212);
plot(t,s_t,'b','LineWidth',3); hold on; grid on;
xlabel('Temps(s)','fontsize',13);
xlim([0 2*t0]);
ylabel('Amplitude(V)','fontsize',13);
legend({'s(t)'},'fontsize',13);
set(gca,'color','none');

Analyse fréquentielle d’un signal (Code Matlab)

Analyse fréquentielle - Signal fréquentiel

%% Init
clear all;
close all;
clc;


%% Signal temporel
N=2^12;
f0=1;t0=1/f0;
t=linspace(0,5*t0,N);
ts=t(2)-t(1); fs=1/ts;

s_0=1; % DC
s_1=2*sin(2*pi*f0*t); % f0
s_2=4*sin(2*pi*3*f0*t); % 3f0
s_3=6*sin(2*pi*7*f0*t); % 7f0
s_b=0*randn(1,N); % Bruit/Normal
s_t=s_0+s_1+s_2+s_3+s_b; % Signal

% Affichage
figure(1);
subplot(211);
plot(t,s_1,'r-o','LineWidth',2); hold on; grid on;
plot(t,s_2,'m-o','LineWidth',2);
plot(t,s_3,'k-o','LineWidth',2);
xlabel('Temps(s)','fontsize',13);
xlim([0 2*t0]);
ylabel('Amplitude(V)','fontsize',13);
legend({'s_1(t), f_0','s_2(t), 3f_0','s_3(t), 7f_0'},'fontsize',13);
set(gca,'color','none');

subplot(212);
plot(t,s_t,'b','LineWidth',3); hold on; grid on;
xlabel('Temps(s)','fontsize',13);
xlim([0 2*t0]);
ylabel('Amplitude(V)','fontsize',13);
legend({'s(t)'},'fontsize',13);
set(gca,'color','none');



%% Spectre fréquentiel

% Calcul de la DFT (Manuelle)
nfft=floor(N);
df=fs/nfft;
f=linspace(-fs/2-df,fs/2,nfft);%
s_f=zeros(1,nfft);


for k=0:nfft-1
somme=0.0;
for j=0:N-1
somme=somme+(s_t(j+1)*exp(-1i*2*pi*k*j/N));
end
s_f(k+1)= somme;
end


% Calcul de la DFT (Matlab)
s_fm=fft(s_t,nfft);

% Affichage
figure(2);
subplot(211);
plot(f,fftshift(abs(s_f)),'r-o','LineWidth',3); hold on; grid on;
plot(f,fftshift(abs(s_fm)),'b-','LineWidth',3);
xlabel('Fréquence(Hz)','fontsize',13);
% xlim([f(1) f(end)]);
xlim([-10*f0, 10*f0]);
ylabel('||FFT||(V)','fontsize',13);
legend({'FFT Manuelle','FFT Matlab'},'fontsize',13);
set(gca,'color','none');

subplot(212);
plot(f,fftshift((abs(s_f))/(N)),'r-o','LineWidth',3); hold on; grid on;
plot(f,fftshift((abs(s_fm))/(N)),'b-','LineWidth',3);
xlabel('Fréquence(Hz)','fontsize',13);
% xlim([f(1) f(end)]);
xlim([-10*f0, 10*f0]);
ylabel('||FFT||/(N/2)(V)','fontsize',13);
legend({'FFT Manuelle','FFT Matlab'},'fontsize',13);
set(gca,'color','none');

On verra dans le prochain tuto l’implémentation en C sur Arduino et le test de la DFT.


Analyse fréquentielle #2: Simulation de la DFT (Transformée de Fourier Discrète) was first posted on septembre 1, 2022 at 1:45 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-2-simulation-de-la-dft-transformee-de-fourier-discrete/feed/ 0
Analyse fréquentielle #1: Introduction https://www.electronique-mixte.fr/analyse-frequentielle-1-introduction/ https://www.electronique-mixte.fr/analyse-frequentielle-1-introduction/#respond Tue, 30 Aug 2022 06:58:10 +0000 https://www.electronique-mixte.fr/?p=20238 Analyse fréquentielle #1: Introduction was first posted on août 30, 2022 at 6:58 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Comprendre la notion de la fréquence
  • Savoir la relation entre la fréquence et la longueur d’onde
  • Savoir définir la fréquence d’échantillonnage
  • Savoir la formule de la transformée de Fourier discrète (DFT)
  • Comprendre la notion du spectre
  • Etc.

longueur-d-onde-couleurs

Le spectre visible est la partie du spectre électromagnétique qui est perceptible par l’humain. Le spectre se décompose en rayonnements monochromatiques par le passage de la lumière à travers un dispositif disperseur (prisme ou réseau diffractant) : c’est l’analyse spectrale. Lire la suite…

 

On verra dans le prochain tuto comment implémenter la DFT avec Matlab.


Analyse fréquentielle #1: Introduction was first posted on août 30, 2022 at 6:58 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/analyse-frequentielle-1-introduction/feed/ 0
Onduleur triphasé #6: Algorithme générique – Commande polyphasée https://www.electronique-mixte.fr/onduleur-triphase-6-algorithme-generique-commande-polyphasee/ https://www.electronique-mixte.fr/onduleur-triphase-6-algorithme-generique-commande-polyphasee/#respond Sun, 21 Aug 2022 07:55:17 +0000 https://www.electronique-mixte.fr/?p=20182 Onduleur triphasé #6: Algorithme générique – Commande polyphasée was first posted on août 21, 2022 at 7:55 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir implémenter une commande générique polyphasée
  • Savoir synchroniser son code avec une horloge externe
  • Savoir implémenter la commande MLI ou sPWM (PWM de type sinusoïdal)
  • Savoir implémenter la commande décalée (deux techniques)
  • Savoir le schéma d’un onduleur triphasé
  • Savoir les caractéristiques d’un onduleur
  • Savoir choisir les transistors de la partie puissance
  • Savoir commander un onduleur triphasé
  • Savoir implémenter la commande d’un onduleur triphasé
  • Savoir augmenter les performances de son code & améliorer la fréquence maximale de  l’onduleur
  • Etc.

Applications

  • Commande des Machines polyphasées
  • Réseau polyphasé
  • Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
  • Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
  • Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
  • Variateur de vitesse des machines asynchrones
  • Etc.

Principe de la synthèse de la commande

Commande générique - Onduleur polyphasée - Schéma de principe 2

 

Réseau Triphasé (N=3)

Commande générique - Onduleur polyphasée - Principe 2

 

Réseau 4-Phases (N=4)

Commande générique - Onduleur Quadriphase

Réseau 5-Phases (N=5)

Commande générique - Onduleur Hexaphase

Stratégie de la commande

Commande générique - Onduleur polyphasée - Stratégie de la commande

Voir le tuto pour les détails techniques

Programme Arduino

La fonction getCmd()

int getCmd(unsigned long *cmdOut, int n_0, int numphase)

La fonction getCmd() permet de synthétiser la commande de l’onduleur en fonction de nombres de phases. Elle prend en entrée le nombre de phases (numphase), un tableau vide et sa taille. Puis, elle renvoie le même tableau rempli et le nombre de séquences dans le tableau. On fait appel à la fonction une seule fois, dans la fonction setup().

int getCmd(unsigned long *cmdOut, int n_0, int numphase) 
{
int n_out=0;
int i,j;
unsigned long SyqT1=0x00000000, SyqT2=0x00000000, Syq0=0x00000000; //32-bits

if ((numphase<=1) || (numphase>15)) return;
for (i=0;i<n_0; i++) cmdOut[i]=0;

/***************************************************/
/*********** Monophasé - Cas particulier ***********/
/***************************************************/
if (numphase==2)
{
cmdOut[0]=0x00000001; //Serial.println(cmd[0], BIN); //1:B01
cmdOut[1]=0x00000002; //Serial.println(cmd[1], BIN); //2:B10
n_out=2;
return n_out;
}

/***************************************************/
/********************* Polyphasé *******************/
/***************************************************/
// A. Génération de la séquence principale
n_out=2*numphase;
SyqT1=0x00000000; Syq0=0x00000001;
for(j=0;j<numphase; j++)
{
SyqT1|=Syq0;
Syq0= Syq0<<1;
}
SyqT2=SyqT1<<(numphase);

// B. Génération des séquences binaires
unsigned long T1i_B0, T2i_B0;
unsigned long T1i[numphase], T2i[numphase], T12i[n_out];
for(int j=0;j<numphase; j++)
{
T1i[j]=0; T2i[j]=0;
}
T1i[0]=SyqT1;T2i[0]=SyqT2;
//Serial.print(T1i[0], BIN); Serial.print(" , "); Serial.println(T2i[0], BIN);

for(j=1;j<numphase; j++)
{
// 1. Extraction du bit b(0)
T1i_B0=(0x00000001&SyqT1);
T2i_B0=(0x00000001&SyqT2);

// 2. Décalage à droite
T1i[j]=SyqT1>>1;
T2i[j]=SyqT2>>1;

// 3. b(n-1) =b(0)
T1i[j]|=T1i_B0<<(n_out-1);
T2i[j]|=T2i_B0<<(n_out-1);

// 4. Mise à jour des séqs Init
SyqT1=T1i[j];
SyqT2=T2i[j];
}

// Combinaision des tableaux
int ii=0, jj=0;
for(j=0;j<n_out; j++)
{
if(j%2==0)
{
T12i[j]=T1i[ii];
ii++;
//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);
}
if(j%2==1)
{
T12i[j]=T2i[jj];
jj++;
//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);
}
}

// C. Génération des séquences finales
Serial.println("****************************");
Serial.println("T1|T2|T3|T4|T5|T6|T7|T8|T9|... ");
Serial.println("****************************");
unsigned long cmd_i=0;
for(i=0;i<n_out; i++)
{
cmd_i=0;
for(j=0;j<n_out; j++)cmd_i|=(((T12i[j]>>i)&0x1)<<(j));
cmdOut[i]=cmd_i;
for (int k=0;k<32;k++)Serial.print(((cmd_i>>k)&0x1));
Serial.println("");
}
Serial.println("****************************");

return n_out;
}

La fonction setCmd()

void setCmd(unsigned long *cmdOut, int n_0)

la fonction setCmd() sert à transmettre la commande aux ports de sorties. Elle prend en entrée le tableau de commande généré par la fonction getCmd(), puis elle envoie une séquence par itérations de la boucle. La fonction doit être intégrée dans la boucle principale loop() ou dans une routine d’interruption. Elle peut transmettre la commande via 4 ports de 8-bits (PORTA, PORTB, PORC et PORD) au maximal (commande avec 15 phases ==> 32-bits).   Ci-dessous la déclaration et la définition de la fonction.

void setCmd(unsigned long *cmdOut, int n_0) 
{
static int K=0;

// Commenté les lignes non utilisées
PORTA=cmdOut[K] &0x000000ff; // (0) -(1*8-1) --LSB
//PORTB=(cmdOut[K]>>8) &0x000000ff; // (8) -(2*8-1)
//PORTC=(cmdOut[K]>>16)&0x000000ff; // (16)-(3*8-1)
//PORTD=(cmdOut[K]>>24)&0x000000ff; // (24)-(4*8-1) --MSB

// Affichage du contenu des ports sur 8-bits (A commenté)
/*
for (int k=0;k<8;k++) Serial.print(((PORTA>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTB>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTC>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTD>>k)&0x1));Serial.print(",");
Serial.println("");
*/

K++;
if (K==n_0) K=0;
}

Le programme complet


/*
* Algorithme de la commande Symétrique Générique
* La commande peut etre codée sur 32 bits (15 Phases Maximales)
* via 4 ports sur 8-bits (µC 8-bits)
* (ou bien un bus sur 32-bits (µC 32-bits))
*
* PORTA: de (0) à (1*8-1) --LSB
* PORTB: de (8) à (2*8-1)
* PORTC: de (16) à (3*8-1)
* PORTD: de (24) à (4*8-1) --MSB
*
*/

#define T0_us 333 // Période de l'onduleur (Symétrique) : T~n*T0 (µs)
#define Nphs 15 // Nb de phases [2,15]




int n; // Nombre de séquences/ Période
const int nCmd=35; // !!! Ne pas toucher!
unsigned long CmdTab[nCmd]; // !!! Ne pas toucher!



void setup()
{
// Pinout
DDRA =0xff; PORTA=0x00;
//DDRB =0xff; PORTA=0x00;
//DDRC =0xff; PORTA=0x00;
//DDRD =0xff; PORTA=0x00;

// Afficahge
Serial.begin(115200);

// Synthèse de la commande getCmd()
n= getCmd(CmdTab, nCmd, Nphs);
Serial.print("Nseq=");Serial.println(n);
}






void loop()
{
// Génération de la commande setCmd()
setCmd(CmdTab, n);
//delayMicroseconds(T0_us);
}


int getCmd(unsigned long *cmdOut, int n_0, int numphase)
{
int n_out=0;
int i,j;
unsigned long SyqT1=0x00000000, SyqT2=0x00000000, Syq0=0x00000000; //32-bits

if ((numphase<=1) || (numphase>15)) return;
for (i=0;i<n_0; i++) cmdOut[i]=0;

/***************************************************/
/*********** Monophasé - Cas particulier ***********/
/***************************************************/
if (numphase==2)
{
cmdOut[0]=0x00000001; //Serial.println(cmd[0], BIN); //1:B01
cmdOut[1]=0x00000002; //Serial.println(cmd[1], BIN); //2:B10
n_out=2;
return n_out;
}

/***************************************************/
/********************* Polyphasé *******************/
/***************************************************/
// A. Génération de la séquence principale
n_out=2*numphase;
SyqT1=0x00000000; Syq0=0x00000001;
for(j=0;j<numphase; j++)
{
SyqT1|=Syq0;
Syq0= Syq0<<1;
}
SyqT2=SyqT1<<(numphase);

// B. Génération des séquences binaires
unsigned long T1i_B0, T2i_B0;
unsigned long T1i[numphase], T2i[numphase], T12i[n_out];
for(int j=0;j<numphase; j++)
{
T1i[j]=0; T2i[j]=0;
}
T1i[0]=SyqT1;T2i[0]=SyqT2;
//Serial.print(T1i[0], BIN); Serial.print(" , "); Serial.println(T2i[0], BIN);

for(j=1;j<numphase; j++)
{
// 1. Extraction du bit b(0)
T1i_B0=(0x00000001&SyqT1);
T2i_B0=(0x00000001&SyqT2);

// 2. Décalage à droite
T1i[j]=SyqT1>>1;
T2i[j]=SyqT2>>1;

// 3. b(n-1) =b(0)
T1i[j]|=T1i_B0<<(n_out-1);
T2i[j]|=T2i_B0<<(n_out-1);

// 4. Mise à jour des séqs Init
SyqT1=T1i[j];
SyqT2=T2i[j];
}

// Combinaision des tableaux
int ii=0, jj=0;
for(j=0;j<n_out; j++)
{
if(j%2==0)
{
T12i[j]=T1i[ii];
ii++;
//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);
}
if(j%2==1)
{
T12i[j]=T2i[jj];
jj++;
//Serial.print(j);Serial.print(" , ");Serial.println(T12i[j], BIN);
}
}

// C. Génération des séquences finales
Serial.println("****************************");
Serial.println("T1|T2|T3|T4|T5|T6|T7|T8|T9|... ");
Serial.println("****************************");
unsigned long cmd_i=0;
for(i=0;i<n_out; i++)
{
cmd_i=0;
for(j=0;j<n_out; j++)cmd_i|=(((T12i[j]>>i)&0x1)<<(j));
cmdOut[i]=cmd_i;
for (int k=0;k<32;k++)Serial.print(((cmd_i>>k)&0x1));
Serial.println("");
}
Serial.println("****************************");

return n_out;
}

void setCmd(unsigned long *cmdOut, int n_0)
{
static int K=0;

// Commenté les lignes non utilisées
PORTA=cmdOut[K] &0x000000ff; // (0) -(1*8-1) --LSB
//PORTB=(cmdOut[K]>>8) &0x000000ff; // (8) -(2*8-1)
//PORTC=(cmdOut[K]>>16)&0x000000ff; // (16)-(3*8-1)
//PORTD=(cmdOut[K]>>24)&0x000000ff; // (24)-(4*8-1) --MSB

// Affichage du contenu des ports sur 8-bits (A commenté)
/*
for (int k=0;k<8;k++) Serial.print(((PORTA>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTB>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTC>>k)&0x1));Serial.print(",");
for (int k=0;k<8;k++) Serial.print(((PORTD>>k)&0x1));Serial.print(",");
Serial.println("");
*/

K++;
if (K==n_0) K=0;
}

Onduleur triphasé #6: Algorithme générique – Commande polyphasée was first posted on août 21, 2022 at 7:55 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/onduleur-triphase-6-algorithme-generique-commande-polyphasee/feed/ 0
Onduleur triphasé #5: Trigger externe – Horloge Externe https://www.electronique-mixte.fr/onduleur-triphase-5-trigger-externe-horloge-externe/ https://www.electronique-mixte.fr/onduleur-triphase-5-trigger-externe-horloge-externe/#respond Tue, 16 Aug 2022 15:08:52 +0000 https://www.electronique-mixte.fr/?p=20156 Onduleur triphasé #5: Trigger externe – Horloge Externe was first posted on août 16, 2022 at 3:08 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir synchroniser son code avec une horloge externe
  • Savoir implémenter la commande MLI ou sPWM (PWM de type sinusoïdal)
  • Savoir implémenter la commande décalée (deux techniques)
  • Savoir le schéma d’un onduleur triphasé
  • Savoir les caractéristiques d’un onduleur
  • Savoir choisir les transistors de la partie puissance
  • Savoir commander un onduleur triphasé
  • Savoir implémenter la commande d’un onduleur triphasé
  • Savoir augmenter les performances de son code & améliorer la fréquence maximale de  l’onduleur
  • Etc.

Applications

  • Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
  • Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
  • Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
  • Variateur de vitesse des machines asynchrones
  • Etc.

Projets annexes

Ci-dessous les liens qui vont vous permettre de mieux comprendre et pratiquer la notion des interruptions.

Pourquoi une horloge externe ?

La synthèse d’une période (inverse de la fréquence) par l’intermédiaire des temporisations matérielles (Timers) ou logicielles (delay()) n’est pas assez précises. En effet, les performances de l’oscillateur de la carte Arduino peuvent dériver dans le temps à cause de la température. Et par conséquent, la gestion efficace du temps. L’idée consiste à synchrones le code avec une source externe indépendante.

Schéma Onduleur triphasé Trigger externe – Horloge Externe 1

Fonctionnement

L’idée consiste à lancer le programme via le front montant (ou descendant) d’une horloge externe en utilisant une interruption externe. L’horloge sera branchée directement dans une entrée digitale de la carte dédiée au déclenchement de l’interruption. En résumé, le programme sera équivalent à une boucle loop() qui se lance chaque période de l’horloge externe. On distingue deux configurations.

Horloge lente

La fréquence d’horloge externe doit être choisie en tenant en compte du temps d’exécution du programme a synchronisé. En effet, il faut que l’horloge soit assez lente par rapport à la durée d’exécution du programme comme il est indiqué dans la figure ci-dessous. Par exemple Tp=10ms, alors il faut choisir Tt>2*Tp=20ms dans le cas idéal.

Onduleur triphasé Trigger externe – Horloge lente

Horloge rapide

Si l’horloge est trop rapide par rapport à la durée d’exécution du programme, alors la priorité sera donner au programme. Autrement dit, les fronts montants apparus durant l’exécution du programme seront ignorés. Les fronts ne seront pris en compte qu’à la fin d’exécution du programme (voir la figure ci-dessous).

Onduleur triphasé Trigger externe – Horloge rapide

Pour obtenir une bonne synchronisation, essaye d’utiliser Tt>=2*Tp.

 

Programme (Trigger)

unsigned char State=0x00; 

void setup()
{
DDRA =0xff;PORTA=State;
}

void loop()
{
State=0xff*(!State);
PORTA=State;
delayMicroseconds(8);
}

Programme (Program)

/*
* Commande Symétrique: SetCMD1() & SetCMD2()
* Commande Décalée: SetCMD3() & SetCMD4()
* Commande PWM(MLI): Voir le programme
*/

#define Tr11 22 // Transistor 1/Bras 1
#define Tr12 23 // Transistor 2/Bras 1
#define Tr21 24 // Transistor 1/Bras 2
#define Tr22 25 // Transistor 2/Bras 2
#define Tr31 26 // Transistor 1/Bras 3
#define Tr32 27 // Transistor 2/Bras 3

#define T0_us 333 // Période de l'onduleur (Symétrique) : T=6*T0 (µs)
// Période de l'onduleur (Décalée) : T=12*T0 (µs)
// sPWM: Période d'incrémentation du Timer
// sPWM: Période globale T=2*N*T0_us => F=1/F: Fréquence de l'Onduleur
/* Params sPWM */
#define N 64 // Niveaux de l'onduleur: Nombre d’échantillons (foramt 2^n)
#define TimerStep 13 // Pas d'incrémentation du Timer rapide (>>1)


int Trans[6]; // Ou bien PORTA
unsigned long MedSine[N];
unsigned long TimerSPWM=0;
unsigned long i_sin[3]={0,0,0};
bool sPWM_l[3]={false,false,false};
bool sPWM_r[3]={true,true,true};
bool sinePolar[3]={false,false,false};
double sine_val=0.0, A=0.0;
int Nbit=0; // Amplitude du signal sinusoïdal 2^8

void setup()
{
// Pinout
Trans[0]=Tr11; Trans[1]=Tr12;
Trans[2]=Tr21; Trans[3]=Tr22;
Trans[4]=Tr31; Trans[5]=Tr32;
for (int i=0;i<6; i++)
{
pinMode(Trans[i], OUTPUT);
digitalWrite(Trans[i], LOW);
}
// Ou bien: Init du port A en sortie
//DDRA =0xff; PORTA=0x00;

// Cogade binaire de l'amplitude
Nbit=(int)round((log((float)N)/log(2.0)));

// Init Timers // Déphasage de 60°/Bras (60°=>T/6)
i_sin[0]=0; // Bras 1 - 0°
i_sin[1]=round((float)N/6.0); // Bras 2 - 60°
i_sin[2]=round(2.0*(float)N/6.0); // Bras 3 - 120°

// Génération du signal sinusoïdal: 1/2 Période (2*N échantillons/période)
A=(double)(pow(2.0,(double)Nbit)-1.0);
for (int i=0; i<N; i++)
{
sine_val=A*sin(PI*(double)i/(double)(N));
MedSine[i]=(int)(abs(floor(sine_val)));
}

// Afficahge
Serial.begin(9600);
pinMode(3,OUTPUT);

// Configuration de l'Interruption (Trigger Externe)

// Câblage du pin et configuration en entrée: INT0 => PD0 (pin 21 de la carte)
DDRD =0x00; // Port D en entrée

// Activation de l'interruption globale (registre SREG)
SREG|=0x80;

// Validation de l'interruption INT0 (Registre EIMSK)
EIMSK|=0x01; // INT0

// Choix du mode de détection: Front montant dans INT0
EICRA|=0x01;
}

void loop(){}


//ISR(_VECTOR(1)) // Ou _VECTOR(2)
ISR(INT0_vect)
{
//SetCMD1(Trans);
//SetCMD2(Trans);
//SetCMD3(Trans);
SetCMD2(Trans);




/*********** sPWM ***********/
// Incrémentation du Timer: Compteur rapide (signal triangulaire)
/*
TimerSPWM+=TimerStep;
if (TimerSPWM>N) TimerSPWM=0;

// Génération de la commande
for (int i=0; i<3; i++)
{
// 1. Incrémentation du Timer du signal: Compteur long (signal sinusoïdal)
i_sin[i]+=1;
if (i_sin[i]>N) i_sin[i]=0;

// 2. Inversion de la polarité de la période
if(!i_sin[i]) sinePolar[i]=!sinePolar[i];

// 3. Génération des signaux PWM
if(sinePolar[i]) // Période (+)
{
sPWM_l[i] =MedSine[i_sin[i]] > TimerSPWM;
sPWM_r[i] =false;
}
else // Période (-)
{
sPWM_l[i] = false;
sPWM_r[i] =MedSine[i_sin[i]] > TimerSPWM;
}
}

// Envoie des signaux au Port A
PORTA=(B00000001*sPWM_l[0])+ (B00000010*sPWM_r[0])+
(B00000100*sPWM_l[1])+ (B00001000*sPWM_r[1])+
(B00010000*sPWM_l[2])+ (B00100000*sPWM_r[2]);

*/
}



void SetCMD1( int *pins)
{
static int I=0;
const bool Cmd[6][6]={{0,1,1,0,0,1},
{1,0,1,0,0,1},
{1,0,0,1,0,1},
{1,0,0,1,1,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0}};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++; I%=6;

return 0;
}





void SetCMD2( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[6]={B00011001,
B00101001,
B00100101,
B00100110,
B00010110,
B00011010};

PORTA=Cmd[I];
I++;

//I%=6; // Fréquence: +
//I=I*(I<6); // Fréquence: ++
if (I>=6)I=0; // Fréquence: +++

return 0;
}



void SetCMD3( int *pins)
{
static unsigned char I=0;
const bool Cmd[12][6]={
{0,1,1,0,0,0},
{0,0,1,0,0,1},
{0,0,1,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,1,0,0},
{1,0,0,1,0,0},
{0,0,0,1,1,0},
{0,0,0,1,1,0},
{0,1,0,0,1,0},
{0,1,0,0,1,0},
{0,1,1,0,0,0},
};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++;
if (I>=12)I=0;

return 0;
}


void SetCMD4( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[12]= {
B00011000,
B00001001,
B00001001,
B00100001,
B00100001,
B00100100,
B00100100,
B00000110,
B00000110,
B00010010,
B00010010,
B00011000
};

PORTA=Cmd[I];
I++;
if (I>=12)I=0;

return 0;
}

On verra dans le prochain tuto la commande générique d’un onduleur polyphasée. N’oublie pas me laisser un commentaire :


Onduleur triphasé #5: Trigger externe – Horloge Externe was first posted on août 16, 2022 at 3:08 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/onduleur-triphase-5-trigger-externe-horloge-externe/feed/ 0
Projet Onduleur Triphasé #4: Commande sPWM (MLI) https://www.electronique-mixte.fr/projet-onduleur-triphase-4-commande-spwm-mli/ https://www.electronique-mixte.fr/projet-onduleur-triphase-4-commande-spwm-mli/#comments Sun, 14 Aug 2022 18:34:02 +0000 https://www.electronique-mixte.fr/?p=20138 Projet Onduleur Triphasé #4: Commande sPWM (MLI) was first posted on août 14, 2022 at 6:34 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir implémenter la commande MLI ou sPWM (PWM de type sinusoïdal)
  • Savoir implémenter la commande décalée (deux techniques)
  • Savoir le schéma d’un onduleur triphasé
  • Savoir les caractéristiques d’un onduleur
  • Savoir choisir les transistors de la partie puissance
  • Savoir commander un onduleur triphasé
  • Savoir implémenter la commande d’un onduleur triphasé
  • Savoir augmenter les performances de son code & améliorer la fréquence maximale de l’onduleur
  • Etc.

Applications

  • Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
  • Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
  • Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
  • Variateur de vitesse des machines asynchrones
  • Etc.

Fonctionnement

La commande MLI (Modulation de Largeur d’Impulsion) de type sinusoïdal sPWM est largement utilisée dans la commande des convertisseurs (AC/DC, DC/AC, AC/AC, etc.). Elle permet de synthétiser un signal qui s’approche du signal sinusoïdal à partir d’un signal tout ou rien (signal carré). En effet, un signal carré est une combinaison linaire d’une multitude des harmoniques (f0, 2f0, 3f0,…, nf0). Un signal carré est simple à générer via les composants de puissances. En revanche, il n’est pas efficace en termes du rendement et pertes dus aux harmoniques secondaires. Le transfert de puissance est maximale lorsque le signal est constitué d’une seule harmonique (sinus pur).

Avant d’entamer la suite, veuillez consulter les parties précédentes.

Les aspects théoriques de la modulation MLI sont abordés dans le projet onduleur monophasé. Concernant l’onduleur triphasé, il suffit de générer trois sinusoïdes décalées de 60°. La technique consiste d’utiliser un seul tableau pour les phases contenant les échantillons d’une demi période du signal sinusoïdal. Ensuite, utiliser trois indices décalés les uns par rapport aux autres de 60°. Si le tableau est constitué de N échantillons, alors le décalage 60° est équivalent à N/6 échantillons. Durant l’initialisation des indices, on définit : I_Phase1=0,  I_Phase2=N/6 et I_Phase3=2*N/6. Voir le tuto pour plus de détails.

Programme complet

/*
* Commande Symétrique : SetCMD1() & SetCMD2()
* Commande Décalée : SetCMD3() & SetCMD4()
* Commande PWM(MLI) : Voir le programme
*/

#define Tr11 22 // Transistor 1/Bras 1
#define Tr12 23 // Transistor 2/Bras 1
#define Tr21 24 // Transistor 1/Bras 2
#define Tr22 25 // Transistor 2/Bras 2
#define Tr31 26 // Transistor 1/Bras 3
#define Tr32 27 // Transistor 2/Bras 3

#define T0_us 333 // Période de l'onduleur (Symétrique) : T=6*T0 (µs)
// Période de l'onduleur (Décalée) : T=12*T0 (µs)
// sPWM: Période d'incrémentation du Timer
// sPWM: Période globale T=2*N*T0_us => F=1/F: Fréquence de l'Onduleur
/* Params sPWM */
#define N 64 // Niveaux de l'onduleur : Nombre d’échantillons (format 2^n)
#define TimerStep 13 // Pas d'incrémentation du Timer rapide (>>1)


int Trans[6]; // Ou bien PORTA
unsigned long MedSine[N];
unsigned long TimerSPWM=0;
unsigned long i_sin[3]={0,0,0};
bool sPWM_l[3]={false,false,false};
bool sPWM_r[3]={true,true,true};
bool sinePolar[3]={false,false,false};
double sine_val=0.0, A=0.0;
int Nbit=0; // Amplitude du signal sinusoïdal 2^8

void setup()
{
// Pinout
Trans[0]=Tr11; Trans[1]=Tr12;
Trans[2]=Tr21; Trans[3]=Tr22;
Trans[4]=Tr31; Trans[5]=Tr32;
for (int i=0;i<6; i++)
{
pinMode(Trans[i], OUTPUT);
digitalWrite(Trans[i], LOW);
}
// Ou bien: Init du port A en sortie
//DDRA =0xff; PORTA=0x00;

// Codage binaire de l'amplitude
Nbit=(int)round((log((float)N)/log(2.0)));

// Init Timers // Déphasage de 60°/Bras (60°=>T/6)
i_sin[0]=0; // Bras 1 - 0°
i_sin[1]=round((float)N/6.0); // Bras 2 - 60°
i_sin[2]=round(2.0*(float)N/6.0); // Bras 3 - 120°

// Génération du signal sinusoïdal : 1/2 Période (2*N échantillons/période)
A=(double)(pow(2.0,(double)Nbit)-1.0);
for (int i=0; i<N; i++)
{
sine_val=A*sin(PI*(double)i/(double)(N));
MedSine[i]=(int)(abs(floor(sine_val)));
}

// Affichage
Serial.begin(9600);
pinMode(3,OUTPUT);
}

void loop()
{
/*
SetCMD1(Trans);
SetCMD2(Trans);
SetCMD3(Trans);
SetCMD4(Trans);
delayMicroseconds(T0_us);
return;
*/

/*
delayMicroseconds(11);
digitalWrite(3, sinePolar[0]);
*/

// Prévisualisation des signaux du Bras 1 + sin(t)
/*
Serial.print(MedSine[i_sin[0]]); Serial.print(",");
Serial.print(i_sin[0]); Serial.print(",");
Serial.print(A*sPWM_l[0]); Serial.print(",");
Serial.println(-A*sPWM_r[0]);
*/

// Visualisation des signaux de l'onduleur
/*
Serial.print(sPWM_l[0]+0); Serial.print(",");
Serial.print(sPWM_r[0]+1); Serial.print(",");
Serial.print(sPWM_l[1]+2); Serial.print(",");
Serial.print(sPWM_r[1]+3); Serial.print(",");
Serial.print(sPWM_l[2]+4); Serial.print(",");
Serial.println(sPWM_r[2]+5);
*/

// Incrémentation du Timer: Compteur rapide (signal triangulaire)
TimerSPWM+=TimerStep;
if (TimerSPWM>N) TimerSPWM=0;

// Génération de la commande
for (int i=0; i<3; i++)
{
// 1. Incrémentation du Timer du signal : Compteur long (signal sinusoïdal)
i_sin[i]+=1;
if (i_sin[i]>N) i_sin[i]=0;

// 2. Inversion de la polarité de la période
if(!i_sin[i]) sinePolar[i]=!sinePolar[i];

// 3. Génération des signaux PWM
if(sinePolar[i]) // Période (+)
{
sPWM_l[i] =MedSine[i_sin[i]] > TimerSPWM;
sPWM_r[i] =false;
}
else // Période (-)
{
sPWM_l[i] = false;
sPWM_r[i] =MedSine[i_sin[i]] > TimerSPWM;
}
}

// Envoie des signaux au Port A
PORTA=(B00000001*sPWM_l[0])+ (B00000010*sPWM_r[0])+
(B00000100*sPWM_l[1])+ (B00001000*sPWM_r[1])+
(B00010000*sPWM_l[2])+ (B00100000*sPWM_r[2]);
}



void SetCMD1( int *pins)
{
static int I=0;
const bool Cmd[6][6]={{0,1,1,0,0,1},
{1,0,1,0,0,1},
{1,0,0,1,0,1},
{1,0,0,1,1,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0}};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++; I%=6;

return 0;
}





void SetCMD2( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[6]={B00011001,
B00101001,
B00100101,
B00100110,
B00010110,
B00011010};

PORTA=Cmd[I];
I++;

//I%=6; // Fréquence: +
//I=I*(I<6); // Fréquence: ++
if (I>=6)I=0; // Fréquence: +++

return 0;
}



void SetCMD3( int *pins)
{
static unsigned char I=0;
const bool Cmd[12][6]={
{0,1,1,0,0,0},
{0,0,1,0,0,1},
{0,0,1,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,1,0,0},
{1,0,0,1,0,0},
{0,0,0,1,1,0},
{0,0,0,1,1,0},
{0,1,0,0,1,0},
{0,1,0,0,1,0},
{0,1,1,0,0,0},
};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++;
if (I>=12)I=0;

return 0;
}


void SetCMD4( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[12]= {
B00011000,
B00001001,
B00001001,
B00100001,
B00100001,
B00100100,
B00100100,
B00000110,
B00000110,
B00010010,
B00010010,
B00011000
};

PORTA=Cmd[I];
I++;
if (I>=12)I=0;

return 0;
}

On verra dans le prochain tuto comment utiliser une horloge externe de l’onduleur. N’oublie pas un commentaire pour nous encourager et contribuer au développement du blog.


Projet Onduleur Triphasé #4: Commande sPWM (MLI) was first posted on août 14, 2022 at 6:34 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-onduleur-triphase-4-commande-spwm-mli/feed/ 2
Projet Onduleur Triphasé #3: Commande Décalée https://www.electronique-mixte.fr/projet-onduleur-triphase-3-commande-decalee/ https://www.electronique-mixte.fr/projet-onduleur-triphase-3-commande-decalee/#respond Fri, 12 Aug 2022 05:37:14 +0000 https://www.electronique-mixte.fr/?p=20108 Projet Onduleur Triphasé #3: Commande Décalée was first posted on août 12, 2022 at 5:37 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir implémenter la commande décalée (deux techniques)
  • Savoir le schéma d’un onduleur triphasé
  • Savoir les caractéristiques d’un onduleur
  • Savoir choisir les transistors de la partie puissance
  • Savoir commander un onduleur triphasé
  • Savoir implémenter la commande d’un onduleur triphasé
  • Savoir augmenter les performances de son code & améliorer la fréquence maximale de l’onduleur
  • Etc.

Applications

  • Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
  • Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
  • Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
  • Variateur de vitesse des machines asynchrones
  • Etc.

Fonctionnement

Avant d’entamer la suite, veuillez consulter la partie Une et Deux du projet pour mieux comprendre le concept de la commande.

On reprend les chronogrammes de la commande symétrique abordée dans la section précédente dont chaque transistor est activé une demi période (3*60=180°). Pour la commande symétrique, les transistors dans un bras sont complémentaires. Durant la transition, on se retrouve avec deux transistors actifs en même temps. Ce mode de fonctionnement induit un micro-court-circuit de la source (batterie, alimentation DC, etc.). Par conséquent, dans le cas d’une batterie, on chauffe, réduit l’autonomie ainsi la durée de vie de la batterie, d’où l’importance de la commande décalée. Elle permet d’ajouter un déphasage à l’ouverture ou à la fermeture des transistors de telle manière à ne jamais avoir deux actifs en même temps.

Les signaux de la commande d’un bras ne sont pas complémentaires !

Les chronogrammes ci-dessous montrent la conversion de la commande symétrique vers la commande décalée des transistors T1 et T2 en utilisant un déphasage fixe de 30° (1/12 de la période). On constate a remise à zéros du T1 et T2 au début et à la fin de mi-période.

L’utilisation d’un déphasage de 30° (π/6) permet de supprimer l’harmonique 3. 

 

Onduleur triphasé - commande décalée 1

Le codage de la commande symétrique nécessite 6 séquences par période (360/60 = 6). En revanche, la commande décalée, dans le cas d’un déphasage de 30°, on aura besoin de 12 séquences par période. Le tableau ci-dessous montre les 12 états des transistors T1 et T2. On constate que T1 (ou T2) est actif seulement pendant 4 cycles de 30° (4*30=120) qui correspond à 1/3 (1/2 période dans le cas de la commande symétrique). Par contre, avant la transition de T1 (ou T2), les deux transitons sont positionnés à zéros durant deux cycles !

Onduleur triphasé - commande décalée 2

Voir le tuto pour en savoir plus sur le codage de T3 à T6.

Cours onduleur triphasé

Voir les cours ci-dessous pour plus de détails théoriques concernant le fonctionnement ainsi les chronogrammes des tensions de l’onduleur.

Programme Arduino

La fonction SetCMD3()

La fonction permet de faire le codage séquentiel des 12 états des six transistors.

void SetCMD3( int *pins)
{
static unsigned char I=0;
const bool Cmd[12][6]={
{0,1,1,0,0,0},
{0,0,1,0,0,1},
{0,0,1,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,1,0,0},
{1,0,0,1,0,0},
{0,0,0,1,1,0},
{0,0,0,1,1,0},
{0,1,0,0,1,0},
{0,1,0,0,1,0},
{0,1,1,0,0,0},
};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++;
if (I>=12)I=0;

return 0;
}

La fonction SetCMD4()

La fonction permet de faire le codage parallèle (plus rapide) des 12 états des six transistors.

void SetCMD4( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[12]= {
B00011000,
B00001001,
B00001001,
B00100001,
B00100001,
B00100100,
B00100100,
B00000110,
B00000110,
B00010010,
B00010010,
B00011000
};

PORTA=Cmd[I];
I++;
if (I>=12)I=0;

return 0;
}

Programme complet

#define Tr11            22         // Transistor 1/Bras 1 
#define Tr12 23 // Transistor 2/Bras 1
#define Tr21 24 // Transistor 1/Bras 2
#define Tr22 25 // Transistor 2/Bras 2
#define Tr31 26 // Transistor 1/Bras 3
#define Tr32 27 // Transistor 2/Bras 3

#define T0_us 333 // Période de l'onduleur (Symétrique) : T=6*T0 (µs)
// Période de l'onduleur (Décalée) : T=12*T0 (µs)

int Trans[6];

void setup()
{
// Pinout
Trans[0]=Tr11; Trans[1]=Tr12;
Trans[2]=Tr21; Trans[3]=Tr22;
Trans[4]=Tr31; Trans[5]=Tr32;

for (int i=0;i<6; i++)
{
pinMode(Trans[i], OUTPUT);
digitalWrite(Trans[i], LOW);
}
// Ou bien: Init du port A en sortie
//DDRA =0xff; PORTA=0x00;

Serial.begin(9600);
}

void loop()
{
SetCMD4(Trans);
//delayMicroseconds(T0_us);
}







void SetCMD1( int *pins)
{
static int I=0;
const bool Cmd[6][6]={{0,1,1,0,0,1},
{1,0,1,0,0,1},
{1,0,0,1,0,1},
{1,0,0,1,1,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0}};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++; I%=6;

return 0;
}





void SetCMD2( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[6]={B00011001,
B00101001,
B00100101,
B00100110,
B00010110,
B00011010};

PORTA=Cmd[I];
I++;

//I%=6; // Fréquence: +
//I=I*(I<6); // Fréquence: ++
if (I>=6)I=0; // Fréquence: +++

return 0;
}



void SetCMD3( int *pins)
{
static unsigned char I=0;
const bool Cmd[12][6]={
{0,1,1,0,0,0},
{0,0,1,0,0,1},
{0,0,1,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,1,0,0},
{1,0,0,1,0,0},
{0,0,0,1,1,0},
{0,0,0,1,1,0},
{0,1,0,0,1,0},
{0,1,0,0,1,0},
{0,1,1,0,0,0},
};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++;
if (I>=12)I=0;

return 0;
}


void SetCMD4( int *pins)
{
static unsigned char I=0;
const unsigned char Cmd[12]= {
B00011000,
B00001001,
B00001001,
B00100001,
B00100001,
B00100100,
B00100100,
B00000110,
B00000110,
B00010010,
B00010010,
B00011000
};

PORTA=Cmd[I];
I++;
if (I>=12)I=0;

return 0;
}

On verra dans le prochain tuto la commande MLI (PWM) d’un onduleur triphasé. N’oublie pas un commentaire pour nous encourager et contribuer au développement du blog.

 


Projet Onduleur Triphasé #3: Commande Décalée was first posted on août 12, 2022 at 5:37 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-onduleur-triphase-3-commande-decalee/feed/ 0
Projet Onduleur Triphasé #2: Commande Adjacente (Symétrique) https://www.electronique-mixte.fr/projet-onduleur-triphase-2-commande-adjacente-symetrique/ https://www.electronique-mixte.fr/projet-onduleur-triphase-2-commande-adjacente-symetrique/#respond Wed, 10 Aug 2022 03:32:29 +0000 https://www.electronique-mixte.fr/?p=20072 Projet Onduleur Triphasé #2: Commande Adjacente (Symétrique) was first posted on août 10, 2022 at 3:32 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir le schéma d’un onduleur triphasé
  • Savoir les caractéristiques d’un onduleur
  • Savoir choisir les transistors de la partie puissance
  • Savoir commander un onduleur triphasé
  • Savoir implémenter la commande d’un onduleur triphasé
  • Savoir augmenter les performances de son code & améliorer la fréquence maximale de l’onduleur
  • Etc.

Applications

  • Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
  • Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
  • Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
  • Variateur de vitesse des machines asynchrones
  • Etc.

Fonctionnement

Schéma de principe onduleur triphasé

Un onduleur triphasé est un convertisseur DC/AC. L’onduleur triphasé est constitué de trois bras parallèles. Chaque bras contient deux transistors comme il est indiqué dans la figure. Il peut être alimenté par une batterie (ou pack batterie), un panneau solaire ou par la sortie d’un redresseur monophasé (Convertisseur AC/DC).  Le transformateur est utilisé pour booster la tension à la sortie de l’onduleur vers la tension désirée. Il peut être utilisé pour obtenir le conducteur du neutre également  (couplage étoile à l’entrée du transformateur). De plus, le transformateur peut jouer le rôle d’un filtre passé bas afin de réduire les harmoniques des signaux carrés.

Voir les cours ci-dessous pour plus de détails théoriques concernant le fonctionnement ainsi les chronogrammes des tensions de l’onduleur.

Cours onduleur triphasé

La Commande Adjacente (Symétrique, 180°)

La commande symétrique est une commande rapide d’un onduleur triphasé. Elle consiste à faire commuter un seul transistor par bras. La durée de commutation de chaque transistor est de 180° (1/2 période). Les transistors dans un seul bras sont complémentaires (T1 commuté ou T2 à la fois). On constate un déphasage de commutation entre les bras de 60° (1/6 de la période) comme il est indiqué dans la figure. Par conséquent, on obtient un signal carré par bras.

Onduleur triphasé - commande symétrique 1

On prolonge les chronogrammes ci-dessous, on obtient

Onduleur triphasé - commande symétrique 2

On extrait une période complète constituée par 6 cycles (le début et la fin de la période n’a pas d’importance). Puis, on définit les états des transistors par cycles, on obtient

 

Onduleur triphasé - commande symétrique 3

Voir le tuto pour plus d’informations.

Codes du projet

La fonction SetCMD1()

La fonction SetCMD1() permet de générer les signaux de commande de l’onduleur. Une période est continuée par 8 cycles/séquences périodiques. Chaque séquence est constituée par 6 bits pour la commande des 3 bras de l’onduleur comme il est indiqué par le tableau de la section précédente. L’idée consiste à coder la période par un tableau binaire de taille 6×6 éléments (voir la fonction). La fonction prend en entrée le pinout de six transistors, puis elle génère une séquence par itération de la boucle. L’incrémentation est effectuée d’une façon automatique par  l’intermédiaire d’une variable de type static .

Voir le tuto pour plus de détails.

void SetCMD1( int *pins)
{
static int I=0;
const bool Cmd[6][6]={{0,1,1,0,0,1},
{1,0,1,0,0,1},
{1,0,0,1,0,1},
{1,0,0,1,1,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0}};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++; I%=6;

return 0;
}

L’implémentation de la fonction SetCMD1() n’est pas optimale. En effet, la synthèse des signaux des bras est effectuée d’une manière séquentielle non simultanée.  De plus, la boucle for de mise à jour des sorties réduit la fréquence maximale de l’onduleur (voir le tuto).

La fonction SetCMD2()

La fonction SetCMD2() est une version améliorée de la fonction SetCMD1(). Elle permet de générer les signaux d’une manière simultanée et augmenter la fréquence de l’onduleur avec un rapport supérieur à 3 au voisinage de 10 KHz! L’idée consiste à remplacer la boucle for par le PORTA de la carte Arduino Mega comme il est indiqué dans la figure ci-dessous. Pa conséquent, chaque séquence est constituée par un mot de 6 bits de type unsigned char.

Port A Arduino Mega

void SetCMD2( int *pins)
{
static int I=0;
const unsigned char Cmd[6]={B00011001,
B00101001,
B00100101,
B00100110,
B00010110,
B00011010};

PORTA=Cmd[I];
I++; I%=6;

return 0;
}

Le programme complet

#define Tr11            22         // Transistor 1/Bras 1 
#define Tr12 23 // Transistor 2/Bras 1
#define Tr21 24 // Transistor 1/Bras 2
#define Tr22 25 // Transistor 2/Bras 2
#define Tr31 26 // Transistor 1/Bras 3
#define Tr32 27 // Transistor 2/Bras 3

#define T0_us 3333 // Période de l'onduleur: T=6*T0 (µs)

int Trans[6];

void setup()
{
// Pinout
Trans[0]=Tr11; Trans[1]=Tr12;
Trans[2]=Tr21; Trans[3]=Tr22;
Trans[4]=Tr31; Trans[5]=Tr32;
for (int i=0;i<6; i++)
{
pinMode(Trans[i], OUTPUT);
digitalWrite(Trans[i], LOW);
}
// Ou bien: Init du port A en sortie
DDRA =0xff; PORTA=0x00;
}

void loop()
{
SetCMD1(Trans);
delayMicroseconds(T0_us);
}

void SetCMD1( int *pins)
{
static int I=0;
const bool Cmd[6][6]={{0,1,1,0,0,1},
{1,0,1,0,0,1},
{1,0,0,1,0,1},
{1,0,0,1,1,0},
{0,1,0,1,1,0},
{0,1,1,0,1,0}};

for (int i=0;i<6; i++) digitalWrite(pins[i], Cmd[I][i]);
I++; I%=6;

return 0;
}

void SetCMD2( int *pins)
{
static int I=0;
const unsigned char Cmd[6]={B00011001,
B00101001,
B00100101,
B00100110,
B00010110,
B00011010};

PORTA=Cmd[I];
I++; I%=6;

return 0;
}

On verra dans la prochaine partie la commande décalée. N’hésitez pas de poster un commentaire. Ça fait toujours plaisir de vous lire 🙂


Projet Onduleur Triphasé #2: Commande Adjacente (Symétrique) was first posted on août 10, 2022 at 3:32 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-onduleur-triphase-2-commande-adjacente-symetrique/feed/ 0
Projet Onduleur Triphasé #1: Introduction https://www.electronique-mixte.fr/projet-onduleur-triphase-1-introduction/ https://www.electronique-mixte.fr/projet-onduleur-triphase-1-introduction/#respond Fri, 05 Aug 2022 08:57:06 +0000 https://www.electronique-mixte.fr/?p=20052 Projet Onduleur Triphasé #1: Introduction was first posted on août 5, 2022 at 8:57 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  • Savoir le schéma d’un onduleur triphasé
  • Savoir les caractéristiques d’un onduleur
  • Savoir choisir les transistors de la partie puissance
  • Savoir commander un onduleur triphasé
  • Etc.

Applications

  • Alimentation AC à partir d’une source DC (Alimentation à panneaux solaires, batteries, etc.)
  • Conversion de réseaux : Monophasé vers triphasé, monophasé vers un réseau polyphasé, etc.
  • Convertisseur de fréquence d’un réseau 50 Hz vers 60 Hz, 50 Hz vers 400 Hz, etc.
  • Variateur de vitesse des machines asynchrones
  • Etc.

Fonctionnement

Un onduleur est un convertisseur DC/AC. Il permet de transformer une tension DC en une tension alternative. Un onduleur peut être utilisé comme variateur de vitesse pour les machines asynchrones triphasées. Les onduleurs sont basés sur une structure en pont en H monophasée ou polyphasés, constituée le plus souvent d’interrupteurs électroniques tels que les transistors CMOS, IGBT, transistors de puissance ou thyristors. Par un jeu de commutations commandées de manière appropriée (généralement une modulation de largeur d’impulsion), on module la source afin d’obtenir un signal alternatif de fréquence désirée. Lire la suite.

N’hésitez pas de consulter l’onduleur monophasé avec Arduino via les liens ci-dessous :

Exemple de test

L’exemple permet de générer un signal carré d’une fréquence égale à 4 Hz (250 ms). La sortie 22  de la carte Arduino est utilisée. Elle est branchée à la gâchette du transistor MOSFET à travers un pont diviseur d’un rapport au voisinage de 1.

Voir le tuto pour plus de détails concernant l’utilité du pont diviseur et les précautions à prendre durant la conception de l’onduleur.

Programme

#define Tr11            22          // Transistor 1/Bras 1 


const unsigned long T0=250; // T=2*T0 (µs)
bool State=false;

void setup()
{
// Pinout
pinMode(Tr11, OUTPUT);
digitalWrite(Tr11, State);
}

void loop()
{
digitalWrite(Tr11, State);
delay(T0);
State=!State;
}

On verra dans la prochaine partie la commande adjacente avec Arduino et des techniques d’optimisations du code.


Projet Onduleur Triphasé #1: Introduction was first posted on août 5, 2022 at 8:57 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
https://www.electronique-mixte.fr/projet-onduleur-triphase-1-introduction/feed/ 0
Commande d’un actionneur linéaire #3 : Commande Automatique https://www.electronique-mixte.fr/projet-commande-dun-actionneur-lineaire-arduino3-commande-automatique/ https://www.electronique-mixte.fr/projet-commande-dun-actionneur-lineaire-arduino3-commande-automatique/#respond Sat, 30 Jul 2022 06:45:30 +0000 https://www.electronique-mixte.fr/?p=20030 Commande d’un actionneur linéaire #3 : Commande Automatique was first posted on juillet 30, 2022 at 6:45 .
©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
]]>
Obtenir le fichier PDF

Objectifs

  1. Savoir l’utilité d’un actionnaire linéaire
  2. Savoir asservir la distance
  3. Savoir comment utiliser un capteur à ultrason
  4. Savoir les caractéristiques d’un actionnaire linéaire
  5. Savoir le fonctionnement d’un actionnaire linéaire
  6. Savoir commander un actionnaire linéaire
  7. Etc.

Applications

  1. Déplacement linéaire d’une charge, pièce
  2. Systèmes à vérin électrique
  3. Systèmes de translation : Portière, fenêtre, tables mobiles, etc.
  4. Procédés avec mouvement de translation précis
  5. Automatismes industriels
  6. Et, d’autres applications !

Principe de fonctionnement

Dans cette partie, on va voir comment asservir la distance de déplacement de l’arbre d’un actionneur linéaire (ou vérin électrique). L’idée consiste à définir une consigne par l’utilisateur, par exemple 20 mm. En suite, l’arabe va se déplacer d’une façon automatique jusqu’à l’obtention de la consigne, puis s’arrêter. Le système reste en revanche en asservissement permanent. Autrement dit, lorsque l’arabe s’éloigne de la consigne durant le fonctionnement, la commande va le ramener au voisinage de la consigne sans intervention humaine, c’est le principe de l’asservissement automatique !

  • Consigne : En pratique, la consigne peut être réglée par l’utilisateur soit par un potentiomètre, soit par deux boutons poussoir Up/Donw, une télécommande, etc. Un afficheur numérique est très utile afin de visualiser la cosigne réglée ainsi la sortie atteinte. On le voit souvent dans les systèmes asservis. Ici, la consigne sera définie dans le programme pour des raisons de simplifications. On verra peut-être dans un autre projet un système avec une consigne externe.
  • Capteur à ultrason : Il assure le retour de la distance de l’actionneur ou du vérin électrique. Il permet de passer d’une commande en boucle ouverte en une commande en boucle fermée.
  • Module PWM: Il permet de faire varier la vitesse de l’actionneur ainsi le changement de la polarité (sens de rotation). Le module est constitué d’un pont H complet avec une logique de commande. La partie commande nécessite 4 pins comme indiqué dans la figure. Les pins ( 6,7) dédiés à l’activation des bras droite/gauche du pont. Les pins (8, 9) sont des sorties PWM droite/gauche.  Par exemple, pour activer le sens 1, on positionne les pins (6, 7) à ‘1’ logique, ensuite, on envoie un signal PWM dans la sortie (8). La sortie  (9) en revanche reste à 0.
  • Actionneur linéaire : Il est alimenté avec la sortie du pont H complet
  • Arduino : Génération de la commande en fonction de la distance de l’arbre de l’actionneur

Commande d'un actionneur linéaire - Partie 3 Commande automatique

Le réglage du zéro

La procédure du réglage du zéro consiste à positionner l’actionner dans la position initiale durant la mise sous tension de la carte. La position initiale est définie par la fin de course basse. Lorsque le système se trouve dans la position initiale, le capteur de distance mesure une distante dite distance au repos (d0). Elle sera mémorisée et utilisée dans la boucle principale (voir le tuto pour plus de détails).  L’objectif du réglage du zéro est de réduire les dérives de la distance dans le temps (déplacement de la position du capteur ou celui de l’obstacle en face du capteur, etc.) et avoir une bonne précision sur l’obtention de la consigne. On peut supprimer la phase d’initialisation. En revanche, il faut définir une constante (d0) qu’elle sera introduite dans le programme. Une autre stratégie à deux capteurs à ultrason est envisageable pour se passer de la phase du réglage de zéros.

  // Remise à zéro de l'actionneur (Position initiale)  
const unsigned long TCourse=10; // Temps de la course max en secondes
unsigned long T=millis();
while((millis()-T)<TCourse*1000)
{
UpDown(PinOut, 1, 255); // Vitesse max
}
UpDown(PinOut, 0, 0); delay(2000);

Inversez la polarité du moteur si l’arbre translate dans le sens opposé.

Caractéristiques du pont H complet BTS7960

N’hésitez pas de consulter la partie 1 & 2 pour en savoir plus sur le fonctionnement du circuit BTS7960.

    Capteur à ultrason

    On va utiliser un capteur à ultrason pour la mesure de la distance de déplacement.

    module ultrason pour Arduino

    Les caractéristiques techniques du capteur – HC-SR04

    • Alimentation : 5 V
    • Consommation : 15 mA.
    • Portée : 2 cm à 5 m.
    • Résolution : 0.3 cm.
    • Angle de mesure : < 15°

    Chronogramme de fonctionnement

    Projet électronique FPGA 4 1 sur 3 Capteur de distance ultrasonique à base du FPGA et Arduino - capteur ultr

    Le capteur contient deux signaux TRIG et ECHO, et une broche d’alimentation à 5V et une masse.

    Le signal TRIG (une entrée) est une impulsion de 10 us qui permet de déclencher le circuit à l’intérieur du capteur pour activer l’émetteur ultrason (signal interne) et attendre l’arrivée de l’onde. Le capteur génère une sortie ECHO sous forme d’une impulsion électrique avec une largeur proportionnelle à la distance Aller/Retour.

    Nos avons abordé (voir ci-dessous) plusieurs projets dans le passé à base du capteur à ultrason avec Arduino. On va récupérer, amélioré et adapté le code à notre projet.

    Commentaires sur le code

    Pinout

    #define L_EN            6         // Left Enable   
    #define R_EN 7 // Right Enable
    #define L_PWM 8 // Left PWM
    #define R_PWM 9 // Right PWM
    #define RapCyc 30.0 // Duty Cycle (%)

    #define Consigne_mm 30.0 // Consigne en (mm)
    #define Epsilon_mm 3.0 // Consigne en (mm)

    #define Echo_in_pin 2 // Entrée: Retour de l'onde
    #define Trig_out_pin 3 // Sortie: Déclenchement de l'onde
    #define Speed_sound 340.0e-3 // Vitesse du son (mm/us)
    #define NMoy 150 // Filtrage de la distance

    Initialisation

    Définition de la fonction UpDown()

    La fonction UpDown() permet de générer les signaux de commande du module PWM en fonction du type de la commande. Elle prend en entrée le nom du tableau de 4 éléments content la numérotation des pins. La numérotation doit respecter l’ordre suivant : (L_EN, R_EN, L_PWM, R_PWM) (voir le code). Ensuite, le Type de la commande :

    • Type=1: Sens 1
    • Type=2: Sens 2
    • Type=0 ou autres valeurs : Arrêt

    La fonction prend également la valeur du rapport cyclique comprise entre 0 et 255. Par conséquent, grâce à la fonction, on peut faire varier le sens ainsi la vitesse du déplacement !  Ci-dessous la définition de la fonction.

    void UpDown(int* Pins, int Type,  unsigned int rapCyc)
    {
    switch (Type)
    {
    // Sens 1
    case 1:
    digitalWrite(Pins[0], HIGH);
    digitalWrite(Pins[1], HIGH);
    analogWrite(Pins[2], rapCyc);
    analogWrite(Pins[3], 0);
    break;

    // Sens 2
    case 2:
    digitalWrite(Pins[0], HIGH);
    digitalWrite(Pins[1], HIGH);
    analogWrite(Pins[2], 0);
    analogWrite(Pins[3], rapCyc);
    break;

    // Arrêt
    default:
    digitalWrite(Pins[0], LOW);
    digitalWrite(Pins[1], LOW);
    analogWrite(Pins[2], 0);
    analogWrite(Pins[3], 0);
    }
    }

    Définition de la fonction getMean()

    Mesure de la distance moyenne.

    float getMean(float *tabMoy, int Nm, float vin0)
    {
    // Variables locales
    static int J=0;
    float somme_1=0.0;
    float VMFiltre=0.0;

    // Filtrage: Calcul de la Moyenne Glissante
    for (int i=0; i<Nm; i++) somme_1+=tabMoy[i];
    VMFiltre=(somme_1/(float)Nm);

    // Mise à jour du tableau des VM
    tabMoy[J]=(vin0+VMFiltre)/2.0;
    J++; J%=Nm;

    // Retour de la VM
    return VMFiltre;
    }

    Définition de la fonction getDistmm()

    Lecture du capteur à ultrason. La fonction retourne la distance courante en (mm) entre le capteur et l’obstacle en face du capteur.

    double getDistmm(int trigpin, int echopin, double speedson) 
    {
    // Déclanchement mesure avec l'envoie d'une impulsion de 10µs
    digitalWrite(trigpin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigpin, LOW);

    // Lecture du temps aller/retour de l'onde
    double HC_val = pulseIn(echopin, HIGH, 30000);

    // Calcul de distance d(mm), V=d/t==> v*t
    // Le coefficient 2 pour la distance aller/retour
    double Dist_mm = (HC_val/2.0) * speedson;


    // Renvoi de la distance en (mm)
    if (Dist_mm <= 10.0) return 10.0; // Zone aveugle du capteur
    else return Dist_mm;
    }

    Application de la commande

    La commande utilisée est analogue à une commande incrémentale. La génération de la commande est effectuée d’une façon permanente en fonction de la distance en cours de l’arbre. On agit sur l’actionneur en fonction de la distance de retour de la façon suivante :

    • Augmentation du déplacement (Sens 1) : Distance de retour < Consigne – Epsilon
    • Diminution de déplacement (Sens 2) : Distance de retour >  Consigne – Epsilon
    • Arrêt : Distance au voisinage de la consigne à Epsilon près (désactivation du module PWM, pas de consommation à vide de l’actionneur).
      // Sens 1 - Down
    if (dist_mm> Consigne_mm+Epsilon_mm) UpDown(PinOut, 1, RP);

    // Sens 2 - Up
    else if (dist_mm< Consigne_mm-Epsilon_mm) UpDown(PinOut, 2, RP);

    // Arrêt
    else UpDown(PinOut, 0, RP);

     

    Vous pouvez tester d’autre stratégie de la commande en utilisant le même schéma électrique ! Il suffit de changer le code. Voir la série Asservissement avec Arduino pour plus de détails.

    Programme complet

     

    N’oublie pas de laisser un commentaire, ça nous encourage pour continuer à partager de nouveaux projets 🙂


    Commande d’un actionneur linéaire #3 : Commande Automatique was first posted on juillet 30, 2022 at 6:45 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    https://www.electronique-mixte.fr/projet-commande-dun-actionneur-lineaire-arduino3-commande-automatique/feed/ 0
    Commande d’un actionneur linéaire #2 : Commande manuelle https://www.electronique-mixte.fr/commande-dun-actionneur-lineaire-2-commande-manuelle/ https://www.electronique-mixte.fr/commande-dun-actionneur-lineaire-2-commande-manuelle/#respond Sun, 24 Jul 2022 03:30:40 +0000 https://www.electronique-mixte.fr/?p=19990 Commande d’un actionneur linéaire #2 : Commande manuelle was first posted on juillet 24, 2022 at 3:30 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    Obtenir le fichier PDF

    Objectifs

    1. Savoir l’utilité d’un actionnaire linéaire
    2. Savoir les caractéristiques d’un actionnaire linéaire
    3. Savoir le fonctionnement d’un actionnaire linéaire
    4. Savoir commander un actionnaire linéaire
    5. Etc.

    Applications

    1. Déplacement linéaire d’une charge, pièce
    2. Systèmes de translation : Portière, fenêtre, tables mobiles, etc.
    3. Procédés avec mouvement de translation précis
    4. Automatismes industriels
    5. Et, d’autres applications !

    Principe de fonctionnement

    Dans cette partie, on abordera la commande manuelle d’un actionneur linéaire avec Arduino. L’idée consiste à faire varier le sens ou la vitesse de déplacement de l’arbre d’une façon manuelle. Autrement dit, l’utilisateur va effectuer une manœuvre dans les deux sens, ainsi une inspection visuelle afin d’assurer le bon déplacement de l’arbre en utilisant un Joystick. Le schéma est constitué des éléments suivants :

    • Joystick: La manette est branchée dans le pin A0. La tension au repos du pin est égale à 2.5 V  (moitié de la tension d’alimentation). L’utilisateur peut faire croitre la tension (plage 2.5-5 V, Sens 1), ou le décroitre (plage 2.5-0 V, Sens 2).
    • Module PWM: Il permet de faire varier la vitesse de l’actionneur ainsi le changement de la polarité (sens de rotation). Le module est constitué d’un pont H complet avec une logique de commande. La partie commande nécessite 4 pins comme indiqué dans la figure. Les pins ( 6,7) dédiés à l’activation des bras droite/gauche du pont. Les pins (8, 9) sont des sorties PWM droite/gauche.  Par exemple, pour activer le sens 1, on positionne les pins (6, 7) à ‘1’ logique, ensuite, on envoie un signal PWM dans la sortie (8). La sortie  (9) en revanche reste à 0.
    • Actionneur linéaire : Il est alimenté avec la sortie du pont H
    • Arduino : Génération de la commande en fonction de l’état du Joystick (voir le tuto pour plus de détails).

    Commande d'un actionneur linéaire - Partie 2 Commande manuelle

    Caractéristiques du pont H complet BTS7960

    • Pont H complet aux transistors MOSFET (x4) avec les diodes  (pour les charges inductives)
    • La tension d’alimentation (partie puissance) : 5.5V à 27V
    • Alimentation partie commande : 3.3-5V
    • Courant maximal (partie puissance) : 43A
    • Insolation entre la partie commande et la partie puissance
    • Le module peut être utilisé pour les charges DC (Inversion du sens/vitesse des moteurs DC) ou AC (onduleur)
    • Fréquence maximale des entrées PWM : DC-25KHz
    • Protection contre surtension/surintensité
    • Module intègre deux capteurs du courant (Sens 1 / Sens 2)
    • Regarder la vidéo pour plus de détails

    A quoi sert le composant BTS6960 ?

    Le pont H est constitué de deux composants BTS7960 identiques sous forme de deux demi-ponts à base des transistors MOS complémentaires. Chaque transistor est muni d’une diode de roue libre pour les charges inductives pour permettre la circulation du courant de la bobine de la charge lorsque l’ensemble des transistors sont en circuit ouvert. Chaque circuit protège la charge contre la surtension, surintensité, etc. et un capteur du courant. Ci-dessous le datasheet du mo.

    Obtenir le datasheet du composant

    Commentaires sur le code

    Pinout

    #define L_EN            6         // Left Enable   
    #define R_EN 7 // Right Enable
    #define L_PWM 8 // Left PWM
    #define R_PWM 9 // Right PWM
    #define RapCyc 90.0 // Duty Cycle (%)

    Initialisation

    void setup() 
    {
    // Pinout Module PWM
    pinMode(L_EN, OUTPUT);
    pinMode(R_EN, OUTPUT);
    pinMode(L_PWM, OUTPUT);
    pinMode(R_PWM, OUTPUT);

    // Init Module PWM
    digitalWrite(L_EN, LOW);
    digitalWrite(R_EN, LOW);
    analogWrite(L_PWM, 0);
    analogWrite(R_PWM, 0);

    // Init tableau des pins
    PinOut[0]=L_EN;
    PinOut[1]=R_EN ;
    PinOut[2]=L_PWM;
    PinOut[3]=R_PWM;

    // Init rapport cyclique
    RP=(unsigned short)(RapCyc*255.0/100.0);

    // Affichage (Test)
    Serial.begin(115200);
    }

    Définition de la fonction UpDown()

    La fonction UpDown() permet de générer les signaux de commande du module PWM en fonction du type de la commande. Elle prend en entrée le nom du tableau de 4 éléments content la numérotation des pins. La numérotation doit respecter l’ordre suivant : (L_EN, R_EN, L_PWM, R_PWM) (voir le code). Ensuite, le Type de la commande :

    • Type=1: Sens 1
    • Type=2: Sens 2
    • Type=0 ou autres valeurs : Arrêt

    La fonction prend également la valeur du rapport cyclique comprise entre 0 et 255. Par conséquent, grâce à la fonction, on peut faire varier le sens ainsi la vitesse du déplacement !  Ci-dessous la définition de la fonction.

    void UpDown(int* Pins, int Type,  unsigned int rapCyc)
    {
    switch (Type)
    {
    // Sens 1
    case 1:
    digitalWrite(Pins[0], HIGH);
    digitalWrite(Pins[1], HIGH);
    analogWrite(Pins[2], rapCyc);
    analogWrite(Pins[3], 0);
    break;

    // Sens 2
    case 2:
    digitalWrite(Pins[0], HIGH);
    digitalWrite(Pins[1], HIGH);
    analogWrite(Pins[2], 0);
    analogWrite(Pins[3], rapCyc);
    break;

    // Arrêt
    default:
    digitalWrite(Pins[0], LOW);
    digitalWrite(Pins[1], LOW);
    analogWrite(Pins[2], 0);
    analogWrite(Pins[3], 0);
    }
    }

    Application de la commande

    La génération de la commande est effectuée d’une façon permanente en fonction de l’état du Joystick. Au repos, la tension est égale à 2.5 V. On agit sur l’actionneur uniquement lorsque la tension dépasse de 1 V la tension au repos dans les deux sens pour être sûre que la variation n’est pas due au bruit et pour éviter de chauffer l’actionneur et consommer du courant (réduire la durée de vie). En effet, si on fixe un seuil égal à 2.5 V, on risque de solliciter l’actionneur en permanence à cause d’une faible variation de la tension dans le pin A0 qui peut être due au bruit.

    • Sens 1: Tension A0 >2.5+1
    • Sens 2: Tension A0<2.5-1
    • Arrêt : Sinon (désactivation du module PWM, pas de consommation à vide de l’actionneur).
      // Sens 1 
    if (Vin> 2.5+1.0)UpDown(PinOut, 1, RP);

    // Sens 2
    else if (Vin< 2.5-1.0) UpDown(PinOut, 2, RP);

    // Arrêt
    else UpDown(PinOut, 0, RP);

    Programme complet

    #define L_EN            6         // Left Enable   
    #define R_EN 7 // Right Enable
    #define L_PWM 8 // Left PWM
    #define R_PWM 9 // Right PWM
    #define RapCyc 90.0 // Duty Cycle (%)

    float Vin=0.0;
    unsigned short RP= 0;
    int PinOut[4];

    void setup()
    {
    // Pinout Module PWM
    pinMode(L_EN, OUTPUT);
    pinMode(R_EN, OUTPUT);
    pinMode(L_PWM, OUTPUT);
    pinMode(R_PWM, OUTPUT);

    // Init Module PWM
    digitalWrite(L_EN, LOW);
    digitalWrite(R_EN, LOW);
    analogWrite(L_PWM, 0);
    analogWrite(R_PWM, 0);

    // Init tableau des pins
    PinOut[0]=L_EN;
    PinOut[1]=R_EN ;
    PinOut[2]=L_PWM;
    PinOut[3]=R_PWM;

    // Init rapport cyclique
    RP=(unsigned short)(RapCyc*255.0/100.0);

    // Affichage (Test)
    Serial.begin(115200);
    }

    void loop()
    {
    // Lecture & Affichage du pin A0
    Vin=(float)analogRead(A0)*5.0/1023.0;
    //Serial.println(Vin); return; // Test A0

    // Sens 1
    if (Vin> 2.5+1.0)UpDown(PinOut, 1, RP);

    // Sens 2
    else if (Vin< 2.5-1.0) UpDown(PinOut, 2, RP);

    // Arrêt
    else UpDown(PinOut, 0, RP);
    }

    void UpDown(int* Pins, int Type, unsigned int rapCyc)
    {
    switch (Type)
    {
    // Sens 1
    case 1:
    digitalWrite(Pins[0], HIGH);
    digitalWrite(Pins[1], HIGH);
    analogWrite(Pins[2], rapCyc);
    analogWrite(Pins[3], 0);
    break;

    // Sens 2
    case 2:
    digitalWrite(Pins[0], HIGH);
    digitalWrite(Pins[1], HIGH);
    analogWrite(Pins[2], 0);
    analogWrite(Pins[3], rapCyc);
    break;

    // Arrêt
    default:
    digitalWrite(Pins[0], LOW);
    digitalWrite(Pins[1], LOW);
    analogWrite(Pins[2], 0);
    analogWrite(Pins[3], 0);
    }
    }

    On verra  prochainement la partie commande. N’oublie pas de laisser un commentaire, ça nous encourage pour continuer  à partager des projets 🙂


    Commande d’un actionneur linéaire #2 : Commande manuelle was first posted on juillet 24, 2022 at 3:30 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    https://www.electronique-mixte.fr/commande-dun-actionneur-lineaire-2-commande-manuelle/feed/ 0
    Commande d’un actionneur linéaire #1 : Introduction https://www.electronique-mixte.fr/arduino-commande-actionneur-lineaire-1-introduction/ https://www.electronique-mixte.fr/arduino-commande-actionneur-lineaire-1-introduction/#respond Sat, 23 Jul 2022 04:10:31 +0000 https://www.electronique-mixte.fr/?p=19964 Commande d’un actionneur linéaire #1 : Introduction was first posted on juillet 23, 2022 at 4:10 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    Obtenir le fichier PDF

    Objectifs

    1. Savoir l’utilité d’un actionnaire linéaire
    2. Savoir les caractéristiques d’un actionnaire linéaire
    3. Savoir le fonctionnement d’un actionnaire linéaire
    4. Savoir commander un actionnaire linéaire
    5. Etc.

    Applications

    1. Déplacement linéaire d’une charge, pièce
    2. Systèmes de translation : Portière, fenêtre, tables mobiles, etc.
    3. Procédés avec mouvement de translation précis
    4. Automatismes industriels
    5. Et, d’autres applications !

    Principe de fonctionnement

    Principe actionneur linéaire

    Un actionneur linéaire électrique est similaire à un vérin électrique. Il permet d’assurer un mouvement de translation dans les deux sens. Il est généralement constitué d’un moteur à courant continue (DC), d’un réducteur et arbre visé comme indiqué dans la figure. Par conséquent, les caractéristiques de l’actionneur vont dépendre de celles du moteur-réducteur, ainsi la longueur de l’arbre. Ci-dessous une liste non exhaustive des principaux critères du choix d’un actionneur linéaire :

    • Type & Tension d’alimentation 12/24/48, etc.
    • Type du moteur (à CC, pas à pas, servomoteur,
    • Courant maximal (pour une charge maximale)
    • Courant à vide (sans charge)
    • Vitesse maximale du déplacement, souvent en mm/s
    • Type de l’entraînement (vissage, courroie, miniature, etc.)
    • Poids maximal en (N), environ un rapport 10 par rapport à la charge en Kg
    • Plage du mouvement ou la longueur effective de l’arbre en pleine échelle (minimale & maximale)
    • Indice de protection (étanchéité)
    • Température de fonctionnement
    • Type de la commande
    • Etc.

    Ci-dessous un exemple typique d’un actionnaire linéaire électrique NW-1000-12

    Les caractéristiques d'un actionneur linéaire NW-1000-12

    On verra  prochainement la partie commande. N’oublie pas de laisser un commentaire, ça nous encourage pour continuer  à partager des projets 🙂

     


    Commande d’un actionneur linéaire #1 : Introduction was first posted on juillet 23, 2022 at 4:10 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    https://www.electronique-mixte.fr/arduino-commande-actionneur-lineaire-1-introduction/feed/ 0
    Projet Arduino: Asservissement PWM – Correcteur Proportionnel (P) https://www.electronique-mixte.fr/projet-arduino-asservissement-pwm-correcteur-p/ https://www.electronique-mixte.fr/projet-arduino-asservissement-pwm-correcteur-p/#comments Thu, 14 Jul 2022 08:23:22 +0000 https://www.electronique-mixte.fr/?p=19930 Projet Arduino: Asservissement PWM – Correcteur Proportionnel (P) was first posted on juillet 14, 2022 at 8:23 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    Obtenir le fichier PDF

    Objectifs

    1. Savoir implémenter une boucle d’asservissement traditionnelle
    2. Savoir les limites du correcteur proportionnel (P)
    3. Savoir implémenter la fonction de saturation et son utilité
    4. Savoir optimiser le correcteur P

    Applications

    1.  Asservissement de la vitesse
    2. Systèmes de régulation automatique
    3. Convertisseurs AC/DC, DC/AC, DC/DC, etc. Asservis
    4. Asservissement de la température, humidité, etc.
    5. Et, d’autres applications !

    Principe de fonctionnement

    Projet Arduino Asservissement PWM - Correcteur proportionnel Arduino

     

    Voir le tuto pour plus de détails techniques.

    La fonction getMean()

    La fonction getMean() permet de renvoyer la valeur moyenne actuelle du signal PWM. Elle prend en entrée la tension PWM actuelle, le tableau des anciennes valeurs moyennes, puis elle revoie la valeur moyenne récente. Elle contient l’indice d’incrémentation des éléments du tableau au format static : Pour chaque appel, l’indice s’incrémente d’un pas égal à 1. Ci-dessous la définition de la fonction.

    float getMean(float *tabMoy, int Nm, float vin0)
    {
    // Variables locales
    static int J=0;
    float somme_1=0.0;
    float VMFiltre=0.0;

    // Filtrage: Calcul de la Moyenne Glissante
    for (int i=0; i<Nm; i++) somme_1+=tabMoy[i];
    VMFiltre=(somme_1/(float)Nm);

    // Mise à jour du tableau des VM
    valMoy[J]=(vin0+VMFiltre)/2.0;
    J++; J%=Nm;

    // Retour de la VM
    return VMFiltre;
    }

    La fonction Satur()

    La fonction Satur() permet de garantir le non-débordement de la commande. Elle assure que la valeur de la commande soit comprise entre [-Vmax, Vmax]. Elle est basée sur la fonction mathématique tangente hyperbolique modifiée tanh() (voir le tutoriel pour plus de détails). La fonction sert à générer une commande « soft » et convergente grâce aux propriétés limites de la tanh() . Elle joue également le rôle de stabilisation de la commande en cas d’une mauvaise manœuvre des paramètres du correcteur ou du système.  La fonction Satur() prend en entrée la commande, la valeur maximale Vmax, puis elle retourne la commande écrêtée. Ci-dessous la définition de la fonction.

    double Satur(double vin, double vmax)
    {
    double vout=0.0;
    double x=0.0;
    const double Eps=1E-12 ; // Eviter la division /0

    vout=vmax*tanh(vin/(vmax+Eps));

    // Ou bien
    /*
    x=vin/(vmax+Eps); // tanh(x)=(1.0-exp(-2.0*x))/(1.0+exp(-2.0*x));
    vout=vmax*(1.0-exp(-2.0*x))/(1.0+exp(-2.0*x));
    */

    return vout;
    }

    Programme complet


    #define Out 9 // Sortie PWM
    #define In A0 // Entrée analogique
    #define OutTOR 2 // Sortie TOR
    #define Consigne 3.5 // Tension de la consigne
    #define K 5.0 // Action Proportionnelle
    #define NMoy 150 // Moyenne glissante
    #define TCycMicroS 20000 // Délai de la boucle en µS


    float v_fil=0.0;
    float v_fil_old=0.0;
    bool LoopCyc=false;
    float somme =0.0;
    float vin_volat=0.0;
    float valMoy[NMoy];
    int Vin_A0=0;
    int I=0;
    float OutPWM=0.0;
    float Cmd=0.0;
    float Erreur_t=0.0;


    void setup()
    {
    // Pinout
    pinMode(Out, OUTPUT);
    pinMode(OutTOR, OUTPUT);

    // Init PWM
    analogWrite(Out, 0);

    // Calcul de la moyenne actuelle
    for (int i=0; i<NMoy; i++)
    {
    vin_volat=(float)analogRead(A0)*5.0/1023.0;
    somme+=vin_volat;
    }
    v_fil=(somme/(float)NMoy);
    somme=0.0;

    // Initialisation du tableau des VM
    for (int i=0; i<NMoy; i++) valMoy[i]= v_fil;

    // Affichage
    Serial.begin(250000);
    }


    void loop()
    {
    // 1. Lecture de l'entrée A0
    vin_volat=(float)analogRead(A0)*5.0/1023.0;

    // 2. Extraction de la valeur moyenne
    v_fil= getMean(valMoy, NMoy, vin_volat);

    //3.1 Calul de l'erreur
    Erreur_t=(Consigne - v_fil); // [-5, 5]

    //3.2 Génération du signal de la commande
    Cmd=(K*Erreur_t)*255.0/5.0; // [-X, X]

    //3.3 Saturation
    OutPWM=Satur(Cmd, 255.0); // [-255, 255]

    //4. Génération de la commande PWM
    analogWrite(Out, (unsigned char)abs(round(OutPWM))); // [0, 255]

    //5. Affichage (Uniquement pour le test)
    Serial.print(0.5*vin_volat-2.5); Serial.print(",");
    Serial.print(Consigne); Serial.print(",");
    Serial.print(v_fil); Serial.print(",");
    //Serial.println(Cmd*5.0/255.0);
    Serial.println(OutPWM*5.0/255.0);

    //6. Délai de la boucle
    delayMicroseconds(TCycMicroS);

    /*
    LoopCyc=!LoopCyc;
    digitalWrite(OutTOR, LoopCyc);
    */
    }


    double Satur(double vin, double vmax)
    {
    double vout=0.0;
    double x=0.0;
    const double Eps=1E-12 ; // Eviter la division /0

    vout=vmax*tanh(vin/(vmax+Eps));

    // Ou bien
    /*
    x=vin/(vmax+Eps); // tanh(x)=(1.0-exp(-2.0*x))/(1.0+exp(-2.0*x));
    vout=vmax*(1.0-exp(-2.0*x))/(1.0+exp(-2.0*x));
    */

    return vout;
    }



    float getMean(float *tabMoy, int Nm, float vin0)
    {
    // Variables locales
    static int J=0;
    float somme_1=0.0;
    float VMFiltre=0.0;

    // Filtrage: Calcul de la Moyenne Glissante
    for (int i=0; i<Nm; i++) somme_1+=tabMoy[i];
    VMFiltre=(somme_1/(float)Nm);

    // Mise à jour du tableau des VM
    valMoy[J]=(vin0+VMFiltre)/2.0;
    J++; J%=Nm;

    // Retour de la VM
    return VMFiltre;
    }

    On verra  prochainement le correcteur PI. N’oublie pas de laisser un commentaire, ça nous encourage pour continuer  à partager des projets 🙂

    Le Correcteur Proportionnel Intégral (PI)  – Numérisation

    Le Correcteur Proportionnel Intégral (PI)  – Implémentation

    Le Correcteur Avance de Phase – Numérisation

    Le Correcteur Avance de Phase –Implémentation

    Autres correcteurs.


    Projet Arduino: Asservissement PWM – Correcteur Proportionnel (P) was first posted on juillet 14, 2022 at 8:23 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    https://www.electronique-mixte.fr/projet-arduino-asservissement-pwm-correcteur-p/feed/ 2
    Projet Arduino: La Commande Incrémentale – Version 2 [TUTO] https://www.electronique-mixte.fr/projet-arduino-la-commande-incrementale-version-2-tuto/ https://www.electronique-mixte.fr/projet-arduino-la-commande-incrementale-version-2-tuto/#respond Sun, 10 Jul 2022 02:48:23 +0000 https://www.electronique-mixte.fr/?p=19912 Projet Arduino: La Commande Incrémentale – Version 2 [TUTO] was first posted on juillet 10, 2022 at 2:48 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    Obtenir le fichier PDF

    Objectifs

    1. Savoir implémenter une boucle de régulation
    2. Savoir le principe de la Commande Incrémentale
    3. Savoir implémenter une moyenne glissante
    4. Savoir asservir un signal PWM

    Applications

    1.  Asservissement de la vitesse
    2. Systèmes de régulation automatique
    3. Convertisseurs AC/DC, DC/AC, DC/DC, etc. Asservis
    4. Asservissement de la température, humidité, etc.
    5. Et, d’autres applications !

    Principe de fonctionnement

    schémas Commande incrémentale - version améliorée - V2

    Nous avons abordé dans la V1 le concept et comment implémenter une commande incrémentale avec Arduino. Le point  fort d’une commande incrémentale est sa convergence assurée vers la consigne Quelle que soit la charge avec une erreur statique nulle. C’est une commande générique contrairement aux stratégies d’asservissement traditionnelles par correcteurs (P, PI, PID, etc.). En revanche, le temps de réponse est un peu long. La version actuelle permet d’améliorer la stabilité de la commande (réduction des ondulations autour de la consigne) et réduire le temps de réponse. Les améliorations, on était apportés en particulier au filtre moyenneur. L’idée consiste à garder en mémoire les valeurs moyennes calculées (les moyennes précédentes). La valeur filtrée actuelle sera donc la somme des valeurs moyennes précédentes et la valeur actuelle du port A0. Le reste du programme reste le même comme celui de la V1.

    Voir la version #1 concernant  le fonctionnement.

    Voir le tuto pour plus de détails techniques.

    Programme complet

    #define Out         9       
    #define In A0
    #define Consigne 2.5 // Tension de la consigne
    #define N 150 // Moyenne: valeur initiale (setup)
    #define NMoy 100 // Moyenne glissante (loop)
    #define Epsilon 1E-3 // Epsilon
    #define StepCyc 1E-2 // Pas d'incrémentation du Rapport Cyclique / Cycle


    float v_fil=0.0;
    float v_fil_old=0.0;
    bool LoopCyc=false;
    float somme =0.0;
    float vin_volat=0.0;
    float valMoy[NMoy];
    int Vin_A0=0;
    int I=0;
    float OutPWM=0; //Consigne*255.0/5.0;


    void setup()
    {
    // Pinout
    pinMode(Out, OUTPUT);
    analogWrite(Out, 180);

    // Calcul de la moyenne actuelle
    for (int i=0; i<N; i++)
    {
    vin_volat=(float)analogRead(A0)*5.0/1023.0;
    somme+=vin_volat;
    }
    v_fil=(somme/(float)N);
    somme=0.0;

    // Initialisation du tableau des VM
    for (int i=0; i<NMoy; i++) valMoy[i]= v_fil;

    // Affichage
    Serial.begin(115200);
    }

    void loop()
    {

    // 1. Lecture de l'entrée A0
    vin_volat=(float)analogRead(A0)*5.0/1023.0;

    // 2. Filtrage: Calcul de la Moyenne Glissante
    for (int i=0; i<NMoy; i++) somme+=valMoy[i];
    v_fil=(somme/(float)NMoy);
    somme=0.0;

    // 3. Mise à jour du tableau des VM
    valMoy[I]=(v_fil+vin_volat)/2.0;
    I++; I%=NMoy;

    /*4. Mise à jour de la commande */
    // 4.1: Consigne Atteinte
    if (((v_fil>=Consigne -1.5*Epsilon) && (v_fil<=Consigne +1.5*Epsilon)))
    {
    return; // Ne rien faire!
    }

    // 4.2: Incrémentation
    if ((v_fil<Consigne))
    {
    OutPWM+=StepCyc;
    if (OutPWM>=255.0) OutPWM-=StepCyc;
    }

    // 4.3: Décrémentation
    if ( (v_fil>Consigne))
    {
    OutPWM-=StepCyc;
    if (OutPWM<=0.0) OutPWM+=StepCyc;
    }

    //5. Génération de la commande PWM
    analogWrite(Out, (unsigned int)OutPWM);
    v_fil_old= v_fil;

    // 6. Affichage (Test Seulement)
    Serial.print(vin_volat);
    Serial.print(",");
    Serial.print(Consigne);
    Serial.print(",");
    Serial.print(v_fil);
    Serial.print(",");
    Serial.println(OutPWM*5.0/255.0);

    /*
    LoopCyc=!LoopCyc;
    Serial.println(LoopCyc);
    */
    }

    On verra  prochainement la version améliorée du code. N’oublie pas de laisser un commentaire, ça nous encourage pour continuer  à partager des projets 🙂


    Projet Arduino: La Commande Incrémentale – Version 2 [TUTO] was first posted on juillet 10, 2022 at 2:48 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    https://www.electronique-mixte.fr/projet-arduino-la-commande-incrementale-version-2-tuto/feed/ 0
    Projet Arduino: La Commande Incrémentale – Version 1 [TUTO] https://www.electronique-mixte.fr/projet-arduino-la-commande-incrementale-version-1-tuto/ https://www.electronique-mixte.fr/projet-arduino-la-commande-incrementale-version-1-tuto/#comments Tue, 05 Jul 2022 17:28:55 +0000 https://www.electronique-mixte.fr/?p=19901 Projet Arduino: La Commande Incrémentale – Version 1 [TUTO] was first posted on juillet 5, 2022 at 5:28 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    Obtenir le fichier PDF

    Objectifs

    1. Savoir implémenter une boucle de régulation
    2. Savoir le principe de la Commande Incrémentale
    3. Savoir implémenter une moyenne glissante
    4. Savoir asservir un signal PWM

    Applications

    1.  Asservissement de la vitesse
    2. Systèmes de régulation automatique
    3. Convertisseurs AC/DC, DC/AC, DC/DC, etc. Asservis
    4. Asservissement de la température, humidité, etc.
    5. Et , d’autres applications!

    Principe de fonctionnement

    Commande Incrémentale avec Arduino

    Le mini projet consiste à mettre en pratique le principe de fonctionnement d’une commande incrémentale avec Arduino. On utilise dans l’exemple un bouclage unitaire d’un signal PWM. L’objectif du programme est de maintenir la tension DC à la borne de la charge constante en faisant varier le rapport cyclique du signal PWM. La consigne est définit par le programme. Le concept d’incrémentation consiste à faire incrémenter (ou décrémenter) le rapport cyclique jusqu’à l’obtention de la consigne. Le programme extrait la valeur moyenne du signal PWM avant de décider si on incrémente ou décrémenter la commande. La qualité du filtrage ainsi le pas d’incrémentation sont définit dans le programme.

    Voir le tuto pour plus de détails techniques.

    Notes sur le programme

    Les paramètres du programme

    #define Out         9

    #define In          A0

    #define Consigne    4.0       // Tension de la consigne

    #define N           100       // Filtrage de l'entrée

    #define Step        1E-3      // Erreur sur la consigne (Epsilon)

    #define StepCyc     1E-1      // Pas d'incrémentation du Rapport Cyclique / Cycle

    Initialisation

    Le pin 9 est utilisé pour générer le signal PWM. Il est rebouclé dans le pin analogique A0. On initialise aussi le tableau avec le contenu de l’entrée A0. Le port série sera utilisé afin d’observer en temps réel la valeur moyenne, le rapport cyclique ainsi le signal PWM.

    void setup() 
    {
    // Pinout
    pinMode(Out, OUTPUT);
    analogWrite(Out, 180);

    // Init Vin
    for (int i=0; i<N; i++) vinTab[i]=analogRead(A0);

    // Affichage
    Serial.begin(115200);
    }

    La boucle principale

    Lecture de l’entrée A0

    Vin_A0=analogRead(A0);

    vinTab[I]=Vin_A0;

    Mise à jour de l’indice

    I=I+1;

    if (I==N) I=0;

    Filtrage: Calcul de la Moyenne Glissante

      for (int i=0; i<N; i++)
    {
    vin_volat=(float)vinTab[i]*5.0/1023.0;
    somme+=vin_volat;
    }
    v_fil=(somme/(float)N);
    somme=0.0;

    Mise à jour de la sortie

    Consigne Atteinte

      if ((v_fil>=Consigne -1.5*Step) && (v_fil<=Consigne +1.5*Step))  
    return; // Ne rien faire!

    Incrémentation

      if ((v_fil<Consigne))  
    {
    OutPWM+=StepCyc;
    if (OutPWM>=255.0) OutPWM-=StepCyc;
    }

    Décrémentation

      if ( (v_fil>Consigne))  
    {
    OutPWM-=StepCyc;
    if (OutPWM<=0.0) OutPWM+=StepCyc;
    }

    Génération de la commande PWM

    analogWrite(Out, (unsigned int)OutPWM);

    Affichage

    Serial.print((float)Vin_A0*5.0/1023.0);

    Serial.print(",");

    Serial.print(Consigne);

    Serial.print(",");

    Serial.print(v_fil);

    Serial.print(",");

    Serial.println((float)OutPWM*5.0/255.0);

    Programme complet

    #define Out         9       
    #define In A0

    #define Consigne 4.0 // Tension de la consigne
    #define N 100 // Filtrage de l'entrée
    #define Step 1E-3 // Epsilon
    #define StepCyc 1E-1 // Pas d'incrémentation du Rapport Cyclique / Cycle



    float v_fil=0.0;
    float somme =0.0;
    float vin_volat=0.0;
    int vinTab[N];
    int Vin_A0=0;
    int I=0;
    float OutPWM=180.0;


    void setup()
    {
    // Pinout
    pinMode(Out, OUTPUT);
    analogWrite(Out, 180);

    // Init Vin
    for (int i=0; i<N; i++) vinTab[i]=analogRead(A0);

    // Affichage
    Serial.begin(115200);
    }

    void loop()
    {

    // 1. Lecture de l'entrée A0
    Vin_A0=analogRead(A0);
    vinTab[I]=Vin_A0;

    // 2. Mise à jour de l'indice
    I=I+1;
    if (I==N) I=0;

    // 3. Filtrage: Calcul de la Moyenne Glissante
    for (int i=0; i<N; i++)
    {
    vin_volat=(float)vinTab[i]*5.0/1023.0;
    somme+=vin_volat;
    }
    v_fil=(somme/(float)N);
    somme=0.0;

    /*4. Mise à jour de la sortie */
    // 4.1: Consigne Atteinte
    if ((v_fil>=Consigne -1.5*Step) && (v_fil<=Consigne +1.5*Step))
    return; // Ne rien faire!

    // 4.2: Incrémentation
    if ((v_fil<Consigne))
    {
    OutPWM+=StepCyc;
    if (OutPWM>=255.0) OutPWM-=StepCyc;
    }

    // 4.3: Décrémentation
    if ( (v_fil>Consigne))
    {
    OutPWM-=StepCyc;
    if (OutPWM<=0.0) OutPWM+=StepCyc;
    }

    //5. Génération de la commande PWM
    analogWrite(Out, (unsigned int)OutPWM);


    // 6. Affichage
    Serial.print((float)Vin_A0*5.0/1023.0);
    Serial.print(",");
    Serial.print(Consigne);
    Serial.print(",");
    Serial.print(v_fil);
    Serial.print(",");
    Serial.println((float)OutPWM*5.0/255.0);
    }

    On verra  prochainement la version améliorée du code. N’oublie pas de laisser un commentaire, ça nous encourage pour continuer  à partager des projets 🙂


    Projet Arduino: La Commande Incrémentale – Version 1 [TUTO] was first posted on juillet 5, 2022 at 5:28 .
    ©2021 "Arduino | Cours | Électronique | Drone | Matlab". Use of this feed is for personal non-commercial use only. If you are not reading this article in your feed reader, then the site is guilty of copyright infringement. Please contact me at eaitmansour@electronique-mixte.fr
    ]]>
    https://www.electronique-mixte.fr/projet-arduino-la-commande-incrementale-version-1-tuto/feed/ 2