Example code to generate signals#
Python and NI DAQ#
# generated using chatgpt `generate sample code that make NI DAQ generate sawtooth wave using python`
import nidaqmx
from nidaqmx.constants import WaveformType
import numpy as np
# Parameters
device_name = "Dev1" # Replace with your device name
ao_channel = f"{device_name}/ao0" # Analog output channel
rate = 1000 # Sample rate (samples per second)
duration = 2 # Duration of the signal in seconds
frequency = 2 # Frequency of the sawtooth wave in Hz
amplitude = 5 # Peak-to-peak amplitude in volts
offset = 0 # DC offset in volts
# Calculate the total number of samples
num_samples = int(rate * duration)
# Generate the sawtooth waveform data
t = np.linspace(0, duration, num_samples, endpoint=False) # Time vector
sawtooth_wave = amplitude * (t * frequency - np.floor(t * frequency)) + offset
# Create a task to output the waveform
with nidaqmx.Task() as task:
# Add an analog output channel
task.ao_channels.add_ao_voltage_chan(ao_channel, min_val=-10.0, max_val=10.0)
# Configure the timing for continuous waveform generation
task.timing.cfg_samp_clk_timing(rate, sample_mode=nidaqmx.constants.AcquisitionType.CONTINUOUS)
# Write the waveform to the buffer
task.out_stream.write_regen_mode = nidaqmx.constants.RegenerationMode.ALLOW_REGENERATION
task.write(sawtooth_wave, auto_start=False)
# Start the task
print(f"Generating sawtooth wave on {ao_channel}. Press Ctrl+C to stop.")
task.start()
# Keep the script running until interrupted
try:
while True:
pass
except KeyboardInterrupt:
print("\nStopping waveform generation.")
Arduino#
TTL pulse every 1 second
int outputPin = 0; // use digital pin 0 for output
void setup() {
Serial.begin(115200);
pinMode(outputPin, OUTPUT);
digitalWrite(outputPin, LOW);
}
void loop() {
digitalWrite(outputPin, HIGH);
delay(1); // sleep 1ms
digitalWrite(outputPin, LOW);
delay(999); // sleep 999 ms
}
TTL pulse every 10 input triggers (50% duty cycle at 10ms interval)
int outputPin = 0; // use digital pin 0 for output
int inputPin = 1;
int volatile counter = 0;
void setup() {
Serial.begin(115200);
pinMode(outputPin, OUTPUT);
digitalWrite(outputPin, LOW);
pinMode(inputPin, OUTPUT);
}
void loop() {
if(digitalRead(inputPin) == HIGH){
counter++;
if (counter >= 10){
digitalWrite(outputPin, HIGH);
counter = 0;
}
delay(7); // wait till trigger goes low
}
delay(1);
}
Triangle wave using Digital-to-analog Converter (DAC) on UNO R4
/*
based on
docs.arduino.cc/tutorials/uno-r4-wifi/dac
*/
#include "analogWave.h"
analogWave wave(DAC);
int freq = 10; // in hertz, change accordingly
void setup() {
Serial.begin(115200);
wave.saw(freq);
}
void loop() {
}
Triangle wave and timed triggers using separate MCP4725 DAC
When performing imaging with piezo scanning we sometimes want to trigger camera at repeatable positions, for example, in case of light-sheet imaging. Let’s say we want to take 10 images while scanning through 100µm range
#include <Wire.h> //wire library
#include <Adafruit_MCP4725.h> // MCP4725 library from adafruit
int vol_per_second = 1; // volumes per second
int z_steps = 10; // steps (frames) per volume
float step_duration = 1000*1000/vol_per_second/z_steps; // duration of one frame in µs
int symmetry = 0.9; // symmetry of triangle wave, defines how much time we spend on flyback
int trigger_pin = D1;
int dac_value = 0; // goes from 0 to 4095
void setup(){
// https://electronoobs.com/eng_arduino_tut119.php
MCP4725.begin(0x60); // Default I2C Address of MCP4725 breakout board (sparkfun). If not try 0x61 or 0x62
}
void loop(){
for (int step = 0; step++; step <z_steps){
// define one step size
dac_value = step/z_steps * 4095;
// move stage
MCP4725.setVoltage(dac_value, false);
// trigger camera
digitalWrite(trigger_pin, HIGH);
// pause after moving stage
delay((symmetry) * step_duration);
// end camera trigger
digitalWrite(trigger_pin, LOW);
}
MCP4725.setVoltage(0, false); // back to baseline
// wait for steady-state
delay((1-symmetry) * step_duration * z_steps);
}