mercredi 27 juillet 2011

Asservissement vitesse d'un moteur à courant continu

Dans le cadre d'un projet en matière technologie d’acquisition et d'interfaçage j'ai réaliser ce projet qui est mieux expliquer dans la photo en bas.
Schéma synoptique
l'interface:
La carte sur isis:
 PCB sur ARES:

 

Code en c#


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace WindowsFormsApplication1
{
    using ZedGraph;
    public partial class Form1 : Form
    {
        float temps=0;
        float consigne=0;
        float commande=0;
        float fecartold;
        float fIntegral = 0;
        float fDerive = 0;
        float freponseOld=0;
        byte[] buffer = new byte[8];
        #region partie test pour une foction de transfert numerique        
        float reponse = 0;
        #endregion        
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            CreerGraphique(zedGraphControl1);
        }
        #region  creeer graphique
        private void CreerGraphique(ZedGraphControl zgc)
        {
            GraphPane Pane = zgc.GraphPane;
            PointPairList list1 = new PointPairList();
            PointPairList list2 = new PointPairList();
            PointPairList list3 = new PointPairList();
            LineItem CourbeConsigne = Pane.AddCurve("Consigne", list1, Color.Red);
            LineItem CourbeMesure = Pane.AddCurve("Commande", list2, Color.Black);
            LineItem CourbeCommande = Pane.AddCurve("Mesure", list3, Color.Green);
            Pane.Title.Text = "Simulation en temps réel de la vitesse";
            Pane.XAxis.Title.Text = "Axe X";
            Pane.YAxis.Title.Text = "Axe Y";
            CourbeConsigne.Symbol.Size = 1.0F;
            CourbeConsigne.Line.Width = 2.0F;
            CourbeMesure.Symbol.Size = 1.0F;
            CourbeMesure.Line.Width = 2.0F;
            CourbeCommande.Symbol.Size = 1.0F;
            CourbeCommande.Line.Width = 2.0F;
        }
        #endregion

        #region taswer mte3 lgraph
        private void addDataToGraph(ZedGraphControl zg1, XDate x, double tconsigne,double tcommande, double treponse )
        {
            LineItem curve = zg1.GraphPane.CurveList[0] as LineItem;
            IPointListEdit list = curve.Points as IPointListEdit;
            list.Add(x,tconsigne);
            LineItem curve2 = zg1.GraphPane.CurveList[1] as LineItem;
            IPointListEdit list2 = curve2.Points as IPointListEdit;
            list2.Add(x, tcommande);
            LineItem curve3 = zg1.GraphPane.CurveList[2] as LineItem;
            IPointListEdit list3 = curve3.Points as IPointListEdit;
            list3.Add(x, treponse);            
            zg1.Invalidate();
            zedGraphControl1.AxisChange();
        }
#endregion

    

        private void zedGraphControl1_Load(object sender, EventArgs e)
        {
        }

        private void rdncnvar_CheckedChanged(object sender, EventArgs e)
        {
            if (rdncnvar.Checked==true)
            {
                hscrCons.Value = 0;
                hscrCons.Enabled = true;
                NumConVar.Enabled = true;
            }
            else
            {
                hscrCons.Enabled = false;
                NumConVar.Text = "0";
                NumConVar.Enabled = false;
            }
        }

        private void hscrCons_Scroll(object sender, ScrollEventArgs e)
        {
            NumConVar.Text = hscrCons.Value.ToString();
        }

        private void chkConsBoucleOuverte_CheckedChanged(object sender, EventArgs e)
        {
            if (chkConsBoucleOuverte.Checked == true)
            {
                Régulation.Enabled = false;                
            }
            else
            {
                Régulation.Enabled = true;                
            }
        }

        private void btnOuvrPort_Click(object sender, EventArgs e)
        {
            try
            {
                serialPort1.Open();
                lbCommunication.BackColor = Color.Green;
                lbCommunication.Text = "Connexion établie";
                Consignes.Enabled = true;                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Impossible d'ouvrir le port ");
                
            }
        }

        private void comboCom_SelectedIndexChanged(object sender, EventArgs e)
        {
            serialPort1.PortName = comboCom.Text;
        }

        private void ComboBaude_SelectedIndexChanged(object sender, EventArgs e)
        {
            serialPort1.BaudRate = int.Parse(ComboBaude.Text);
        }

        private void btnFermPort_Click(object sender, EventArgs e)
        {
            timer.Enabled = false;
            serialPort1.Close();
            lbCommunication.BackColor = Color.Red;
            lbCommunication.Text = "Pas de connexion";
            Consignes.Enabled = false;
        }

        private void btnValider_Click(object sender, EventArgs e)
        {
          
            timer.Enabled = true;            
            
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            float inter;
            temps += 0.1F;
            if (rdnEchel.Checked == true)
            {
                float.TryParse(numConEche.Text,out consigne);
            }
            if (rdnRamp.Checked == true)
            {
                if (consigne >= 100) consigne = 100;
                else
                {
                    float.TryParse(NumConRamp.Text, out inter);
                    consigne = inter * temps;
                }                
            }
            if (rdncnvar.Checked == true) //Consigne variable
            {
                float.TryParse(NumConVar.Text,out consigne);
            }            
            float rconsigne = (commande / 100) * 255;
            int iconsigne = (int)rconsigne;
            if (iconsigne>255)
            {
                iconsigne = 255;
            }
            else if(iconsigne<0)
            {
                iconsigne = 0;
            }
            txtMesVit.Text = iconsigne.ToString();
            #region envoi serial
            byte[] wbuffer = new byte[1];
            byte buffe = Convert.ToByte(iconsigne);
            wbuffer[0] = buffe;
            serialPort1.Write(wbuffer, 0, wbuffer.Length);
            #endregion  
            serialPort1.Read(buffer, 0, 1);            
            reponse= BitConverter.ToInt16(buffer, 0);
            reponse = (reponse / 255) * 100;
            if (chkConsBoucleOuverte.Checked == true) commande = consigne;
            else RegulationPID();
            prgbrVitesse.Value = (int)reponse;
            if (commande < 0) commande = 0;
            if (commande > 100) commande = 100;
            txtMesEcar.Text = commande.ToString();    
            addDataToGraph(zedGraphControl1, temps, consigne, commande, reponse);            
            serialPort1.DiscardInBuffer();
            serialPort1.DiscardOutBuffer();
            freponseOld = reponse;  //enregistre la dernière mesure de la reponse
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            timer.Enabled = false;
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (chkSimul.Checked == true)
            {
                GrpRs232.Enabled = false;
                chkSimul.Text = "End Simulation";
                timer.Enabled = false;
                serialPort1.Close();
                lbCommunication.BackColor = Color.Red;
                lbCommunication.Text = "Pas de connexion";
                Consignes.Enabled = true;
            }
            if (chkSimul.Checked == false)
            {
                GrpRs232.Enabled = true;
                chkSimul.Text = "Start Simulation";
                Consignes.Enabled = false;
            }
        }

        private void RegulationPID()
        {
            float ftermeP = 0;
            float ftermeI = 0;
            float ftermeD = 0;
            float fEcart = consigne-reponse;
            if (rdbTypeIntegral.Checked == true)
            {
                float fI0 = (fEcart + fecartold) / 2f;
                fIntegral+=fI0;
            }
            else fIntegral=0F;

            if (rdbTypeDeriv.Checked == true)
            {
                fDerive = freponseOld - reponse;
            }
            else fDerive = 0f;
           float kp = 0;
           float Ti = 0;
           float Td = 0;
           float.TryParse(txtParaKp.Text.ToString(), out kp);
           float.TryParse(txtParaTi.Text.ToString(), out Ti);
           float.TryParse(txtParaTd.Text.ToString(), out Td);
           ftermeP = fEcart * kp;
           if (Ti > 0.01f)
           ftermeI = fIntegral / Ti;
           ftermeD = Td * fDerive;

           if (rdbTypeProp.Checked==true)//P
           {
               commande = ftermeP;
           }
           else if (rdbTypeIntegral.Checked == true)//PI
           {
               commande = ftermeP + ftermeI;
           }
           else
           {
               commande = ftermeP+ftermeI+ftermeD;
           }
            fecartold=fEcart;
        }

        private void numConEche_TextChanged(object sender, EventArgs e)
        {
            if (this.Text == "1") this.Text = "2";
        }

        private void lbCommunication_Click(object sender, EventArgs e)
        {

        }
    }
}
Code C for PIC
unsigned int reponse=0;
int commande=0;
char txt[4];
void init(){
adc_init();//initialisation du module ANALOGIQUE
uart1_init(9600);//initialisation du module RS232
pwm1_init(12000);
pwm1_set_duty(0);
pwm1_start();
}
void main() {
     init();
     while(1){
        reponse=adc_read(0);
        reponse/=4;
        uart1_write(reponse);
        delay_ms(10);
        if(uart1_data_ready()){
          commande=uart1_read();
          pwm1_set_duty(commande);
        }
     }
}