Modulated 38kHz signal from ATtiny85

I am trying to generate a modulated square wave using an ATtiny85. It should generate bursts of 38kHz at whatever rate I specify (I will make many of these at different frequencies so that they act as identifiers).

I have had this functioning on a Pro Micro so I am confident the approach is right but I would like to port it to ATtiny85. (I had it working on one Pro Micro but I seem to be bricking all the the subsequent ones and they cost significantly more; plus the physical size difference would be genuinely handy).

When running the code below, I see a perfect output on my oscilloscope for one or two seconds. Then the signal changes to gibberish. I have no idea why and would truly appreciate any input. The oscilloscope is connected to the output of a 38kHz sensor which demodulates the signal.

Image shows the expected 31.5Hz...

Then very shortly after it changes to this...

The code

const byte LED_PIN = PB0;

ISR (TIMER1_COMPA_vect) {
  TCCR0A ^= _BV(COM0A0); // Toggle OC0A (pin PB0)

  if ((TCCR0A & _BV(COM0A0)) == 0) {
    digitalWrite(LED_PIN, LOW); // ensure off
  }
}

void setup() {
  delay(1000);

  pinMode(LED_PIN, OUTPUT);

  cli();

  TCCR0A = 0;
  TCCR0B = 0;
  TCCR0A |= _BV(COM0A0); // Toggle pin PB0
  TCCR0A |= _BV(WGM01); // Count up to OCR0A
  TCCR0B |= _BV(CS00); // No prescaler
  OCR0A = 104; // 38kHz
  TCNT0 = 0; // Reset count

  TCCR1 = 0;
  GTCCR = 0;
  TCCR1 |= _BV(CTC1); // Count up to OCR1C
  TCCR1 |= _BV(CS13) | _BV(CS11); // Prescaled by 512
  OCR1C = 255; // 30.5Hz
  TIMSK |= _BV(OCIE1A); 

  sei();
}

void loop() {}

Did you account for the difference in the hardware timer registers, between the two processors?

Yes, I'm not using the same code I used for the Pro Micro. I've found it much harder to come by guides for the Tiny but I thought I had understood the datasheet correctly.

The fact that I get the correct signal for a short amount of time seems to vindicate this at least somewhat. Just need to understand why this signal doesn't stick around :person_shrugging:

I removed the unnecessary stuff in the ISR, and this seems to work as expected, using the ATtinycore:

// ATtiny core, ATtiny85
const byte LED_PIN = PB0;

ISR (TIMER1_COMPA_vect) {
  TCCR0A ^= _BV(COM0A0); // connect/disconnect PB0 from timer
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW); // ensure output LOW when disconnected from timer
  cli();

  TCCR0A = 0;
  TCCR0B = 0;
  TCCR0A |= _BV(COM0A0); // Toggle pin PB0
  TCCR0A |= _BV(WGM01); // Count up to OCR0A
  TCCR0B |= _BV(CS00); // No prescaler
  OCR0A = 104; // 38kHz
  TCNT0 = 0; // Reset count

  TCCR1 = 0;
  GTCCR = 0;
  TIMSK = 0;  //ensure no unwanted interrupts
  TCCR1 |= _BV(CTC1); // Count up to OCR1C
  TCCR1 |= _BV(CS13) | _BV(CS11); // Prescaled by 512
  OCR1C = 255; // 30.5Hz
  TIMSK |= _BV(OCIE1A); 

  sei();
}

void loop() {}

8.25vmax. Is that going through the chip? Do you have a working function generator to try out the rest of the circuit?

4.6Vpp, probably a scope offset artifact or wiring error.

@apf1979 @jremington Yeah I believe it's some scope offset problem. I set the offset when I first plugged it in and haven't really thought about it since. It's powered by 5v and the signal is 5v, I've verified that.

@jremington I hadn't heard of ATTinyCore but it seems I was using it too:

http://drazzy.com/package_drazzy.com_index.json

I uploaded your code and I did get a different result. However going back to my original code also gives me the same new result: A signal around 2.4Hz with a duty cycle of 90%.

I've tried multiple ATtiny85s, I've swapped all the other components and wires multiple times, I've got the original Pro Micro still working so can verify the oscilloscope and the reader circuit I have built.

Really banging my head against the wall. Especially as I can't even get back to the problem I originally reported here... :exploding_head:

PS, really appreciate that you took the time to try this at home.

As soon as I posted that, I got it working! Realised that when I tried new chips I didn't update the bootloader so they were still running at 1MHz. Flashed it to 8MHz, tried @jremington code again and it works a treat. I haven't tried retracing my steps yet to see exactly where the problem was because I'm going to sit on the sofa now :slightly_smiling_face:

Thank you very much for your help.

Glad it works! I don't know what might have been wrong, either. But note that I made one other potentially decisive change:

TIMSK = 0; //ensure no unwanted interrupts

Arduino cores tend to initialize timers on startup, so take no chances.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.