Messing with Uno Sounds, not getting what I expected. I know it's a pebcac error, just not sure which one

Salutations all!
I've been messing around with audio on an Arduino Uno. My code is below. I tried to generate a sine wave alternating from 220 and 440 Hz. I'm getting some of the ugliest sounds back. I'd appreciate any ideas.

Hardware: I have a passive piezo buzzer on pin 11 of my Uno R3. I know it can't really do sine waves, but I'm in the back yard and just using it to get an idea of my progress. Yes, I'm very sure it's passive, supplying direct dc voltage produces no tone, and square waves can be heard without problem.

I'd appreciate any ideas and guidance. I'm new to Arduino, but have 35 years programming experience. Apple Basic counts, right? :slight_smile:

I know reading and answering my question is voluntary, so thank you in advance for taking time for it, I'm grateful.

#include <math.h>


//sample rate = 16000 / (8*256), 8 is OCR1A.
#define SAMPRATE 7812.5

//I multiplied by 256 because I wanted 8bit resolution. is this correct?

float f = 440; //frequency in Hz.
byte pinState = LOW; //only change the pin if its different from last time.
unsigned int samples = 0; //how many samples have been played.
int counter = 0; //duty cycle for current sample.
byte curSamp = 0; //the currently playing sample.

//I stole some of this, still trying to wrap my head around registers and flags for AVR timers. If I went astray, please let me know.
void setup() {
      DDRB |= B00001000;   // set pin11 to output without affecting other pins
      cli();
      TCCR1A = 0; 
      TCCR1B = 0;
      OCR1A = 8;
    TCCR1B |= (1 << WGM12); // CTC mode on
    TCCR1B |= (1 << CS10);// Set CS10 bit for 1 prescaler.
    TIMSK1 |= (1 << OCIE1A);// timer compare intrupt
    sei();
}

void loop() {
    //generate warble, 440 - 220, swaping every 1/2 second.
delay(500);
    if (f == 440) {
      f = 220;
    } else {
      f=220;
    } //if
} //loop

ISR(TIMER1_COMPA_vect) {
  counter++; //tracks duty cycle.
  byte dstate = (counter <= curSamp);
  if (dstate != pinState) {
    pinState = dstate;
    PORTB ^= B00001000; // toggles bit which affects pin11.
  } //if samp bounds
  if (counter >= 256) {
    counter = 0;
    samples++;
    curSamp = ((byte)(sin((2 * PI * samples * f) / SAMPRATE) * 127) + 128); //should generate <F> sine wave at <SAMPRATE> samples per second.
    //Something is wrong here, even if I replace (127) with 1, the tone doesn't change frequency, but does have less distortion. It doesn't sound like 440Hz either.
  } //if time
} //timer

Thanks again for your time.

Break your calculation of curSamp up into individual calculations print each result on the serial monitor.
Paul

Just curious why you don't just use tone() and noTone()?

@Paul_KD7HB: Thank you, I will. I can compare it to the signal I expected. I can't see, literally, so the serial plotter doesn't do me much good, but the monitor should be awesome, thank you! I'll post back.

@ToddL1962: There are at least 3 reasons.

  1. I'm still trying to wrap my head around interrupt and timer registers, I thought this would be a fun way to do that.
  2. I'd like to work with the ATTiny85 soon, its my understanding that tone() doesn't work with that.
  3. I also wanted to work with different wave shapes, triangle for example, but tone only produces square waves.

Did you look at toneAC()
Leo..

I hadn't looked at toneAC until you suggested it, but I have now and I'm confused. In the compatibility list, ATTiny is not listed. Did I miss something?

Thanks.

No experience with toneAC on an aTTiny85, but did you see this page.
Also look at the last link at the bottom of that page.
Leo..

This looks like it'll work well, thank you! I missed something else yesterday. I looked the ToneAC page over again today, and it seems like ToneAC2 could work too.

ToneAC didn't look adaptable because it needs a 16-bit timer. The ATTiny85 only has 8-bit timers, 0 and 1, so I'd have to modify ToneAC2, but the library works with an 8-bit timer, so maybe. If I'm successful, I'll post back.

Thank you!

I'm still interested in why my code doesn't work. As I said yesterday, I'm just messing around, so it isn't to important, but I am still curious.

Questions are a burden to others; answers a prison for oneself.

Village Motto, "The Prisoner"
:grin:

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