Go Down

Topic: PWM trigger ADC interrupts (Read 1 time) previous topic - next topic

vorkiej

For my project, I'm emulating a quadrature encoder signal (A+B+index and 3 inverse). I use pwm signals for this with 50% dutycycle and a varying frequency dependent on the voltage read by pin A9 (analog channel 11). The phase shifts of the B signal I made with the deadtime generator. The Index signal is not yet implemented.
During the PWM period I want to trigger the ADC to read the voltage. This works, but when the voltage gets zero, the PWM doesnt trigger an event line and doesn't read anymore. Is there a way to manually trigger the ADC? Or other solutions to this problem? Thanks!

Code: [Select]
void pwmWrite(uint32_t ulFreq) {

  static uint8_t PWMEnabled = 0;
  static uint8_t ADCEnabled = 0;
  static uint8_t pin6Enabled = 0;
  static uint8_t pin7Enabled = 0;
  static uint8_t pin8Enabled = 0;
  static uint8_t pin9Enabled = 0;

  int duty_100 = 255;
  int duty_75 = (((duty_100+1)/4)*3)-1;
  int duty_50 = ((duty_100+1)/2)-1;
  int duty_25 = ((duty_100+1)/4)-1;
 
  if (!ADCEnabled) {
    pmc_enable_periph_clk(ID_ADC);
    adc_init(ADC, VARIANT_MCK, ADC_FREQ_MAX, 0);
    adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_0, 0);
    adc_stop_sequencer(ADC);
    adc_enable_channel(ADC, (adc_channel_num_t)11);
    adc_enable_interrupt(ADC, ADC_IER_DRDY);
    NVIC_EnableIRQ(ADC_IRQn);
    ADCEnabled = 1;
  }   
 
  if (!PWMEnabled) {
    pmc_enable_periph_clk(ID_PWM);
    PWMC_ConfigureClocks(0, 0, VARIANT_MCK );
    PWMEnabled = 1;
  }
   
  // SETUP PINS 6 T/M 9
  uint32_t chan6 = g_APinDescription[6].ulPWMChannel;
  uint32_t chan7 = g_APinDescription[7].ulPWMChannel;
  uint32_t chan8 = g_APinDescription[8].ulPWMChannel;
  uint32_t chan9 = g_APinDescription[9].ulPWMChannel;
 
  if (!pin6Enabled || !pin7Enabled || !pin8Enabled || !pin9Enabled) {
    PIO_Configure(g_APinDescription[6].pPort, g_APinDescription[6].ulPinType, g_APinDescription[6].ulPin, g_APinDescription[6].ulPinConfiguration);
    PIO_Configure(g_APinDescription[7].pPort, g_APinDescription[7].ulPinType, g_APinDescription[7].ulPin, g_APinDescription[7].ulPinConfiguration);
    PIO_Configure(g_APinDescription[8].pPort, g_APinDescription[8].ulPinType, g_APinDescription[8].ulPin, g_APinDescription[8].ulPinConfiguration); 
    PIO_Configure(g_APinDescription[9].pPort, g_APinDescription[9].ulPinType, g_APinDescription[9].ulPin, g_APinDescription[9].ulPinConfiguration);
             
    // CONFIGURE CHANNELS
    PWMC_ConfigureChannel(PWM, chan6, PWM_CMR_CPRE_CLKA, 0, 0);
    PWMC_ConfigureChannel(PWM, chan7, PWM_CMR_CPRE_CLKA, 0, PWM_CMR_CPOL);
    PWMC_ConfigureChannel(PWM, chan8, PWM_CMR_CPRE_CLKA, 0, 0);           
    PWMC_ConfigureChannel(PWM, chan9, PWM_CMR_CPRE_CLKA, 0, PWM_CMR_CPOL);
       
    // SET PERIODS
    PWMC_SetPeriod(PWM, chan6, duty_100);
    PWMC_SetPeriod(PWM, chan7, duty_100);
    PWMC_SetPeriod(PWM, chan8, duty_100);
    PWMC_SetPeriod(PWM, chan9, duty_100);  // PWM_MAX_DUTY_CYCLE (100%)
       
    // SET DUTY CYCLES   
    PWMC_SetDutyCycle(PWM, chan6, duty_50);   
    PWMC_SetDutyCycle(PWM, chan7, duty_50); 
    PWMC_SetDutyCycle(PWM, chan8, duty_75);   
    PWMC_SetDutyCycle(PWM, chan9, duty_75); 
       
    //SET DEAD TIME
    PWM->PWM_CH_NUM[chan8].PWM_CMR |= PWM_CMR_DTE;  // added, enable channel dead time DTE=1
    PWM->PWM_CH_NUM[chan9].PWM_CMR |= PWM_CMR_DTE;
    PWMC_SetDeadTime(PWM, chan8, 0, duty_25);
    PWMC_SetDeadTime(PWM, chan9, 0, duty_25);
       
    //SYNC CHANNELS
    PWMC_ConfigureSyncChannel(PWM, ( PWM_SCM_SYNC4 |  PWM_SCM_SYNC5 | PWM_SCM_SYNC6 | PWM_SCM_SYNC7), PWM_SCM_UPDM_MODE2, 0, 0); 
    PWMC_SetSyncChannelUpdateUnlock(PWM);              // PWM_SCUC set UPDULOCK to 1, update next period
    PWMC_SetSyncChannelUpdatePeriod(PWM, duty_100);    //  update period of the synchronous channels PWM_SCUP
       
    // EVENT LINES FOR ADC
    PWMC_ConfigureEventLineMode( PWM, 0, 1 ) ;
    PWMC_ConfigureComparisonUnit(PWM, 0, (duty_100/2), 1);
         
    // SET CHANNEL 0 FOR SYNC
    PWMC_ConfigureChannel(PWM, 0, PWM_CMR_CPRE_CLKA, 0, 0);
    PWMC_SetPeriod(PWM, 0, duty_100);
    PWMC_SetDutyCycle(PWM, 0, duty_50);
    PWMC_EnableChannel(PWM, 0);
   
    // CONFIGURE TRIGGER ON EVENT LINE
    adc_configure_trigger(ADC, ADC_TRIG_PWM_EVENT_LINE_0, 0);
       
    pin6Enabled = 1;
    pin7Enabled = 1;
    pin8Enabled = 1;
    pin9Enabled = 1;
  }
   
  if (lastState == 0 && CW == 1) {
    PWM->PWM_CH_NUM[chan8].PWM_CMR |= PWM_CMR_CPOL;  // set CPOL 0
    PWM->PWM_CH_NUM[chan9].PWM_CMR &= 0xFFFFFDFF;
    lastState = 1;
  }
 
  if (lastState == 1 && CW == 0) {
    PWM->PWM_CH_NUM[chan8].PWM_CMR &= 0xFFFFFDFF;  // set CPOL 0
    PWM->PWM_CH_NUM[chan9].PWM_CMR |= PWM_CMR_CPOL;
    lastState = 0;
  }
   
  PWMC_ConfigureClocks(ulFreq * duty_100, 0, VARIANT_MCK );
   
  return;
}


Code: [Select]
// ADC Interrupt handler.
void ADC_Handler(){
  uint32_t ul_Value;
  if ((adc_get_status(ADC) & ADC_ISR_DRDY) == ADC_ISR_DRDY)  {
    ul_Value = adc_get_latest_value(ADC);
    //Serial.println(ul_Value);
  }
  PWMC_ConfigureClocks(ul_Value*255, 0, VARIANT_MCK );

}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy