> For the complete documentation index, see [llms.txt](https://docs.aic-eec.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.aic-eec.com/interfacing-with-infineon-psoc-tm-edge/basic-mcu-interfacing/workshops/potentiometer-adc.md).

# Potentiometer (ADC)

## Lab 3: Potentiometer (ADC) — อ่านค่า Analog

#### วัตถุประสงค์

* **Analog Input**: อ่านค่าแบบ Analog (ไม่ใช่แค่ 0/1)
* **ADC**: เข้าใจหลักการแปลง Analog → Digital
* **Scaling**: แปลงค่า ADC เป็นหน่วยที่เข้าใจได้

#### จะได้เรียนรู้อะไร

* **ADC Concept**: 12-bit resolution (0-4095)
* **Unit Conversion**: ADC counts → millivolts → percentage
* **Periodic Reading**: อ่านค่าเป็นช่วงเวลา

***

### หลักการ ADC

```
   Analog Input        ┌─────────┐        Digital Output         
   (0 - 1.8V)    ────► │   ADC   │ ────►  (0 - 4095)             
                       └─────────┘        12-bit      

Analog Input (0V - 1.8V)     ADC     Digital Output (0 - 4095)
         │                    │              │
    1.8V ├────────────────────┼─────────────→ 4095
    0.9V ├────────────────────┼─────────────→ 2048
    0.0V ├────────────────────┼─────────────→ 0
```

**Resolution 12-bit:** 2^12 = 4096 ระดับ

สูตรแปลงเป็น mV:

$$
mV = \frac{ADC\_count \times VREF\_mV}{4096}
$$

#### Hardware Info

| Component           | Pin      | หมายเหตุ       |
| ------------------- | -------- | -------------- |
| Potentiometer (POT) | P15\_1   | 0-1800mV range |
| ADC Reference       | Internal | 1.8V           |

***

### Lab 3.1 : แก้ไข Macros เดิมจาก

```c
/*******************************************************************************
 * Macros
 ******************************************************************************/
#define CM55_BOOT_WAIT_TIME_USEC    (10U) 
#define ADC_SCAN_DELAY_MSEC         (500U) <-- เดิม
#define SAR_ADC_INDEX               (0U)
#define SAR_ADC_SEQENCER            (0U)  <-- เดิม
#define SAR_ADC_CHANNEL             (0U)
#define SAR_ADC_VREF_MV             (1800U)
```

#### เป็น Macros ใหม่ , เพิ่ม Variables  และ ชื่อฟังก์ชันเพิ่มเติม ดังนี้

```c
/*******************************************************************************
 * Macros
 ******************************************************************************/
#define CM55_BOOT_WAIT_TIME_USEC    (10U)
#define ADC_READ_INTERVAL_MS        (100U)
#define SAR_ADC_INDEX               (0U)
#define SAR_ADC_SEQUENCER           (0U)
#define SAR_ADC_CHANNEL             (0U)
#define SAR_ADC_VREF_MV             (1800U)

/*******************************************************************************
* Global Variables
*******************************************************************************/
static bool adc_initialized = false;

/*******************************************************************************
* Function Prototypes
*******************************************************************************/
static cy_rslt_t init_adc(void);
static int16_t read_potentiometer_mv(void);
static uint8_t get_pot_percentage(int16_t voltage_mv);
```

#### สร้างฟังก์ชัน init\_adc()

```c
/*******************************************************************************
* Function Name: init_adc
********************************************************************************
* Summary:
*   Initializes the SAR ADC using autonomous analog control.
*   Sets up interrupt masks and enables autonomous operation.
*
* Parameters:
*   none
*
* Return:
*   cy_rslt_t - CY_RSLT_SUCCESS if initialization successful
*
*******************************************************************************/
static cy_rslt_t init_adc(void)
{
    cy_rslt_t result;

    /* Initialize SAR ADC with autonomous analog configuration */
    result = Cy_AutAnalog_Init(&autonomous_analog_init);

    if (CY_AUTANALOG_SUCCESS != result)
    {
        return result;
    }

    /* Set interrupt mask to enable SAR0 result interrupt */
    Cy_AutAnalog_SetInterruptMask(CY_AUTANALOG_INT_SAR0_RESULT);

    /* Start autonomous control of the ADC */
    Cy_AutAnalog_StartAutonomousControl();

    adc_initialized = true;

    return CY_RSLT_SUCCESS;
}
```

#### สร้างฟังก์ชัน read\_potentiometer\_mv()

```c
/*******************************************************************************
* Function Name: read_potentiometer_mv
********************************************************************************
* Summary:
*   Reads the potentiometer value from ADC and converts to millivolts.
*   Uses the autonomous analog SAR ADC API.
*
* Parameters:
*   none
*
* Return:
*   int16_t - Voltage in millivolts (0-1800 mV)
*
*******************************************************************************/
static int16_t read_potentiometer_mv(void)
{
    int32_t adc_count;
    int16_t voltage_mv;

    /* Read ADC result (raw counts) */
    adc_count = Cy_AutAnalog_SAR_ReadResult(SAR_ADC_INDEX,
                                            CY_AUTANALOG_SAR_INPUT_GPIO,
                                            SAR_ADC_CHANNEL);

    /* Convert ADC counts to millivolts */
    voltage_mv = Cy_AutAnalog_SAR_CountsTo_mVolts(SAR_ADC_INDEX,
                                                   false,
                                                   SAR_ADC_SEQUENCER,
                                                   CY_AUTANALOG_SAR_INPUT_GPIO,
                                                   SAR_ADC_CHANNEL,
                                                   SAR_ADC_VREF_MV,
                                                   adc_count);

    return voltage_mv;
}
```

#### สร้างฟังก์ชัน get\_pot\_percentage()

```c
/*******************************************************************************
* Function Name: get_pot_percentage
********************************************************************************
* Summary:
*   Converts potentiometer voltage to percentage (0-100%).
*   Maps the voltage range (0 to VREF_MV) to percentage scale.
*
* Parameters:
*   voltage_mv - Input voltage in millivolts
*
* Return:
*   uint8_t - Percentage value (0-100)
*
*******************************************************************************/
static uint8_t get_pot_percentage(int16_t voltage_mv)
{
    int32_t percentage;

    /* Ensure voltage is within valid range */
    if (voltage_mv < 0)
    {
        voltage_mv = 0;
    }
    else if (voltage_mv > SAR_ADC_VREF_MV)
    {
        voltage_mv = SAR_ADC_VREF_MV;
    }

    /* Calculate percentage: (voltage / VREF) * 100 */
    percentage = ((int32_t)voltage_mv * 100) / SAR_ADC_VREF_MV;

    return (uint8_t)percentage;
}
```

#### ปรับปรุง main() ใหม่

```c
int main(void)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    int16_t voltage_mv;
    uint8_t percentage;

    /* Initialize the device and board peripherals. */
    result = cybsp_init();

    /* Board initialization failed. Stop program execution. */
    if (CY_RSLT_SUCCESS != result)
    {
        handle_app_error();
    }

    /* Enable global interrupts */
    __enable_irq();

    /* Initialize retarget-io middleware */
    init_retarget_io();

    /* \x1b[2J\x1b[;H - ANSI ESC sequence for clear screen. */
    printf("\x1b[2J\x1b[;H");
    printf("***********************************************************\r\n");
    printf("            PSOC Edge MCU: Potentiometer ADC               \r\n");
    printf("***********************************************************\r\n\n");

    /* Initialize SAR ADC using helper function */
    result = init_adc();

    if (CY_RSLT_SUCCESS != result)
    {
        printf("ADC initialization failed!\r\n");
        handle_app_error();
    }

    /* Inform user about potentiometer connection */
    printf("ADC initialized successfully!\r\n");
    printf("Reading potentiometer on pin P15_1\r\n");
    printf("VREF = %d mV (12-bit resolution)\r\n\n", SAR_ADC_VREF_MV);

    /* CY_CM55_APP_BOOT_ADDR must be updated if CM55 memory layout is changed.*/
    Cy_SysEnableCM55(MXCM55, CY_CM55_APP_BOOT_ADDR, CM55_BOOT_WAIT_TIME_USEC);

    for(;;)
    {
        /* Read potentiometer voltage using helper function */
        voltage_mv = read_potentiometer_mv();

        /* Convert to percentage using helper function */
        percentage = get_pot_percentage(voltage_mv);

        /* Print ADC output in millivolts and percentage */
        printf("POT: %4d mV  |  %3d%%\r\n", voltage_mv, percentage);

        /* Toggle user LED to indicate activity */
        Cy_GPIO_Inv(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);

        /* Delay between ADC readings */
        Cy_SysLib_Delay(ADC_READ_INTERVAL_MS);
    }

}
```

#### ตัวอย่าง Output บน Serial Terminal

```bash
***********************************************************
            PSOC Edge MCU: Potentiometer ADC               
***********************************************************

ADC initialized successfully!
Reading potentiometer on pin P15_1
VREF = 1800 mV (12-bit resolution)

POT:    0 mV  |    0%
POT:  450 mV  |   25%
POT:  900 mV  |   50%
POT: 1350 mV  |   75%
POT: 1800 mV  |  100%
```

### ADC Potentiometer Flowcharts

#### Overall Program Flow and init\_adc() Flowchart

<figure><img src="https://1856353139-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MClo3nC-1US0rbK8Qau%2Fuploads%2F7iPNzVHnegdaUgc19GYH%2FEmbedded%20Systems%20and%20IoT-Page-8.drawio%20(1).png?alt=media&amp;token=75e3c140-b76d-4442-9c1d-c2954c049324" alt=""><figcaption></figcaption></figure>

***

#### read\_potentiometer\_mv() Flowchart

```bash
┌─────────────────────────────────────────────────────────────────┐
│                read_potentiometer_mv() Function                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌──────────────────┐                                          │
│   │      START       │                                          │
│   └────────┬─────────┘                                          │
│            │                                                    │
│            ▼                                                    │
│   ┌──────────────────────────────────────┐                      │
│   │  adc_count = Cy_AutAnalog_SAR_       │                      │
│   │     ReadResult(                      │                      │
│   │       SAR_ADC_INDEX,                 │                      │
│   │       CY_AUTANALOG_SAR_INPUT_GPIO,   │                      │
│   │       SAR_ADC_CHANNEL                │                      │
│   │     )                                │                      │
│   └────────┬─────────────────────────────┘                      │
│            │                                                    │
│            │  adc_count = 0 ~ 4095 (12-bit)                     │
│            ▼                                                    │
│   ┌──────────────────────────────────────┐                      │
│   │  voltage_mv = Cy_AutAnalog_SAR_      │                      │
│   │     CountsTo_mVolts(                 │                      │
│   │       SAR_ADC_INDEX,                 │                      │
│   │       false,                         │                      │
│   │       SAR_ADC_SEQUENCER,             │                      │
│   │       CY_AUTANALOG_SAR_INPUT_GPIO,   │                      │
│   │       SAR_ADC_CHANNEL,               │                      │
│   │       SAR_ADC_VREF_MV,    ◄── 1800   │                      │
│   │       adc_count                      │                      │
│   │     )                                │                      │
│   └────────┬─────────────────────────────┘                      │
│            │                                                    │
│            │  voltage_mv = 0 ~ 1800 mV                          │
│            ▼                                                    │
│   ┌──────────────────┐                                          │
│   │ return voltage_mv│                                          │
│   └──────────────────┘                                          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

#### get\_pot\_percentage() Flowchart

```bash
┌─────────────────────────────────────────────────────────────────┐
│                 get_pot_percentage() Function                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌──────────────────┐                                          │
│   │  START           │                                          │
│   │  Input: voltage  │                                          │
│   └────────┬─────────┘                                          │
│            │                                                    │
│            ▼                                                    │
│   ┌──────────────────────────────────────┐                      │
│   │         voltage_mv < 0 ?             │                      │
│   └────────┬──────────────────┬──────────┘                      │
│            │ YES              │ NO                              │
│            ▼                  ▼                                 │
│   ┌──────────────────┐  ┌──────────────────────────────────┐    │
│   │ voltage_mv = 0   │  │      voltage_mv > 1800 ?         │    │
│   └────────┬─────────┘  └────────┬──────────────┬──────────┘    │
│            │                     │ YES          │ NO            │
│            │                     ▼              │               │
│            │            ┌──────────────────┐    │               │
│            │            │voltage_mv = 1800 │    │               │
│            │            └────────┬─────────┘    │               │
│            │                     │              │               │
│            └─────────────────────┴──────────────┘               │
│                                  │                              │
│                                  ▼                              │
│            ┌─────────────────────────────────────────┐          │
│            │                                         │          │
│            │  percentage = (voltage_mv × 100)        │          │
│            │                ─────────────────        │          │
│            │                  VREF (1800)            │          │
│            │                                         │          │
│            └────────────────────┬────────────────────┘          │
│                                 │                               │
│                                 ▼                               │
│            ┌──────────────────────────────────┐                 │
│            │  return (uint8_t) percentage     │                 │
│            │         (0 ~ 100%)               │                 │
│            └──────────────────────────────────┘                 │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

#### ADC Conversion Diagram

```bash
┌─────────────────────────────────────────────────────────────────┐
│                    ADC Conversion Process                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Potentiometer (P15_1)                                         │
│        │                                                        │
│        │  Analog Voltage                                        │
│        │  (0V ~ 1.8V)                                           │
│        ▼                                                        │
│   ┌──────────────────┐                                          │
│   │    SAR ADC       │                                          │
│   │   12-bit         │                                          │
│   │   Resolution     │                                          │
│   └────────┬─────────┘                                          │
│            │                                                    │
│            │  Digital Count                                     │
│            │  (0 ~ 4095)                                        │
│            ▼                                                    │
│   ┌──────────────────────────────────────┐                      │
│   │  CountsTo_mVolts()                   │                      │
│   │                                      │                      │
│   │  mV = (count × VREF) / 4096          │                      │
│   │     = (count × 1800) / 4096          │                      │
│   │                                      │                      │
│   └────────┬─────────────────────────────┘                      │
│            │                                                    │
│            │  Voltage in mV                                     │
│            │  (0 ~ 1800 mV)                                     │
│            ▼                                                    │
│   ┌──────────────────────────────────────┐                      │
│   │  get_pot_percentage()                │                      │
│   │                                      │                      │
│   │  % = (mV × 100) / 1800               │                      │
│   │                                      │                      │
│   └────────┬─────────────────────────────┘                      │
│            │                                                    │
│            │  Percentage                                        │
│            │  (0% ~ 100%)                                       │
│            ▼                                                    │
│   ┌──────────────────┐                                          │
│   │  Display Output  │                                          │
│   │  "POT: 900 mV |  │                                          │
│   │        50%"      │                                          │
│   └──────────────────┘                                          │
│                                                                 │
│   ═══════════════════════════════════════════════════════════   │
│                                                                 │
│   Examples:                                                     │
│   ─────────                                                     │
│   Count = 0    → 0 mV    → 0%                                   │
│   Count = 1024 → 450 mV  → 25%                                  │
│   Count = 2048 → 900 mV  → 50%                                  │
│   Count = 3072 → 1350 mV → 75%                                  │
│   Count = 4095 → 1800 mV → 100%                                 │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

### <mark style="color:blue;">Program Code ทั้งหมด</mark>

```c
/*******************************************************************************
* File Name        : main.c
*
* Description      : This source file contains the main routine for non-secure
*                    application in the CM33 CPU
*
*******************************************************************************/

/*******************************************************************************
* Header Files
*******************************************************************************/

#include "cybsp.h"
#include "retarget_io_init.h"
#include <stdbool.h>

/*******************************************************************************
 * Macros
 ******************************************************************************/
#define CM55_BOOT_WAIT_TIME_USEC    (10U)
#define ADC_READ_INTERVAL_MS        (100U)
#define SAR_ADC_INDEX               (0U)
#define SAR_ADC_SEQUENCER           (0U)
#define SAR_ADC_CHANNEL             (0U)
#define SAR_ADC_VREF_MV             (1800U)

/*******************************************************************************
* Global Variables
*******************************************************************************/
static bool adc_initialized = false;

/*******************************************************************************
* Function Prototypes
*******************************************************************************/
static cy_rslt_t init_adc(void);
static int16_t read_potentiometer_mv(void);
static uint8_t get_pot_percentage(int16_t voltage_mv);

/*******************************************************************************
* Function Name: init_adc
********************************************************************************
* Summary:
*   Initializes the SAR ADC using autonomous analog control.
*   Sets up interrupt masks and enables autonomous operation.
*
* Parameters:
*   none
*
* Return:
*   cy_rslt_t - CY_RSLT_SUCCESS if initialization successful
*
*******************************************************************************/
static cy_rslt_t init_adc(void)
{
    cy_rslt_t result;

    /* Initialize SAR ADC with autonomous analog configuration */
    result = Cy_AutAnalog_Init(&autonomous_analog_init);

    if (CY_AUTANALOG_SUCCESS != result)
    {
        return result;
    }

    /* Set interrupt mask to enable SAR0 result interrupt */
    Cy_AutAnalog_SetInterruptMask(CY_AUTANALOG_INT_SAR0_RESULT);

    /* Start autonomous control of the ADC */
    Cy_AutAnalog_StartAutonomousControl();

    adc_initialized = true;

    return CY_RSLT_SUCCESS;
}

/*******************************************************************************
* Function Name: read_potentiometer_mv
********************************************************************************
* Summary:
*   Reads the potentiometer value from ADC and converts to millivolts.
*   Uses the autonomous analog SAR ADC API.
*
* Parameters:
*   none
*
* Return:
*   int16_t - Voltage in millivolts (0-1800 mV)
*
*******************************************************************************/
static int16_t read_potentiometer_mv(void)
{
    int32_t adc_count;
    int16_t voltage_mv;

    /* Read ADC result (raw counts) */
    adc_count = Cy_AutAnalog_SAR_ReadResult(SAR_ADC_INDEX,
                                            CY_AUTANALOG_SAR_INPUT_GPIO,
                                            SAR_ADC_CHANNEL);

    /* Convert ADC counts to millivolts */
    voltage_mv = Cy_AutAnalog_SAR_CountsTo_mVolts(SAR_ADC_INDEX,
                                                   false,
                                                   SAR_ADC_SEQUENCER,
                                                   CY_AUTANALOG_SAR_INPUT_GPIO,
                                                   SAR_ADC_CHANNEL,
                                                   SAR_ADC_VREF_MV,
                                                   adc_count);

    return voltage_mv;
}

/*******************************************************************************
* Function Name: get_pot_percentage
********************************************************************************
* Summary:
*   Converts potentiometer voltage to percentage (0-100%).
*   Maps the voltage range (0 to VREF_MV) to percentage scale.
*
* Parameters:
*   voltage_mv - Input voltage in millivolts
*
* Return:
*   uint8_t - Percentage value (0-100)
*
*******************************************************************************/
static uint8_t get_pot_percentage(int16_t voltage_mv)
{
    int32_t percentage;

    /* Ensure voltage is within valid range */
    if (voltage_mv < 0)
    {
        voltage_mv = 0;
    }
    else if (voltage_mv > SAR_ADC_VREF_MV)
    {
        voltage_mv = SAR_ADC_VREF_MV;
    }

    /* Calculate percentage: (voltage / VREF) * 100 */
    percentage = ((int32_t)voltage_mv * 100) / SAR_ADC_VREF_MV;

    return (uint8_t)percentage;
}

/*******************************************************************************
* Function Name: main
*******************************************************************************
* Summary:
*   Main function - entry point for the ADC potentiometer demo.
*
*   This demo reads the potentiometer connected to P15_1 and displays:
*   - Raw voltage in millivolts (0-1800 mV)
*   - Percentage value (0-100%)
*
*   The LED toggles with each ADC reading to indicate activity.
*
* Parameters:
*   none
*
* Return:
*   int
*
******************************************************************************/
int main(void)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    int16_t voltage_mv;
    uint8_t percentage;

    /* Initialize the device and board peripherals. */
    result = cybsp_init();

    /* Board initialization failed. Stop program execution. */
    if (CY_RSLT_SUCCESS != result)
    {
        handle_app_error();
    }

    /* Enable global interrupts */
    __enable_irq();

    /* Initialize retarget-io middleware */
    init_retarget_io();

    /* \x1b[2J\x1b[;H - ANSI ESC sequence for clear screen. */
    printf("\x1b[2J\x1b[;H");
    printf("***********************************************************\r\n");
    printf("            PSOC Edge MCU: Potentiometer ADC               \r\n");
    printf("***********************************************************\r\n\n");

    /* Initialize SAR ADC using helper function */
    result = init_adc();

    if (CY_RSLT_SUCCESS != result)
    {
        printf("ADC initialization failed!\r\n");
        handle_app_error();
    }

    /* Inform user about potentiometer connection */
    printf("ADC initialized successfully!\r\n");
    printf("Reading potentiometer on pin P15_1\r\n");
    printf("VREF = %d mV (12-bit resolution)\r\n\n", SAR_ADC_VREF_MV);

    /* CY_CM55_APP_BOOT_ADDR must be updated if CM55 memory layout is changed.*/
    Cy_SysEnableCM55(MXCM55, CY_CM55_APP_BOOT_ADDR, CM55_BOOT_WAIT_TIME_USEC);

    for(;;)
    {
        /* Read potentiometer voltage using helper function */
        voltage_mv = read_potentiometer_mv();

        /* Convert to percentage using helper function */
        percentage = get_pot_percentage(voltage_mv);

        /* Print ADC output in millivolts and percentage */
        printf("POT: %4d mV  |  %3d%%\r\n", voltage_mv, percentage);

        /* Toggle user LED to indicate activity */
        Cy_GPIO_Inv(CYBSP_USER_LED_PORT, CYBSP_USER_LED_PIN);

        /* Delay between ADC readings */
        Cy_SysLib_Delay(ADC_READ_INTERVAL_MS);
    }

}

/* [] END OF FILE */
```

***

#### ✍️ Exercise

1. **LED Brightness Indicator** : ใช้ POT ควบคุมความเร็วการกระพริบ (Blink Rate) ของ LED

* 0-25%: Blink Rate --> 1000 ms&#x20;
* 25-50%: Blink Rate --> 500 ms
* 50-75%: Blink Rate --> 250 ms
* 75-100%: Blink Rate --> 100 ms

{% hint style="info" %}
**Hint**

ตัวอย่าง

```c
uint8_t pot_pct = get_pot_percentage(); 
uint32_t blink_delay;

if (pot_pct < 25) { 
    blink_delay = 1000; /* Slow blink */ } 
else if (pot_pct < 50) {
.
.
. 
} else {
...
}
```

{% endhint %}

2. **Threshold Alert** : แจ้งเตือนเมื่อ POT เกิน threshold ที่กำหนด

{% hint style="info" %}
**Hint**

ตัวอย่าง

```c
#define THRESHOLD_PCT   (75U)
static bool alert_triggered = false;

for(;;)
{
    uint8_t pot_pct = get_pot_percentage();

    if (pot_pct >= THRESHOLD_PCT && !alert_triggered)
    {
        .
        .
        alert_triggered = true;
    }
    else if (pot_pct < THRESHOLD_PCT && alert_triggered)
    {
        .
        .
        alert_triggered = false;
    }

    Cy_SysLib_Delay(100);
}
```

{% endhint %}

***
