EE lab track, module 9

Microcontroller digital I/O

Graded Arduino digital I/O labs that run your own sketch: blink at a set period and duty, read and debounce a button, set a PWM duty, time a loop in assembly.

On the syllabus

  • Digital output, pinMode and timing with delay()
  • Digital input, floating pins and the internal pull-up
  • Switch bounce and debouncing in software
  • PWM output with analogWrite: frequency and duty cycle
  • Instruction cycles, and a delay loop written in AVR assembly

You will be able to

  • Drive an output at a set period and duty cycle.
  • Read a switch reliably with INPUT_PULLUP, and explain why a floating input fails.
  • Count presses of a bouncing switch correctly.
  • Set a PWM duty cycle and measure it on a scope.
  • Design a delay from instruction cycles and the clock frequency.

The first challenge is free. The rest, the viva and the certificate are part of Pro, and everything is here to read.

Graded challenges

Values like 4.7k, 100n or 2.2u are fine. Readings are the number only, in the unit shown. Every check measures the simulation, not a bench: ideal parts within their models, no noise.

1. Blink at 2 Hz with a 25% duty cycle

A blink loop is a square wave you write by hand. The time the pin is high plus the time it is low is the period. The share of the period it is high is the duty cycle.

FormulaPeriod = t on + t off, duty = t on / period

Worked exampleFor 4 Hz at 50%: the period is 1 / 4 = 250 ms, so 125 ms on and 125 ms off. For 1 Hz at 10%: 100 ms on and 900 ms off.

On the scope or meterThe LED flashes. On the scope pin 13 is a square wave with the period and duty you chose.

Your task

The starter sketch blinks the LED on pin 13 once a second, half on and half off.

Change it so the LED flashes twice a second, on for a quarter of each cycle: a 500 ms period at 25% duty.

Build and run it in the simulator, then paste your sketch here and check it.

    Write it here, or paste it from the editor. It is built in your browser with the editor’s compiler, then run in the lab’s own circuit.

    It is checked for

    • Pin 13 makes one cycle every 500 ms
    • Pin 13 is high 25% of each cycle

    2. Read a button with INPUT_PULLUP

    An input pin joined to nothing floats: it reads whatever noise it picks up. A pull-up resistor holds it at 5 V until a button pulls it to ground. The Uno has one built in, about 35 kΩ, that you switch on with the INPUT_PULLUP mode.

    FormulaReleased: pin = HIGH. Pressed: pin = LOW (active low)

    Worked exampleWith a 10 kΩ external pull-up on 5 V, a pressed button to ground takes 0.5 mA and the pin reads LOW. Released, the pin reads HIGH through the resistor.

    On the scope or meterThe LED stays off until the press at 0.5 s, lights while held, and goes off after the release at 0.9 s.

    Your task

    A push button joins pin 2 to GND. There is no resistor in the circuit. The LED on pin 13 should light while the button is held.

    The starter sets pin 2 as a plain INPUT and looks for HIGH. With the button up the pin is joined to nothing, so it floats.

    Fix the sketch. The check presses the button from 0.5 s to 0.9 s.

      Part of Pro. Read it all here. The trial has no card, and module 1 and the first challenge of every module stay free.

      Write it here, or paste it from the editor. It is built in your browser with the editor’s compiler, then run in the lab’s own circuit.

      It is checked for

      • The LED is off before the press
      • The LED is on while the button is held
      • The LED is off again after the release

      3. Count presses of a bouncing switch

      Switch contacts bounce for a few milliseconds when they close or open. Each bounce is an edge, so one press can look like five. Debouncing means only believing a new state once it has held still longer than the bounce.

      FormulaAccept a change only after it is stable for t > bounce time (about 10 to 20 ms)

      Worked exampleIf the contacts chatter for 5 ms, waiting until the pin has held one level for 10 ms is enough. A button that reads LOW at 0, 1, 3 and 4 ms and HIGH between them counts once, not three times.

      On the scope or meterThe serial monitor prints count= after each counted press. Without debouncing the numbers jump by more than one a press.

      Your task

      A real switch bounces: for a few milliseconds after it closes or opens, its contacts make and break many times. This button bounces the way a typical one does.

      The starter counts every falling edge and prints count= after each. The check presses the button three times; fix the sketch so the last line printed is count=3.

        Part of Pro. Read it all here. The trial has no card, and module 1 and the first challenge of every module stay free.

        Write it here, or paste it from the editor. It is built in your browser with the editor’s compiler, then run in the lab’s own circuit.

        It is checked for

        • The last count printed is 3

        4. Set a PWM duty cycle

        analogWrite does not make a voltage. It makes PWM: the pin switches between 0 V and 5 V at a fixed rate, about 490 Hz on pin 9, and the value sets how long it stays high in each cycle.

        FormulaDuty = value / 255

        Worked exampleanalogWrite(9, 191) gives 191 / 255 = 75% duty. analogWrite(9, 26) gives about 10%.

        On the scope or meterA square wave at about 2 ms per cycle on the scope. The LED looks dimmer as the duty falls.

        Your task

        analogWrite(pin, value) on an Uno makes PWM: a square wave at about 490 Hz on pin 9, high for value/255 of each cycle.

        Change the starter so pin 9 is high for 25% of each cycle, within 2 percentage points.

          Part of Pro. Read it all here. The trial has no card, and module 1 and the first challenge of every module stay free.

          Write it here, or paste it from the editor. It is built in your browser with the editor’s compiler, then run in the lab’s own circuit.

          It is checked for

          • Pin 9 is high 25% of each cycle
          • Pin 9 runs at about 490 Hz

          5. AVR assembly: count the cycles

          Every AVR instruction costs a fixed number of clock cycles, printed in the data sheet. So a delay written in assembly is not a guess: you count the cycles one turn of the loop spends, and divide the time you want by it. The Uno runs at 16 MHz, so one cycle is 62.5 ns.

          FormulaCycles = time × clock, turns = cycles / cycles per turn

          Worked exampleFor 100 ms at 16 MHz: 0.1 × 16,000,000 = 1,600,000 cycles. At 4 cycles a turn that is 400,000 turns, which does not fit in a 16-bit counter, so it is split into an outer and an inner loop.

          On the scope or meterOn the scope pin 13 is a square wave. Too few cycles and the period is milliseconds instead of half a second.

          Your task

          There is no delay() in this sketch. The delay is a counted loop written in AVR assembly, inside the C function with asm volatile, and the only thing that decides how long it lasts is how many clock cycles it spends.

          One turn of the loop is 4 cycles: SBIW takes 2 and a taken BRNE takes 2. The starter runs 25,000 turns, which is 100,000 cycles, or 6.25 ms at 16 MHz, so the LED flickers instead of blinking.

          Work out how many cycles 250 ms is, then wrap the loop so the delay spends that many. The check measures the blink on pin 13 and wants one whole cycle every 500 ms, within 2 percent.

            Part of Pro. Read it all here. The trial has no card, and module 1 and the first challenge of every module stay free.

            Write it here, or paste it from the editor. It is built in your browser with the editor’s compiler, then run in the lab’s own circuit.

            It is checked for

            • Pin 13 makes one cycle every 500 ms
            • Pin 13 is high half of each cycle

            Viva questions

            The questions an examiner asks at the bench. 75% passes; every answer comes with why.

            Part of Pro. Read it all here. The trial has no card, and module 1 and the first challenge of every module stay free.

            1. What does a digital input read when nothing is connected to it?

            2. With INPUT_PULLUP and a button to ground, what does digitalRead return while the button is pressed?

            3. Roughly how much current should one Uno I/O pin supply?

            4. What is switch bounce?

            5. Name two ways to debounce a switch.

            6. What value of analogWrite gives 50% duty on an Uno?

            7. Why is delay() a problem in a sketch that must also watch a button?

            8. Is analogWrite a true analog output on an Uno?