Bob's use of a single crystal to drive two oscillators was new to me, but hey it worked!
Using two Arduinos rather than one is apparently easier because of a limitation in the standard Arduino library, which is that the tone() function can only be used on one output at a time. Bob's project needs two outputs.
There are alternatives that don't require board surgery.
It is possible to synchronise two Arduinos using the code below, but they drift apart over time. I tested the code using a Duemilanove and a Mega2560. An oscilloscope shows that the Arduino's start exactly in step but drift apart thereafter. For a nominal 400Hz the Mega2560 outputs 400.7Hz whilst the Duemilanove outputs 400.64Hz. Their 16000kHz crystals are oscillating at slightly different frequencies (16000.30kHz and 16000.48kHz). For Bob's application I doubt this would matter, but his solution fixes that problem.
const int input_sync_pin = 6;
const int output_sync_pin = 7;
const int tone_out_pin = 8;
const int led_pin = 13;
void setup() {
// put your setup code here, to run once:
pinMode( input_sync_pin, INPUT_PULLUP );
pinMode( output_sync_pin, OUTPUT );
digitalWrite( output_sync_pin, LOW );
while ( digitalRead( input_sync_pin ) == HIGH )
{
; // Waiting
}
// Synchronised now
pinMode( led_pin, OUTPUT );
digitalWrite( led_pin, HIGH );
}
void loop() {
// put your main code here, to run repeatedly:
tone( tone_out_pin, 400 );
}
Connect GND to GND, and pin 7 on one to pin 6 on the other, twice.
Another way is to use one Arduino to produce two tones at the same time. This is possible by installing the third-party library at *LINK*. The library needs a small fix before it will work. After installing the library, find the file "Tone.cpp" and edit it. Change the line reading "#include <wiring.h>" to "#include <Arduino.h>" Don't forget to tell the Arduino IDE to use this library.
The tones produced by this example program are based on the same clock and are closely synchronised.
#include <Tone.h>
Tone t1;
Tone t2;
int f1 = 500; // Hz
int f2 = 1000; // Hz
void setup() {
// put your setup code here, to run once:
t1.begin(6); // Tone1 Output on pin 6
t2.begin(7); // Tone2 Output on pin 7
t1.play(f1);
t2.play(f2);
}
void loop() {
// put your main code here, to run repeatedly:
// Example increases Tone2 by 1000Hz after a second. Resets to 1000Hz when the output is higher than 65kHz
// Tone1 stays at 500Hz. The two tones are output on different pins at the same time.
delay(1000); //mS
f2 = f2 + 1000;
if ( f2 > 65000 )
f2=1000;
t2.play(f2);
}
Microcontrollers like the Arduino offer lots of opportunity to model makers. It's probably heresy but I think a well-built steam engine using an Arduino with sensors to control valve events and boiler pressure etc would be rather more efficient than a mechanical equivalent. I wish my workshop skills were up to it!
Kudos to Bob for having a go.
Regards,
Dave