Hashtag Octothorpe
Joined: Jun 11, 2017 Posts: 57 Location: Grand Rapids MI
|
Posted: Wed Mar 24, 2021 3:06 am Post subject:
Event timer for Arduino Subject description: Why is my event timer missing events!? |
|
|
Hey, I'm developing a trigger sequencer for Eurorack, and I've got the trigger sequencing part working GREAT, but I had a suggestion to make it work as an event timer.
So I've got something here, but it's super unreliable. I can't figure out why... basically the code sets up an "elapsed" variable with the number of milliseconds since the timer loop started. There's a "sequence" array of 300 events, and when you press a key as read by direct port manipulation, it enters the "elapsed" time into 16 bits of the sequence variable, along with an 8 bit representation of which key was pressed and therefore which of the eight channels should be triggered.
The loop is always counting up stepNum, comparing the sequence[stepNum] to the elapsed time, and sends out a trigger, and also flips a bit in the variable to say "just play this event once". When the timer loop restarts, it flips that "already played' bit back to 0.
So here's the code of the event timer mode. Why is this missing triggers? Thanks!
Code: |
unsigned long tempo;
unsigned long flash;
unsigned long debounce;
unsigned long debounce2;
unsigned long sixteenth;
unsigned long newTap;
unsigned long oldTap;
unsigned long pressed;
word tapAvg[33];
word glitch[9];
unsigned long temporary;
unsigned long elapsed;
unsigned long quarterNote = 500; // sets the default internal tempo, quarter notes, in milliseconds. 500 = 120BPM
word sixteenthNote;
int swingValue;
unsigned long sequence[300];
byte played[300];
byte recPins;
byte oldRecPins;
byte tempRecPins;
byte oldTempRecPins;
byte playPins;
byte switchPosition;
byte seqNum = 3; // sets the default sequence number, change this ONLY when...
word seqLength;
word seqStep;
word oldStep;
byte triggered;
byte mute = B11111111;
byte extTap = 10; // = 0 means external clock, = 1 means internal clock (10 or 11 means event timer mode)
byte rollOneshot = 1; // = 0 means kepresses roll, = 1 means kepresses are one-shot
byte FSmode = 0; // selects the default freestyle mode
const byte triggerLength = 8; // sets how long triggers go HIGH. 10 is prplayPinsably the longest you want to do, 2 might be too short.
byte resetted;
unsigned long USreset;
byte tapped;
int tapNum = -9;
int oldTapNum;
byte UQFS = 10;
int glitchCounter;
byte pingPong;
int TV;
int TV2;
void setup() {
// SLselect();
pinMode(0, INPUT_PULLUP); //PIND B0000000x (breaks when Serial is used)
pinMode(1, OUTPUT); //PORTD B000000x0 (breaks when Serial is used)
pinMode(2, INPUT_PULLUP); //PIND B00000x00 button 1
pinMode(3, INPUT_PULLUP); //PIND B0000x000 2
pinMode(4, INPUT_PULLUP); //PIND B000x0000 3
pinMode(5, INPUT_PULLUP); //PIND B00x00000 4
pinMode(6, INPUT_PULLUP); //PIND B0x000000 5
pinMode(7, INPUT_PULLUP); //PIND Bx0000000 6
pinMode(8, INPUT_PULLUP); //PINB B0000000x 7
pinMode(9, INPUT_PULLUP); //PINB B000000x0 8
pinMode(10, OUTPUT); //PORTB B00000x00 output 1
pinMode(11, OUTPUT); //PORTB B0000x000 2
pinMode(12, OUTPUT); //PORTB B000x0000 3
pinMode(13, OUTPUT); //PORTB B00x00000 4
pinMode(A0, OUTPUT); //PORTC B0000000x 5
pinMode(A1, OUTPUT); //PORTC B000000x0 6
pinMode(A2, OUTPUT); //PORTC B00000x00 7
pinMode(A3, OUTPUT); //PORTC B0000x000 8
pinMode(A4, INPUT_PULLUP); //PINC B000x0000 clock trigger in
pinMode(A5, OUTPUT); //PORTC B00x00000 flashy light
// Serial.begin(115200);
}
void loop() {
recPins = PIND >> 2;
recPins |= ((PINB << 6) & B11000000);
recPins = ~recPins;
if (recPins > oldRecPins) {
if ((extTap == 10) || (extTap == 11)) {
tempo = millis();
extTap += 10;
USreset = 65535;
seqLength = 0;
// stuff to delete the sequence
}
seqLength++;
if (seqLength > 299) seqLength = 0;
sequence[seqLength] = elapsed;
playPins = recPins ^ oldRecPins;
sequence[seqLength] |= (unsigned long)playPins << 16;
flash = millis();
}
elapsed = ((millis() - tempo) & 65535); // this weird number leaves 16 zeros in the five MSBs of the variable
if ((USreset == 65535) && (analogRead(A7) < 100)) {
USreset = elapsed;
}
if (elapsed > USreset) {
tempo = millis();
for (int i = 0; i <= seqLength; i++) {
bitWrite(sequence[i], 30, 0);
PORTC |= B00100000;
}
}
seqStep++;
if (seqStep > seqLength) seqStep = 1;
if (elapsed > (sequence[seqStep] & 65535) & (bitRead(sequence[seqStep], 30) == 0)) {
playPins = (sequence[seqStep] >> 16);
bitWrite(sequence[seqStep], 30, 1);
flash = millis();
}
// if (elapsed > (sequence[seqStep] & 134217727)) Serial.println(seqStep);
if (flash > 0) {
PORTB |= (playPins << 2) & B00111100;
PORTC |= (playPins >> 4) & B00001111;
}
if (millis() - flash > 20) {
PORTB &= B11000011;
PORTC &= B11010000;
flash = 0;
}
oldRecPins = recPins;
}
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24085 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Wed Mar 24, 2021 5:41 am Post subject:
|
|
|
Hashtag Octothorpe wrote: | Wow, code got messed up okay I'll upload the sketch as an attachment. |
I've disabled HTML in your original post and then re-inserted the contents of the ino file in the [code] section .. it should look better now ... _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
petegaggs
Joined: Jan 04, 2018 Posts: 23 Location: Cambridge, UK
Audio files: 1
|
Posted: Sun Apr 04, 2021 5:34 am Post subject:
|
|
|
When you say it's unreliable, can you give some more info about how it's failing?
Having had a quick look at the code, one possible issue here might be mechanical switch bounce. E.g. when a button is pressed you see multiple transitions as the switch contact bounces back and forth. There does not seem to be any software de-bouncing being done here, so you could try that and see what happens. |
|