Continuing from last time...I am focusing on another corner of the Arduino for audio world: interrupts. The idea; your code is running, we want to interrupt things (say, a note has just been pressed) and have something happen (say, play a note). When you are done, go back to whatever you were doing (like, wait for another note).
With further ado: the coding examples here were tested on an ATTINY85. All the interrupt information you see is available for most if not all Arduinos but the code will be different (because, for instance, a Nano has more than 8 pins).
Goes like this: When I started using Arduinos for Synth DIY, it quickly became clear I needed to figure out a good way to accept a gate input signal and control my code with it. Duh! We synth guys use 0-5V gates all over right? But let's not create a loop like this: did someone press a key yet? No? How about Now? No! Um, Now? No!!!! Now? Yes!!!! Etc. all that waiting around ends up sounding, well, not very musical.
Instead, you want to press a key, and then as close to real time as possible, you want something to happen.
So: what's a really good way to do this? Use interrupts....specifically change pin interrupts--then using a boolean variable to trap if the gate signal was going from 0 to 5V or from 5V to 0. That worked great for me.
Turns out it's not hard to stick all of this into your ATTINY85 sketch, once you know the secret:
First declare this:
void setup()
{
// (pin declarations, variables, whatever blah blah....
//but then this...
GIMSK = 0b00100000; // turn on pin change interrupts
PCMSK = 0b00010000; // turn on interrupt on ATTINY pin PB4
/* you can enable more than one pin for this.....
a "1" in the above PCMSK line means use pins as interrupts, following this logic: 0bxx54321 where
the "54321" business are physical pins on an ATTINY.
*/
sei(); // enables interrupts
Wait a minute, what are "pin change interrupts"? Information is here but: Easy!
That means, you're using external hardware interrupts--change the voltage present at this pin, relative to ground, and you can immediately change what your Arduino is doing.
Added bonus: with "pin change interrupts" you can pick the pins you want to use for interrupts. Including more than one or two or three pins on the same chip at the same time. And, depending on the Arduino you use, the pins allow you create up to 3 completely independent interrupts, each of which can do something different! Handy!
BTW, an incredibly good explanation of the the Arduino interrupt universe--from the Atmel ATTINY to the big huge crapping ones--is here.
(The "change pin" moniker threw me for a bit. Shouldn't it be a "pickyerown" interrupt? Whatever.)
Added bonus: with "pin change interrupts" you can pick the pins you want to use for interrupts. Including more than one or two or three pins on the same chip at the same time. And, depending on the Arduino you use, the pins allow you create up to 3 completely independent interrupts, each of which can do something different! Handy!
BTW, an incredibly good explanation of the the Arduino interrupt universe--from the Atmel ATTINY to the big huge crapping ones--is here.
(The "change pin" moniker threw me for a bit. Shouldn't it be a "pickyerown" interrupt? Whatever.)
OK after your GIMSK PCMSK etc. you have declare an "interrupt vector"--this tells the ATTINY what to do when the interrupt is thrown.
Here I am reading whatever voltage is present at PB4 pin and assigning it to "gatemaker", a boolean variable I do declare.
Here I am reading whatever voltage is present at PB4 pin and assigning it to "gatemaker", a boolean variable I do declare.
void setup()
volatile boolean gatemaker = LOW;
// blah blah, other stuff here....
ISR(PCINT0_vect)
{
gatemaker = digitalRead(PB4);
}
This code can thus act on incoming data--a gate rising edge, a new midi note on, etc., fast--very, very fast. More musical!
So--do that like this and this like that:
void loop()
if (gatemaker == LOW)
// I see a falling edge, 5V to 0V, on my gate signal. When I see that:
{
///do something; charge a cap, turn on an LED, change pitch, //whatever.....
}
//but if I see 0V to 5V......
if (gatemaker == HIGH)
{
//do something even still more different; discharge a cap, turn off //an LED, don't change pitch, whatever.....
}
Wow! That's really easy! A million and one uses: ARs, gate to trigger, trigger delays, on and on. Trap when your gate signal is going up or down, then do something fun. NNNNNNext!
Again this is useful for ATTINY but by studying Arduino coding on line can be done with all the chips I've seen in this large family--so, whatever other Arduino widget suits you.
This ATTINY methodology took me a few evenings to figure out, mostly because there are so many different documented ways to get at the interrupt paradigm, but this whole change pin interrupt/boolean method seems to work every time and is simple, simple, SIMPLE!!! For the Nano, there are two pins already all set for interrupts, and the code needed is the usual super simple stuff we all expect here in Arduinoland.
Again this is useful for ATTINY but by studying Arduino coding on line can be done with all the chips I've seen in this large family--so, whatever other Arduino widget suits you.
This ATTINY methodology took me a few evenings to figure out, mostly because there are so many different documented ways to get at the interrupt paradigm, but this whole change pin interrupt/boolean method seems to work every time and is simple, simple, SIMPLE!!! For the Nano, there are two pins already all set for interrupts, and the code needed is the usual super simple stuff we all expect here in Arduinoland.
Back to Audio: Final thing to do is protect your ATTINY interrupt pins from an obnoxious gate signals from (say) your 15V power supply (oops! Patched my modular wrong....blew up that ATTINY....magic smoke....yeh baby yeh!)
For that I used this circuit fragment plugged into the PB4 pin used above; as always, many ways to do this, but this simple NPN circuit fragment worked for me. Transistor is a 2N3904....this inverts the gate, so you have to code accordingly.
For that I used this circuit fragment plugged into the PB4 pin used above; as always, many ways to do this, but this simple NPN circuit fragment worked for me. Transistor is a 2N3904....this inverts the gate, so you have to code accordingly.
OK for now that's it. I created an ATTINY based module I call "ConBrio" allowing a gate to speed up up up or down down down. It uses this whole pin Change interrupt thing extensively. It works on the bench but I am trying to make it "more musical" whatever the hell that means. I figure I will finish the code and hardware for that and post it soon.
Until then, don't breathe the TINY and have fun!!!
Until then, don't breathe the TINY and have fun!!!
No comments:
Post a Comment