Hey Everyone,
I haven't been on AAC for a little while, my job has kept me busy. I still browse the other posts when I can, and I try to remain assiduous at my projects after I finish work each day, if time permits of course.
Project:
I just began programming with PICs and have run through a series of projects to exercise my skill level in programming; this particular project is entitled a "PIC Sound Generator" in which it will generate notes at my command.
Theory & Operation:
I begin with all my header files, definings, etc. until I reach my first function. This function allows me to enter a note that I previously stored into an array, and then define how long of a duration I wish it to play for.
My frequency is set by Timer0 on the PIC, in which I rapidly turn RA0 on and off depending on my TMR0L and TMR0H values, and furthermore, my array value. TMR0H and TMR0L enable me to use 16-bit mode since my lowest note is 1515μS. Remember that I wish to know my lowest frequency note since the delay is longer. If I were to use 8-bit, my maximum delay would be 128μS. Thus, equation for 16-Bit timer:
\(Frequency Delay = [(65536 - Delay)*0.5uS]2\)
Which simplifies to:
\(Frequency Delay (uS) = (65536 - Delay)\)
It has already been noted to me that Timer2 would be a better choice, but I wish to become more familliar with all the PICs abilities and attributes, so I will eventually learn about Timer2 as well.
In the main() function, you see I have a long list of the playNote function commands. These, as I mentioned, give me what note I want and for how long I wish to play it. The latter statement is based on whole notes (actually quarter notes) and half notes (actually eighth notes). The music is depicted here:
http://upload.wikimedia.org/wikipedia/commons/4/49/Gstk.png
The time signature is 3/4; meaning there are 3 quarter (1/4) notes per measure; or section in my comments. Therefore, to make the music even, a section must eventually add up to 3 quarter notes. Otherwise, the music becomes convoluted and not very pleasant to listen to. I can, at my disposal, change how fast I want my music to play if I change my WHOLE or HALF values previously defined at the beginning. Note that they correlate with one another; if I have 800 as the WHOLE, I must have half of that for the HALF value. I was fortunate to have experience in this regard (I play classical guitar), so that made things much easier.
Code:
A picture of my setup is depicted in the attachements and to see it working click the following link:
http://s974.photobucket.com/albums/ae227/ElectroNerdy/uC%20Video/?action=view¤t=PICSoudGenerator.mp4&newest=1
On the o'scope you'll notice that the waveform is somewhat distorted, this is due to the speaker. If I were to take that off, not only would you not have any sound (obviously), but it would then give you an adequate square wave.
I hope you all enjoyed this! If you have any suggestions or comments for me, please feel free to mention them! I would be grateful for any comments in order to edify myself.
I would like to thank 3v0 and Hayato for their help!
Austin
I haven't been on AAC for a little while, my job has kept me busy. I still browse the other posts when I can, and I try to remain assiduous at my projects after I finish work each day, if time permits of course.
Project:
I just began programming with PICs and have run through a series of projects to exercise my skill level in programming; this particular project is entitled a "PIC Sound Generator" in which it will generate notes at my command.
Theory & Operation:
I begin with all my header files, definings, etc. until I reach my first function. This function allows me to enter a note that I previously stored into an array, and then define how long of a duration I wish it to play for.
My frequency is set by Timer0 on the PIC, in which I rapidly turn RA0 on and off depending on my TMR0L and TMR0H values, and furthermore, my array value. TMR0H and TMR0L enable me to use 16-bit mode since my lowest note is 1515μS. Remember that I wish to know my lowest frequency note since the delay is longer. If I were to use 8-bit, my maximum delay would be 128μS. Thus, equation for 16-Bit timer:
\(Frequency Delay = [(65536 - Delay)*0.5uS]2\)
Which simplifies to:
\(Frequency Delay (uS) = (65536 - Delay)\)
It has already been noted to me that Timer2 would be a better choice, but I wish to become more familliar with all the PICs abilities and attributes, so I will eventually learn about Timer2 as well.
In the main() function, you see I have a long list of the playNote function commands. These, as I mentioned, give me what note I want and for how long I wish to play it. The latter statement is based on whole notes (actually quarter notes) and half notes (actually eighth notes). The music is depicted here:
http://upload.wikimedia.org/wikipedia/commons/4/49/Gstk.png
The time signature is 3/4; meaning there are 3 quarter (1/4) notes per measure; or section in my comments. Therefore, to make the music even, a section must eventually add up to 3 quarter notes. Otherwise, the music becomes convoluted and not very pleasant to listen to. I can, at my disposal, change how fast I want my music to play if I change my WHOLE or HALF values previously defined at the beginning. Note that they correlate with one another; if I have 800 as the WHOLE, I must have half of that for the HALF value. I was fortunate to have experience in this regard (I play classical guitar), so that made things much easier.
Code:
- Using PIC18F1320, with C18 compiler
Rich (BB code):
//
// CreatingSound2.C Song "God Save The Queen"
//
#include <p18f1320.h>
#include <delays.h>
#include <stdlib.h>
#pragma config OSC=INTIO2, WDT=OFF, LVP=OFF, DEBUG=ON
#define PAUSE Delay1KTCYx(50);
#define WHOLE 1000
#define HALF 500
#define LONG 2000
void playNote(unsigned int note, unsigned int timer) // Note & Timer driver; determines which note will be played and for how long
{
unsigned int times, freq, notes[] = {64021, 64105, 64185, 64260, 64331, 64398, 64462, 64522, 64578, 64632, 64682, 64730, 64774, 64817, 64856, 64895};
freq = notes[note]; // Determine frequency based on array value
INTCONbits.TMR0IF = 0; // Clear OVF Flag
LATA = 0x01; // Initialize LATA
TMR0L = freq & 0xFF;
TMR0H = (freq >> 8) & 0xFF;
T0CON|=0x80;
for(times=timer;times>0;times--) // Duration of playing
{
TMR0H = (freq >> 8) & 0xFF; //Load TMR0H byte first
TMR0L = freq & 0xFF; // Load TMR0L byte next
while(!INTCONbits.TMR0IF); // Wait for timer
` INTCONbits.TMR0IF = 0; // Clear OVF Flag
LATA = ~LATA; // Invert output
}
PAUSE;
}
void main()
{
OSCCONbits.IRCF0=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF2=1;
T0CONbits.TMR0ON = 0; // Don't turn timer on yet
T0CONbits.T08BIT = 0; // Timer0 is configured as 16-bit timer
T0CONbits.T0CS = 0; // Use internal clock
T0CONbits.PSA = 1; // Prescaler is not assigned
T0CONbits.T0PS2 = 0;
T0CONbits.T0PS1 = 0;
T0CONbits.T0PS0 = 0;
while(!OSCCONbits.IOFS);
TRISA = 0b11111110; // Use RA0 as output
while(1)
{
playNote(3, WHOLE); // Section 1
playNote(3, WHOLE);
playNote(3, WHOLE);
playNote(1, WHOLE); // Section 2
playNote(3, HALF);
playNote(5, WHOLE);
playNote(7, WHOLE); // Section 3
playNote(7, WHOLE);
playNote(8, WHOLE);
playNote(5, WHOLE); // Section 4
playNote(7, HALF);
playNote(8, WHOLE);
playNote(12, WHOLE); // Section 5
playNote(0, WHOLE);
playNote(12, WHOLE);
playNote(7, WHOLE); // Section 6
playNote(8, HALF);
playNote(10, WHOLE);
playNote(12, WHOLE); // Section 7
playNote(12, WHOLE);
playNote(13, WHOLE);
playNote(10, WHOLE); // Section 8
playNote(10, HALF);
playNote(12, WHOLE);
playNote(5, WHOLE); // Section 9
playNote(1, WHOLE);
playNote(3, HALF);
playNote(3, LONG); // Section 10
playNote(10, WHOLE); // Section 11
playNote(10, WHOLE);
playNote(10, WHOLE);
playNote(10, WHOLE); // Section 12
playNote(8, HALF);
playNote(7, WHOLE);
playNote(8, WHOLE); // Section 13
playNote(8, WHOLE);
playNote(8, WHOLE);
playNote(8, WHOLE); // Section 14
playNote(7, HALF);
playNote(5, WHOLE);
playNote(5, WHOLE); // Section 15
playNote(7, WHOLE);
playNote(7, HALF);
playNote(0, LONG); // Section 16
playNote(15, WHOLE); // Section 17
playNote(15, WHOLE);
playNote(15, WHOLE);
playNote(15, WHOLE); // Section 18
playNote(13, HALF);
playNote(12, WHOLE);
playNote(13, WHOLE); // Section 19
playNote(13, WHOLE);
playNote(13, WHOLE);
playNote(13, WHOLE); // Section 20
playNote(12, HALF);
playNote(10, WHOLE);
playNote(7, WHOLE); // Section 21
playNote(8, HALF);
playNote(7, HALF);
playNote(5, HALF);
playNote(3, HALF);
playNote(7, WHOLE); // Section 22
playNote(8, HALF);
playNote(10, WHOLE);
playNote(12, WHOLE); // Section 23
playNote(5, WHOLE);
playNote(3, HALF);
playNote(3, LONG); // Section 24
playNote(12, WHOLE); // Section 25
playNote(13, HALF);
playNote(12, HALF);
playNote(10, HALF);
playNote(8, HALF);
playNote(7, WHOLE); // Section 26
playNote(5, HALF);
playNote(3, WHOLE);
playNote(5, WHOLE); // Section 27
playNote(7, WHOLE);
playNote(7, HALF);
playNote(0, LONG); // Section 28
Delay100TCYx(255);
}
}
A picture of my setup is depicted in the attachements and to see it working click the following link:
http://s974.photobucket.com/albums/ae227/ElectroNerdy/uC%20Video/?action=view¤t=PICSoudGenerator.mp4&newest=1
On the o'scope you'll notice that the waveform is somewhat distorted, this is due to the speaker. If I were to take that off, not only would you not have any sound (obviously), but it would then give you an adequate square wave.
I hope you all enjoyed this! If you have any suggestions or comments for me, please feel free to mention them! I would be grateful for any comments in order to edify myself.
I would like to thank 3v0 and Hayato for their help!
Austin
Attachments
-
281.8 KB Views: 72
-
276.5 KB Views: 53
Last edited: