Subversion Repositories chibiosIgnition

Rev

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