Lab 7
Lab 7
Lab. 7
External Interrupts and Timers
Objectives:
Program 1:
esp_rom_gpio_pad_select_gpio(INTERRUPT_PIN); gpio_set_direction(INTERRUPT_PIN,
GPIO_MODE_INPUT); gpio_set_intr_type(INTERRUPT_PIN, GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0); gpio_isr_handler_add(INTERRUPT_PIN,
GPIO_INT_ISR, NULL);for(;;);}
Task 1:
Make changes in Program 1 such that the two GPIOs (18 and 19) trigger two separate
interrupts. GPIO18 should trigger a falling-edge-sensitive interrupt whereas GPIO19 should
trigger a rising-edge-interrupt. Falling-edge interrupt should turn on the on-board LED for 200
ms whereas rising-edge interrupt should turn on the on-board LED for 500 ms.
Use a breadboard to implement the circuit. Show your work to the instructor and record your
observations in the box below.
Behavior:
• Pressing or toggling the signal at GPIO18 will trigger the ISR, turning the LED on for
200 ms.
• Pressing or toggling the signal at GPIO19 will trigger its ISR, turning the LED on for
500 ms.
Shared LED Resource:
• Both ISRs control the same LED. If interrupts occur simultaneously or in quick
succession, behavior may be unpredictable (e.g., timing overlap or LED flicker).
void
LEDC_Timer_Config(){ledc_timer_config_
t ledc_timer = { .speed_mode
LEDC_MODE, .timer_num = LEDC_TIMER,
.duty_resolution = LEDC_TIMER_10_BIT,
.freq_hz = LEDC_FREQUENCY,.clk_cfg = LEDC_AUTO_CLK };ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,.timer_sel = LEDC_TIMER, .intr_type = LEDC_INTR_DISABLE,
.gpio_num = LEDC_OUTPUT_IO,.duty = 512, // 50% duty cycle (1024 max for 10-bit
resolution) .hpoint = 0 }; ledc_channel_config(&ledc_channel); }
void Set_DutyCycle(unsigned char dc_percent)}
ledc_set_duty(LEDC_MODE,LEDC_CHANNEL, dc_percent*10.24);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL); }void
app_main(){
LEDC_Timer_Config();
unsigned char DC;
while(1){
for (DC = 0; DC <= 100; DC += 5) {Set_DutyCycle(DC);delay_ms(50);}}}
Task 1:
Make changes in Program 2 such that the GPIO23 is used as the PWM output. Set frequency
of PWM equal to 5 kHz. Use an external LED connected with GPIO18 to show the response
of PWM waveform. Use a breadboard to implement the circuit. Show your work to the
instructor and record your observations in the box below.
PWM Behavior:
• The PWM waveform on GPIO23 has a frequency of 5 kHz.
• The duty cycle changes gradually from 0% to 100% in 5% increments, repeating in a
loop.
External LED Response:
• When the PWM duty cycle exceeds 50%, the external LED on GPIO18 turns on.
Below 50%, it remains off. This demonstrates a binary threshold response to the duty
cycle.
PWM Visualization:
• The PWM signal can be verified on GPIO23 using an oscilloscope or logic analyzer,
where the pulse width will vary as the duty cycle changes.
LED Smoothness:
• A connected LED (on GPIO23 or GPIO18) visually dims and brightens smoothly as
the duty cycle changes, creating a "breathing" effect.
Lab Task 1:
Construct an embedded system using ESP32 that drives a DC motor. DC motor should run in
both directions and its speed is to be controlled through PWM. Use a GPIO18 as input to select
the direction of rotation of the motor. If GPIO18 is at logic 1, the motor should run clockwise,
and if GPIO18 is at logic 0, the motor should run counterclockwise. The ES must contain a
potentiometer that controls the dutycycle of PWM. Save your code and attach it to this Lab.
Use breadboard to construct the circuit.
Page 4 of 7
#include "freertos/FreeRTOS.h" };
#include "freertos/task.h" ledc_channel_config(&ledc_channel);
#include "driver/ledc.h" }void Set_DutyCycle(unsigned char
#include "driver/gpio.h" duty_cycle) {
#include "driver/adc.h" uint32_t duty = (duty_cycle * 1023) /
#include "esp_adc_cal.h"
100;
#define DIR_PIN GPIO_NUM_18
#define IN1_PIN GPIO_NUM_19 ledc_set_duty(LEDC_MODE,
#define IN2_PIN GPIO_NUM_21 LEDC_CHANNEL, duty);
#define PWM_PIN GPIO_NUM_23 ledc_update_duty(LEDC_MODE,
#define POT_PIN ADC1_CHANNEL_6 LEDC_CHANNEL);
#define LEDC_TIMER LEDC_TIMER_0 }
#define LEDC_MODE
LEDC_HIGH_SPEED_MODE void Motor_Config() {
#define LEDC_CHANNEL gpio_pad_select_gpio(DIR_PIN);
LEDC_CHANNEL_0 gpio_set_direction(DIR_PIN,
#define PWM_FREQUENCY 1000 GPIO_MODE_INPUT);
#define ADC_MAX_VALUE 4095
void ADC_Config() {
gpio_pad_select_gpio(IN1_PIN);
adc1_config_width(ADC_WIDTH_BIT_12);
gpio_set_direction(IN1_PIN,
adc1_config_channel_atten(POT_PIN,
GPIO_MODE_OUTPUT);
ADC_ATTEN_DB_11);
}unsigned char Get_DutyCycle() {
gpio_pad_select_gpio(IN2_PIN);
int adc_reading =
gpio_set_direction(IN2_PIN,
adc1_get_raw(POT_PIN);
GPIO_MODE_OUTPUT);
return (adc_reading * 100) /
}
ADC_MAX_VALUE;
}void PWM_Config() {
void Set_Direction(bool clockwise) {
ledc_timer_config_t ledc_timer = {
if (clockwise) {
.speed_mode = LEDC_MODE,
gpio_set_level(IN1_PIN, 1);
.timer_num = LEDC_TIMER,
gpio_set_level(IN2_PIN, 0);
.duty_resolution =
} else {
LEDC_TIMER_10_BIT,
gpio_set_level(IN1_PIN, 0);
.freq_hz = PWM_FREQUENCY,
gpio_set_level(IN2_PIN, 1);
.clk_cfg = LEDC_AUTO_CLK
}
};ledc_timer_config(&ledc_timer);
}
ledc_channel_config_t ledc_channel = {
void app_main() {
.speed_mode = LEDC_MODE,
ADC_Config();
.channel = LEDC_CHANNEL,
PWM_Config();
.timer_sel = LEDC_TIMER,
Motor_Config();
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = PWM_PIN,
while (1) {
.duty = 0,
bool clockwise =
.hpoint = 0
gpio_get_level(DIR_PIN);
Set_Direction(clockwise);
unsigned char duty_cycle =
Get_DutyCycle();
Set_DutyCycle(duty_cycle);
vTaskDelay(pdMS_TO_TICKS(100));
}
}
Page 5 of 7
Lab Task 2:
Construct an embedded system using ESP32 that drives a servo motor. Generate servo motor
control waveform using on-chip timer. Save your code and attach it to this Lab. Use
breadboard to construct the circuit.
#include "freertos/FreeRTOS.h" };
#include "freertos/task.h" ledc_channel_config(&ledc_channel);
#include "driver/ledc.h" } uint32_t Calculate_PulseWidth(uint8_t angle)
#define SERVO_PIN GPIO_NUM_23 { return SERVO_MIN_PULSEWIDTH +
#define LEDC_TIMER LEDC_TIMER_0 ((SERVO_MAX_PULSEWIDTH -
#define LEDC_MODE SERVO_MIN_PULSEWIDTH) * angle) /
LEDC_HIGH_SPEED_MODE SERVO_MAX_ANGLE;
#define LEDC_CHANNEL }
LEDC_CHANNEL_0 void Set_Servo_Angle(uint8_t angle) {
#define LEDC_FREQUENCY 50 uint32_t pulse_width =
#define SERVO_MIN_PULSEWIDTH 500 Calculate_PulseWidth(angle);
#define SERVO_MAX_PULSEWIDTH 2500 uint32_t duty = (pulse_width * 65536) /
#define SERVO_MAX_ANGLE 180 (1000000 / LEDC_FREQUENCY);
void LEDC_Timer_Config() { ledc_set_duty(LEDC_MODE,
ledc_timer_config_t ledc_timer = { LEDC_CHANNEL, duty);
.speed_mode = LEDC_MODE, ledc_update_duty(LEDC_MODE,
.timer_num = LEDC_TIMER, LEDC_CHANNEL);
.duty_resolution = LEDC_TIMER_16_BIT, }void app_main() {
.freq_hz = LEDC_FREQUENCY, LEDC_Timer_Config();
.clk_cfg = LEDC_AUTO_CLK LEDC_Channel_Config();
}; while (1) {
ledc_timer_config(&ledc_timer); for (uint8_t angle = 0; angle <= 180; angle
} += 10) {
void LEDC_Channel_Config() { Set_Servo_Angle(angle);
ledc_channel_config_t ledc_channel = { vTaskDelay(pdMS_TO_TICKS(500));
.speed_mode = LEDC_MODE, }
.channel = LEDC_CHANNEL, for (uint8_t angle = 180; angle >= 10; angle
.timer_sel = LEDC_TIMER, -= 10) {
.intr_type = LEDC_INTR_DISABLE, Set_Servo_Angle(angle);
.gpio_num = SERVO_PIN, vTaskDelay(pdMS_TO_TICKS(500));}
.duty = 0, }}
.hpoint = 0
Page 6 of 7
Page 7 of 7
Page 8 of 7
Page 9 of 7
Page 10 of
7
Page 11 of
7