2 Replies Latest reply on Aug 23, 2019 1:01 AM by MoSP_1672341

    ADC read issue

    MoSP_1672341

      Hello,

      I am using PSoC 4200M series (CY8C4247AZI-M485). I was trying to use the ADC. Just to get a feel for it, I uploaded the ADC_SAR_Seq_Die_Temp_PSoC4 example code in the PSoC creator 4.2 to check the measured voltage. When I ground the ADC pin the ADC does not read 0mV, instead it reads any value ranging from a few tens of mV to about 3-4V. However when I give it a voltage equal to the reference voltage (VDDA) it reads it properly. Can someone please guide me on what might be happening and how to fix it?

        • 1. Re: ADC read issue
          MoTa_728816

          Hi,

           

          That is a nice example code!

          I did not know about "DieTemp", so I gave it a try.

           

          Since you are using CY8C4247AZI-M485, I imagined that you are using

          either CY8CKIT-044 or CY8CKIT-043.

          To go with these board, I modified the schematic so that we can use KitProg UART.

           

          schematic

          001-schematic.JPG

           

          CY8CKIT-044

          IMG_3785.JPG

          pin list

          002-pin-list.JPG

           

          Tera Term log when I moved the pot

          000-TeraTerm-log.JPG

          So the reading was from 0mV to 1024mV (actual VDD was 3.3V, with this)

           

          Then I tried with CY8CKIT-043

          IMG_3787.JPG

           

          pin list (schematic was same)

          004-pin-list-043.JPG

           

          Tera Term log

          003-TeraTerm-043.JPG

           

          So, with my usage, both CY8CKIT-044 and CY8CKIT-043 printed out 0mV ~ 1024mV.

           

          FYI, modified main.c

          ====================

          /*******************************************************************************

          * File Name: main.c

          *

          * Version: 2.10

          *

          * Description:

          *  Sequencing SAR ADC and DieTemp datasheet example project.

          *

          * Note:

          *  Pin_Vin pin (P0[4]) must be connected to the GND.

          *  UART_tx pin (P0[5]) must be connected to the pin (P12[6]) of J8 header.

          *  Verify that J9 is connected to 5V.

          *

          * Hardware Dependency:

          *  PSoC4 Pioneer kit

          *

          ********************************************************************************

          * Copyright 2013-2017, Cypress Semiconductor Corporation. All rights reserved.

          * This software is owned by Cypress Semiconductor Corporation and is protected

          * by and subject to worldwide patent and copyright laws and treaties.

          * Therefore, you may use this software only as provided in the license agreement

          * accompanying the software package from which you obtained this software.

          * CYPRESS AND ITS SUPPLIERS MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,

          * WITH REGARD TO THIS SOFTWARE, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT,

          * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

          *******************************************************************************/

           

           

          #include <project.h>

          #include <stdio.h>

           

           

          /* ADC SAR sequencer component header to access Vref value */

          #include <ADC_SAR_SEQ.h>

           

           

          #define CH0_N              (0x00u)

          #define TEMP_CH            (0x01u)

          #define DELAY_1SEC          (1000u)

           

           

          /* Get actual Vref. value from ADC SAR sequencer */

          #define ADC_VREF_VALUE_V    ((float)ADC_SAR_SEQ_DEFAULT_VREF_MV_VALUE/1000.0)

           

           

          volatile uint32 dataReady = 0u;

          volatile int16 result[ADC_SAR_SEQ_TOTAL_CHANNELS_NUM];

          volatile uint32 timer_delay = 0u;

           

           

          char str[128] ; /* print buffer */

          void print(char *str)

          {

              UART_UartPutString(str) ;

          }

           

           

          /******************************************************************************

          * Function Name: ISR_TIMER_LOC

          *******************************************************************************

          *

          * Summary:

          *  Handle Interrupt Service Routine. Source - TIMER.

          *

          ******************************************************************************/

          CY_ISR(ISR_TIMER_LOC)

          {

              timer_delay++;

            

              /* Measures temperature once per second */

              if(timer_delay > DELAY_1SEC)

              {

                  /* Enables injection channel for next scan */

                  ADC_SAR_SEQ_EnableInjection();

                  timer_delay = 0u;

              }  

            

              /* Clears interrupt request from terminal count */

              PWM_ClearInterrupt(PWM_INTR_MASK_TC);

          }

           

          /******************************************************************************

          * Function Name: ADC_SAR_SEQ_ISR_LOC

          *******************************************************************************

          *

          * Summary:

          *  Handle Interrupt Service Routine. Source - ADC SAR Seq.

          *

          ******************************************************************************/

          CY_ISR(ADC_SAR_SEQ_ISR_LOC)

          {

              uint32 intr_status;

              uint32 range_status;

           

           

              /* Read interrupt status registers */

              intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;

              /* Check for End of Scan interrupt */

              if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)

              {

                  /* Read range detect status */

                  range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;

                  /* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit  */

                  if((range_status & (uint32)(1ul << CH0_N)) != 0u)

                  {

                      /* Read conversion result */

                      result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);

                      /* Set PWM compare from channel0 */

                      PWM_WriteCompare(result[CH0_N]);

                  }  

           

           

                  /* Clear range detect status */

                  ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;

                  dataReady |= ADC_SAR_SEQ_EOS_MASK;

              }  

           

           

              /* Check for Injection End of Conversion */

              if((intr_status & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)

              {

                  result[TEMP_CH] = ADC_SAR_SEQ_GetResult16(TEMP_CH);

                  dataReady |= ADC_SAR_SEQ_INJ_EOC_MASK;

              }  

           

           

              /* Clear handled interrupt */

              ADC_SAR_SEQ_SAR_INTR_REG = intr_status;

          }

           

          /*******************************************************************************

          * Function Name: main

          ********************************************************************************

          *

          * Summary:

          *

          * Parameters:

          *  None.

          *

          * Return:

          *  None.

          *

          *******************************************************************************/

          int main()

          {

              int16 res = 0;

              int32 temperature;

              char  uartLine[250];

              int16 ADCCountsCorrected;

           

           

              /* Initialize the UART */

              UART_Start();

              print("\r\n") ; // UART_PutCRLF();

              print("\r\n") ; // UART_PutCRLF();

              // UART_PutString("Starting temperature measurement...");

              print("Starting temperature measurement...");

              print("\r\n") ; // UART_PutCRLF();

            

              PWM_Start();

              PWM_TriggerCommand(PWM_MASK, PWM_CMD_START);

           

           

              /* Init and start sequencing SAR ADC */

              ADC_SAR_SEQ_Start();

              ADC_SAR_SEQ_StartConvert();

              /* Enable interrupt and set interrupt handler to local routine */

              ADC_SAR_SEQ_IRQ_StartEx(ADC_SAR_SEQ_ISR_LOC);

            

              /* Init interrupt from timer to measure the temperature rarely */

              ISR_TIMER_StartEx(ISR_TIMER_LOC);

           

           

              CyGlobalIntEnable;

           

           

              for(;;)

              {

                  /* When conversion of sequencing channels has completed */

                  if((dataReady & ADC_SAR_SEQ_EOS_MASK) != 0u)

                  {

                      /* Get voltage, measured by ADC */

                      dataReady &= ~ADC_SAR_SEQ_EOS_MASK;

                      res = ADC_SAR_SEQ_CountsTo_mVolts(CH0_N, result[CH0_N]);

                  }  

                

                  /* When conversion of the injection channel has completed */

                  if((dataReady & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)

                  {

                      dataReady &= ~ADC_SAR_SEQ_INJ_EOC_MASK;

           

                      /******************************************************************************

                      * Adjust data from ADC with respect to Vref value.

                      * This adjustment is to be done if Vref is set to any other than

                      * internal 1.024V.

                      * For more detailed description see Functional Description section

                      * of DieTemp P4 datasheet.

                      *******************************************************************************/

                      ADCCountsCorrected = (int16)(result[TEMP_CH]*(((float)ADC_VREF_VALUE_V/1.024)));

                    

                      temperature = DieTemp_CountsTo_Celsius(ADCCountsCorrected);

           

                      /* Print temperature value to UART */

                      sprintf(

                              uartLine, "Temperature value: %dC",

                              (int16) temperature

                              );

                      print(uartLine) ;  // UART_PutString(uartLine);

                      print("\r\n") ;    // UART_PutCRLF();

                    

                      /* Print voltage value to UART */

                      sprintf(

                          uartLine, "ADC measured voltage: %dmV",

                          (uint16) res

                          );

                    

                      print(uartLine) ;  // UART_PutString(uartLine);

                      print("\r\n") ;    // UART_PutCRLF();

                  }

              }

          }

           

          /* [] END OF FILE */

          ====================

           

          moto

          • 2. Re: ADC read issue
            MoSP_1672341

            Hey this is awesome! Thanks a lot for the quick reply. I am using CY8CKIT-043. I just tried your code with the pot. It's working fine. But looks like a sudden jump from 0-5V seems to have some settling time. Other than that I think I was having some loose connection. So I rigged up a GPCB and tried it with the pot. And it properly measure a 0 when grounded.