0

I'm new to Arduino and I'm trying to use PWM to generate a tone through a buzzer. I've created a for loop, however, the for loop doesn't seem to break when the variable ms is < 1000000.

int second = 1000000; //1 second in microseconds

void setup() {
  pinMode(3, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  //Play middle C for 1 second
  for(int ms=0; ms <= second; ms+=3830)
  {
    digitalWrite(3, HIGH);
    delayMicroseconds(1915);
    digitalWrite(3, LOW);
    delayMicroseconds(1915);
    Serial.println(ms);
  }
  Serial.write("Finished C");
}

Screenshot of serial monitor

We can see on the serial output that the value of ms exceeds 1000000 but the for loop is still going. Can anyone see where I am going wrong?

4

An int can't hold 1000000. It is a signed 16-bit variable, which means it can only hold between -32768 and +32767.

To store larger numbers you need to use long, or unsigned long which are signed and unsigned 32-bit variables.

  • Just one more question for my own understanding. Why on the serial output do values > 32767 display in the serial output? – madewithrealfruit Nov 10 '18 at 10:18
  • ms may have been promoted to long since println expects long. However second will hold -31072. When you have the wrong variable type strange things can happen. – Majenko Nov 10 '18 at 11:16
  • Ok thanks, at least I know now that it's important to think about what type a variable is. – madewithrealfruit Nov 10 '18 at 11:18
2

In addition to Majenko's answer (an int on this platform can't hold a number greater than 32767) you have a second problem. You are evidently trying to make a middle C tone (261.6 Hz) by toggling a pin with a period of 1/261.6 seconds. However your Serial.println takes time. In particular at 9600 baud each byte you send will take 1/960 of a second (because there are 8 data bits, one start bit and one stop bit per byte), and assuming the number you are printing is roughly 4 digits, plus carriage return plus linefeed, you are sending 6 bytes for each time around the loop.

6 bytes of 1/960 (1042 µs) would be 6252 µs which completely dwarves your delays of 1915 µs.

Whenever you try to do things with timing loops you need to take account that everything in the loop takes time, not just your delayMicroseconds statements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.