Brief intro: I am looking for 2 sinusoidal outputs at 211 Hz and 531 Hz, with Vmin and Vmax between 0 and 5V, and record an analog input with maximum at 12V, with at least 16 bit accuracy and 12 ksamples/sec. Doing this will greatly advance science. Looking to use the Teensy 3.6.
Science background: There is a system to monitor specific neuronal cells within a population of a behaving animal called fiber photometry. It uses two high powered LED at different wavelengths to excite a protein called gcamp. When these lights hit gcamp, the protein will fluoresce and we can measure that with a photodetector. There are two wavelengths because the florescence at one wavelength changes in the presence of calcium and the other does not (Calcium is released when a neuron fires). Therefore, you can use two wavelengths to remove a lot of noise and understand when a specific cell is firing. We can learn a lot from this (!). In order to tease apart the florescence from each wavelength, we modulate the LEDs with a sinusoidal signal. This allows for FFT analysis after recording. We choose to modulate at 211Hz and 531Hz.
I therefore need to drive two LEDs at 211Hz and 531Hz, ‘rather smoothly’ (12 bit?). Simultaneously I need to record an analog signal from a photodetector, at probably 16 bit, 12 kHz, probably dumped to the serial port to record.
Voltages: the sinusoidal outputs need to go from near zero to 5V. But I also need to control the Vmin and Vmax. I believe I can use the Sparkfun PN TXB0104. But that is 4 bit. Does that mean that even if I output 12 bit analog signal, only 4 bits come out of the TXB0104. What else can I use? The Photodetector is 12 V. I think I can just use a voltage divider to bring this down to the 3.3 V of the Teensy, right?
I based my code thus far on https://www.pjrc.com/teensy/teensy31.html. But the frequencies seem inconsistent. (It’s a work in progress, I don’t have any analog read or serial dump yet). And I don’t understand why, but when I set the Vmin and Vmax to 3.3 V and 0 V respective, the output is a sine that looks more like a square wave (the sine is obviously going beyond the 3.3 and 0 V of the system, so the system clips).
I think that perhaps the best way to get true frequencies would be to abandon this code, and move to the Teensy Audio Library. But I was hoping for some reassurance that that could work from someone that knows that they are doing. I am a simple ME. Any thoughts or reassurance would be GREATLY APPRECIATED. Sorry for the long post.
Science background: There is a system to monitor specific neuronal cells within a population of a behaving animal called fiber photometry. It uses two high powered LED at different wavelengths to excite a protein called gcamp. When these lights hit gcamp, the protein will fluoresce and we can measure that with a photodetector. There are two wavelengths because the florescence at one wavelength changes in the presence of calcium and the other does not (Calcium is released when a neuron fires). Therefore, you can use two wavelengths to remove a lot of noise and understand when a specific cell is firing. We can learn a lot from this (!). In order to tease apart the florescence from each wavelength, we modulate the LEDs with a sinusoidal signal. This allows for FFT analysis after recording. We choose to modulate at 211Hz and 531Hz.
I therefore need to drive two LEDs at 211Hz and 531Hz, ‘rather smoothly’ (12 bit?). Simultaneously I need to record an analog signal from a photodetector, at probably 16 bit, 12 kHz, probably dumped to the serial port to record.
Voltages: the sinusoidal outputs need to go from near zero to 5V. But I also need to control the Vmin and Vmax. I believe I can use the Sparkfun PN TXB0104. But that is 4 bit. Does that mean that even if I output 12 bit analog signal, only 4 bits come out of the TXB0104. What else can I use? The Photodetector is 12 V. I think I can just use a voltage divider to bring this down to the 3.3 V of the Teensy, right?
I based my code thus far on https://www.pjrc.com/teensy/teensy31.html. But the frequencies seem inconsistent. (It’s a work in progress, I don’t have any analog read or serial dump yet). And I don’t understand why, but when I set the Vmin and Vmax to 3.3 V and 0 V respective, the output is a sine that looks more like a square wave (the sine is obviously going beyond the 3.3 and 0 V of the system, so the system clips).
I think that perhaps the best way to get true frequencies would be to abandon this code, and move to the Teensy Audio Library. But I was hoping for some reassurance that that could work from someone that knows that they are doing. I am a simple ME. Any thoughts or reassurance would be GREATLY APPRECIATED. Sorry for the long post.
HTML:
/*
Fiber Photometry on a Teensy
Optogenetics and Neural Engineering Core ONE Core
University of Colorado
3.Oct.17
See optogenetic.ucdenver.edu for more information, including a detailed write up and BNC housing 3D Model
y = a sin (bx+c)
*/
//////////// This section defines the pins on the Teensy. These are global variables. /////////////////////////////////////////
float twopi = 2 * 3.14159;
float thetaCh1 = 0.0;
float thetaCh2 = 0.0;
elapsedMicros usec = 0;
//The analog in through which we we will record from the photodetector. Photodetector outputs up to 12V, so run through a voltage divider.
//From the Photodetector, run through a 1 k Ohm resistor, divide into this pin and another resisotor of 2.61 k Ohm to ground.
//…? ADC0 (A0-A9) and ADC1 (A14-A22), they are multiplexed to 25 pins that we can access. Meaning you can access 2 pins at the exact same time.
///////////////////////////////////////////////////// INputs //////////////////////////////////////////////
#define bitOut 12 //Bit depth of the outputs
#define bitIn 16 //Bit depth of the input (from the Photodetector)
float voltz = 3.3; //The max voltage output. The Teensy outputs only in 3.3V. LED drivers are looking for 5V. TXB0104 can change between the two.
float VmaxCh1 = 2.3; //In volts, MAXIMUM of 3.3
float VminCh1 = 1.0; //In volts
float freqCh1 = 211.0; //In Hz
float VmaxCh2 = 2.3; //In volts, MAXIMUM of 3.3
float VminCh2 = 1.0; //In volts
float freqCh2 = 531.0; //In Hz
//Math on INputs
double statez = pow(2, bitOut); //Top bit corresponds to max voltage, 5 V. That is, (0 to 5 v) is (0 to states) bits.
float VmaxCh1bitOut = (VmaxCh1 / voltz) * statez; //The Vmax of Ch1 in bits
float VminCh1bitOut = (VminCh1 / voltz) * statez; //The Vmin of Ch1 in bits
float VmaxCh2bitOut = (VmaxCh2 / voltz) * statez; //The Vmax of Ch2 in bits
float VminCh2bitOut = (VminCh2 / voltz) * statez; //The Vmin of Ch2 in bits
float AmpCh1bitOut = VmaxCh1bitOut - VminCh1bitOut; //The Amplitude of Ch1 in bitOut
float offSetCh1bitOut = AmpCh1bitOut / 2 + VminCh1bitOut; //Offset of Ch1 in bitOut
float AmpCh2bitOut = VmaxCh2bitOut - VminCh2bitOut; //The Amplitude of Ch1 in bitOut
float offSetCh2bitOut = AmpCh2bitOut / 2 + VminCh2bitOut; //Offset of Ch1 in bitOut
///////////////////////////////////////////////////// Setup //////////////////////////////////////////////
void setup() {
Serial.begin(38400);
// pinMode(TTL1, OUTPUT);
// pinMode(buttonPin, INPUT_PULLUP);
analogReadRes(16); //Can be from 0-16. Should match CPU speed??
analogReference(EXTERNAL);
analogReadAveraging(16); // ???????????????????????average this many readings
analogWriteResolution(bitOut); //Can be from 0-16. Should match CPU speed?? See https://www.pjrc.com/teensy/td_pulse.html. Don't use pins 16 or 17.
}
//This is the code that the Teensy loops through.
void loop() {
//Serial.println(offSetCh1bitOut);
//Serial.println(AmpCh1bitOut);
float Ch1OutPut = AmpCh1bitOut * sin(thetaCh1) + offSetCh1bitOut; //Sin calculates the sine of an angle (in radians). The result will be between -1 and 1.
float Ch2OutPut = AmpCh2bitOut * sin(thetaCh2) + offSetCh2bitOut; //Sin calculates the sine of an angle (in radians). The result will be between -1 and 1.
analogWrite(A21, (int)Ch1OutPut); //Labeled as DA0 on board
analogWrite(A22, (int)Ch2OutPut); //Labeled as DA1 on board
thetaCh1 = thetaCh1 + 0.002;
thetaCh2 = thetaCh2 + 0.02;
if (thetaCh1 >= twopi) thetaCh1 = 0;
if (thetaCh2 >= twopi) thetaCh2 = 0;
while (usec < 500) ; // wait
usec = usec - 500;
}