Outils pour utilisateurs

Outils du site


votre temps local: :: ()

heure officielle (en France) : ::(TZ:)

Heure UTC client: :: Offset client: s - delai: ms - - timeZone: Heure UTC: ::
fr:asservissement_numerique_de_temperature_pour_cavite_laser_ultra-stable

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
fr:asservissement_numerique_de_temperature_pour_cavite_laser_ultra-stable [2018/03/23 11:10]
fwiotte créée
fr:asservissement_numerique_de_temperature_pour_cavite_laser_ultra-stable [2018/04/06 11:01] (Version actuelle)
fwiotte
Ligne 1: Ligne 1:
-**Asservissement en température d'une cavité ultra-sable au LPL pour le Strontium** +**Asservissement en température ​numérique ​d'une cavité ultra-stable ​au LPL pour le Strontium** 
-//condition de stabilité//​+ 
 +**//condition de stabilité// ​+/- 10mK** 
 + 
 +**Résultas obtenus : 1mk sur la journée** 
 + 
 +Compte tenu des constantes de temps d'​intégration nous avons opté pour un lock 
 +numérique avec un uC 16 bits. ADC et DAC 12 bits  
 +  
 +**MSP430F169 16bits Texas instruments,​ and IAR Workbench for MSP430 or Code composer studio** 
 + 
 +Cahier des charges: 
 +La précision du lock en température devrait être de l'​ordre de 10 mK, pour assurer une stabilité en fréquence du laser de l'​ordre de quelques kHz.  
 +L'​élément chauffant a une résistance de 6 Ohm. Un courant de l'​ordre de 0.6 A devrait fournir la puissance pour nous amener au point de fonctionnement vers 27°C. 
 +Élément de mesure : thermistor MC65F103B 
 + 
 +Ci-joint le code C du projet:  
 +gestion affiche LCD + calcul température + fonction standby + contrôle de la consigne de température + lock  
 ++ timer + déclaration des variables + déclaration prototypes + fichier init système (ADC-DAC TIMER-PORT IN OUT) 
 + 
 +Manuel descriptif de la cavité: 
 +{{ vh6010-4_inst_manual.pdf}} 
 + 
 + 
 +{{:​fr:​pcb_asservissement.png?​600 |}} 
 +{{:​fr:​asservissement_de_temperature.png?​800|}} 
 + 
 + 
 + 
 +** Function prototypes** 
 +   void init_sys(void); ​               // MSP430 Initialisation routine  
 +   void tempo_loop(long loop_number); ​         // wait 
 +   void write_DAC12_0(int out_data); // write DAC12_0 routine 
 +   void write_DAC12_1(unsigned short out_data); // write DAC12_1 routine 
 +   int read_ADC12(int chanel); ​      // read routine on ADC12 
 +   char lock(); 
 +   void standby(); ​                // init state of state machine 
 +   ​unsigned short racine(unsigned long valIn); 
 +   int Lcd_Cmd(int portP4); 
 +   int lcd_display(char *disp); 
 +   int lcd_display2(char *disp2); 
 +   int lcd_print(char *s); 
 +   int Lcd_Clear();​ 
 +   void Lcd_Init(void);​ 
 +   int load_LCD_consigne(void);​ 
 +   int calcul_Resistor_thermistance(void);​ 
 +   void visu_etat_lock(void);​ 
 + 
 +** déclaration des variables** 
 +    
 +   int consigne=2048;​ 
 +   ​static unsigned int DAC0_out; 
 +   ​static unsigned int DAC1_out; 
 +   ​static int ADC_in; 
 +   ​static int ADC_in_2; 
 +   ​static float ADC_in_2_convert_in_volt;​ 
 +   ​static long error_signal;​ 
 +   ​static long accu_out; 
 +   ​static long prop; 
 +   ​static unsigned long valIn; 
 +   ​static unsigned short valOut; 
 +   ​static long control; 
 +   ​static char next_state = 0; 
 +   ​static char state = 0; 
 +   ​static char s[20]; 
 +   ​static char t[20]; 
 +   ​static double RTH; 
 +   ​static double Temperature_in_degre;​ 
 +   ​static double calcul_ln;​ 
 +   char i = 0; 
 +   char j = 0; 
 + 
 +** main** 
 + 
 +   void main(void) 
 +   { 
 +    init_sys(); ​ // Initialise the MSP430 
 +    Lcd_Init();  
 +    tempo_loop(10);​ 
 +    Lcd_Clear();​ 
 +    tempo_loop(10);​ 
 +    Lcd_Cmd(0x80);​ 
 +    lcd_display("​Welcome to"​);​ 
 +    Lcd_Cmd(0xc0);​ 
 +    lcd_display("​CNRS-LPL-IG-UP13"​);​ 
 +    tempo_loop(10);​ 
 +    Lcd_Clear();​ 
 +    tempo_loop(10);​ 
 +    Lcd_Cmd(0x84);​ 
 +    lcd_display("​Atelier"​);​ 
 +    Lcd_Cmd(0xc2);​ 
 +    lcd_display("​Electronique"​);​ 
 +    tempo_loop(10);​ 
 +    Lcd_Clear();​ 
 +    tempo_loop(10);​ 
 +    sprintf(t,"​T in Deg= %.3f",​Temperature_in_degre);​ 
 +    Lcd_Cmd(0x80);​ 
 +    lcd_display(t);​ 
 +    copy_RAM_to_consigne();​ 
 +    Lcd_Cmd(0xc0);​ 
 +    sprintf(s,"​consigne= %d",​consigne);​ 
 +    lcd_display(s);​ 
 +     
 +    standby();​ 
 +     
 +    _BIS_SR(LPM0_bits + GIE);             // Enter LPM0 w/ interrupt 
 +   ​} ​   
 +  
 +    
 +**gestion affichage LCD** 
 +   //​Table 1: Character LCD pins with 1 Controller 
 +   //​**********************************************//​ 
 +   //​1 VSS Power supply (GND) 
 +   //​2 VCC Power supply (+5V) 
 +   //​3 VEE Contrast adjust 
 +   //​4 RS 0 = Instruction input 
 +   //1 = Data input 
 +   //​5 R/​W 0 = Write to LCD module 
 +   //1 = Read from LCD module 
 +   //​6 EN Enable signal 
 +   //​7 D0 Data bus line 0 (LSB) 
 +   //​8 D1 Data bus line 1 
 +   //​9 D2 Data bus line 2 
 +  //​10 D3 Data bus line 3 
 +  //​11 D4 Data bus line 4 
 +  //​12 D5 Data bus line 5 
 +  //​13 D6 Data bus line 6 
 +  //​14 D7 Data bus line 7 (MSB) 
 +   
 +    int Lcd_Port(int portP4) 
 +     { 
 +     P4OUT = portP4; 
 +     ​return 0; 
 +     }  
 +      
 +     // ​ Function for sending command to LCD 
 +     int Lcd_Cmd(int portP4) 
 +     { 
 +     //RS = 0x00;             // => RS = 0 
 +     P1OUT &= ~BIT7; ​   /* Pin P1.6 = 0 */ 
 +     ​Lcd_Port(portP4);​ 
 +     //​E ​ = 0x40;             // Enable = 1 
 +     P1OUT |= BIT6;     /* Pin P1.7 = 1 */ 
 +     ​tempo_loop(1000);​ 
 +     //​E ​ = 0x00;             // Enable = 0 
 +     P1OUT &= ~BIT6; ​   /* Pin P1.7 = 0 */ 
 +     ​return 0; 
 +     } 
 +      
 +     // ​ Function for sending data to LCD 
 +     int Lcd_data(int portP4) 
 +     { 
 +     ​Lcd_Port(portP4);​ 
 +     //​RS ​  = 0x80;  // RS = 1 
 +     P1OUT |= BIT7;     /* Pin P1.6 = 1 */ 
 +     //​E ​  = 0x40;    //Enable = 1 
 +     P1OUT |= BIT6;     /* Pin P1.7 = 1 */ 
 +     ​tempo_loop(1000);​ 
 +     //​E ​  = 0x00;    // Enable = 0 
 +     P1OUT &= ~BIT6; ​   /* Pin P1.7 = 0 */ 
 +     ​return 0; 
 +     } 
 +      
 +     int Lcd_Clear() 
 +     { 
 +     ​Lcd_Cmd(0);​ 
 +     ​Lcd_Cmd(1);​ 
 +     ​return 0; 
 +     } 
 +      
 +     void Lcd_display_off() 
 +     { 
 +     ​Lcd_Cmd(0);​ 
 +     ​Lcd_Cmd(0x0C);​ 
 +     } 
 +      
 +     void Lcd_Shift_Right() 
 +     { 
 +     ​Lcd_Cmd(0x01);​ 
 +     ​Lcd_Cmd(0x18);​ 
 +     } 
 +     void Lcd_Shift_Left() 
 +     { 
 +     ​Lcd_Cmd(0x01);​ 
 +     ​Lcd_Cmd(0x1C);​ 
 +     } 
 +     // ​ Function for initializing LCD 
 +    void Lcd_Init() 
 +    {  
 +     ​Lcd_Cmd(0x38); ​    //​Function set: 2 Line, 8-bit, 5x7 dots 
 +     ​Lcd_Cmd(0x0c);​ 
 +     ​Lcd_Cmd(0x01); ​    //​Clear LCD 
 +     ​Lcd_Cmd(0x06); ​    //​Entry mode, auto increment with no shift 
 +     ​Lcd_Cmd(0x83); ​ // DDRAM addresses 0x80..0x8F + 0xC0..0xCF are used. 
 +    } 
 +    //  Function for sending string to LCD 
 +     int lcd_display(char *disp) 
 +     { 
 +    int x=0; 
 +    while(disp[x]!=0) 
 +    { 
 +        Lcd_data(disp[x]);​ 
 +        x++; 
 +    } 
 +    return 0; 
 +    } 
 +   
 +**Calcul température + affichage**  
 + 
 +    int calcul_Resistor_thermistance(void) 
 +    { 
 +    WDTCTL = WDTPW + WDTHOLD; ​  // stop Watch Dog Timer 
 +    ADC_in_2_convert_in_volt = (ADC_in_2*2.498)/​4096;​ 
 +    RTH = (ADC_in_2_convert_in_volt*9100)/​(2.498 - ADC_in_2_convert_in_volt);​ 
 +    float K = 298.15; ​    // T(25°C) 
 +    calcul_ln = log((RTH/​10000)); ​            //log népérien  
 +    Temperature_in_degre = 1/​(calcul_ln/​3988 + 1/K) - 273.15; ​  //​température en degrès C 
 +    sprintf(t,"​T in Deg= %.3f",​Temperature_in_degre);​ 
 +    Lcd_Cmd(0x80);​ 
 +    lcd_display(t);​ 
 +    return 0; 
 +    } 
 + 
 +**fonction standby**  
 + 
 +    void standby() 
 +    { 
 +    WDTCTL = WDTPW + WDTHOLD; ​           // stop WatchDog ​    
 +    DAC0_out= consigne; ​                 // init DAC0 
 +    DAC1_out= 0;                        // init DAC1 
 +    accu_out= 0; 
 +    P2OUT &= ~BIT1; ​   /* Pin P2.1 = 0 */ 
 +    P2OUT &= ~BIT2; ​   /* Pin P2.2 = 0 */ 
 +    P2OUT &= ~BIT3; ​   /* Pin P2.3 = 0 */ 
 +    P2OUT &= ~BIT4; ​   /* Pin P2.4 = 0 */ 
 +    P2OUT &= ~BIT5; ​   /* Pin P2.5 = 0 */ 
 +    } 
 + 
 +**fonction lock** 
 +     
 +    char lock() 
 +    { 
 +    error_signal = (ADC_in - consigne); // error_signal => int (16 bits) (-32768 to 32767) 
 +    prop = error_signal << 21; 
 +    control = prop + accu_out ; // + (accu_out >> 8);  
 +   
 +    visu_etat_lock();​ 
 +   
 +    if(P1IN & 0x20) 
 +    { 
 +      if (accu_out >= 2147000000 | accu_out <= -2147000000) ​      
 +      { 
 +        accu_out = accu_out; 
 +      } 
 +      else {accu_out = (error_signal << 7) + accu_out;​} 
 +       
 +    }      
 +   
 +    if(control < 0) 
 +    { valIn = 0;} 
 +    else 
 +    {valIn = (control << 1);} 
 +    valOut = racine(valIn);​ 
 +    DAC1_out = valOut >> 4; 
 +    return 0; 
 +    } 
 +    unsigned short racine(unsigned long valIn) //on linéarise la réponse de la thermistance 
 +    { 
 +    unsigned short valOut=0; 
 +    unsigned long diff=0L; 
 +    for(int i=0; i<16; i++) 
 +   { 
 + diff <<= 2; 
 + valOut <<​=1;​ 
 + diff |= valIn >> 30; 
 + valIn <<​=2;​ 
 + if(diff > 2*valOut) 
 +
 + diff -= (2*valOut)+1;​ 
 + valOut++;​ 
 +
 +
 + return valOut; 
 +     } 
 +**fonction TIMER pour échantillonnage**  
 + 
 +     
 +     #​pragma vector = TIMERB0_VECTOR ​   // timer pour échantillonner à 0.1s 
 +     ​__interrupt void Timer_B (void) 
 +    { 
 +    WDTCTL = WDTPW + WDTCNTCL; ​                   // clear and start WatchDog  
 +    write_DAC12_1(DAC1_out); ​                     // write DAC1_out to DAC12_1 
 +    write_DAC12_0(DAC0_out); ​                     // write DAC0_out to DAC12_0 
 +    ADC_in = read_ADC12(INCH_3); ​                 // read signal erreur 
 +    ADC_in_2 = read_ADC12(INCH_4); ​               // read tension thermistor 
 +    calcul_Resistor_thermistance();​ 
 +     
 +    if((P2IN & 0x01)==0x01) ​      //​P2.0 ​ modification de la valeur de consigne + 
 +    { 
 +      if(P3IN & 0x01) 
 +      {consigne = consigne + 10;}  //handle P1.7 switch 
 +      if (P3IN & 0x02) 
 +      {consigne = consigne + 100;}  
 +      if(( P3IN & BIT0 ) == 0 && ( P3IN & BIT1 ) == 0 ) 
 +      {consigne = consigne + 1;} 
 +       
 +    }P1IFG &= ~BIT1;  
 +     
 +     ​if((P1IN & 0x01)==0x01) ​      //​P1.0 modification de la valeur de consigne - 
 +     { 
 +      if(P3IN & 0x01) 
 +      {consigne = consigne - 10;} //handle P1.7 switch 
 +      if (P3IN & 0x02) 
 +      {consigne = consigne - 100;}  
 +      if(( P3IN & BIT0 ) == 0 && ( P3IN & BIT1 ) == 0 ) 
 +      {consigne = consigne - 1;} 
 +           
 +     ​}P1IFG &= ~BIT0; 
 +    
 +     ​chargement_consigne();​ 
 +     ​DAC0_out = consigne; 
 +     ​Lcd_Cmd(0xc0);​ 
 +     ​sprintf(s,"​consigne= %d",​consigne);​ 
 +     ​lcd_display(s); ​    
 +     state = next_state;  
 +       
 +     ​if(P1IN & 0x10)   // P1.4  mode standby ou lock 
 +     { 
 +     ​state=0;​ 
 +     } 
 +     else {state=1;​} 
 +       
 +     ​switch (state) 
 +     { 
 +     case 0:​{standby();​}break;​ 
 +     case 1:​{lock();​}break; ​      
 +     ​} ​   
 +     } 
 +      
 +** fonction init system** 
 +      
 +    void init_sys(void) 
 +    { 
 +    P1SEL = 0x00;                             // P1 I/O select 
 +    P2SEL = 0x00;                             // P2 I/O select 
 +    P3SEL = 0x00;                             // P3 I/O select 
 +    P4SEL = 0x00;                             // P4 I/O select  
 +    P5SEL = 0x1B;                             // P5.1,3 SPI option select CS P5.0 
 +    P6SEL = 0x18;                             // P6.5 ADC_3 options select ​ Enable A/D channel A3 channel A4 
 +    P1DIR = 0xC0;                             // P1 inputs direction P1.6 P1.7 outputs 
 +    P2DIR = 0xFE;                             // P2 input direction P2.0 input 
 +    P3DIR = 0xFC;                             // P3 output direction P3.0 P3.1 inputs 
 +    P4DIR = 0xFF;                             // P4 output direction  
 +    P5DIR = 0xFF;                             // P5 output direction 
 +    P6DIR = 0xF7;                             // P6.3 input/other output 
 +    //ADC12CTL0 = REF2_5V + REFON; ​             // Internal 2.5V ref on 
 +    ADC12CTL0 |= SHT0_4 + ADC12ON; ​           // Set sampling time, turn on ADC12 
 +    ADC12CTL1 |= SHP + ADC12SSEL_3; ​          // Use sampling timer & SMCLK clock 
 +    //​ADC12MCTL0 |= SREF_1; ​                    // Use Internal 2.5V for ADC 
 +    ADC12MCTL0 = SREF_2; ​                     // Vr+ = VeREF+ (external) 
 +    //​DAC12_0CTL = DAC12IR + DAC12AMP_2 + DAC12RES; ​ // 8bits, internal ref gain 1 (DAC_0 select with DAC12AMP_2) 
 +    //​DAC12_1CTL = DAC12IR + DAC12AMP_2 + DAC12RES; ​ // 8bits, internal ref gain 1 (DAC_1 select with DAC12AMP_2)  
 +    DAC12_0CTL = DAC12IR + DAC12SREF_3 + DAC12AMP_7 + DAC12ENC; ​ //Ref = Veref+, Full-Speed, Enable Conv.   
 +    DAC12_1CTL = DAC12IR + DAC12SREF_3 + DAC12AMP_7 + DAC12ENC; ​ //Ref = Veref+, Full-Speed, Enable Conv.      
 +    // DCO frequency ~200 kHz 
 +    DCOCTL &= ~(DCO1 + DCO0);  
 +    BCSCTL1 &= ~RSEL2; 
 +    BCSCTL1 |= RSEL1; // + ~RSEL0; 
 +    // timer B 
 +    TBCCTL0 = CCIE;                           // CCR0 interrupt enabled 
 +    TBCTL = TASSEL_2 + MC_1 + ID_3;           // clk = SMCLK/8 (=DCO/8), Up mode 
 +    //TBCCR0 = 2500;                           // timer count at 1/2500 clk : 0,1s 
 +    TBCCR0 = 250;   
 +    } 
 + 
fr/asservissement_numerique_de_temperature_pour_cavite_laser_ultra-stable.1521799803.txt.gz · Dernière modification: 2018/03/23 11:10 par fwiotte