Subversion Repositories chibiosIgnition

Rev

Rev 14 | Rev 18 | 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.  
  25.  
  26. #define SAMPLE_BUFF_SIZE 16
  27. uint16_t nominal = 0;
  28. uint16_t halfRot;
  29. uint16_t phase10 = 100; // 10 degrees
  30. volatile uint16_t sampleRefCount = 0;
  31. uint16_t outSampleRefCount = 0;
  32. volatile uint16_t  sampleVar;
  33. volatile uint16_t sampleRef;
  34. volatile uint16_t  sampleDiffBuff[SAMPLE_BUFF_SIZE];
  35. volatile uint16_t samplePeriodBuff[SAMPLE_BUFF_SIZE];
  36. volatile uint8_t   refCountBuff[SAMPLE_BUFF_SIZE];
  37. volatile uint8_t  varCountBuff[SAMPLE_BUFF_SIZE];
  38.  
  39.  
  40. int gainControl = 1000 ;
  41.  
  42. volatile uint8_t haveSlowPulse = 0;
  43.  
  44. uint16_t rpm;
  45. signed count;
  46. signed delta;
  47.  
  48. void initTimer2()
  49. {
  50.         rccEnableTIM2(FALSE);
  51.         rccResetTIM2();
  52.  
  53.         TIM2->PSC = 72*MICROSECS_PULSE;
  54.         TIM2->ARR = 60000;
  55.         TIM2->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN |
  56.                         TIM_CR1_ARPE );
  57.  
  58.         /// pulse width 200 uS
  59.         TIM2->CCR1 = 200/MICROSECS_PULSE;
  60.  
  61.     TIM2->CCER =  TIM_CCER_CC1E | TIM_CCER_CC1P  ; //enabled and active high
  62.  
  63.     TIM2->CCMR1 = TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 |
  64.                            TIM_CCMR1_OC1PE ;
  65.  
  66.  
  67.     TIM2->CR2 = TIM_CR2_MMS_1 ; // trigger out is 010 = update
  68.  
  69.  
  70.     // change the TIM2 CC2 to TIM3 CC1
  71.         rccEnableTIM3(FALSE);
  72.         rccResetTIM3();
  73.         // TIM3 on the PA6 ... pins : remap code 00
  74.         AFIO->MAPR &= ~ AFIO_MAPR_TIM3_REMAP;
  75.  
  76.         TIM3->PSC = 72*MICROSECS_PULSE;
  77.         TIM3->ARR = 0xFFFF;
  78.  
  79.  
  80.         TIM3->CCMR1 = TIM_CCMR1_CC1S_0 /* | TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_2 */ ;  // filter 16, input
  81.  
  82.  
  83.     // link TIM3 ITR2 to TIM2 reload
  84.     // use TS = 001 to make TRC from Tim2 TRIGGER
  85.         TIM3->SMCR  &= ~(TIM_SMCR_TS_Msk );
  86.         TIM3->SMCR  |=  TIM_SMCR_TS_0; // select ITR2 as trigger source TRC
  87.  
  88.     TIM3->CCMR1 |=  TIM_CCMR1_CC2S_1 |  TIM_CCMR1_CC2S_0 ; //  The CC2S bits are 11, use TRC
  89.  
  90.         TIM3->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E;
  91.  
  92.         TIM3->CR1 = ~TIM_CR1_CKD  & (TIM_CR1_CEN | TIM_CR1_ARPE );
  93.  
  94.  
  95.     nvicEnableVector(TIM3_IRQn,
  96.                           4);
  97.  
  98.  
  99.  
  100.     TIM3->DIER |= TIM_DIER_CC1IE  | TIM_DIER_CC2IE;
  101. }
  102.  
  103.  
  104. void recalcPhase(void)
  105. {
  106.         nominal = halfRot * (long) (phase10)/ 1800;
  107. }
  108.  
  109. void adjustRPM(void)
  110. {
  111.         if(rpm < 600)
  112.                 rpm = 600;
  113.         if(rpm >  5000)
  114.                 rpm = 5000;
  115.  
  116.  
  117. }
  118.  
  119. uint16_t setRPM(uint16_t rpm_ )
  120. {
  121.         if(rpm_ >= 600 && rpm_ < 6000)
  122.         {
  123.           rpm = rpm_;
  124.           adjustRPM();
  125.         }
  126.           return halfRot;
  127. }
  128.  
  129. uint16_t getRPM(void)
  130. {
  131.         return rpm;
  132. }
  133.  
  134. signed getDelta(void)
  135. {
  136.         return delta;
  137. }
  138.  
  139. signed getCount(void)
  140. {
  141.         return  count;
  142. }
  143.  
  144. void setGain(int gain)
  145. {
  146.         gainControl = gain;
  147. }
  148.  
  149.  
  150. uint8_t slowPulse(void)
  151. {
  152.         return haveSlowPulse;
  153. }
  154.  
  155. // waits for ignition pulse reading in the buffer, returns
  156. // the sample index of the next sample.
  157.  
  158. uint16_t getNextRefPulseIndex(void)
  159. {
  160.         while (outSampleRefCount == sampleRefCount)
  161.                 chThdSleep(10);
  162.  
  163.         uint16_t sampleIndex = outSampleRefCount;
  164.  
  165.     if(++outSampleRefCount == SAMPLE_BUFF_SIZE)
  166.         outSampleRefCount = 0;
  167.     return sampleIndex;
  168. }
  169.  
  170.  
  171. void processNextPulse(uint16_t index)
  172. {
  173.  
  174.     // scale it up by 32
  175.         static int32_t periodEstimate = 2000 * 256 ;
  176.         // at this point we should try to phase lock
  177.  
  178.         uint16_t sampleDiff = sampleDiffBuff[index];
  179.  
  180.         signed pd = 0;
  181.         bool lock = false;
  182. // basically locked
  183.         if(refCountBuff[index]==1 && varCountBuff[index]==1 )
  184.         {
  185.                 lock = true;
  186.        pd = (sampleDiff <  32768 ? sampleDiff : sampleDiff - 65536L) ;
  187.         }
  188.         else if (refCountBuff[index] > 1)
  189.         {
  190.                 pd = (refCountBuff [index]*32768L);
  191.         }
  192.         else if (varCountBuff[index] > 1)
  193.         {
  194.                 pd = (-varCountBuff[index] * 32768L);
  195.         }
  196.     float delta_phi = pd/ (gainControl * 1.0);
  197.  
  198.  
  199.     delta = delta_phi;
  200.  
  201.  
  202.  
  203.     // phase detector returns +/
  204.  
  205.  
  206.  
  207.     float const wn = 0.03f;
  208.     float const zeta = 0.707f;
  209.     float const K = 1;
  210.  
  211.     float const t1 = K/(wn*wn);
  212.     float const t2 = 2 * zeta/wn;
  213.     float const  b0 = (4*K/t1)*(1.+t2/2.0f);
  214.     float const b1 = (8*K / t1);
  215.     float const b2 = (4*K/t1)*(1.-t2/2.0f);
  216.  
  217.     float const a1 = -2.0f;
  218.     float const a2 = 1.0f;
  219.     static float v0=0, v1 = 0, v2 = 0 ;
  220.  
  221.  
  222.     static float phi_hat = 0.0f;
  223.  
  224.  
  225.     v2=v1; v1=v0;
  226.     v0 = delta_phi -v1 *a1 -v2 *a2;
  227.  
  228.  
  229.     phi_hat = v0 * b0 + v1 * b1 + v2 * b2 ;
  230.  
  231.     // 6.283 = 1.0 Hz
  232.  
  233.     // 62.2 = 10Hz
  234.     // decide on whether to go for forcing loop or to track
  235.  
  236.     int32_t arr;
  237.  
  238.    //   if(lock)
  239.  
  240.  
  241.        arr = (6283000L/MICROSECS_PULSE)/ phi_hat;
  242.  
  243.     if(arr > 5000)
  244.         arr = 5000;
  245.     if(arr < 500)
  246.         arr = 500;
  247.  
  248.     // compute period error]
  249.       // periodErr +=   periodEstimate - (arr * 256);
  250.  
  251.  
  252.      count = arr;
  253.  
  254.     TIM2->ARR = arr ;
  255.     recalcPhase();
  256.  
  257.  
  258.  
  259. // calculate RPM
  260.     float nomRPM = 30E6 / (MICROSECS_PULSE * (periodEstimate/256));
  261.  
  262.         rpm =  nomRPM ;
  263.  
  264.  
  265.  
  266. //      rpm += delta / 256;
  267.  
  268.         adjustRPM();
  269.     }
  270.  
  271.  
  272.  
  273.  
  274. // set the timing advance from reference to
  275. void setAdvance(int16_t deg10)
  276. {
  277.     phase10 = deg10;
  278.     recalcPhase();
  279.  
  280. }
  281.  
  282. // timer 3 interrupt
  283. void VectorB4(void)
  284. {
  285.     static uint16_t lastSampleRef = 0;
  286.     static uint8_t refCount = 0;
  287.         static uint8_t varCount = 0;
  288.         uint16_t samplePeriod;
  289.  
  290.         uint16_t stat = TIM3->SR;
  291.         if(stat & TIM_SR_CC1IF)
  292.         {
  293.                 TIM3->SR &= ~TIM_SR_CC1IF;
  294.                 uint16_t sample = TIM3->CCR1;
  295.                 if(sample-lastSampleRef >  100 /*BREAKER_COUNT_MIN */)
  296.                 {
  297.                         sampleRef = sample;
  298.  
  299.                         ++refCount;
  300.                 }
  301.         samplePeriod = sample-lastSampleRef;
  302.  
  303.         chDbgCheck(samplePeriod != 65535);
  304.         lastSampleRef = sample;
  305.         }
  306.         if(stat & TIM_SR_CC2IF)
  307.         {
  308.                 TIM3->SR &= ~TIM_SR_CC2IF;
  309.                  sampleVar  = TIM3->CCR2;
  310.                  ++varCount;
  311.         }
  312.  
  313.  
  314.  
  315.  
  316.     if(refCount != 0 && varCount != 0  ) /*we have an R,V pair  */
  317.     {
  318.  
  319. //
  320.  
  321.     refCountBuff[sampleRefCount] = refCount;
  322.     varCountBuff[sampleRefCount] = varCount;
  323.  
  324.     haveSlowPulse = (varCount > 20);
  325.  
  326.      sampleDiffBuff[sampleRefCount] = sampleRef - sampleVar;
  327.  
  328.      samplePeriodBuff[sampleRefCount] = samplePeriod;
  329.  
  330.  
  331.  
  332.             if(++sampleRefCount == SAMPLE_BUFF_SIZE)
  333.                   sampleRefCount = 0;
  334.  
  335.    refCount = 0;
  336.    varCount = 0;
  337.    }
  338.  
  339.  
  340.  
  341. }
  342.  
  343.  
  344.  
  345.