HIDE NAV

Lab 1 - Multi-Blink

Practice three ways to generate square waves



Summary

Create a classic 'hello world' LED blinker, then change it to run using PWM & Alarms.
Demonstrate control multiple LEDs blinking at different rates.

1. Basic wiring & wiring verification
  - create a pico project: blink-cpu-timed
  - wire 2-4 exteral leds
  - ensure all gpios output independant signals using gpio_put()

2.  PWM Muli-Blink
  -create a pico project: blink-pwm-timed
  - use same wiring
  - setup all gpio pins (including 25/built-in) as PWM
  - alternate - use a dimmer

3.  Alarm Multi-Blink
  - create a pico project: blink-alarm-timed
  - use same wiring
  - setup all gpio pins (including 25/built-in) as gpio
  - setup an one or more alarms to toggle the pins at different rates



Required Equipment and Supplies

- Rasperry Pi Pico with Headers - pinout diagram

- LED - indicator [x2-4]

- 820Ω Resistor [x2-4]

- USB Micro Cable

- Breadboard

- Cables and 22ga wire as needed



Wiring

- Only begin adding external LEDs after your basic blink and alarm blink are working.

- LEDs consume very little power, you may power everything from the USB cable.

- Use VBus or Vsys to supply your breadboard power rail from the Pi Pico.

- Connect each LED to separate GPIO pin and in series with a current limiting resistor connected to ground like the example below.

Part 1 - CPU Timed Blink


main.c


#include "pico/stdlib.h"
#define LED_ONB 25

int main() {
// setup and  initialize
gpio_init(LED_ONB);
gpio_set_dir(25, GPIO_OUT);

// primary loop
	while (true) {
		gpio_put(LED_ONB, 1);
		sleep_ms(500);
		gpio_put(LED_ONB, 0);
		sleep_ms(500);
	}
}

Part 2 - PWM Timed Blink



PWM Period Timing Formula


PWM Duty Cycle Formula


PWM Pulse Width Timing Formula

main.c


#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include "math.h"

#define LED_EXT_1 18

void led_blinking_pwm_setup(uint gp_pin_no, float blinks_per_second, float duty);

void main(){

  led_blinking_pwm_setup(LED_EXT_1, 15, 0.65);


  while(true) {
    //primary loop - runs until reboot
    sleep_ms(10);
  }
}


void led_blinking_pwm_setup(uint gp_pin_no, float blinks_per_second, float duty){
  //turn the requested pin on PWM mode
  gpio_set_function(gp_pin_no, GPIO_FUNC_PWM);
  //look up the slice for our pin
  uint slice_num = pwm_gpio_to_slice_num(gp_pin_no);
  // k = clock div * (wrap + 1)

  double k = 125000000.0 / blinks_per_second;

  uint16_t wrap_counts;
  if(k > 65534) wrap_counts = 65534;
  else wrap_counts = k;

  double clock_div = k / (wrap_counts + 1);


  pwm_set_clkdiv_int_frac(slice_num, clock_div, 0);
  pwm_set_wrap(slice_num, wrap_counts);
  uint16_t level = (wrap_counts + 1) * duty;

  pwm_set_gpio_level(gp_pin_no, level); //set duty

  pwm_set_enabled(slice_num, true);
}

Part 3 - Alarm Timed Blink



main.c


#include "pico/stdlib.h"
#include "led-alarm-blinker.h"

#define LED_ONB 25
#define LED_EXT1 18
led_alarm_blinker_t led_onb_blinker, led_ext1_blinker;

void main(){
  setup_led_blinker(&led_onb_blinker, LED_ONB, 10000, 500000);
  setup_led_blinker(&led_ext1_blinker, LED_EXT1, 10000, 311000);

  while(1){
    sleep_ms(10);
  }
}


led-alarm-blinker.h


//.h HEADER
//led-alarm-blinker.h
#include "pico/stdlib.h"

typedef struct led_alarm_blinker_t {
  uint gp_pin;
  int64_t on_us, off_us;
  bool state;
} led_alarm_blinker_t;

void setup_led_blinker(led_alarm_blinker_t *led_blinker, int pin_no,
   int64_t on_delay_us, int64_t off_delay_us);

int64_t led_blinker_alarm_callback(alarm_id_t id, void *user_data);

led-alarm-blinker.c


//.c SOURCE
//led-alarm-blinker.c
#include "led-alarm-blinker.h"

void setup_led_blinker(led_alarm_blinker_t *led_blinker, int pin_no,
   int64_t on_delay_us, int64_t off_delay_us){

     led_blinker->gp_pin = pin_no;
     led_blinker->on_us = on_delay_us;
     led_blinker->off_us = off_delay_us;
     led_blinker->state = false; //assume the light is off at first
      //pin setup
     gpio_init(led_blinker->gp_pin);
     gpio_set_dir(led_blinker->gp_pin, GPIO_OUT);
     gpio_put(led_blinker->gp_pin, led_blinker->state);
      //alarm setup
     add_alarm_in_us(led_blinker->on_us, led_blinker_alarm_callback,
      led_blinker, true);

   }

 int64_t led_blinker_alarm_callback(alarm_id_t id, void *user_data){
    //cast userdata as an led_blinker struct pointer
    led_alarm_blinker_t *led_blinker = (led_alarm_blinker_t *)user_data;
    //toggle the state
    led_blinker->state = !(led_blinker->state);
    //set the gpio state
    gpio_put(led_blinker->gp_pin, led_blinker->state);
    //return the timing data
    if(led_blinker->state == true) {
      return -1*led_blinker->on_us;
    } else {
      return -1*led_blinker->off_us;
    }
 }