.. note:: Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts. **Why Join?** - **Expert Support**: Solve post-sale issues and technical challenges with help from our community and team. - **Learn & Share**: Exchange tips and tutorials to enhance your skills. - **Exclusive Previews**: Get early access to new product announcements and sneak peeks. - **Special Discounts**: Enjoy exclusive discounts on our newest products. - **Festive Promotions and Giveaways**: Take part in giveaways and holiday promotions. πŸ‘‰ Ready to explore and create with us? Click [|link_sf_facebook|] and join today! .. _2.1.7_py_pi5_mcp3008: 2.1.7 Potentiometer(MCP3008) ============================= .. note:: .. image:: ../img/mcp3008_and_adc0834.jpg :width: 25% :align: left Depending on your kit version, please identify whether you have **ADC0834** or **MCP3008** and proceed with the matching section. Introduction ------------ The ADC function is used to convert analog signals into digital values. In this experiment, we use the MCP3008 ADC chip to perform this conversion. A potentiometer is used to generate a variable voltage, which changes the physical quantity. The MCP3008 then converts this analog voltage into a digital value that can be read and processed by the Raspberry Pi. Required Components ------------------------------ In this project, we need the following components. .. image:: ../python_pi5/img/list2_2.1.4_potentiometer.png It's definitely convenient to buy a whole kit, here's the link: .. list-table:: :widths: 20 20 20 :header-rows: 1 * - Name - ITEMS IN THIS KIT - LINK * - Raphael Kit - 337 - |link_Raphael_kit| You can also buy them separately from the links below. .. list-table:: :widths: 30 20 :header-rows: 1 * - COMPONENT INTRODUCTION - PURCHASE LINK * - :ref:`cpn_gpio_board` - |link_gpio_board_buy| * - :ref:`cpn_breadboard` - |link_breadboard_buy| * - :ref:`cpn_wires` - |link_wires_buy| * - :ref:`cpn_resistor` - |link_resistor_buy| * - :ref:`cpn_led` - |link_led_buy| * - :ref:`cpn_potentiometer` - |link_potentiometer_buy| * - :ref:`cpn_mcp3008` - \- Schematic Diagram ----------------- .. list-table:: :widths: 30 30 30 30 :header-rows: 1 * - T-Board Name - physical - WiringPi - BCM * - SPICE0 - pin24 - 10 - 8 * - SPIMOSI - pin19 - 12 - 10 * - SPIMISO - pin21 - 13 - 9 * - SPISCLK - pin23 - 14 - 11 * - GPIO22 - pin15 - 3 - 22 .. image:: ../python_pi5/img/schematic_2.1.7_potentiometer_mcp3008.png Experimental Procedures ----------------------- **Step 1:** Build the circuit. .. image:: ../python_pi5/img/july24_2.1.7_potentiometer_mcp3008.png .. note:: Please place the chip by referring to the corresponding position depicted in the picture. Note that the grooves on the chip should be on the left when it is placed. **Step 2:** Set up the SPI interface and install the ``spidev`` library (see :ref:`spi_configuration` for detailed instructions). If you have already completed these steps, you can skip this. **Step 3:** Open the code file .. raw:: html .. code-block:: cd ~/raphael-kit/python-pi5 **Step 4:** Run. .. raw:: html .. code-block:: sudo python3 2.1.7-2_Potentiometer_zero.py After the code runs, rotate the knob on the potentiometer, the intensity of LED will change accordingly. .. warning:: If there is an error prompt ``RuntimeError: Cannot determine SOC peripheral base address``, please refer to :ref:`faq_soc` **Code** .. note:: You can **Modify/Reset/Copy/Run/Stop** the code below. But before that, you need to go to source code path like ``raphael-kit/python-pi5``. After modifying the code, you can run it directly to see the effect. .. raw:: html .. code-block:: python #!/usr/bin/env python3 import spidev import time from gpiozero import PWMLED # Initialize PWM LED on GPIO22 led = PWMLED(22) # Initialize SPI spi = spidev.SpiDev() spi.open(0, 0) # Bus 0, CS0 (CE0) spi.max_speed_hz = 1000000 def read_adc(channel): """ Read analog value from MCP3008 :param channel: ADC channel (0-7) :return: 10-bit integer (0-1023) """ if channel < 0 or channel > 7: return -1 # MCP3008 protocol adc = spi.xfer2([1, (8 + channel) << 4, 0]) value = ((adc[1] & 3) << 8) | adc[2] return value def MAP(x, in_min, in_max, out_min, out_max): """ Map a value from one range to another """ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min try: while True: # Read from MCP3008 channel 0 res = read_adc(0) print('res = %d' % res) # Map 0–1023 to 0–100% R_val = MAP(res, 0, 1023, 0, 100) # Set LED brightness led.value = R_val / 100.0 time.sleep(0.2) except KeyboardInterrupt: led.value = 0 # Turn off the LED **Code Explanation** #. ``gpiozero`` for PWM LED control, ``spidev`` for SPI communication with MCP3008, and ``time`` for implementing delays. .. code-block:: python #!/usr/bin/env python3 import spidev import time from gpiozero import PWMLED #. Initialize a PWMLED object connected to GPIO pin 22 and configure SPI communication (Bus 0, CE0) with MCP3008. .. code-block:: python # Initialize PWM LED on GPIO22 led = PWMLED(22) # Initialize SPI spi = spidev.SpiDev() spi.open(0, 0) # Bus 0, CS0 (CE0) spi.max_speed_hz = 1000000 #. Define a function named ``read_adc`` to communicate with MCP3008 and read analog values from the specified channel (0–7). .. code-block:: python def read_adc(channel): """ Read analog value from MCP3008 :param channel: ADC channel (0-7) :return: 10-bit integer (0-1023) """ if channel < 0 or channel > 7: return -1 adc = spi.xfer2([1, (8 + channel) << 4, 0]) value = ((adc[1] & 3) << 8) | adc[2] return value #. Define a function named ``MAP`` to convert one range of values to another, useful for mapping ADC values to appropriate LED brightness levels. .. code-block:: python def MAP(x, in_min, in_max, out_min, out_max): return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min #. Continuously read the ADC value in a loop, mapping the 10-bit ADC value (0–1023) to a brightness level (0–100) for the LED. Adjust the LED’s brightness accordingly. Wait 0.2 seconds between each read. .. code-block:: python try: while True: # Read from MCP3008 channel 0 res = read_adc(0) print('res = %d' % res) # Map 0–1023 to 0–100% R_val = MAP(res, 0, 1023, 0, 100) # Set LED brightness led.value = R_val / 100.0 time.sleep(0.2) except KeyboardInterrupt: led.value = 0 # Turn off the LED