Pulses and triggers

Digital pin outputs are often used as control outputs. This is when an output signal will set a condition at the receiving device input. A control signal says the some condition should happen for a period of time or it triggers an action on the receiving device.

Pulsed output

An ouput pulse causes the pin to change to a new ouput level, stay at that level for some time, and then switch to the level it was before. These level changes can be occasional in order to set condition at the input of another device. Also, pulses can happen over and over again with the same duration in output level. These repeating, identical pulses create a signal to set timing which is called a clock signal.

On and off pulse

A output is pulsed when it changes to another level for a period of time and then goes back to its original level. This can be either low-high-low or high-low-high.

Single output pulse

This example writes a 20 millisecond pulse out on pin A1.

pins.A1.digitalWrite(false)
input.buttonA.onEvent(ButtonEvent.Click, function () {
    pins.A1.digitalWrite(true)
    pause(20)
    pins.A1.digitalWrite(false)
})

Clock signal

Clock signals were discussed earlier in the digital input section. Clock singals are regular pulses that alternate between high and low.

Clock signal pulses

A clock signal is output at a pin by writing a high level for half of the clock period and then writing a low level for the other half of the clock period. The following code will generate a clock signal on pin A1 with a period of 10 milliseconds. The high and low pulses have a width of 5 milliseconds each.

forever(function () {
    pins.A1.digitalWrite(true)
    pause(5)
    pins.A1.digitalWrite(false)
    pause(5)
})

Experiment: Simulate a clock signal


Two ||loops:forever|| loops simulate the actions of two pins. One loop simulates switching the pin output level from 0 to 3.3 every second. The other loop reads the current pin level every 100 milliseconds to simulate a pin read, and then logs the value.

Setup: Copy the following code into the editor.

let pinValue = 0
forever(function () {
    console.logValue("clock", pinValue)
    pause(100)
})
forever(function () {
    if (pinValue > 0) {
        pinValue = 0
    } else {
        pinValue = 3.3
    }
    pause(1000)
})

Test: Run the code and switch to the data view to see the console output in the chart.

Clock signal simulation

Result: The graph in the chart shows the clock value switching from 0 to 3.3 and back again at a regular interval.


A clock signal can establish a time base for a digital system. If the frequency of the time base signal is fast, then longer durations for other intervals are calculated by adding some amount of clock ticks. This example adds 100 ticks of the the clock signal an then resets the tick count. It makes an interval of 2 seconds by counting the fall of the clock signal every 20 milliseconds.

let clockCount = 0
pins.A6.onEvent(PinEvent.Fall, function () {
    if (clockCount < 100) {
        clockCount += 1
    } else {
        clockCount = 0
    }
    light.graph(clockCount, 100)
})
forever(function () {
    pins.A1.digitalWrite(true)
    pause(10)
    pins.A1.digitalWrite(false)
    pause(10)
})

Experiment: Frequency divider


A second clock signal with half the freqency can be made from the first one. By waiting for the rise of the original clock signal, a second one is generated by alternating the outpul level in a ||pins:on pin rise|| event.

Setup:

  1. Connect on end of an alligator clip lead to the A1 pin.
  2. Connect the other end of that lead to the A6 pin.
  3. Get another alligator clip lead and connect one end to the A2 pin.
  4. Connect the other end of the second lead to the A5 pin.

Frequency divider connection

  1. Copy the following code into the editor.
let clock2 = false
pins.A6.onEvent(PinEvent.Rise, function () {
    clock2 = !(clock2)
    pins.A2.digitalWrite(clock2)
})
forever(function () {
    pins.A1.digitalWrite(true)
    light.setPixelColor(0, 0xff0000)
    pause(1000)
    pins.A1.digitalWrite(false)
    light.setPixelColor(0, 0x000000)
    pause(1000)
})
forever(function () {
    if (pins.A5.digitalRead()) {
        light.setPixelColor(0, 0x00ff00)
    } else {
        light.setPixelColor(0, 0x000000)
    }
})

Test: Watch how often the red and green LEDs blink.

Result: The green LED should blink at half of the rate that red LED blinks at.


Pulse width

As mentioned in the pin events section, the pulse width is the time between when a pin input detects a change in logic level and when it changes back to the previous level again. Of course, when writing out a pulse, the pulse width is set by the delay between writing one logic level and then writing the other. In the following example, a 20 millisecond pulse is written at pin A3 after a setting the output to low for 1 second.

20 millisecond pulse high

pins.A3.digitalWrite(false)
pause(1000)
pins.A3.digitalWrite(true)
pause(20)
pins.A3.digitalWrite(false)

There are blocks that let you know how long a pulse lasted. These are the pulse duration blocks. In this next example, we are using button A to generate a pulse. If the pulse is longer than half of a second, we count it as a long pulse. Otherwise, the pulse is counted as a short one. The ||pins:pulse duration|| block is used to get the width of the last pulse in microseconds.

let shortPulses = 0
let longPulses = 0
pins.A2.onEvent(PinEvent.PulseHigh, function () {
    if (pins.pulseDuration() > 500000) {
        longPulses += 1
    } else {
        shortPulses += 1
    }
})
input.buttonA.onEvent(ButtonEvent.Down, function () {
    pins.A1.digitalWrite(true)
})
input.buttonA.onEvent(ButtonEvent.Up, function () {
    pins.A1.digitalWrite(false)
})
pins.A1.digitalWrite(false)

To capture a pulse without using a pin event block like ||pins:on pin pulse||, you can chose to wait for a pulse on a pin with the ||pins:pulse in|| block. When your program comes to a ||pins:pulse in||, it will wait until a pulse with the duration (width) you asked for occurs before it continues on.

let pulseWidth = pins.A5.pulseIn(PulseValue.High)

Triggers

Often changes in pin output are used to tell a device connected to that pin to take some action. This type of output signal is a trigger.

One-shot trigger

A trigger signal written on an output pin can occur as either a pulse of simply as a level change. This depends on how the device connected to it wants the notification. A single change in output level to send a trigger is sometimes called a one-shot event. A one-shot trigger could be just a short duration pulse. The connected device is usually waiting for an input level rise or fall before it takes an action.

One shot pulse signal

Another one-shot trigger is just a level change that remains at the new level. This is used when just one trigger is needed for a long period of time.

One shot level signal

Pulse train

Sometimes a device is triggered to do something on a regular basis. You could send it a clock type signal but using equal high and low pulses aren’t needed to accomplish this. Instead, a sequence of short pulses that happen at regular intervals is used. This is called a pulse train. This lets the device connected to your output pin detect the a level change at the front of the interval but only a very short pulse is used.

Pulse train triggers

Experiment: Pulse train


  1. Connect an alligator clip lead to the A1 pin.
  2. Connect the other end of the lead to the A6 pin.
  3. Download the following code to the board:
forever(function () {
    pins.A1.digitalWrite(true)
    pins.A1.digitalWrite(false)
    pause(500)
})
let pixelNum = 0

pins.A6.onEvent(PinEvent.Rise, function () {
    light.clear()
    if (pixelNum > 9) {
        pixelNum = 0
    } else {
        pixelNum += 1
    }
    light.setPixelColor(pixelNum, 0xff0000)
})

Test: Watch which pixel lights up as pulses are sent to pin A6.

Result: Each pixel on the board lights in sequences as pin A6 is triggered by the pulse train.