How to generate 40 kHz square waves on arduino output pins?
Show older comments
I would like to generate multiple 40 kHz 50% duty cycle square waves and send them to digital output pins on an arduino nano. The playtone function doesn't go up to 40 kHz so I'm not really sure what to do.
I built a PCB that drives ultrasonic transducers from arduino digital outputs. In that case, I used interrupt timers to toggle the pins on and off at the required frequency. I'm trying to integrate a MATLAB application that calculates time delays for an ultrasonic phased array to drive actual ultrasonic transducers through an arduino. I'd like to use those time delays to specify when to flip on 40 kHz outputs but I don't know how to generate 40 kHz square waves. Thank you!
5 Comments
Hi Keaton :)
I am wondering if you managed to do this ? I also trying to implement an ultraosnic phased array. I am struggling to find out how to code for delays. Any chance you have the arduino code ? This is my code so far which generates 40kHz square waves on the analog pins (for Arduino mega) :
byte TP = 0b10101010; // Every other port receives the inverted signal
void setup() {
DDRF = 0b11111111; // Set all analog ports to be outputs
DDRK = 0b11111111; // Set all analog ports to be outputs
// Initialize Timer1
noInterrupts(); // Disable interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 200; // Set compare register (16MHz / 200 = 80kHz square wave -> 40kHz full wave)
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS10); // Set prescaler to 1 ==> no prescaling
TIMSK1 |= (1 << OCIE1A); // Enable compare timer interrupt
interrupts(); // Enable interrupts
}
ISR(TIMER1_COMPA_vect) {
PORTF = TP; // Send the value of TP to the outputs
PORTK = TP;
TP = ~TP; // Invert TP for the next run
}
void loop() {
// Nothing left to do here :)
}
Walter Roberson
on 27 Sep 2019
If I understand correctly, you need to be able to each of three 40khz signals independently (x, y, z) or possibly more signals because you have a phased array. Or more correctly, the base rate is the same for all, but you need to be able to delay differently by up to one clock period for each?
N/A
on 27 Sep 2019
Hi Walter! :) yes i have 7 transducers so i need 7 differently phased signals but all 40kHZ square wave. I am not sure how to apply the delays to the different pins.
Walter Roberson
on 27 Sep 2019
What is the time resolution that you need for the phase changes?
Where does the information about the needed phases come from? How often does it need to be changed?
Which arduino are you using?
I think this might be hard for you to accomplish with an arduino. Have you considered an FPGA?
I calculate the phases by calculating the difference between the distances from one transducer to the focal point and another. These calcualtions are done in a simple matlab code. I am using the arduino mega. The phases do not be changed within a single run, I will just set the delays for each implementation. I do not need precise resolution. I had not considered FPGA when I started the project so am committed to arduino for now but will definitely consider FPGA next time! :) I chose arduino as I found the Ultraino project which recommends arduino for a phased array. https://www.instructables.com/id/Ultrasonic-Array/
Answers (2)
Aviel Moos
on 23 Jul 2019
Edited: Aviel Moos
on 23 Jul 2019
0 votes
You can setup a Timer interrupt that will accur 80,000 times per second. When the interrupt accurs you can change a flag then according to this flag you can one time change the output to high and for the other time change the output to low.
The resone for 80,000 time is that after 2 times you get one high and one low = one cycle, then you wiil get a frequency of 40kHz.
Walter Roberson
on 23 Jul 2019
0 votes
You will need be able to program this at the MATLAB level talking to the device via the standard serial over usb connection. That connection can fire at most 1000 times per second, and has enough latency and jitter to be a problem for your purposes.
You would need to use your device like a signal generator, sending it instructions on how you want the pulses to be shaped and having a dedicated c or c++ program on the device to do most of the work.
This limit is imposed by the usb standards on polling rate. There is no possibility of getting close to your requirements by controlling individual pulses over usb.
Usb over serial csn transmit about 1000 bytes per transaction. If you csn precompute say 400 pulses at a time then you could probably stay within the bandwidth constraints.
Categories
Find more on MATLAB Support Package for Arduino Hardware in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!