What frequency is this crystal?

I purchased what was advertised as a 32.768KHz crystal from a small UK supplier on eBay. There are no markings on the crystal, or on the little plastic bag it came in.

I have connected it to the clock pins of an atmega328p on a breadboard which is running @8MHz internal oscillator. My sketch sets up timer2 (8-bit) to use the external crystal, with a pre-scale of 128, and the overflow interrupt increments a counter which I have named "elapsedSeconds", because 32768 / 128 / 256 = 1, so the interrupt should occur once every second. Am I right so far?

Here's my sketch:

volatile unsigned int elapsedSeconds = 0;

ISR(TIMER2_OVF_vect) {
  elapsedSeconds++;
}

void setup() {
  Serial.begin(115200);
  //Set up timer 2 to use external 32.768KHz crystal
  TIMSK2 = 0; //Disable timer2 interrupts
  ASSR   = _BV(AS2); //enable asynchronous mode for timer2, so it uses the external crystal
  TCNT2  = 0; //Reset timer2
  TCCR2B = _BV(CS22) | _BV(CS20); //Start the timer (128 pre-scale)
  while (ASSR != _BV(AS2)); //Wait for TCN2xUB, OCR2xUB, and TCR2xUB.
  TIFR2  = 0; //Clear the interrupt flag
  TIMSK2 = _BV(TOIE2); //Enable the overflow interrupt
}

void loop() {
  static unsigned int elapsedSecondsBefore;
  unsigned int elapsedSecondsNow = elapsedSeconds;
  if (elapsedSecondsNow != elapsedSecondsBefore) {
    Serial.println(elapsedSecondsNow);
    elapsedSecondsBefore = elapsedSecondsNow;
  }
}

Here is the serial monitor output, with "Show Timestamp" enabled, so the time to the left of the arrow is according to my PC, and the number to the right of the arrow is "elapsedSeconds".

11:28:52.311 -> 1
11:28:52.311 -> 2
11:28:54.433 -> 3
11:28:56.422 -> 4
11:28:58.412 -> 5
11:29:00.401 -> 6
11:29:02.390 -> 7
11:29:04.413 -> 8
11:29:06.374 -> 9
11:29:08.397 -> 10
11:29:10.387 -> 11
11:29:12.376 -> 12
11:29:14.365 -> 13
11:29:16.354 -> 14
11:29:18.343 -> 15
11:29:20.333 -> 16
11:29:22.322 -> 17
11:29:24.312 -> 18
11:29:26.301 -> 19
11:29:28.290 -> 20

The counter gets incremented once every 2 seconds! (actually slightly less than 2 seconds, by 10~11ms)

What do you think? Is there an error in my code, or is this in fact a 16.384KHz crystal? Or 16.000KHz?

I actually purchased 2 crystals from the supplier. Both behave the same.

(@moderators, this is a problem I described on another topic, but that topic is getting very long and involved, so I have started this topic with a minimal sketch to illustrate the problem in the hope that more experts here will read it.)

Probe it with an oscilloscope while running and measure the actual frequency.

I don't own a scope. I would normally go down to my local maker group and use one there, but, being in a "vulnerable group", I'm in 12 week isolation at the moment.

Code looks OK. Do you have the required 2 x 22-33 pF caps connected?

32 kHz watch crystals are ubiquitous in small devices, and are easily scrounged from junked items, along with the matching caps.

jremington: Code looks OK. Do you have the required 2 x 22-33 pF caps connected?

I don't. I found several sources mentioning they were not needed with low frequency crystals. But you seem pretty convinced that they are. I don't have anything that low, so will order some.

not needed with low frequency crystals

That is not correct. The crystal data sheet will state the parallel capacitance required for proper operation. I've found that 2x33 pF works for several salvaged watch crystals.

It could be that the capacitance of the breadboard tracks is sufficient for intermittent or off-frequency operation, but you can always make your own capacitors.

A standard approach is a "gimmick" capacitor made by twisting two lengths of insulated wire tightly together. See https://hackaday.com/2018/07/03/these-capacitors-are-a-cheap-gimmick/.

Sorry for the delay in responding. I finally got around to fitting 2 x 22pF caps to the crystal. Unfortunately I cant see any difference with them. Output using that same sketch:

17:53:51.274 -> 1
17:53:51.274 -> 2
17:53:53.862 -> 3
17:53:55.852 -> 4
17:53:57.842 -> 5
17:53:59.831 -> 6
17:54:01.822 -> 7
17:54:03.812 -> 8
17:54:05.802 -> 9
17:54:07.793 -> 10
17:54:09.784 -> 11
17:54:11.774 -> 12
17:54:13.798 -> 13
17:54:15.789 -> 14
17:54:17.778 -> 15
17:54:19.769 -> 16
17:54:21.759 -> 17
17:54:23.749 -> 18
17:54:25.739 -> 19
17:54:27.729 -> 20
17:54:29.719 -> 21
17:54:31.710 -> 22
17:54:33.701 -> 23
17:54:35.692 -> 24
17:54:37.682 -> 25
17:54:39.673 -> 26
17:54:41.663 -> 27
17:54:43.654 -> 28
17:54:45.645 -> 29
17:54:47.635 -> 30
17:54:49.626 -> 31

Neat wiring.

Do you need a jumper on the black bus bar ?

Maybe the crystal is about 16 kHz. The crystal impedance goes through a minimum at the series resonant frequency and a max at the parallel resonant frequency.

You may be able to detect the effect using a sine wave audio oscillator.

Good article on quartz crystals here.

larryd: Neat wiring.

Do you need a jumper on the black bus bar ?

Thanks, trying to set a good example!

No, the markings on the bus bar are accurate.

jremington: Maybe the crystal is about 16 kHz.

I feel the need to order more 32KHz crystals from a different supplier... Will read that article, thanks.

Reading the article, I couldn't understand any reason why a 32.768KHz crystal would oscillate at around 16KHz. All the other likely frequencies (series frequency, harmonics) seem to be higher than the basic parallel frequency, not lower.

Given that 32768 oscillation periods take around 1.99s, my crystals (X2) would both appear to have a frequency around 16.4~16.5KHz. I couldn't find crystals offered around that frequency, except maybe vintage Russian ones with glass cases and 6 or 8 pins!

I've ordered more 32.768KHz crystals from a different UK eBay supplier. Hoping I won't be unlucky twice... Will report back.

Clutching at straws but I notice your code does not set TCCR2A to a known value and the datasheet says both TCCR2x registers could be corrupted when Asynchronous Operation is changed.

PaulRB: Given that 32768 oscillation periods take around 1.99s, my crystals (X2) would both appear to have a frequency around 16.4~16.5KHz.

Thinking about it, I'm comparing the crystal with my PC's clock which is unknown accuracy, maybe that could account for the 10~11ms discrepancy, so perhaps this is a slightly less rare 15KHz of 16.384KHz crystal.

Anyway thanks for the help up to now, everyone, I'll try setting TCCR2A also.

Riva: Clutching at straws but I notice your code does not set TCCR2A to a known value and the datasheet says both TCCR2x registers could be corrupted when Asynchronous Operation is changed.

It worked! +1 karma @Riva!

Updated sketch:

volatile unsigned int elapsedSeconds = 0;

ISR(TIMER2_OVF_vect) {
  elapsedSeconds++;
}

void setup() {
  Serial.begin(115200);
  //Set up timer 2 to use external 32.768KHz crystal
  TIMSK2 = 0; //Disable timer2 interrupts
  ASSR   = _BV(AS2); //enable asynchronous mode for timer2, so it uses the external crystal
  TCNT2  = 0; //Reset timer2
  TCCR2A = 0;
  TCCR2B = _BV(CS22) | _BV(CS20); //Start the timer (128 pre-scale)
  while (ASSR != _BV(AS2)); //Wait for TCN2xUB, OCR2xUB, and TCR2xUB.
  TIFR2  = 0; //Clear the interrupt flag
  TIMSK2 = _BV(TOIE2); //Enable the overflow interrupt
}

void loop() {
  static unsigned int elapsedSecondsBefore;
  unsigned int elapsedSecondsNow = elapsedSeconds;
  if (elapsedSecondsNow != elapsedSecondsBefore) {
    Serial.println(elapsedSecondsNow);
    elapsedSecondsBefore = elapsedSecondsNow;
  }
}

Updated output:

13:11:59.298 -> 1
13:12:00.725 -> 2
13:12:01.720 -> 3
13:12:02.748 -> 4
13:12:03.743 -> 5
13:12:04.739 -> 6
13:12:05.735 -> 7
13:12:06.729 -> 8
13:12:07.725 -> 9
13:12:08.720 -> 10
13:12:09.748 -> 11
13:12:10.744 -> 12
13:12:11.739 -> 13
13:12:12.734 -> 14
13:12:13.729 -> 15
13:12:14.725 -> 16
13:12:15.720 -> 17
13:12:16.748 -> 18
13:12:17.743 -> 19
13:12:18.738 -> 20
13:12:19.733 -> 21
13:12:20.728 -> 22
13:12:21.724 -> 23
13:12:22.719 -> 24
13:12:23.747 -> 25
13:12:24.742 -> 26
13:12:25.738 -> 27
13:12:26.733 -> 28
13:12:27.728 -> 29
13:12:28.725 -> 30

If you have a logic analyzer you may use the crystal as the main clock source and program CKOUT fuse and look at the crystal this way.

It worked!

Great, but now I wonder what was in TCCR2A when the timer was misbehaving!

Can you go back one step and print out that value?

I do have one of those cheap-n-cheerful usb 8 channel logic analysers and I have sigrok pulseview installed. I tried connecting it directly to the atmega clock pins, but it just sent the clock circuit absolutely loopy. Can I set that fuse from the Arduino IDE somehow?

jremington: Great, but now I wonder what was in TCCR2A when the timer was misbehaving!

Can you go back one step and print out that value?

Ok, will do. I felt the same, but a little voice said "you broke a rule specified in the datasheet, and random stuff happened".

I think the problem was phase correct PWM was selected. However how that value can get repeatedly into the register I don't know. Arduino silently sets the timer registers for PWM even before loop() but AFAIK it used fast PWM, not phase correct.

Updated code:

volatile unsigned int elapsedSeconds = 0;

ISR(TIMER2_OVF_vect) {
  elapsedSeconds++;
}

void setup() {
  Serial.begin(115200);
  //Set up timer 2 to use external 32.768KHz crystal
  TIMSK2 = 0; //Disable timer2 interrupts
  ASSR   = _BV(AS2); //enable asynchronous mode for timer2, so it uses the external crystal
  TCNT2  = 0; //Reset timer
  //TCCR2A = 0;
  TCCR2B = _BV(CS22) | _BV(CS20); //Start the timer (128 pre-scale)
  while (ASSR != _BV(AS2)); //Wait for TCN2xUB, OCR2xUB, and TCR2xUB.
  TIFR2  = 0; //Clear the interrupt flag
  TIMSK2 = _BV(TOIE2); //Enable the overflow interrupt
  Serial.print("TCCR2A="); Serial.print(TCCR2A, BIN);
  Serial.print(" TCCR2B="); Serial.println(TCCR2B, BIN);
}

void loop() {
  static unsigned int elapsedSecondsBefore;
  unsigned int elapsedSecondsNow = elapsedSeconds;
  if (elapsedSecondsNow != elapsedSecondsBefore) {
    Serial.println(elapsedSecondsNow);
    elapsedSecondsBefore = elapsedSecondsNow;
  }
}

Output:

18:11:35.519 -> TCCR2A=1 TCCR2B=101
18:11:35.519 -> 1
18:11:35.519 -> 2
18:11:38.074 -> 3
18:11:40.066 -> 4
18:11:42.058 -> 5
18:11:44.049 -> 6
18:11:46.041 -> 7
18:11:48.032 -> 8
18:11:50.024 -> 9
18:11:52.015 -> 10

So TCCR2B has bits CS20 and CS22 set, all other bits clear, including WGM22. TCCR2A has bit WGM20 set and WGM21 clear, because not explicitly assigned in my sketch. I believe this means Smajdalf is correct and "PWM, phase correct" mode has been selected.

214.7.4 Phase Correct PWM Mode The phase correct PWM mode (WGM02:0 = 1 or 5) provides a high resolution phase correct PWM waveform generation option. The phase correct PWM mode is based on a dual-slope operation. The counter counts repeatedly from BOTTOM to TOP and then from TOP to BOTTOM.

So I guess that's why it was taking almost twice as long as expected - counting up, overflowing, then counting down, then up, then overflowing...