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.

Problems comparing a previous value with the current ADC value (parameter AdcResult.ADCRESULT0)(TMS320F28055)

Other Parts Discussed in Thread: TMS320F28055

Hello folks,
I have a question about the ADC I use the TMS320F28055 controller. There is a POTI on the output pin. I can successfully do a conversion with the ADC. My trigger source is a timer, which means my ADC value is updated every millisecond. The converted ADC value is in the AdcResult.ADCRESULT0 register. I converted the digital value for my application in a state machine the value runs for example between 0-200 and is stored in a variable "A" and is sent to another controller. Now we come to the main problem, I only want to send the value stored in variable "A" when the ADC value changes. For this I created a struct with previous value and current value. I update the current value in my timer interrupt and constantly compare it in the state machine, if the values ​​are not the same, "A" should be sent again. The problem is that it constantly jumps into the send function, although the debug mode shows that both values ​​(previous and current) are the same. To test, I turned the potentiometer up all the way or set it to 0, but it doesn't work. Can someone tell me how I could solve it?

I suspect that it is due to the Adc Result.ADC RESULT 0 parameter.(because the parameter is always constantly changing)

I thank you for your help.

GLOBALS_statusMotorcontroller.frequenz_sollwert = is the value to be sent

freqsollwert.vorherigerSollwert = previous value 

freqsollwert.aktuellerSollwert = this is the current value which is constantly updated in the timer interrupt

sendesollwert  = this is a boolean variable to ensure that the value is only sent if it has changed.

        faktor_frequenz =  4095 / diff;
        GLOBALS_statusMotorcontroller.frequenz_sollwert = offset +  AdcResult.ADCRESULT0  / faktor_frequenz;



        if(freqsollwert.vorherigerSollwert != freqsollwert.aktuellerSollwert)
        {
            sendesollwert = false;
        }


        ////////////FREQUENZ-SOLLWERT auf Änderung senden/////////////

        if(sendesollwert == false)
        {
            //testcounter++;
            freqsollwert.vorherigerSollwert = freqsollwert.aktuellerSollwert;
            INTERFACE_MOTORCONTROLLER_addtokritischeQueue(Motorcontroller_Befehl_Write_BE_FREQUENZ_SOLLWERT, GLOBALS_statusMotorcontroller.frequenz_sollwert );
            STATEMACHINE_SPI_MOTORCONTROLLER_kommunikation();
            sendesollwert = true;
        }

  • Markus,

    If you are comparing the full 12-bit value of the ADC run to run, I think you are going to see that even for a DC input you will see some amount of code change due to system noise in general; likely on the order of 4 or 5 LSBs, with an ideal standard distribution of 0.6LSBs or so.  As such this is going to cause the compare to mis-match and set the flag almost every ADC conversion.

    Likely what you will need to do is increase the tolerance of the comparison function to accommodate the noise(assuming that is acceptable) or oversample/average the signal to lower the noise floor so you have better repeatibility.

    Let me know if I'm understanding the issue correctly.

    Best,

    Matthew

  • hello matthew

    you got the problem right. The voltage is not stable so the ADC always fluctuates. I only want to send a value if it is not equal. Do you have a solution for this problem. I've already tried cutting off the last bits of the ADC value with &&FFF0 but without success.
    thank you for your help

  • Markus,

    Can you let me know the data range you are seeing currently on your setup; Min/Max/stddev?

    Best,

    Matthew

  • What do you mean? the ADC range goes from 0 to 4095? and my values ​​that I want to set are adjustable, for example between 0-200 or 100-400. these should be variable.

  • Markus,

    For your current setup, where there is too much ADC result variability for the code to be stable I wanted to see for a given input to the ADC what code(s) you see from the ADC Result.  For example for a given (static) input if you take ~50 ADC samples what is the ADC code distribution min/max/stddev.  If you just want to post the ADC results to this thread that is fine as well.

    Best,

    Matthew

  • Hello Matthew

    for an ADC Value of 3665 i got these results

  • Markus,

    Based on the results, most of the time the value is in a "stable" condition i.e. ~3666 +/-1 or 2 LSBs.  There are time where I would say that the analog input voltage is truly changing, for instance at array location 15 = 3581 or at 41 = 3634

    I think what we have to determine is based on your system what amount of change is just sample/sample noise and what amount is real perturbation and something you need to act on in the ISR.

    Perhaps if you set a threshold to anything more than 10LSBs away from 3666 or so, based on the data

    Best,

    Matthew

  • Matthew,


    how would you set a threshold of 10 LSB?

    I don't use an ADC interrupt. My triggersource is simply a timer. The ADC value updates every millisecond.


    In the meantime I have tried this function. The value has become more stable as a result. But the maximum ADC value only runs up to 4032, which is still questionable why that is. Normally the value should go up to 4095.

    long berechneterWert = 0;
    long alterWert = 0;
    
    
    
    long send_mean_value_from_ADC()
    {
    
            uint16_t neuerWert = AdcResult.ADCRESULT0;
    
            berechneterWert = ((alterWert * 63) + neuerWert) / 64;
    
            alterWert = berechneterWert;
    
            return alterWert;
    }

  • Markus,

    For my technique I may have mis-understood your system, I had supposed there was a target voltage you were trying to stay within, but based on the above code I think you are looking for absolute movement from what may be a variable centerpoint.

    With regards to the 4095 issue, the ADC has some amount of offset error in its untrimmed state; if it is negative it will cause the behavior you describe, where 3.3V input does not give 4095.  You should see a function in our examples called  AdcOffsetSelfCal(), please make sure you are calling this as part of your init routine(and using your ADC settings) as this should remove the offset error.

    Best,

    Matthew

  • hi matthew,

    Thanks for your reply, I've thought of an offset as well. When I left out the function I posted last time, I could see the value moving from 0 to 4095 as it should. But when I activate the function, an average is formed the way I wanted it to be so that the value no longer fluctuates greatly. The problem is when I activate the AdcOffsetSelfCal() function, my bits are always overwritten by this function so that the timer is no longer triggered and the other bits are no longer what I wanted.

  • Markus,

    I understand the issue you are describing with the OffsetCal.  You can add this feature to your code if you want, using your same trigger to a different SOC connected to the VREFLO sampling channel.  In fact, if you are not using A5(or B5, one is VREFLO the other is the temp sensor), you could leave it permanently connected to VREFLO and just sample it every so often and re-apply the offset correction formula inline with your other samples.  You can C/P the SOC settings for ACQPS, etc from the Offset Cal example.

    Best,

    Matthew