Arduino Timer

I was recently playing around with my Arduino Uno, and, out of curiosity, I tried to make it play a musical note, by attaching the output to a speaker from a telephone. However, when I compared the result to the actual note on my piano, I found that that the note from the Arduino was a whole tone too high (12% too fast). I tried this for 440hz and for 220hz, and got the same result. Is there a limit to the accuracy of the Arduino timer of around 100?s that's reflected here, or is there something else going on? For reference, here is the code I used.

int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(2.272);
  digitalWrite(speaker, LOW);
  delay(2.272);
}
int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(1.136);
  digitalWrite(speaker, LOW);
  delay(1.136);
}

I did not know that delay(ms) might work with a non integer number of ms. I'd read somewhere that miilis() is not that accurate.

On a nano v.3 328 type arduino, delayMicroseconds(1200); would work more repeatably than delay(1.2); The time returned by micros() was off by +- 3 parts in 10000 and drifted with time of day (possibly temperature?) by +- 1 part in 10000 per half-day during a couple of days. It was different by 4 parts in 10000 on a second nominally identical nano.

I hope that gives you some hard figures to know what you can expect.

I don't know about that speaker phone, the impedance could be too low, or it has a heavy coil which could have dangerous inductivity for the Arduino.

There is a tone library: http://arduino.cc/en/reference/tone

Have a look at the Audio in the Playground section : http://playground.arduino.cc/Main/InterfacingWithHardware#Audio The Mozzi library pushes the normal Arduino to the limit : http://sensorium.github.io/Mozzi/

You might try using interrupts to create more accurate outputs. You can play with prescallers etc. to get a pretty good range of frequencies and interrupts should be considerably more accurate than delay functions as they rely on hardware timers.

http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS

Not sure if Tone library uses interrupts it may do that in which case using the Tone library should be fine too.

Lemur: For reference, here is the code I used.

int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(2.272);
  digitalWrite(speaker, LOW);
  delay(2.272);
}
int speaker = 12;
void setup() {
  pinMode(speaker, OUTPUT);
}
void loop() {
  digitalWrite(speaker, HIGH);
  delay(1.136);
  digitalWrite(speaker, LOW);
  delay(1.136);
}

delay() doesn't accept floating point values...