Data AcQuisition And Real-Time AnalysisScope - Spectrum - Spectrogram - Signal Generator
Software for Windows
Science with your Sound Card!
Contact us about
The Arduino_Oscillators macro mini-app demonstrates the high-resolution square wave oscillator functions of the DaqPort Arduino Sketch that is included with Daqarta. These functions are also used in the DaquinOscope mini-app, which is much more sophisticated and also includes arbitrary waveform generation along with its oscilloscope functions.
While DaquinOscope makes extensive use of Custom Controls, Multitasking, and macro subroutines, here Arduino_Oscillators has no controls at all; you have to edit variables at the start of the macro code to change timing, frequencies, and pin usage. However, the result of these simplifications is that the code is all in one listing, and is much easier to understand and customize for your own purposes.
The Arduino_Oscillators macro implements up to 4 independent square wave oscillators on selectable output pins. They can all run for a specified overall duration and then turn off, or they can run continuously. In the latter case, they will continue to run even after Daqarta is closed.
These oscillators use phase accumulator techniques to achieve extremely fine frequency resolution (one part in 2^25) using a constant output sample rate. At the default 10000 Hz sample rate the resolution is 10000 / 2^25 or 0.000298 Hz (298 microhertz). That's also the minimum frequency, equivalent to a period of 55.9 minutes. The maximum frequency is half the sample rate.
Note that the phase accumulator method, when used for square waves, can result in a certain amount of cycle-to-cycle jitter, even though the average frequency is very accurate. (See the Square Wave Jitter subtopic of DaquinOscope for details.)
You can also set two or more square waves to the same frequency, but with different phase relationships. The number of useful phases is limited by the number of samples per waveform cycle, which is the sample rate divided by the square wave frequency. See the Set Oscillator Frequency And Phase subtopic under Arduino DaqPort Sketch for more details.
Phase can be set in degrees, or in percent of a full cycle. The default in Arduino_Oscillators is 4 waves that are 25% (90 degrees) apart, at 0, 25, 50, and 75% (0, 90, 180, and 270 degrees), though you'll need to set all frequencies the same for this to be useful.
The default settings are for slow square waves, suitable for flashing LEDs at visible rates. They are also appropriate for calibrating your sound card's voltage sensitivity: See Input Voltage Method under Full-Scale Range Dialog for details.
The Arduino_Oscillators macro mini-app is included with Daqarta. To run it, first hit CTRL+F8 to open the Macro Dialog. Then scroll the Macro List down and double-click on Arduino_Oscillators. (There is no single-letter ID for Hot Key access, as there is for the mini-apps at the top of the list.)
However, before you use Arduino_Oscillators, you may want to change certain parameters that are set near the start of the macro, as explained below. To edit these, single-click on Arduino_Oscillators to select it without running it, then click the Edit button.
(Note that you can open this Help topic by selecting Arduino_Oscillators as above, then clicking the Help button below the list, next to Run. Or, once you have opened the Edit dialog, you can click the duplicate Help button near the upper right.)
The first line of macro code determines how long the oscillators will run. Set R to the number of seconds (which may be a decimal fraction), or set it to 0 if you want them to run continuously, including even after Daqarta is closed, as long as the Arduino has power (which may be by battery). The default is to run for 5 seconds.
R=5 ;Run time, secs (0 = continuous)
The next line indicates whether you want to set the oscillator phases in percent of a full square wave cycle, from 0 to 100%, or in degrees from 0 to 360.
P=100 ;Phase values in percent (360 = degrees)
;Sample rate (7812.5 Hz to 100 kHz): S=10k ;Sample rate = 10000 Hz
Note that the actual sample rate may differ from the value you set here, since the rate must be 2 MHz divided by and integer between 20 and 256, yielding rates from 100 kHz down to 7812.5 Hz. If the value you enter differs from the nearest possible value, the latter will be used and a message will be shown with the requested and actual rates.
However, please note that the number of active oscillators limits the maximum sample rate, due to the time needed to update each oscillator on every sample interrupt. If the updates aren't completed before the next interrupt occurs, the Arduino will "crash". You may continue to get oscillator outputs, but probably not at the frequency you requested. Worse, the Arduino will become unresponsive to future commands until you unplug the USB connector and reconnect it.
Note that using only the default pins 10-13 as oscillator outputs will engage a system that is much faster than using arbitrary pins outside this range. Using even a single other pin will invoke the slower system.
Here are some experimentally determined limits; your board may differ. The first table is for the "slow" arbitrary pin system. The single oscillator limit of 50 kHz is particularly finicky; if you absolutely must run at this speed, it's best to unplug and replug the Arduino just before running Arduino_Oscillators to start with a "fresh" system.
1 Oscillator: 50000 Hz 2 Oscillators: 40816 Hz (enter 41k) 3 Oscillators: 30769 Hz (enter 31k) 4 Oscillators: 25974 Hz (enter 26k)
If you use only "fast" pins 10-13, these are the limits:
1 Oscillator: 100000 Hz 2 Oscillators: 71428 Hz (enter 71k) 3 Oscillators: 54054 Hz (enter 54k) 4 Oscillators: 46512 Hz (enter 47k)
The 10 kHz default is thus a super-safe choice for running all 4 oscillators. If you would like to use integer rates, here are the options that divide evenly into 2 MHz, along with the divisors:
100000 Hz 20 80000 25 62500 32 50000 40 40000 50 31250 64 25000 80 20000 100 15625 128 12500 160 10000 200 8000 250
The highest frequency you can use for any oscillator is half of the sample rate S. The frequency resolution, and the lowest frequency you can set above 0, is 1 / 2^25 of the sample rate. At the maximum sample rate of 100 kHz this is about 0.003 Hz. Setting frequency to 0 does not disable an oscillator. It will continue to function by adding zero to its initial Phase setting for each sample; if the initial Phase is 50% (180 degrees) or more, the output pin will be high. (To disable an output, set its Output Pin to 0, as discussed under that subtopic below.)
;Osc frequencies (limit to S/2 max): A=2.00 ;Osc 0 Freq, Hz B=3.00 ;Osc 1 C=4.00 ;Osc 2 D=5.00 ;Osc 3
Regardless of the values set here, the actual phase resolution for a given oscillator is limited to the fraction found by dividing the frequency by the sample rate S. For example, at the default 10000 Hz sample rate, a frequency of 100 Hz will have a resolution of 100 / 10000 or 10%, so you can only get 0, 10%, 20%, 30% ... 90%. If you set another value you will actually get the next-lower, so setting 25% here would give 20%.
When phase is a consideration, especially at high frequencies, you should use only the default "fast" pins 10-13. These not only allow higher sample rates for better resolution, as noted above, but more importantly the pins all change state at the same time. The "slow" system still updates all pins on the same sample, but it does them one by one. Each takes about 7 microseconds, so the difference between the the first and fourth is 3 * 7 or about 21 microseconds. That can be a big phase difference at high frequencies.
Note that the default Phase values are for illustration, since phase is only meaningful between identical frequencies and the default frequencies are all different. You can set any or all oscillators to have the same frequency, or you can set two pairs to two different frequencies.
;Osc phases, percent or degrees: E=0 ;Osc 0 Phase F=25 ;Osc 1 G=50 ;Osc 2 H=75 ;Osc 3
;Output pins: U0=10 ;Osc 0 output pin U1=11 ;Osc 1 U2=12 ;Osc 2 U3=13 ;Osc 3
You can set any oscillator 0-3 to any pin 2-13 if you don't need high sample rates, high oscillator frequencies, or high phase accuracy.
However, for best performance you should use only the default pins 10-13. This activates a special high-speed system, but please note that proper operation assumes that the pins are assigned in the above order.
If you need less than 4 oscillators, set any unwanted U0 to U3 to 0. (Pin 0 is not a valid output pin, so this acts as a flag to inactivate that oscillator.) But note that if you are using pins 10-13 for the high-speed system, you must still maintain the same numbering for the oscillators you are using. For example, if you only need 3 oscillators you can set any of the U0 to U3 to 0, but the remaining must keep their same 10-13 assignments. U0 must be set to 10 or 0, U1 must be 11 or 0, and so on.
;<Help=H4928 R=5 ;Run time, secs (0 = continuous) P=100 ;Phase values in percent (360 = degrees) ;Sample rate (7812.5 Hz to 100 kHz): S=10k ;Sample rate = 10000 Hz ;Osc frequencies (limit to S/2 max): A=2.00 ;Osc 0 Freq, Hz B=3.00 ;Osc 1 C=4.00 ;Osc 2 D=5.00 ;Osc 3 ;Osc phases, percent or degrees: E=0 ;Osc 0 Phase F=25 ;Osc 1 G=50 ;Osc 2 H=75 ;Osc 3 ;Output pins: U0=10 ;Osc 0 output pin U1=11 ;Osc 1 U2=12 ;Osc 2 U3=13 ;Osc 3 Posn#0="Ardu" ;Find and open Arduino port Posn#1=0 @_ComDev_Scan Port#D2=h41D0 + U0 ;Enable pins for OUTPUT Port#D2=h41D0 + U1 Port#D2=h41D0 + U2 Port#D2=h41D0 + U3 Ut=cint(2e6 / S - 1) ;Sample rate timer step IF.Ut=>255 ;S below 7812.5 Hz? Ut=255 ;Limit to 7812.5 ENDIF. IF.Ut=<19 ;S above 100 kHz? Ut=19 ;Limit to 100 kHz ENDIF. X=2e6/(Ut + 1) ;Actual sample rate IF.S=!X ;Not as requested? Mtr0="<<Sample Rate" ;Show rates Mtr0=S + " Requested" +n + X + " Actual" S=X ;Use actual ELSE. ;Else match Mtr0= ;Clear old display ENDIF. UA=2^25 * A / S ;Compute step sizes UB=2^25 * B / S UC=2^25 * C / S UD=2^25 * D / S QA=2^25 * E / P ;Compute phase starts QB=2^25 * F / P QC=2^25 * G / P QD=2^25 * H / P Port=$(hF0) + "I" + $(Ut) ;Set timer for sample rate S ;Set Osc frequencies and phases: Port=$(hF0) + "F" + $(hC0) ;Oscillators OFF to set IF.U0=0 ;Osc 0 set to Pin 0? Port=$(hF0) + "F" + $(h00) ;Remove Osc 0 if so ELSE. ;Else set it Port=$(hF0) + "F" + $(h80 + h00 + U0) + $d(UA) + $d(QA) ENDIF. IF.U1=0 ;Osc 1 set to Pin 0? Port=$(hF0) + "F" + $(h10) ;Remove Osc 1 if so ELSE. ;Else set it Port=$(hF0) + "F" + $(h80 + h10 + U1) + $d(UB) + $d(QB) ENDIF. IF.U2=0 ;Osc 2 set to Pin 0? Port=$(hF0) + "F" + $(h20) ;Remove Osc 2 if so ELSE. ;Else set it Port=$(hF0) + "F" + $(h80 + h20 + U2) + $d(UC) + $d(QC) ENDIF. IF.U3=0 ;Osc 3 set to Pin 0? Port=$(hF0) + "F" + $(h30) ;Remove Osc 3 if so ELSE. ;Else set it Port=$(hF0) + "F" + $(h80 + h30 + U3) + $d(UD) + $d(QD) ENDIF. Port=$(hF0) + "F" + $(hC1) ;Oscillators ON IF.R=>0 ;Specified run time? WaitSecs=R ;Leave on for run time Port=$(hF0) + "F" + $(hC0) ;Oscillators OFF Port=$(hD0 + U0) + $(0) ;Output states OFF Port=$(hD0 + U1) + $(0) Port=$(hD0 + U2) + $(0) Port=$(hD0 + U3) + $(0) Mtr0= ;Sample rate display off ENDIF. Port#O=0 ;Close port
Questions? Comments? Contact us!We respond to ALL inquiries, typically within 24 hrs.
Over 35 Years of Innovative Instrumentation
© Copyright 2007 - 2023 by Interstellar Research
All rights reserved