Subversion Repositories chibiosIgnition

Rev

Rev 17 | Rev 19 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * timer2.c
  3.  *
  4.  *  Created on: 2 Apr 2018
  5.  *      Author: Mike
  6.  */
  7.  
  8. #include "ch.h"  // needs for all ChibiOS programs
  9. #include "hal.h" // hardware abstraction layer header
  10.  
  11. #include "timer2.h"
  12. #define  MICROSECS_PULSE 10
  13.  
  14.  
  15. // with a dwell angle of 45 degrees , 4 cylinders and a maximum RPM of 5000
  16. // freq = 5000/60 * 2 = 166Hz. Because the breaker might bounce , we accept the
  17. // first pulse longer than 1/300 of a second as being a proper closure .
  18. // the TIM2 counter counts in 10uS increments,
  19. #define BREAKER_COUNT_MIN (1E6/(MICROSECS_PULSE * 300))
  20.  
  21. #define COUNT_FROM_RPM(RPM) ((1E6/(MICROSECS_PULSE * 30 / (RPM ) )))
  22.  
  23.  
  24. uint16_t nominal = 0;
  25. uint16_t halfRot;
  26. uint16_t phase10 = 100; // 10 degrees
  27. volatile uint16_t sampleRefCount = 0;
  28. volatile uint16_t  sampleVar;
  29. volatile uint16_t sampleRef;
  30.  
  31.  
  32. int gainControl = 1000 ;
  33.  
  34. volatile uint8_t haveSlowPulse = 0;
  35.  
  36. uint16_t rpm;
  37. signed count;
  38. signed delta;
  39.  
  40. void initTimer2()
  41. {
  42.         rccEnableTIM2(FALSE);
  43.         rccResetTIM2();
  44.  
  45.         TIM2->PSC = 72*MICROSECS_PULSE;
  46.         TIM2->ARR = 60000;
  47.         TIM2->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN |
  48.                         TIM_CR1_ARPE );
  49.  
  50.         /// pulse width 200 uS
  51.         TIM2->CCR1 = 200/MICROSECS_PULSE;
  52.  
  53.     TIM2->CCER =  TIM_CCER_CC1E | TIM_CCER_CC1P  ; //enabled and active high
  54.  
  55.     TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
  56.                            TIM_CCMR1_OC1PE ;
  57.  
  58.  
  59.     TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update
  60.  
  61.  
  62.     // change the TIM2 CC2 to TIM3 CC1
  63.         rccEnableTIM3(FALSE);
  64.         rccResetTIM3();
  65.         // TIM3 on the PA6 ... pins : remap code 00
  66.         AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP;
  67.  
  68.         TIM3->PSC = 72*MICROSECS_PULSE;
  69.         TIM3->ARR = 0xFFFF;
  70.  
  71.  
  72.         TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ;  // filter 16, input
  73.  
  74.  
  75.     // link TIM3 ITR2 to TIM2 reload
  76.     // use TS = 001 to make TRC from Tim2 TRIGGER
  77.         TIM3->SMCR  &= ~(TIM_SMCR_TS_Msk );
  78.         TIM3->SMCR  |=  TIM_SMCR_TS_0; // select ITR2 as trigger source TRC
  79.  
  80.     TIM3->CCMR1 |=  TIM_CCMR1_CC2S_1 |  TIM_CCMR1_CC2S_0 ; //  The CC2S bits are 11, use TRC
  81.  
  82.         TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
  83.  
  84.         TIM3->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN | TIM_CR1_ARPE );
  85.  
  86.  
  87.     nvicEnableVector(TIM3_IRQn,
  88.                           4);
  89.  
  90.  
  91.  
  92.     TIM3->DIER |= TIM_DIER_CC1IE  | TIM_DIER_CC2IE;
  93. }
  94.  
  95.  
  96. void recalcPhase(void)
  97. {
  98.         nominal = halfRot * (long) (phase10)/ 1800;
  99. }
  100.  
  101. void adjustRPM(void)
  102. {
  103.         if(rpm < 600)
  104.                 rpm = 600;
  105.         if(rpm >  5000)
  106.                 rpm = 5000;
  107.  
  108. }
  109.  
  110. uint16_t setRPM(uint16_t rpm_ )
  111. {
  112.         if(rpm_ >= 600 && rpm_ < 6000)
  113.         {
  114.           rpm = rpm_;
  115.           adjustRPM();
  116.         }
  117.           return halfRot;
  118. }
  119.  
  120. uint16_t getRPM(void)
  121. {
  122.         return rpm;
  123. }
  124.  
  125. signed getDelta(void)
  126. {
  127.         return delta;
  128. }
  129.  
  130. signed getCount(void)
  131. {
  132.         return  count;
  133. }
  134.  
  135. void setGain(int gain)
  136. {
  137.         gainControl = gain;
  138. }
  139.  
  140.  
  141. uint8_t slowPulse(void)
  142. {
  143.         return haveSlowPulse;
  144. }
  145.  
  146.  
  147. void processPhase (int refCount,int varCount, int diff)
  148. {
  149.  
  150.     // scale it up by 32
  151.         // at this point we should try to phase lock
  152.  
  153.  
  154.         signed pd = 0;
  155.         bool lock = false;
  156. // basically locked
  157.         if(refCount==1 && varCount==1 )
  158.         {
  159.                 lock = true;
  160.        pd = (diff <  32768 ? diff : diff - 65536L) ;
  161.         }
  162.         // frequency detector
  163.         else if (refCount > 1)
  164.         {
  165.                 pd = (refCount*32768L);
  166.         }
  167.         else if (varCount > 1)
  168.         {
  169.                 pd = (-varCount * 32768L);
  170.         }
  171.     float delta_phi = pd/ (gainControl * 1.0);
  172.  
  173.  
  174.     delta = pd;
  175.  
  176.  
  177.  
  178.     // phase detector returns +/
  179.  
  180.  
  181.  
  182.     float const wn = 0.01;
  183.     float const zeta = 0.707f; // was 0.707
  184.     float const K = 1000;
  185.  
  186.     float const t1 = K/(wn*wn);
  187.     float const t2 = 2 * zeta/wn;
  188.     float const  b0 = (4*K/t1)*(1.+t2/2.0f);
  189.     float const b1 = (8*K / t1);
  190.     float const b2 = (4*K/t1)*(1.-t2/2.0f);
  191.  
  192.     float const a1 = -2.0f;
  193.     float const a2 = 1.0f;
  194.     static float v0=0, v1 = 0, v2 = 0 ;
  195.  
  196.  
  197.     static float phi_hat = 100.0f;
  198.  
  199.  
  200.     v2=v1; v1=v0;
  201.     v0 = delta_phi -v1 *a1 -v2 *a2;
  202.  
  203.  
  204.     phi_hat = v0 * b0 + v1 * b1 + v2 * b2 ;
  205.  
  206.  
  207.  
  208.     // 6.283 = 1.0 Hz
  209.  
  210.     // 62.2 = 10Hz
  211.     // decide on whether to go for forcing loop or to track
  212.  
  213.     int32_t arr;
  214.  
  215.    //   if(lock)
  216.  
  217.  
  218.        arr = (6283000L/MICROSECS_PULSE)/ (phi_hat+60);
  219.  
  220.     if(arr > 20000)
  221.         arr = 20000;
  222.     if(arr < 100)
  223.         arr = 100;
  224.  
  225.  
  226.  
  227.      count = arr;
  228.  
  229.     TIM2->ARR = arr ;
  230.     recalcPhase();
  231.  
  232.  
  233.  
  234.     float nomRPM = 30E6 / (MICROSECS_PULSE * arr);
  235.  
  236.         rpm =  nomRPM ;
  237.  
  238.  
  239.         adjustRPM();
  240.     }
  241.  
  242.  
  243.  
  244.  
  245. // set the timing advance from reference to
  246. void setAdvance(int16_t deg10)
  247. {
  248.     phase10 = deg10;
  249.     recalcPhase();
  250.  
  251. }
  252.  
  253. // timer 3 interrupt
  254. void VectorB4(void)
  255. {
  256.     static uint16_t lastSampleRef = 0;
  257.     static uint8_t refCount = 0;
  258.         static uint8_t varCount = 0;
  259.         uint16_t samplePeriod;
  260.  
  261.         uint16_t stat = TIM3->SR;
  262.         if(stat & TIM_SR_CC1IF)
  263.         {
  264.                 TIM3->SR &= ~TIM_SR_CC1IF;
  265.                 uint16_t sample = TIM3->CCR1;
  266.                 if(sample-lastSampleRef >  100 /*BREAKER_COUNT_MIN */)
  267.                 {
  268.                         sampleRef = sample;
  269.  
  270.                         ++refCount;
  271.                 }
  272.         samplePeriod = sample-lastSampleRef;
  273.  
  274.         chDbgCheck(samplePeriod != 65535);
  275.         lastSampleRef = sample;
  276.         }
  277.         if(stat & TIM_SR_CC2IF)
  278.         {
  279.                 TIM3->SR &= ~TIM_SR_CC2IF;
  280.                  sampleVar  = TIM3->CCR2;
  281.                  ++varCount;
  282.         }
  283.  
  284.  
  285.  
  286.  
  287.     if(refCount != 0 && varCount != 0  ) /*we have an R,V pair  */
  288.     {
  289.  
  290. //
  291.     processPhase (refCount,varCount,sampleRef-sampleVar);
  292.     haveSlowPulse = (varCount > 20);
  293.    refCount = 0;
  294.    varCount = 0;
  295.    }
  296.  
  297.  
  298.  
  299. }
  300.  
  301.  
  302.  
  303.