This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Using additional analog sensors in an insta-spin system

Hey all,

I'm experiencing a somewhat unexplicable issue when adding additional ADC SOC signals. I've tried modifying the DRV_setupAdcs() function with the following changes;

(removed) ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_1,ADC_IntSrc_EOC7);

(added) ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_1,ADC_IntSrc_EOC10);

And also added;

  // High-side MOSFET temp sensor
  ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_8,ADC_SocChanNumber_B5);
  ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_8,ADC_SocTrigSrc_EPWM1_ADCSOCA);
  ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_8,ADC_SocSampleDelay_9_cycles);

  // Low-side MOSFET temp sensor
  ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_9,ADC_SocChanNumber_B6);
  ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_9,ADC_SocTrigSrc_EPWM1_ADCSOCA);
  ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_9,ADC_SocSampleDelay_9_cycles);

  // Internal core temp sensor
  ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_10,ADC_SocChanNumber_A5);
  ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_10,ADC_SocTrigSrc_EPWM1_ADCSOCA);
  ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_10,ADC_SocSampleDelay_9_cycles);

After the section started with

  // TODO: AAA When switching to HW-REV 0.2, update ADC mux!
  // sample the first sample twice due to errata sprz342f
  ADC_setSocChanNumber(...);

As far as I've understood, this should be fine, however, running this results in two calls to mainISR and the ADCINTOVF flag for ADC Int 1 being set. The total period for these calls is correct FWIW.

Though I'm not sure if it's relevant, I did notice that ADCINTSOCSEL1 is configured to trigger SOC0-SOC7 on ADCINT2 and ADCINTSOCSEL2 is configured to trigger SOC8-SOC15 on ADCINT1. Is this just a remnant from DRV_AdcCalConversion? Based on the initialization in DRV_setupAdc's it seems like ADCINT2 isn't used other than during the startup calibration, but if I disable ADC Int #2 in DRV_enableAdcInts mainISR isn't called at all...

What I would like to do in the end is just trigger SOC 8-m periodically. I don't have any real timing requirements in this case, so I'm more than open to any suggestions.

  • Try changing

    ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_2,ADC_IntSrc_EOC10);

    and in

    void DRV_enableAdcInts(DRV_Handle handle)
    {
      DRV_Obj *obj = (DRV_Obj *)handle;


      // enable the PIE interrupts associated with the ADC interrupts
      PIE_enableAdcInt(obj->pieHandle,ADC_IntNumber_2);


      // enable the ADC interrupts
      ADC_enableInt(obj->adcHandle,ADC_IntNumber_2);


      // enable the cpu interrupt for ADC interrupts
      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_10);

      return;
    } // end of DRV_enableAdcInts() function

     

  • Hi Chris,

    Thanks for the suggestions, but I think something is still missing. With just the suggestions made above mainISR triggers far too fast, which I'm guessing is because of the following changes that I made which I thought would be sufficient;

    in drv_setupADCs;

      ADC_disableInt(obj->adcHandle,ADC_IntNumber_2);
      ADC_setIntMode(obj->adcHandle,ADC_IntNumber_2,ADC_IntMode_ClearFlag);

    in drv_initintvectortable;

    pie->ADCINT2 = &mainISR;

    and, finally, in mainISR;

    DRV_acqAdcInt(drvHandle,ADC_IntNumber_2);

    With these changes mainISR triggers at the correct frequency, but motor operation is severely worsened and has an audible modulation at around 40-60 Hz. Could this be due to missed/delayed/incorrect SOC triggering?

    For my application I don't strictly need to generate an ADC interrupt on SOC 10 complete --- an ADC interrupt on SOC 7 complete (with SOC 8 - SOC 10 still pending) would be fine as long as there is some way to reliably read result registers 8 through 10...

  • Hi Jonathan,

    Certainly you can trigger the interrupt in the middle of the string of conversions. The flow may look something like this:

    *ePWM triggers SOC0 through SOC10 .  SOC7 triggers ISR (interrupt flag 1), SOC10 sets a different interrupt flag (interrupt flag 2), but does not trigger ISR.

    *SOC7 causes ISR

    *ISR reads SOC0 through SOC7 and passes to InstaSPIN

    *ISR checks if interrupt flag 2 is set and waits if necessary (the other conversions may or may not have completed depending on how long the above step takes)

    *ISR reads SOC8 through SOC10 and takes appropriate action based on the results

    I think this should give timings most similar to the case where SOC8 through SOC10 have not been added (base InstaSPIN).

    Also, from your original post, I think it is quite possible that the self-triggering setup is left over from AdcCalConversion and that you will want to disable this to get correct operation when adding additional SOCs.  

  • Hi Devin,

    Ok, that sounds pretty reasonable. In my application I don't really need to guarantee that I read the k'th ADC sample in the k'th ISR call, it would be fine to read k-1 as well (I'm only checking some *very* slowly-changing temperature probes). OTOH potentially reading an old ADC sample is a pretty ugly solution, so it would definitely be far less of a kludge to wait for the conversion to be completed.

    I'm not really sure of the ADC configuration used/needed by instaspin, could you verify that it would be reasonable for me to;

    - set up ADC interrupt 2 to trigger on SOC10 (but not enable ADCINT2 in the PIE)

    - poll the relevant status bit in mainISR and wait until the conversion is reported as complete

    - clear said bit when the conversion is reported as completed.

    This would necessitate some changes in the way the SOC's are triggered, without putting to much thought into it at the moment I would think something along the lines of completely disabling SOC triggers in ADCINTSOCSEL1/2. Is ADCINT2 really used for anything once the ADC initialization/calibration is completed? Does instaspin really do/need anything more than a bog-standard linear SOC chain triggered by EPWM1SOCA?

  • Yeah, that is exactly what I was thinking.

    Yes, InstaSPIN only needs ePWM triggered conversions.  You can and should set all the ADCINTSOCSEL fields to 0.   

  • Thanks for the help Devin, everything seems to be working well. My changes were in the end exactly what you suggested (and posted here for posterity). In DRV_setupAdcs;

    // configure the interrupt sources
      ADC_disableInt(obj->adcHandle,ADC_IntNumber_1);
      ADC_setIntMode(obj->adcHandle,ADC_IntNumber_1,ADC_IntMode_ClearFlag);
      ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_1,ADC_IntSrc_EOC7);

      //ADCINT2 is not used to trigger interrupt, it is only used in the ISR
      //triggered by ADCINT1 to check when the conversion is complete
      ADC_disableInt(obj->adcHandle,ADC_IntNumber_2);
      ADC_setIntMode(obj->adcHandle,ADC_IntNumber_2,ADC_IntMode_ClearFlag);
      ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_2,ADC_IntSrc_EOC10);

      //Clear out any residual ADCINT triggered SOC
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_0, ADC_NoIntTriggersSOC);
      --- similarly for all other SOC's ---
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_15, ADC_NoIntTriggersSOC);

    in mainISR;

        // convert the insta-spin ADC data
        DRV_readAdcData(drvHandle,&gAdcData);

        // Wait for the low-priority conversions to complete and clear when complete
        while(!AdcRegs.ADCINTFLG.bit.ADCINT2){};
        AdcRegs.ADCINTFLGCLR.bit.ADCINT2 = 1;
        do_stuff_with_adcresreg_8_through_10();

    and, finally, in DRV_enableAdcInts;

      // enable the PIE interrupts associated with the ADC interrupts
      // note that ADCINT2 is *not* passed through to the PIE as we only want to poll its status
      PIE_enableAdcInt(obj->pieHandle,ADC_IntNumber_1);


      // enable the relevant ADC interrupts
      ADC_enableInt(obj->adcHandle,ADC_IntNumber_1);
      ADC_enableInt(obj->adcHandle,ADC_IntNumber_2);

      // enable the cpu interrupt for ADC interrupts
      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_10);