Chrisstokes
Member
I'm trying to generate a set of timing pulses out of a teensy 3.2, into a pair of external lasers and flashlamps, and a camera. Currently using TeensyTimerTool and the tck64 timers and delaymicroseconds. I'm on windows, but I'm not interacting with the microcontroller after it is initiated.
I'm getting some results, but I'm not out of the woods, and I'd like advice. I would happily change teensies, libraries, clockrate...
I'm pretty sure I'm making some basic mistakes, and I've marched right out on a skinny limb of inexperience and hubris.
I am a certified coding impostor: I can show you my classics degree if you need to see it.
Here's my goal:
8 signals on a microseconds scale, repeating at 15 Hz.
There's two sets of lasers which need warm-up times (~135us) which work to illuminate a scene.
There's a camera which needs an 'expose' signal.
There is an analog-in (10kpot) that I'd like to use to vary the timing between the two exposures (2nd illuminator and 2nd frame exposure).
The manual trigger is on an interrupt with a debounce in the callback.
Attached is a timing diagram. Sorry, it's a little busy.
What works.
15 hz is good. The whole pulse train crunches along at a very periodic rate:14.997.
Signals happen in proper sequence: exposures happen over the strobes.
Jitter is low enough, looks like 1-2us over the 200us of a pulse train.
What's still broken:
Each restart, I have an indeterminacy due to the way I'm initializing the timers. It's amazing that
it works as it does: (8)64 bit counter screaming along at 98MHz lining up most of the time. but for example, a requested 98us delay measures to 108, 122 or 146. Might work in practice, but it's unsettling.
Also, the pulse train degrades after multiple manual interrupts. That's not how it will be used,
but it is a sign of instability.
When I try to do analog sampling of the duration variable, things get unstable a bit more quickly.
What I've tried.
I used IntervalTimer to start. That worked amazingly well. Felt like hardware. But it is limited to 16 bit, and I can have only 4. I could use a separate teensy... but.
Also, the 1/15Hz = 66,666 us. (mark of the devil!) which is > 65,536. Rats.
I tried TCK, but, for some reason, TCK64 is more stable than TCK. So I have been using that. I don't think it will rollover till global warming has long effected human extinction. I gave an approach with elapsedms a try, but didn't work out how to integrate that.
I will probably figure this out eventually, but if anyone feels like lending an experienced suggestion, specific or general, I'd be grateful.
Code below:
I'm getting some results, but I'm not out of the woods, and I'd like advice. I would happily change teensies, libraries, clockrate...
I'm pretty sure I'm making some basic mistakes, and I've marched right out on a skinny limb of inexperience and hubris.
I am a certified coding impostor: I can show you my classics degree if you need to see it.
Here's my goal:
8 signals on a microseconds scale, repeating at 15 Hz.
There's two sets of lasers which need warm-up times (~135us) which work to illuminate a scene.
There's a camera which needs an 'expose' signal.
There is an analog-in (10kpot) that I'd like to use to vary the timing between the two exposures (2nd illuminator and 2nd frame exposure).
The manual trigger is on an interrupt with a debounce in the callback.
Attached is a timing diagram. Sorry, it's a little busy.
What works.
15 hz is good. The whole pulse train crunches along at a very periodic rate:14.997.
Signals happen in proper sequence: exposures happen over the strobes.
Jitter is low enough, looks like 1-2us over the 200us of a pulse train.
What's still broken:
Each restart, I have an indeterminacy due to the way I'm initializing the timers. It's amazing that
it works as it does: (8)64 bit counter screaming along at 98MHz lining up most of the time. but for example, a requested 98us delay measures to 108, 122 or 146. Might work in practice, but it's unsettling.
Also, the pulse train degrades after multiple manual interrupts. That's not how it will be used,
but it is a sign of instability.
When I try to do analog sampling of the duration variable, things get unstable a bit more quickly.
What I've tried.
I used IntervalTimer to start. That worked amazingly well. Felt like hardware. But it is limited to 16 bit, and I can have only 4. I could use a separate teensy... but.
Also, the 1/15Hz = 66,666 us. (mark of the devil!) which is > 65,536. Rats.
I tried TCK, but, for some reason, TCK64 is more stable than TCK. So I have been using that. I don't think it will rollover till global warming has long effected human extinction. I gave an approach with elapsedms a try, but didn't work out how to integrate that.
I will probably figure this out eventually, but if anyone feels like lending an experienced suggestion, specific or general, I'd be grateful.
Code below:
Code:
#include "Arduino.h"
#include "TeensyTimerTool.h"
using namespace TeensyTimerTool;
const int buttonPin = 15;
int potPin = A9; // 0-3.3v on pin 23
volatile int potValue = 0;
volatile int usVal = 100; // default start value for sample delay
PeriodicTimer lamp1(TCK64); // trying software timers. these all are 66.6k, so >32bit
PeriodicTimer qTrig1(TCK64) ; //
PeriodicTimer lamp2(TCK64) ;
PeriodicTimer qTrig2(TCK64) ;
PeriodicTimer camTrig10n(TCK64);
PeriodicTimer camTrig1Off(TCK64);
PeriodicTimer camTrig2On(TCK64);
PeriodicTimer camTrig2Off(TCK64);
//Callbacks
void pulseLamp1()
{
digitalWriteFast(1,HIGH);
delayMicroseconds(10); //10us min, 11 for saftey?
digitalWriteFast(1,LOW);
}
void pulseLamp2()
{
digitalWriteFast(3,HIGH);
delayMicroseconds(10);
digitalWriteFast(3,LOW);
}
void pulseQ1()
{
digitalWriteFast(2,HIGH);
delayMicroseconds(10);
digitalWriteFast(2,LOW);
}
void pulseQ2()
{
digitalWriteFast(4,HIGH);
delayMicroseconds(10);
digitalWriteFast(4,LOW);
}
void camStartExpose()
{
digitalWriteFast(5,HIGH);
}
void camStopExpose()
{
digitalWriteFast(5,LOW);
}
void trigEvent()
{
delay(10); // 10 ms delay after trigger event for debounce
if (digitalRead(buttonPin) == LOW){
digitalWriteFast(13,HIGH);
delayMicroseconds(100000); // long enough to see it.
digitalWriteFast(13,LOW);
}
}
// elapsedMicros camStart1; // needs to be global, so as to not reset with each loop.
// elapsedMicros camStop1;
void setup()
{
for (unsigned pin =0; pin<=13; pin++) pinMode(pin,OUTPUT); //include 13 for led diags.
//pinMode(buttonPin, INPUT_PULLUP); // 15 is input, normally pulled up, pulled down by hand switch
lamp1.begin(pulseLamp1, 66'666); //no delay, start whole process
delayMicroseconds(98); //todo: turn this const to var fr AD(var from const makes unstable)
lamp2.begin(pulseLamp2, 66'666); // 98us delay becomes ~108, or 122
delayMicroseconds(25); // 138-(108+5usLatency)=25 how to param this? quadr enc?
camTrig10n.begin(camStartExpose,66'666); // Trigger for first frame.
delayMicroseconds(2);
qTrig1.begin(pulseQ1, 66'666); // tests out to 3us. ok.
delayMicroseconds(25); // exposure randomly selected to bracket laser pulse.
camTrig1Off.begin(camStopExpose, 66'666); // 25us gets stopped at 62us exposure.or 49,or 38 hmm.
delayMicroseconds(30); // remainder buffer to space exposures. >2us, 30 catches pulse
camTrig2On.begin(camStartExpose, 66'666); // same function, but different timer name for 2nd frame.
delayMicroseconds(2);
qTrig2.begin(pulseQ2, 66'666);
delayMicroseconds(30); // Expose long enough to catch wherever laser pulse lands.
camTrig2Off.begin(camStopExpose, 66'666);
// Manual trigger pushbutton:
attachInterrupt(digitalPinToInterrupt(buttonPin),trigEvent,FALLING);
}
void loop()
{
//potValue = analogRead(potPin);
//usVal = map(potValue, 0,1023, 100, 500); //takes 0-3.3V analog value, maps to 100-500
//delay(100);
}