If you, like Lao Zhou, especially liked to do damage when you were a child (you dare to dismantle any electrical appliances), you must have seen such a small horn below.
In fact, this kind of speaker was used by many tape recorders in the past, including the portable tape recorder bought for English listening in primary school. Well, it's the kind of recording tape. The recording tape is also called tape or cassette. It has two wheels. The power shaft of the recorder will drive the wheels to rotate, and then you can hear the sound.
When I was a child, when I walked home from school, I could see no less than ten stores selling tapes, including stationery stores, squatting on the roadside, and even some breakfast stores. As for whether it is genuine or not, you know. Anyway, 1.5 yuan to 2 yuan a box. If you save some pocket money, you can buy two or three boxes a week, and then you can go home again. Don't worry about being discovered by the elders, because they also like to listen. If they are discovered, they will share it with you.
The horn used in toys will be slightly smaller than this one, including round and oval; Lao Zhou once removed a square horn from an electronic organ. Based on Lao Zhou's early experience in dismantling the machine, square is very rare, and most of them are round.
If you buy online, you will generally buy those with welded DuPont wires and those without welded wires.
It's cool if there's a welding DuPont line. Go online directly; As for wireless, if you have good welding skills, you can also weld by yourself. If there is no electric soldering iron or solder wire, it doesn't matter. You can use an alligator clip with DuPont head to directly clamp the wiring hole. After all, the wires on both sides are far away. The two crocodile clips won't touch each other, so there's no need to worry about a short circuit.
In addition to the speakers described above, there is another module that can also play music, that is the buzzer.
Note that the buzzer is divided into passive buzzer and active buzzer. In the above figure, the passive buzzer is on the left and the active buzzer is on the right.
The active buzzer can sound as long as the level signal, and can only produce the sound of fixed pitch. Therefore, there is no way to let it play music. As you can see from the picture, the black cylinder (like cow dung) on the active buzzer is pasted with a paper label. If it is not torn off, the sound will be harsh but the volume is very low; If you tear off the paper tag, the volume becomes louder, but not so harsh. We have to use passive buzzer in this experiment to let the speaker play music, so we should see whether it is active or passive when buying.
Well, the above describes the devices to complete the experiment. You can choose whether to choose a small horn or a buzzer, because the two principles are the same - we learned in physics class that the pitch is determined by the frequency.
In the last rotten article, Lao Zhou pulled the experiment of PWM dimming. Because PWM can output level signals at different frequencies, setting different frequencies and sending PWM square wave can make the horn sound with different pitches. The horn cannot be directly connected to the power supply. In that case, music cannot be played. Only the sound of mine explosion can be heard. Again, it is to change the PWM frequency, not the duty cycle. Changing the duty cycle can only control the sound intensity.
Now let's start the experiment. In this experiment, Lao Zhou chose a very simple song, which everyone has heard, "only mother is good in the world". The brief spectrum is as follows:
The speed is 80 beats per minute, so the duration of each beat (quarter note) is 60 / 80 = 750 milliseconds. Next, let's determine the time value of each note in the song.
1. Quarter notes with dots, 750 + 750/2 = 1125 ms. The attachment point is to extend the time value of the current note by half, so the attachment point of a quarter note is to add the time value of a half beat.
2. Quarter note: 750ms.
3. Quaver: 750 / 2 = 375ms.
4. A half note, followed by a horizontal line, is two beats, 750 * 2= 1500 ms.
As for the frequency of each note, you can check it directly online.
Here, Lao Zhou selects the frequency (440 Hz) of the international standard A (Alto La) as the reference point of the Alto range, so he can get the frequency of each scale.
Scale | frequency | Final value | |
Bass part | Bass 5 | 195.998 | 196 Hz |
Bass 6 | 220.0 | 220 Hz | |
Bass 7 | 246.942 | 247 Hz | |
Baritone part | Alto 1 | 261.626 | 262 Hz |
Alto 2 | 293.665 | 294 Hz | |
Alto 3 | 329.628 | 330 Hz | |
Alto 4 | 349.228 | 349 Hz | |
Alto 5 | 391.995 | 392 Hz | |
Alto 6 | 440.0 | 440 Hz | |
Alto 7 | 493.883 | 494 Hz | |
Treble part | Treble 1 | 523.251 | 523 Hz |
Encapsulate a class named {NotePlayer, and call the PlayNote method to play the sound of the specified frequency for X milliseconds.
class NotePlayer : IDisposable { private PwmChannel _pwmch = null; // Constructor public NotePlayer() => _pwmch = PwmChannel.Create(0, 0); public void Dispose() { _pwmch?.Dispose(); } /// <summary> /// Play a specified frequency of sound /// </summary> /// <param name="freq">Sound frequency</param> /// <param name="duration">Duration (MS)</param> public void PlayNote(int freq, int duration) { _pwmch.Frequency = freq; _pwmch.Start(); // Start playing DelayHelper.DelayMillis(duration); _pwmch.Stop(); // stop playing } }
The core part is the PlayNote method. First, set the frequency, then call the PwmChannel Start method to start sending the pulse, then continue for a period of time (this is the base note time value, see above), after playing, call Stop method to stop the pulse, the horn does not give voice.
There is an auxiliary method, DelayMillis, to pause X milliseconds. You can use thread Sleep method, which Lao Zhou wrote here, uses another idea - this is written with reference to Microsoft.
class DelayHelper { public static void DelayMillis(int ms) { long ticks = ms * Stopwatch.Frequency / 1000; long targetTicks = Stopwatch.GetTimestamp() + ticks; do { Thread.SpinWait(1); } while (Stopwatch.GetTimestamp() < targetTicks); } }
The principle is to use the Stopwatch class timer. GetTimestamp method can always return the latest Tick of the timer, then enter the loop, and Thread. middle note in each round of the loop. Spinwait (1) only waits for one code cycle, which is very short, microsecond level. The loop exit condition is that the tick returned by the gettimestamp method reaches the predetermined time.
This scheme is suitable for waiting schemes with high time accuracy, such as waiting for tens of microseconds.
One thing to think about here: if we write the notes of each song into the code, we have to change the code a lot if we want to play other songs, which is very inflexible. Of course, a board like Arduino, which has no operating system and small internal storage space, either writes the code to death, or adds an external SD card module, puts the note information on the SD card, and then reads it in the code. It's a hell of a job for raspberry pie. Raspberry pie comes with an operating system and has its own micro SD card interface, which is very convenient to read and write files.
Therefore, Lao Zhou input the note frequency and time value of "only mother is good in the world" into a text file. If you want to change the music, you can change the file directly. The format is very simple, one note per line, including frequency and time value, separated by spaces. So the document of "only mother is good in the world" is as follows:
440 1125 392 375 330 750 392 750 523 750 440 375 392 375 440 1500 0 750 330 750 392 375 440 375 392 750 330 375 294 375 262 375 220 375 392 375 330 375 294 1500 0 750 294 1125 330 375 392 750 392 375 440 375 330 1125 294 375 262 1500 0 750 392 1125 330 375 294 375 262 375 220 375 262 375 196 1500 0 750
Among them, you will see several lines. The note frequency is 0. This is to make the horn pause.
Write another} MusicPlayer class, which can control the playback of the whole song and specify the number of cycles.
public class MusicPlayer : IDisposable { private bool _playing = false; // Indicates whether it is playing NotePlayer _noteplayer = null; Stream _stream = null;// File stream #region Constructor public MusicPlayer(string noteFilepath) { _noteplayer = new NotePlayer(); _stream = File.OpenRead(noteFilepath); } #endregion /// <summary> /// Play music /// </summary> /// <param name="count">Number of repetitions,-1 Represents an infinite loop</param> public void Start(int count = 1) { _playing = true; if(count == -1) // Infinite loop { while(_playing) { PlaySong(); } } else { while (_playing && count > 0) { PlaySong(); count--; } } } /// <summary> /// stop playing /// </summary> public void Stop() => _playing = false; public void Dispose() { _stream?.Close(); _stream?.Dispose(); _noteplayer?.Dispose(); } #region Private method private void PlaySong() { string line = null; _stream.Seek(0L, SeekOrigin.Begin); // There must be leaveOpen Parameter is true // Otherwise reader When closed, the file will be released directly // You can't play it a second time using StreamReader _noteReader = new(_stream, leaveOpen: true); line = _noteReader.ReadLine(); int freq, dura; while (_playing && (line is not null)) { string[] _s = line.Split(' '); if (!int.TryParse(_s[0].Trim(), out freq)) { continue; } if (!int.TryParse(_s[1].Trim(), out dura)) { continue; } if (freq < 0 || dura < 0) { continue; } // Play notes _noteplayer.PlayNote(freq, dura); // Read the next note after playing line = _noteReader.ReadLine(); } } #endregion }
Open the file containing note frequency and time value and read it line by line. For each line read out, separate the string with a space as a separator - a string array that can be split into two elements. The first element is the frequency and the second element is the time value, which is then played with the previously encapsulated PlayNote.
Note that when instantiating StreamReader, you must ensure that the file is not closed when it is released, otherwise the file can only be played once after it is opened, and subsequent repeated playback will report an error.
Return to the Main method of the program.
class Program { // Declaration field static MusicPlayer ply = null; static void Main(string[] args) { // Clean up resources when the cancel key is pressed Console.CancelKeyPress += (_,_) => { ply?.Stop(); ply?.Dispose(); }; ply = new("./test01.txt"); // Try to get the number of plays through the command line parameter int count = -1; if(args is { Length: > 0}) { string s = args[0]; if(!int.TryParse(s,out count)) { count = -1; } } Console.WriteLine($"play{count}Times"); ply.Start(count); ply.Dispose(); } }
Here, it is also realized to set the cycle playback times through the command line parameters, - 1 is the single cycle.
Finally, it is released and uploaded to raspberry pie.
Let's see how to connect.
1, If you use a small horn, pay attention to the positive and negative poles. As shown in the following figure, the left side is the negative pole (with "-" on the right side of the wiring hole) and the right side is the positive pole (with "+" on the left side of the wiring hole). The negative pole is connected to the GND of raspberry pie (there are several, choose any one), and the positive pole is connected in series with a resistance greater than 100 Ω (the resistance must be connected, otherwise there will be a broken sound, and the horn will be burned over a long time. The resistance value can be 100 - 200, and the noise will be lower when the resistance is higher). Then GPIO 18 is connected. As you know from the previous article, only this pin of 4B can generate the first PWM. You can try other raspberry pies yourself.
2, Use a passive buzzer. This depends on what the module you buy looks like. Lao Zhou bought this one with three pins.
VCC is connected to the raspberry pie power supply pin. It is compatible with 3.3V and 5V. Don't worry. There is a resistance of 100 Ω on it.
GND to raspberry pie.
IO connected to GPIO 18 of raspberry pie.
Execute the program and you can enjoy music.
Sample source code, please click here
=====================================================================
In addition, the development board can only generate square waves, not sinusoidal (including cosine) waves, let alone superimposed AC sound waves. Therefore, it can only produce different pitches according to the frequency. You can't control its timbre, let alone become a self-made Midi. Raspberry pie motherboard has a 3.5mm audio interface. To watch movies and listen to songs, just like a computer, plug in a headset or active speaker (such as subwoofer). You can also buy a special power amplifier module (for a board without audio interface like Arduino) and plug in the stereo without writing code driver. Of course, there are also Bluetooth power amplifier modules. There is no limit to online shopping. It is possible to buy anything. So it's easier to think about DIY these days.
In the next rotten article, Lao Zhou will talk about using PWM to drive the steering gear and adjust the speed of the fan.