The arduino.cc description of tone()
says “Only one tone can be generated at a time”, so presumably you are using some other software to generate tones on multiple pins. For example, Brett Hagman's play()
code, which Arduino tone()
is derived from, uses multiple timers, one per tone.
When using play()
, you probably can adjust phase by calling delayMicroseconds()
between the two play()
calls that start up the tone generation; for example:
play(11, 440);
delayMicroseconds(235); // Move 2nd tone 8 cm closer
play(9, 440);
Note, because tone()
and play()
use one timer per output (for example, timer 2 for first tone, timer 1 for next tone, timer 0 for third tone) there usually will be some timer prescale mismatches between 8-bit and 16-bit timers, which may result in slightly different frequencies, leading to some constant phase shift rate if you use that method.
With the speed of sound about 340.29 m/s in air at standard pressure, the wavelength of say 440 Hz would be under a meter, so I presume you would move speakers just a few tens of cm for phasing; hence a few hundred to a few thousand microseconds of phase offset. If you want good programmatic control, and also want to have quite a few speakers, external hardware in the form of a delay line or a bucket brigade chip is an obvious approach.
You could simulate a program-controlled delay line fairly easily using a handful of 74HC595 SIPO shift registers, as follows: Connect the DS of the first '595 to your tone()
output pin. Connect the Q7S output of each '595 except the last to the DS of the following '595.
Now use another timer to repeatedly clock your tone data into the shift register chain. That is, connect all STCP and SHCP inputs in parallel to a timer output pin. (Eg, OC1A, OC1B, OC2A, or OC2B, which might be pins like 9–12 on an Uno or Nano). Run that timer at 10 to 100 KHz, ie, at some rate f that gives you the resolution and range of phase changing that you need.
Calling the shift register outputs o₀, o₁, o₂..., we have oⱼ delayed by (j-i)/f seconds relative to oᵢ. That is, successive SR outputs represent different taps for different delays.