Outils pour utilisateurs

Outils du site

Traductions de cette page:

votre temps local: :: ()

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

Heure UTC client: :: Offset client: s - delai: ms - - timeZone: Heure UTC: ::

Panneau latéral

  • Corrélateurs
  • Bruits inhérent au numérique : bruit de phase, gigue, stabilité temporelle des circuits numériques
  • Compteur à intervalle de temps
  • Détection synchrone
  • Choix ADC/DAC pour applications TF
  • Mesure Sphi(f) et sigma_y(tau)
  • Servo controls (Liens fibrés, …)
  • Manipulation d'objets et fréquences (atomes froids, spectral hole burning, ions ….)
  • Datations « officielles »
  • Compteurs, avec et sans temps morts.
  • Logiciel / Pilotes
  • IP cores (FPGA)
  • Chipscope
fr:asservissement_numerique_de_temperature_pour_cavite_laser_ultra-stable

Ceci est une ancienne révision du document !


+Asservissement en température d'une cavité ultra-stable au LPL pour le Strontium

condition de stabilité +/- 10mK

Compte tenu des constantes de temps d'intégration nous avons opté pour un lock numérique avec un uC 16 bits.

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

Manuel descriptif de la cavité: vh6010-4_inst_manual.pdf

Schéma de principe:

Ci-joint le code C: 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)

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.1521819153.txt.gz · Dernière modification: 2018/03/23 16:32 par fwiotte