Microcontroller-UE Help

Assignment 1: GPIO & ADC

Prerequisites

  • Development & debugging environment (follow the setup guide)

  • Basic understanding of GPIO, ADCs and registers

Introduction

This assignment consists of three parts:

  1. controlling GPIO by reading/writing the registers

  2. using the ADC to read the motor rotation

  3. programming a vault utilizing the ADC and GPIO

GPIO control using system registers

For this sub-task, you are not allowed to use the Pico SDK. All GPIO functions have to be implemented by using the system registers, pointers for the base registers are provided in gpio.c

You will have to implement the following functions in gpio.c:

void set_gpio_function(int pin, int function)

Configures the pin to be used for the given function using IO_BANK0 (RP2040 datasheet, p. 244ff.) registers. Defines for the GPIO functions are provided in gpio.h. Ensure that a valid GPIO pin (0 - 29) and a valid function (0 - 31) is used.

void set_gpio_mode(int pin, int mode):

Sets the input/output mode of the given pin using the SIO (RP2040 datasheet, p. 43ff.) Defines for the GPIO modes are provided in gpio.h. Ensure that a valid pin (0 - 29) and a valid function (0 or 1) is used.
Furthermore, you need to set the input enable (IE) bit in the corresponding PADS_BANK0 (RP2040 datasheet, p. 300ff.) register.

void set_gpio_level(int pin, int level)

Sets the output level of the given pin using the SIO. Ensure that a valid pin is provided. Any non-zero value for level should result in the output being on, 0 should deactivate the output.

int get_gpio_level(int pin);

Returns the input level of the given pin using the SIO. Ensure that a valid pin is provided, otherwise return -1. The function should return 1 if the pin is high, 0 otherwise.

void set_gpio_pull(int pin, int pull);

Sets the internal pull up/down registers of the given pin using the PADS_BANK0 (RP2040 datasheet, p. 300ff.) registers. Ensure that a valid pin is provided. Defines for the pull up/down values are provided in gpio.h.

Using the Analog-Digital-converter (ADC)

Use of the functions provided in the Pico SDK for configuring and reading the ADC.

You will have to implement the following functions in adc.c:

void init_adc()

Initialize the ADC and configure the ENCODER_PIN for ADC usage.

int get_adc_value(const int channel)

Reads the raw ADC value of the given channel. Ensure that a valid channel (0 - 3) is provided, otherwise return -1.

int translate_adc_value(const int raw_value, const int zero_value)

Translates the raw 12-bit value to eight sectors (0 - 7). The center of sector 0 should be at zero_value, sector 1 should be clockwise from sector 0. Return te sector number.

Your task

Complete all the functions in gpio.c and adc.c. Remember, you are not allowed to use the Pico SDK for GPIO, but it should be used for the ADC.

Furthermore, create a vault as described below in vault.c by using your functions in gpio.c and adc.c. The corresponding header files are already included. Make sure that your vault_logic function will never return.

The vault should be implemented using a finite state machine (FSM) which has the following states:

Vault openVault is openLED is activeSet pinUser enters digits with motorEach digit is confirmed by button pressLED is active (except flashing)LED disables for 100 ms after each digitVault lockedVault is lockedLED is offEnter pinUser enters 4 digits with motorEach digit is confirmed by button pressLED flashes for 100 ms after each digitWrong pinwait 100 msLED flashes 3 times 100 ms on, then 100 ms offSwitch 1 is deactivatedSwitch 1 activated4 digits enteredSwitch 1 is activatedSwitch 1 deactivatedWrong pin enteredCorrect pin entered

The rotation of the motor should be read from the analog output of the encoder. The encoder output is connected to GPIO 28 (ADC channel 2). Defines for the encoder pin (ENCODER_PIN) and encoder ADC channel (ENCODER_CHANNEL) are provided in adc.h.

The ADC inside the RP2040 has a 12-bit resolution, therefore the value is between 0 and 4095. You will need to translate this to 8 sectors for the digits 0 - 7 using translate_adc_value. The arrow on the motor should point towards the side with the power switch at th zero position. You have to set ZERO_OFFSET in vault.h so that the testsystem knows where your zero position is.

The button shall be read using the get_button function declared in button.h. The button is the bootselect-button of the Raspberry PI Pico, which disables the flash when pressed. Therefore, some extra code is needed to ensure that the program does not crash when reading the button. Yo do not have to explain the extra code in button.c for the exercise interviews

Deliverables

  • gpio.c and gpio.h (optional) with implemented GPIO functions (no Pico SDK allowed)

  • adc.c and adc.h (optional) with implemented ADC functions (PicoSDK should be used)

  • vault.c and vault.h (required) with your vault implementation

  • ... do not forget to tag the final commit with SUBMISSION-A1 and push the tag

Interview questions

  • What does SIO stand for and why should the atomic set/clear registers be used ?

  • What other alternate functions can a pin have? Name at least 3 examples and describe one briefly.

  • What type of ADC is inside the RP2040 and which resolution does it have?

  • How many channels can the ADC read simultaneously and what mechanism is used to switch between channels?

  • What has to be considered when using raw ADC values?

  • How can we determine the current rotation of the motor? Describe the connection between rotor position and value in the program.

  • What circuit is necessary for reading the switch value. How could it be implemented externally?

  • Why is it necessary to debounce ("entprellen") buttons and switches?

Last modified: 23 December 2024