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.

How to use all 16 ADC channels while dealing with Initial Conversion bug?

Other Parts Discussed in Thread: LAUNCHXL-F28069M, DRV8305, MOTORWARE

Hello,

I have a dual motor project (based on lab 12c) running on a LAUNCHXL-F28069M with two DRV8305 boards.
Now I and want to connect two potentiometers and read their values (e.g. to set SpeedRef).

I already found the HAL tutorial shipped with MotorWare and, based on it, got one potentiometer working (connected to ADCINA6). I added the following code to HAL_setupAdcs() in hal_2mtr.c:

// Potentiometer
ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_15,ADC_SocChanNumber_A6);
ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_15, ADC_Int1TriggersSOC);
ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_15,ADC_SocSampleDelay_9_cycles);

And the following to hal_2mtr.h:

static inline _iq HAL_readPotentiometerData(HAL_Handle handle)
{
    HAL_Obj *obj = (HAL_Obj *)handle;
    _iq value;
    // convert potentiometer from IQ12 to IQ24.
    value = _IQ12toIQ((_iq)ADC_readResult(obj->adcHandle, ADC_ResultNumber_15));
    return(value);
}

Now I want to add the second potentiometer which is connected to ADCINB6. First I thought, that I could simply duplicate the code and change the numbers but then I realized, that there are no Soc/Result numbers left. They are all in use because due to the "Initial Conversion Bug", ADCINA0 is read two times, using ADC_SocNumber_0 and _1.

Is there another possible workaround to avoid the bad initial conversion which allows me to use all 16 ADCs? Or maybe another way of reading the potentiometer results (these values are not timing critical, so in case this makes things easier, it would be okay if conversion for them is done at a slower rate).

Best, Felix

  • An idea I just had:
    If I understand things correctly, ADC A0 is read two times, the first result is written to ADC_ResultNumber_0 and the second one to ADC_ResultNumber_1. Since the first one is faulty, I guess ADC_ResultNumber_0 is never used then -- is this correct?

    The conversion for the potentiometers is triggerd by ADC_Int1, which will only happen when the other conversions are done. So I guess at this moment, the value of ADC_ResultNumber_0 is already fixed and won't change anymore before the next iteration? Since this value is never used, I could directly reuse ADC_ResultNumber_0 for the result of my second potentiometer.

    Hoping that my assumptions are right, I added the following code to HAL_setupAdcs():

    ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_0,ADC_SocChanNumber_B6);
    ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_0, ADC_Int1TriggersSOC);
    ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_0,ADC_SocSampleDelay_9_cycles);

    Then I read the result of ADC_ResultNumber_0. So far the numbers look reasonable, so I think I can get the value of the second potentiometer this way.

    The essential question is now: Are my assumptions correct, that ADC_ResultNumber_0 is nowhere else used and I can safely reuse it? Or can this break anything?

  • what you have done should be absolutely fine, but I'll send to someone else to double check.
  • Hi Felix,

    Actually the issue here is that after the sequence of SOC0->SOC1->...SOC15->SOC0, the round-robin pointer will give SOC1 the highest priority for the next time all the conversions are triggered. Because of this, SOC1 will be the bad first sample the next time the conversions are triggered (I am assuming you are using an ePWM to trigger all 16 SOCs at once).

    I think you can get around this by setting the SOC priority such that SOC0 is high priority (all the rest of the SOCs are round-robin). In this case I think you will want the ADCINT that re-triggers SOC0 to come from EOC15 in early interrupt mode (this will ensure that SOC0 converts after SOC15, and not in the middle of the other conversions, since it is high priority).
  • Hi Devin,

    okay, so by default the conversion does not always start at SOC0 but at the one where it stopped during the last sequence?

    You are assuming, that I use the same ePWM trigger for all SOCs, this is currently not the case. Currently SOC0-14 are triggered by ADC_SocTrigSrc_EPWM4_ADCSOCA, but the ones I added for the potentiometers (SOC15 and 0 again) are then triggered by ADC_Int2TriggersSOC (I changed this, compared to previous posts where I used Int1). This is due to the instructions of the HAL tutorial, due to which the conversion for the potentiometer should only be started if all the others are finished. I think the reason was to make sure that the less critical potentiometer does not delay the more critical motor phase conversions. I was already wondering, if this could be a problem as I am maybe triggering a new conversion this way (i.e. SOC15 would again be affected by the bug)?

    Regarding your solution: I think I understand the general idea, but I am not sure how to implement it.

    • If I understand it correctly, you are suggesting to trigger SOC15 for the first potentiometer together with the others (i.e. ADC_SocTrigSrc_EPWM4_ADCSOCA), while SOC0 for the second potentiometer is triggered by ADCINT2 which I then should change to fire at EOC15 (currently set to EOC14)?
    • How do I set the priority of an SOC?
    • What does "early interrupt mode" mean and how do I enable it?

    Sorry for the maybe stupid questions, I don't yet fully understand how this ADC process is working and the code is not always self-explaining. Is there some documentation of the ADC module anywhere?

    Best, Felix

  • Hi Felix,

    Yeah, which SOC starts first can depend on quite a few things; see section "8.1.5 ADC Conversion Priority" in the TRM (spruh18f). To change the priority, you can alter the field SOCPRIORITY in the SOCPRICTL register.

    Early interrupt vs. late interrupt mode determines when the ADCINT flag will be set. If SOC0 is configured to set ADCINT1, in early interrupt mode ADCINT1 will get set after the S+H phase of the SOC0, while in late interrupt mode the flag won't get set until after SOC0 completes. The reason you might want to use early interrupt mode is that allows you to set the ADCINT flag a little early on the last SOC in a sequence and enter the ISR right around when the conversions are ready. In the TRM you can see the timing diagrams for both these modes in the section "8.1.12 ADC Timings"
  • Hi Devin,

    thanks a lot, I somehow missed the ADC section in the TRM. I think I understand now and will try to implement it as you suggested.

    One think I noticed when looking at the code again:
    I thought that SOC0-14 are all triggered by the same source, but now I noticed that the ADCs for motor 1 (SOC0-7) are triggered by EPWM1 and the ones for motor 2 (SOC8-14) by EPWM4. In my understanding this means that the conversions for the two motors are done in separate sequences and therefore both separately affected by the bug. However, only the sequence for motor 1 has this workaround (IA is sampled twice). In the sequence for motor 2 this is not the case. Does this mean, that IA of motor 2 is actually affected by the bug and always sampled with some error? Or do I misunderstand something here?