Pulsewidth Management With Arduino

The triggerBounce circuit and its waveforms, showing how it confines the output pulse, on a falling edge, to a few milliseconds without retriggering until the next falling edge.The triggerBounce circuit and its waveforms, showing how it confines the output pulse, on a falling edge, to a few milliseconds without retriggering until the next falling edge.

Triggers for electronic music systems, hey. Unless you're really quick, you can't just push a button, the trigger will stay on until you release it, not passing on a release until said key is released. In a piano or synth keyboard, this is fine, this allows for note dynamics like play/mute for key-pressed/key-released. Drum triggers, though, they have to be short. They are if the sensor is low-pass filtered piezo disk, but what if it's an electro-mechanical, like an "on-off-(a-little-later-on)", falling edge trigger, like a laser beam on a kick drum pedal? No release until the drummer lifts their foot, which doesn't happen very often, even with a really technical drummer (damped kick notes) or at all if the drummer's a chancer on sticks, like me or my guitarist mate.

My guitarist mate and me need an optical kick drum trigger for a top secret, Eurorack gadget we're working on. I'd forgotten bad drumming (and super good) drumming, and sent the prototype off to him with a basic on-off trigger that uses an infrared door sensor laser to create a falling edge trigger for the Behringer 902 ADSR in the rack. He's not great at even repairing cables, by his own admission, let alone full blown electronics. And the trigger's kick=off, release=on - "falling edge." Bugger. Sound doesn't stop until he takes his foot off the gas. It needs to only make attack/decay noises as it hits, then sustain and release a few milliseconds later, to a maximum of 200ms at 120BPM. What to do? It needs a "retrigger" AKA "bouncer". "Drop the ball" and the ball bounces back to high and is caught. Not so easy, though.

You could do it with an analogue, high-pass, comparator-cum-schmidt-trigger, but the timing has to be pretty tight. Within the octave, tight. 60, through 120, to 240 beats per minute is too wide. The sensitivity is a bit tricky to tune, too, as there's potentially not enough dynamic range to easily create a predictable trigger. It's also a high component count, and this project has already run to a few hundred dollars in parts.

So, I opted for an Arduino Nano. It'll fit in a small form factor diecast box, has inbuilt capability of running off 12v and barely needs anymore parts than the board itself. Argh, the coding, though! That broke my brain. I've been playing with edge-triggered libraries for a while now. They're usually used with noticeable blocking delays for switch debouncing. They break my brain, these beasts. I've attempted to write my own library to do this for internal "signals" carried by variables in the code. Its been vexing. So I returned to beginner basics for this device, and wrote the code, completely in-line, from scratch. Edge triggered? Check. Not retriggerable until released? Check? Maximum width of output pulse? Checkeroonies! It took some figuring out. I'm as good a coder as my guitarist mate is at soldering - I can "barely fix cables," as it were. But this works, and I learned! I learned stuff. Heaps.

Here's the code...

/*
    ARDUINO TRIGGER BOUNCE by CRUNCHYSTEVE, shinyhappyrainbows.com
    ©2023 Crunchysteve filthynoisesmusic@gmail.com
    Takes a falling edge trigger input and creates a fixed width pulse that 
    can't be retriggered until after the output pulse the next falling edge.
    The pulsewidth is set by the "period" variable, input is on digital pin 2 
    and output is on digital pin 13. It needs no external libraries although, 
    if you make the mods suggested below, you could use  to control a 
    digital potentiometer to set the pulsewidth and Bounce2.h to debounce 
    the switches.

    - Licence: Australian law requires me to retain my Moral Rights, 
               as asserted by the copyright notice above, so...
    This code is on a modified MIT licence, the modification is that it's free 
    to use on an individual by individual basis but, if you are using it in a mass 
    production context, please contact me, at the address above, to negotiate a 
    commercial licence. You'll find I'm quite reasonable and not greedy, but the 
    free licence will remain for hobbyists & makers and is separate from any 
    commercial agreement, and this part cannot be negotiated away. (More details 
    on my github in the Licence file. https://github.com/crunchysteve/TriggerBounce
*/
const int INPUT_PIN    =    2;          //  Set trigger input pin to D2
const int OUTPUT_PIN   =   13;          //  Set LED output pin    to D13

bool      state        = LOW;           //  input trigger state rest state is opposite
bool      test         = false;         //  Variable to store last input state

uint32_t  rightNow     =   0;           //  Set pulse width timer comparison variable
uint32_t  backThen     =   0;           //  Set pulse width timer start variable
uint32_t  period       =  26;           //  Length of output pulse width in milliseconds
                                        //  (Can be longer: 26ms is 16ths at 285BPM)
void setup(){
  pinMode(INPUT_PIN, INPUT_PULLUP);     //  set trigger input MODE as INPUT_PULLUP
  pinMode(OUTPUT_PIN, OUTPUT);          //  output setup as OUTPUT
      //  potential to add switches or buttons the set the input and/or the output
      //  active states, then modify the branching at "if(input != test)"
}

void loop(){
  bool input = !digitalRead(INPUT_PIN); //  State of INPUT_PIN.
  if(input != test){                    //  Detect edges.
    if(input == HIGH &&                 //  Detect if inverted falling edge and,
       state == LOW){                   //  if LED state is not invert-triggered, then
      state = HIGH;                     //  invert trigger LED state and
      backThen = millis();              //  initialise pulse timer start time.
    }
    test = input;                       //  Store this input edge state.
  }
  rightNow = millis();                  //  Measure time "now."
  if(              state == HIGH &&     //  If LED is invert-LOW and
     rightNow - backThen >= period){    //  if pulse timer has elapsed by period then
    state = LOW;                        //  set LED to invert-off.
  }
  digitalWrite(OUTPUT_PIN,!state);      //  Write LED invert-state to OUTPUT_PIN
        //  It's also possible to add an analogRead routine here, to use a 
        //  potentiometer to set the pulse width in mS. I would recommend using
        //  appropriate prescaler bit sets in the setup() routine to speed up
        //  analogRead, as per https://www.gammon.com.au/adc
}

This, like the parent project it's for, is a prototype, but I've given myself a tight deadline. I'm hoping to build a practical unit, to drop in instead of the current breakout box that's next to the kick pedal. It works in simulation (^image, up-top), that's the important thing at this stage. If you need something like this, and have the Arduino and soldering skills, here's my github for the trigger.

For the supporting circuitry bits, output is straight off digital pin 13, the resistors and LED are because there's no "LED_BUILTIN" macro in my simulator, so I needed an output. If you want an external LED, just leave off the 1K resistor, as it's only for the 'scope trace. Meanwhile, the resistor and 5.6v Zener diode are to regulate the logic voltage, as the optical senser puts out a 12v signal when waiting to be triggered. You could use straight 5v if your system is different, mine will have 12v into the VIN pin of the Nano board, for internal regulation. Eurorack gear will generally consider ground as trigger and take anything over 3 or 4 volts, through to 10v(max) as untriggered. Many are switchable, some are more conventional.

So, to wrap up, the microcontroller takes a falling edge (5v to 0v) trigger input, puts out a 26mS long pulse, then cannot be retriggered until the input returns to 5v and falls again. Enjoy! You're welcome!!!

Comments

Popular posts from this blog

Removing Ollama From My Mac

Open Source Is Essentially Socialist

ALWAYS read the PDS