Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

AVR & melody

Status
Not open for further replies.

FreshMan

New Member
hi all :)
I am a beginner in programming
write in the language С
please tell me how to play the elementary 8-bit melodies with the help of AVR ?
or give good link
thanks !
 
I use the ATmega8
I know that it is necessary to configure the T1 mode PWM
but I don't understand how to convert the notes in the figures for the timer
 
I'm not sure why you think you need a PWM to do music, other than they are good for frequencies, but so are timers. PWM give you the ability to adjust the duty cycle of the frequency, but we aren't worried about that on such a simple scale.

Basically, a note is a frequency. Use your timer to produce a 1/2 cycle time period and toggle the output when the timer times out. You may even be able to use the timer overflow pin instead of toggling a port pin. This will give a square wave, which to the untrained ear, would be good enough to run into an audio amp.

Now, I can see where you'd want to use the PWM function for controlling 6 notes at once. Use the PWM to set up the frequency, and set the duty cycle at 50%.
 
I'm not sure why you think you need a PWM to do music, other than they are good for frequencies, but so are timers. PWM give you the ability to adjust the duty cycle of the frequency, but we aren't worried about that on such a simple scale.

Basically, a note is a frequency. Use your timer to produce a 1/2 cycle time period and toggle the output when the timer times out. You may even be able to use the timer overflow pin instead of toggling a port pin. This will give a square wave, which to the untrained ear, would be good enough to run into an audio amp.

Now, I can see where you'd want to use the PWM function for controlling 6 notes at once. Use the PWM to set up the frequency, and set the duty cycle at 50%.
To get 8 bit melodies you're going to need more than a pin toggle..... If a crappy sound is needed then yes!!
 
You only need 1 pwm output if you use technique called Direct Digital Synthezis.
https://www.youtube.com/watch?feature=player_detailpage&v=pGiD96zY7-M&list=PLD7F7ED1F3505D8D5#t=975
There's more great lectures about the subject in this channel: www.youtube.com/playlist?list=PLD7F7ED1F3505D8D5

I wrote an example program template for it: https://www.electro-tech-online.com...up-table-microcontroller.138626/#post-1150259

Here is a table of notes and their frequencies: www.seventhstring.com/resources/notefrequencies.html
 
Last edited:
it's a bit complicated
I have a project where all was implemented much easier ! :)
there's only one difficulty for me
I don't know how to convert the notes into the array ringtones
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

#define C1 15288
#define C1d 14431
#define D1 13621
#define D1d 12856
#define E1 12134
#define F1 11453
#define F1d 10811
#define G1 10204
#define G1d 9631
#define A1 9090
#define A1d 8580
#define H1 8099
#define C2 7648
#define C2d 7220
#define D2 6814
#define D2d 6430
#define E2 6069
#define F2 5730
#define G2 5102
#define G2d 4815
#define A2 4545
#define A2d 4291
#define H2 4049
#define C3 3822
#define P 0
#define End 1
#define N32 125.000
#define N16 250.000
#define N8 500.000
#define N4 1000.000
#define N2 2000.000
#define N1 4000.000

volatile int track=0;
volatile int NoteLong = 250;
volatile int loaded=0;
volatile int i = 1;
volatile int Bit = 0x00;

volatile char flag;
volatile int count=0;
volatile char status = 1;


int tanki[] PROGMEM={160.000,P,N32,C2,N32,D2,N32,D2d,N32,C2,N32,D2,N32,D2d,N32,D2d,N32,F2,N32,G2,N32,D2d,N32,F2,N32,G2,N32,F2,N32,G2,N32,A2,N32,F2,
            N32,G2,N32,A2,N32,G2d,N32,A2d,N32,C3,N32,G2d,N32,A2d,N32,C3,N32,C3,N32,P,N32,C3,N32,C3,N32,C3,N32,C3,N32,End}; //мелодия танчиков


int mario[] PROGMEM={100.000,P,N16,E2,N32,E2,N32,P,N32,E2,N16,P,N32,C2,N32,E2,N32,P,N32,G2,N32,P,N32,P,N16,G1,N32,P,N16,P,N16,
                C2,N32,P,N16,G1,N32,P,N16,E1,N16,P,N16,P,N32,A1,N32,P,N32,H1,N32,P,N32,A1d,N32,A1,N32,P,N32,
                G1,N32,E2,N32,G2,N32,A2,N32,P,N32,F2,N32,G2,N32,P,N32,E2,N32,P,N32,C2,N32,D2,N32,H1,N32,End};  //мелодия марио


int miniPolka[] PROGMEM={120.000,P,N16,C2,N16,E2,N16,G2,N16,E2,N16,G2,N16,F2,N16,D2,N8,G2,N16,F2,N16,D2,N8,G2,N16,E2,N16,C2,N8,
                C2,N16,E2,N16,G2,N16,E2,N16,A2,N16,G2,N16,F2,N8,G2,N16,F2,N16,E2,N16,D2,N16,C2,N8,End};


int bumer[] PROGMEM={170.000,P,N16,E2,N16,G2,N8,P,N8,P,N8,G2,N16,E2,N8,P,N8,P,N8,A2,N16,G2,N16,A2,N16,G2,N16,A2,N16,G2,N16,A2,N16,G2,N16,A2,N16,H2,N8,P,N8,End};


int nokia[30] PROGMEM={120.000,P,N16,E2,N16,D2,N16,F1d,N8,G1d,N8,C2d,N16,H1,N16,D1,N8,E1,N8,H1,N16,A1,N16,C1d,N8,E1,N8,A1,N8,End};


int mortal[66] PROGMEM={140.000,A1,N16,A1,N16,C2,N16,A1,N16,D2,N16,A1,N16,E2,N16,D2,N16,C2,N16,C2,N16,E2,N16,C2,N16,G2,N16,C2,N16,E2,N16,C2,N16,
                G1,N16,G1,N16,H1,N16,G1,N16,C2,N16,G1,N16,D2,N16,C2,N16,F1,N16,F1,N16,A1,N16,F1,N16,C2,N16,F1,N16,C2,N16,H1,N16,End};


int kuznechik[] PROGMEM={130.000,P,N16,A2,N8,E2,N8,A2,N8,E2,N8,A2,N8,G2d,N8,G2,N8,P,N8,G2d,N8,E2,N8,G2d,N8,E2,N8,G2d,N8,A2,N8,End};

int *playlist[]={
                    kuznechik,
                    tanki,
                    mario,
                    mortal,
                    nokia,
                    miniPolka,
                    bumer
                };


//interrupt [TIM1_COMPA] void timer1_compa_isr(void)
ISR (TIMER1_COMPA_vect)
{
    PORTC^=(1<<1);
}

// Timer 2 overflow interrupt service routine
ISR (TIMER2_OVF_vect)
{
    if(count)count--;


}

void play()
{
    OCR1AH = (char) (Bit >> 8);          //записываем новую ноту в OCR1A
    OCR1AL = (char) Bit;
    TIMSK |= 1 << OCIE1A;                // начали воспроизведение
    _delay_ms(NoteLong);                // длина ноты
    TIMSK &= ~(1 << OCIE1A);            //закончилась нота
    _delay_ms(40);
    i = i + 2;
}

void pause()
{
    TIMSK &= ~(1<<OCIE1A);      // запрещаем прерывания
    _delay_ms(NoteLong);
    TIMSK |= 1<<OCIE1A;        // разрешаем прерывания
    i+=2;
}


void stop()
{
    TIMSK &= ~(1<<OCIE1A);    // запрещаем прерывания
    Bit=0x00;
    PORTC&=~(1<<1);
    i=1;
    _delay_ms(200);

    if(++track>=7)            //если последний, то начать заново
    {
        track=0;
    }
}
//void Loading_melody()
//{
//      i=1;
//      while(playlist[track][i]!=1)
//      {
//      playlist[track][i+1]=playlist[track][i+1]/(playlist[track][0]/60.000);
//          // playlist[track][i+1]=pgm_read_word(playlist[track][i+1])/(pgm_read_word(playlist[track][0])/60.000);
//      i++;
//          if(playlist[track][i]!=1)
//          {
//          i++;
//          }
//      }
//      i=1;
//}

int main(void)
{

PORTC=0x00;
DDRC=0b000000011;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
//TCCR1A=0x00;
//TCCR1B=0x09;
TCCR1B |=1<<WGM12 | 1<<CS10;
//TCNT1H=0x00;
//TCNT1L=0x00;
//ICR1H=0x00;
//ICR1L=0x00;
//OCR1AH=0x00;
OCR1AL=0xFB;
//OCR1BH=0x00;
//OCR1BL=0x00;

// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2|= 1 << WGM20 | 1 << WGM21;  // Fast PWM mode
TCCR2|= 1 << CS22;                // clk/256 - делим основную частоту МК на 256 (предделидель для таймера)
TCNT2=0x00;
OCR2=0x00;

//TIMSK=0x10;
TIMSK |= 1<<TOIE2 | 1<<OCIE1A; // разрешаем прерываемя по совпадению А от теймера/счетчика Т1
sei();

    while (1)
    {

        while (pgm_read_word(&(playlist[track][i])) != 1)      //читаем данные с массива мелодии до тех пор
        {                                                                                        //пока не увидим признак окончания мелодии

            Bit = pgm_read_word(&(playlist[track][i]));                  //считываю ноту
            NoteLong = pgm_read_word(&(playlist[track][i+1]));  //считываю длительность ноты

            if (Bit == 0)
            {
                pause();
            }
            else
            {
                play();
            }
        }

        stop();
    }
}
 
FreshMan
Do You wanna play Notes or complete Samples?
When using Samples you should make a .wav File. The Sample Rate should bes as high than the later PWM frequency.
From that wav File you can create a .c file with a tool.
Than you should give the values of the .c file into the Comparematch Register of the uses Timer in an Timer Overflow Interrupt.
So the Timer give out the PWM Samples of your wished File.
Add an Low Pass Filter and an Audio Amplfier behind this and the Sound will be given out.

Code:
#include <mega32.h>
#include <delay.h>
#include "data.c"
//#include "data1.c"
//#include "data2.c"

#define flashport PORTB.0

//Pointer für die PWM Soundtabelle
volatile unsigned int ui_soundpointer=0;
//Interruptzähler um eine Abtastrate von 15625 bei 8MHz zu erhalten
volatile unsigned char uc_intcounter=0;
...

...
/ Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
uc_intcounter++;
if (uc_intcounter>2)                            //Bei jedem 2ten Durchlauf wird der nächste Wert verwendet
    {
    uc_intcounter=0;
    OCR0=Jakobsleiter8s_wav[ui_soundpointer];    //Tabelle auslesen und ins Comparematch- register tun
    ui_soundpointer++;
    if(ui_soundpointer>Jakobsleiter8s_wav_len)  //Ende der Tabelle feststellen
        {
        ui_soundpointer=0;
        }
    }

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x09;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Fast PWM top=FFh
// OC0 output: Non-Inverted PWM
TCCR0=0x69;
TCNT0=0x00;
OCR0=0x80;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
      //Thats only for a flashing light. The Soud Generation is in the Timer Interrupt Routine
      //Blitzen wird nachgebildet
      flashport=1;
      delay_ms(uc_lighttable[uc_sparkpointer]);
      flashport=0;
      delay_ms(uc_pausetable[uc_sparkpointer]);
      uc_sparkpointer++;
    
      };

Now a litte snippet from the Table

Code:
flash unsigned char Jakobsleiter8s_wav[] = {
  0x8c, 0x81, 0x87, 0x87, 0x84, 0x84, 0x82, 0x7a, 0x7a, 0x89, 0x6f, 0x92,
  0x8c, 0x73, 0x7d, 0x84, 0x8d, 0x7d, 0x77, 0x78, 0x8a, 0x7f, 0x91,
...

...
0x63, 0x70, 0x72
};
#define Jakobsleiter8s_wav_len 20727

At a sample rate of 8000 Bytes per second you have 1 Second Play Time for the whole Flash of the ATMEGA 8

When You want to take Ringtone Files you have to programm a Parser, that rad out such one file and convert it in tones.
To Do that you must know, how the Ringtonefile ist structured.
In an older Elektor there was an articel about this.

!EDIT:
The tool i used to convert .wav into .c files is called vim
 
Last edited:
in principle, I found a project where it is implemented **broken link removed** , this is what I need
but one problem remains unsolved
I don't know how to translate the notes in the array
musical education I don't have
can anyone tell how to do this easily or point to a program that does it ?
 
The array... contains the note..
Look at the table...

C4 ( middle C ) = 261.63 hz = time 3822 uS if you load the ICR you need to divide by 2 ie.. 1922

Lets take a melody... Amazing grace.. https://www.onlinesheetmusic.com/amazing-grace-my-chains-are-gone-p395813.aspx

You can copy the notes / duration etc... and use that in the array The score tells you everything you need to know.

There are FREE ringtone downloads every where on the net that will send the note arrays to your phone...
 
Just google... https://www.wikihow.com/Read-Music Al you need to know... Just use it as a reference..

There are online music creators so you can test your sounds... I use Fast tracker 2 to write scores... I also have NWC
NoteWortyComposer.. I also have sound booth ( Used to be Cool Edit Pro ) until Adobe bought it out...

If you are serious you need to get one
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top