NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Question in Making music with MCU project

March 01, 2011
by meeser
meeser's Avatar

Hi, my Nerdkits's just arrived several days ago. I've gone through all exercises in the Nerdkits guide and now I'm working on the Making music with MCU project. I have question on the play_tone function in the source code provided. Actually at first I cannot understand it so I try to write the code in the way I understand (no switch):

   // musicbox1.c
// for NerdKits with ATtiny26L

// F_CPU defined for delay.c
#define F_CPU 8000000UL // 8MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <inttypes.h>
#include <stdlib.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PC4 -- piezo buzzer

void play_tone(uint16_t delay, uint8_t duration) {

  uint16_t cycles = 500*duration/delay;

while(cycles > 0) {

  PORTC |= (1<<PC4);
  PORTC &= ~(1<<PC4);


#define D5 851
#define E5 758
#define Fsh5 675
#define G5 637
#define A5 568
#define B5 506
#define C6 477
#define D6 425
#define DUR 400

int main() {

    OSCCAL = 176;

    DDRC |= (1<<PC4);

    while(1) {

        play_tone(D5, DUR);
        play_tone(E5, DUR);
        play_tone(D5, DUR);
        play_tone(G5, DUR);
        play_tone(Fsh5, 2*DUR);

        play_tone(D5, DUR);
        play_tone(E5, DUR);
        play_tone(D5, DUR);
        play_tone(A5, DUR);
        play_tone(G5, 2*DUR);


    return 0;

where the duration is in millisecond, which is just directly comes from: duration = 2xdelayxcycles (I also change (duration)DUR to 400)

But it turns out to have a strange behavior, it plays each note very fast and when I increase the duration sometimes it becomes even faster. After that I just copy the play_tone function from the source code provided and it works fine..

void play_tone(uint16_t delay, uint8_t duration) {
  // delay is half-period in microseconds
  // duration is in 10ms increments

  // example: 440Hz --> delay=1136

  // duration = 2*delay * cycles (all in same units)
  // cycles = 10000 * duration / delay / 2
  // cycles = 100 * duration / (delay/50)
  uint16_t tmp = 100 * duration;
  uint16_t delaysm = delay / 50;
  uint16_t cycles = tmp / delaysm; 


I'm wondering if someone could explain me why we have to write the code this way. Mathematically, it's the same so I think it should be due to programming reason..

March 03, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi meeser,

I think your factor should be 5000, not 500 if you want to do it that way. I think it will probably work.


March 03, 2011
by meeser
meeser's Avatar

Thank you very much for your help, I thought I did try that but now I've tried it again and it works now... May be I made some other misatkes that time. Both codes work the same now! Thank you


April 02, 2011
by hariharan
hariharan's Avatar

I did not understand the math you did from lines 23-33. Can you explain it?

April 02, 2011
by hariharan
hariharan's Avatar

srry, the math from the original code.

Post a Reply

Please log in to post a reply.

Did you know that NerdKits has been featured in the MIT Undergraduate Research Journal? Learn more...