playing tones based on micros()

I've got some code running, using a 1284P to allow 13 push buttons and have 13 tones out.
(piezo thread elsewhere got me going on this)
(easily scaled back to 8 & 8 on an UNO).
It's sort of "ultimate blink without delay" if you will.

What I am seeing is long bursts of ~40KHz output for as long as 11 seconds before the output settles down to the intended frequency.
I was thinking that it is taking a long time for the equivalent of "previousMicros" to catch up & get back in sync with the intended frequency.
Any thoughts on how to fix that?

This is the code that oscillates:

  /* Check if key for note C4 is pressed, key0  */

  if ((portDkeys & 0x04) == 0){ // key is pressed D2 -> A2
    // see if time to change hi to lo, or lo to hi
    if ( (currentTime - changeTime[0])>=noteArray[48]){    // <<< seems like the value in changeTime[0] 
                                                      // <<< needs to catch up when a note starts
      changeTime[0] = changeTime[0] + noteArray[48];
      PINA=0x04;  // toggle output bit
    }
  }

This didn't fix it, just stopped the output altogether

  /* Check if key for note C4 is pressed, key0  */

if (keyActive[0] == 0){changeTime[0] = currentTime;}
  if ((portDkeys & 0x04) == 0){ // key is pressed D2 -> A2
    // see if time to change hi to lo, or lo to hi
    if ( (currentTime - changeTime[0])>=noteArray[48]){
      changeTime[0] = changeTime[0] + noteArray[48];
      PINA=0x04;  // toggle output bit
      keyActive[0]=1;
    }
  }
  else{keyActive[0]=0;}

And the entire file is attached.

piano13keyPINx.ino (9.66 KB)

no thoughts to fix it, but I have noticed it for a very long time trying to modulate wav files using it ... since 0.18

I named it the little squawk, for my playing around I squelched it some using a low pass filter, but its a ghetto way of doing it

Ooh! Think I might have it:

  if ((portDkeys & 0x04) == 0){ // key is pressed D2 -> A2
     if (keyActive[0]==0){
       keyActive[0] = 1;
       changeTime[0] = currentTime;
     }
    // see if time to change hi to lo, or lo to hi
    if ( (currentTime - changeTime[0])>=noteArray[48]){ // time for a period toggle?
      changeTime[0] = changeTime[0] + noteArray[48];    // setup time for the next toggle
      PINA=0x04;  // write a 1 to PINx toggles an output bit - NickGammon to the rescue again!
    }
  }
  else{keyActive[0] = 0;}

Adding it in to more keys ...

I think that did it XD

Suppose I could connect the logic analyzer next and see if multiple outputs will mess anything up ...

piano13keyBurstFix.ino (11.2 KB)

Completed code, pic of prototype, schematic.
(cap on the power supply rail didn't make it onto the schematic tho, nor did the FTDI module off to the side of the 1284 board)
I connected to an amplified computer speaker. The sounds do not interfere with each other at all. I only had 8 switches, so I connected c-d-e-f-g-a-b-c. Tried pressing up to all 8 at once, did not hear any frequency fluctuation at all. C4 and C5 sound good together, no "beat frequency at all, and also sounds very in tune with wife's baby grand piano.

piano13keyBurstFix.ino (11.2 KB)

I could see several of these to make up a keyboard with as many octaves as you want.
I used 26 of 32 IO, so add some more notes or use the extra pins for other effects to be written later.

Sounds pretty cool. Maybe make a YouTube video showing it off?

Short video of me sort of hacking out a tune!

[edit 11/23/2016 - link fixed, seems youtube changed cut & paste formats?]

Seems to work pretty well. Well done!

Very nice.

PINA=0x04; // write a 1 to PINx toggles an output bit - NickGammon to the rescue again!

What returns that pin to LOW? Toggle would take:

PINA ^= 0x04;

Um confused.

Datasheet page 77:

13.2.2 Toggling the Pin

Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI instruction can be used to toggle one single bit in a port.

Toggle would take:

PINA ^= 0x04;

You are thinking of PORTA.

What a neat little speed trick!

Yep, those guys at Atmel are sharp. Nick Gammon is pretty sharp too for finding that in the datasheet!

I can't really take the credit. Someone else put me up to it. But it is a nice trick :slight_smile:

(easily scaled back to 8 & 8 on an UNO). I cannot understand this. I've seen the youtube link. This sounds cool. Can I make use of the attached code in UNO? I have another bare ATmtga32A.

Atmega1284 has 32 IO pins, so it can support 13 buttons and create 13 outputs (a full octave), and have some pins left for serial.
Uno has 20 pins, so you can't have quite as many. So the note just refers to having less buttons & less notes. Adjust the code for the hardware you have.

Thank you CrossRoads.
:slight_smile:

Hello,
I have uploaded the sketch & made connections as described in the sketch... Only the CMajor scale notes

Input keys: pin2=C4, 3=C#4, 30=D4, 8=D#4, 9=E5, 31=F5, 4=F5#, 5=G5, 6=G5#, 7=A5, 10=A5#, 11=B5, 12=C5
Output notes: pin 16=C4, 17=C#4, 18=D4, 19=D#4, 20=E5, 21=F5, 22=F5#, 23=G5, 24=G5#, 25=A5, 26=A5#, 27=B5, 28=C5

The schematic & picture is also followed for reference.

I powered up the system & pressed buttons & no sound.
Then I debugged the sketch to see if the port pin detection is working or not. using this code...

if ((portDkeys & 0x04) == 0){ // key is pressed D2 -> A2
     if (keyActive[0]==0){
       keyActive[0] = 1;
       changeTime[0] = currentTime;
       Serial.println("OK"); // added this line
     }

Serial monitor prints the "OK" when I press a portD key, it means the controller is working. Now the second step, want to check if my speakers are working or not. I need your suggestion at this point. I am using a cheap pc stereo speaker 2.0 config. Connected the resistors in (One end is towards capacitor & the other ends are connected together). I put a 10K pot in the resistor node, as shown in pic & connected the wiper pin of the pot to the TIP of the stereo jack. Connected GND to the bottom part of the jack (Image included). Will this speaker work in this project? How to troubleshoot / setup the audio output part of this project? cant determine if any signal is generated from the output pins!

I'm using this speaker.

Oscilloscope handy to test output?
I also built this awesome project (pic attached) and after button/sound issues figured out that I needed to use the ATmegaBOOT_1284P_16MHz.hex bootloader file, after that it works great.
I used these for piano keys.

Crossroads Piano.JPG