差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
mp_buzz [2021/10/01 23:03]
gongyusu
mp_buzz [2023/08/01 10:12] (当前版本)
group003
行 1: 行 1:
-## 用蜂鸣器播放音乐+### 可以在线制作Buzz音乐的工具
  
-### 1. 编程蜂鸣器  +源自:[[https://​onlinesequencer.net|onlinesequencer]]
- +
-1.首先从machine库导入Pin和PWM,从utime库导入sleep+
  
 +James的Buzz_music代码:
 <code python> <code python>
-from machine import Pin, PWM 
-from utime import sleep 
-</​code>​ 
  
-2.初始化PWM(也就是脉宽调制)到管脚PIO(22),并分配它为变量buzzer。 
- 
-<code python> 
-buzzer = PWM(Pin(22)) 
-</​code>​ 
- 
-3.给变量buzzer分配一个频率属性,选择10到12,​000之间的数值,数值越大音调越高,我们可以设定为500. ​ 
- 
-<code python> 
-buzzer.freq(500) 
-</​code>​ 
- 
-4.将蜂鸣器对象的duty_u16属性设置为1000,这就能让蜂鸣器尽可能地响。更低的值更安静,0根本没有声音。 
- 
-<code python> 
-buzzer.duty_u16(1000) 
-</​code>​ 
- 
-5.设置1秒的延迟,然后将duty设置为0,这样声音就会停止。如果不这样做,即使程序执行完毕,嗡嗡声也会继续。 
- 
-<code python> 
-sleep(1) 
-buzzer.duty_u16(0) 
-</​code>​ 
- 
-最终的代码: ​ 
- 
-<code python> 
 from machine import Pin, PWM from machine import Pin, PWM
-from utime import ​sleep+from math import ​ceil
  
-buzzer = PWM(Pin(22)) 
-buzzer.freq(500) 
-buzzer.duty_u16(1000) 
-sleep(1) 
-buzzer.duty_u16(0) 
-</​code>​ 
- 
-### 2. 播放音乐 
-因为你可以使用不同的频率,你可以创造一个完整的音符阵列。网上有一些音符频率的列表,其中许多可以追溯到[[https://​github.com/​bhagman/​Tone|Brett Hagman在Github上的Arduino音调库]]。我们将使用这些值创建一个列表,以便在代码早期播放任何歌曲。 
- 
-1.在管脚PIO(22)上导入必要的库并初始化PWM。 
- 
-<code python> 
-from machine import Pin, PWM 
-from utime import sleep 
- 
-buzzer = PWM(Pin(22)) 
-</​code>​ 
- 
-2.使用下列值创建一个名为tones的字典。 
- 
-<code python> 
 tones = { tones = {
-"B0": 31, +    '​C0':​16,​ 
-"C1": 33, +    '​C#​0':​17,​ 
-"​CS1"​: 35, +    '​D0':​18,​ 
-"D1": 37, +    '​D#​0':​19,​ 
-"​DS1"​: 39, +    '​E0':​21,​ 
-"E1": 41, +    '​F0':​22,​ 
-"F1": 44, +    '​F#​0':​23,​ 
-"​FS1"​: 46, +    '​G0':​24,​ 
-"G1": 49, +    '​G#​0':​26,​ 
-"​GS1"​: 52, +    '​A0':​28,​ 
-"A1": 55, +    '​A#​0':​29,​ 
-"​AS1"​: 58, +    'B0':31, 
-"B1": 62, +    '​C1':33, 
-"C2": 65, +    '​C#​1'​:35, 
-"​CS2"​: 69, +    '​D1':37, 
-"D2": 73, +    '​D#​1'​:39, 
-"​DS2"​: 78, +    '​E1':41, 
-"E2": 82, +    '​F1':44, 
-"F2": 87, +    '​F#​1'​:46, 
-"​FS2"​93+    '​G1':49, 
-"G2": 98, +    '​G#​1'​:52, 
-"​GS2"​: 104, +    '​A1':55, 
-"A2": 110, +    '​A#​1'​:58, 
-"​AS2"​: 117, +    '​B1':62, 
-"B2": 123, +    '​C2':65, 
-"C3": 131, +    '​C#​2'​:69, 
-"​CS3"​: 139, +    '​D2':73, 
-"D3": 147, +    '​D#​2'​:78, 
-"​DS3"​: 156, +    '​E2':82, 
-"E3": 165, +    '​F2':87, 
-"F3": 175, +    '​F#​2'​:92
-"​FS3"​: 185, +    '​G2':98, 
-"G3": 196, +    '​G#​2'​:104, 
-"​GS3"​: 208, +    '​A2':110, 
-"A3": 220, +    '​A#​2'​:117, 
-"​AS3"​: 233, +    '​B2':123, 
-"B3": 247, +    '​C3':131, 
-"C4": 262, +    '​C#​3'​:139, 
-"​CS4"​: 277, +    '​D3':147, 
-"D4": 294, +    '​D#​3'​:156, 
-"​DS4"​: 311, +    '​E3':165, 
-"E4": 330, +    '​F3':175, 
-"F4": 349, +    '​F#​3'​:185, 
-"​FS4"​: 370, +    '​G3':196, 
-"G4": 392, +    '​G#​3'​:208, 
-"​GS4"​: 415, +    '​A3':220, 
-"A4": 440, +    '​A#​3'​:233, 
-"​AS4"​: 466, +    '​B3':247, 
-"B4": 494, +    '​C4':262, 
-"C5": 523, +    '​C#​4'​:277, 
-"​CS5"​: 554, +    '​D4':294, 
-"D5": 587, +    '​D#​4'​:311, 
-"​DS5"​: 622, +    '​E4':330, 
-"E5": 659, +    '​F4':349, 
-"F5": 698, +    '​F#​4'​:370, 
-"​FS5"​: 740, +    '​G4':392, 
-"G5": 784, +    '​G#​4'​:415, 
-"​GS5"​: 831, +    '​A4':440, 
-"A5": 880, +    '​A#​4'​:466, 
-"​AS5"​: 932, +    '​B4':494, 
-"B5": 988, +    '​C5':523, 
-"C6": 1047, +    '​C#​5'​:554, 
-"​CS6"​: 1109, +    '​D5':587, 
-"D6": 1175, +    '​D#​5'​:622, 
-"​DS6"​: 1245, +    '​E5':659, 
-"E6": 1319, +    '​F5':698, 
-"F6": 1397, +    '​F#​5'​:740, 
-"​FS6"​: 1480, +    '​G5':784, 
-"G6": 1568, +    '​G#​5'​:831, 
-"​GS6"​: 1661, +    '​A5':880, 
-"A6": 1760, +    '​A#​5'​:932, 
-"​AS6"​: 1865, +    '​B5':988, 
-"B6": 1976, +    '​C6':1047, 
-"C7": 2093, +    '​C#​6'​:1109, 
-"​CS7"​: 2217, +    '​D6':1175, 
-"D7": 2349, +    '​D#​6'​:1245, 
-"​DS7"​: 2489, +    '​E6':1319, 
-"E7": 2637, +    '​F6':1397, 
-"F7": 2794, +    '​F#​6'​:1480, 
-"​FS7"​: 2960, +    '​G6':1568, 
-"G7": 3136, +    '​G#​6'​:1661, 
-"​GS7"​: 3322, +    '​A6':1760, 
-"A7": 3520, +    '​A#​6'​:1865, 
-"​AS7"​: 3729, +    '​B6':1976, 
-"B7": 3951, +    '​C7':2093, 
-"C8": 4186, +    '​C#​7'​:2217, 
-"​CS8"​: 4435, +    '​D7':2349, 
-"D8": 4699, +    '​D#​7'​:2489, 
-"​DS8"​: 4978+    '​E7':2637, 
 +    '​F7':2794, 
 +    '​F#​7'​:2960, 
 +    '​G7':3136, 
 +    '​G#​7'​:3322, 
 +    '​A7':3520, 
 +    '​A#​7'​:3729, 
 +    '​B7':3951, 
 +    '​C8':4186, 
 +    '​C#​8'​:4435, 
 +    '​D8':4699, 
 +    '​D#​8'​:4978
 +    '​E8':​5274,​ 
 +    '​F8':​5588,​ 
 +    '​F#​8':​5920,​ 
 +    '​G8':​6272,​ 
 +    '​G#​8':​6645,​ 
 +    '​A8':​7040,​ 
 +    '​A#​8':​7459,​ 
 +    '​B8':​7902,​ 
 +    '​C9':​8372,​ 
 +    '​C#​9':​8870,​ 
 +    '​D9':​9397,​ 
 +    '​D#​9':​9956,​ 
 +    '​E9':​10548,​ 
 +    '​F9':​11175,​ 
 +    '​F#​9':​11840,​ 
 +    '​G9':​12544,​ 
 +    '​G#​9':​13290,​ 
 +    '​A9':​14080,​ 
 +    '​A#​9':​14917,​ 
 +    '​B9':​15804
 } }
-</​code>​ 
  
-3.为你的歌曲创建一个音符列表(又名数组)。用字母P表示音乐中的停顿。每个音符都应该用引号括起来。+#Time, Note, Duration, Instrument ​(onlinesequencer.net schematic format) 
 +#0 D4 8 0;0 D5 8 0;0 G4 8 0;8 C5 2 0;10 B4 2 0;12 G4 2 0;14 F4 1 0;15 G4 17 0;16 D4 8 0;24 C4 8 0
  
-<code python> +class music: 
-song ["​E5"​,"​G5"​,"​A5"​,"​P"​,"​E5"​,"​G5","​B5","​A5","​P","​E5","​G5","​A5","​P","​G5","​E5"​+    def __init__(self,​ songString='0 D4 8 0'looping=Truetempo=3duty=2512pin=Nonepins=[Pin(0)]): 
-</​code>​+        ​self.tempo = tempo 
 +        self.song = songString 
 +        self.looping = looping 
 +        self.duty = duty 
 +         
 +        self.stopped = False 
 +         
 +        self.timer = -1 
 +        self.beat = -1 
 +        self.arpnote = 0 
 +         
 +        self.pwms = [] 
 +         
 +        if (not (pin is None)): 
 +            pins = [pin] 
 +             
 +        i = 0 
 +        for pin in pins: 
 +            self.pwms.append(PWM(pins[i])) 
 +            i = i + 1 
 +         
 +        self.notes = []
  
-向在这个帖子上分享这段著名riff音符的人们致敬。+        self.playingNotes = [] 
 +        self.playingDurations = []
  
-4.创建一个名为playtone的函数,可以使用任意频率并以最大音量播放。 
  
-<code python> +        #Find the end of the song 
-def playtone(frequency): +        ​self.end = 0 
-    ​buzzer.duty_u16(1000+        splitSong = self.song.split(";"​) 
-    ​buzzer.freq(frequency+        for note in splitSong
-</code>+            snote = note.split(" "
 +            ​testEnd = round(float(snote[0])) + ceil(float(snote[2])
 +            if (testEnd ​self.end):​ 
 +                self.end = testEnd 
 +                 
 +        #Create empty song structure 
 +        while (self.end > len(self.notes)):​ 
 +            self.notes.append(None)
  
-5.创建一个名为bequiet的函数,通过将duty_u16更改为0来使蜂鸣器静音。+        #Populate song structure with the notes 
 +        for note in splitSong:​ 
 +            snote = note.split("​ ") 
 +            beat = round(float(snote[0])); 
 +             
 +            if (self.notes[beat] == None): 
 +                self.notes[beat] = [] 
 +            self.notes[beat].append([snote[1],​ceil(float(snote[2]))]) #Note, Duration
  
-<code python> 
-def bequiet(): 
-    buzzer.duty_u16(0) 
-</​code>​ 
  
-6.创建一个名为playsong的函数,您将使用它来遍历音符数组并播放每一个音符,或者在看到P时暂停。+        #Round up end of song to nearest bar 
 +        self.end = ceil(self.end / 8) * 8 
 +     
 +    def stop(self):​ 
 +        for pwm in self.pwms:​ 
 +            pwm.deinit() 
 +        self.stopped = True 
 +         
 +    def tick(self):​ 
 +        if (not self.stopped):​ 
 +            self.timer = self.timer + 1 
 +             
 +            #Loop 
 +            if (self.timer % (self.tempo * self.end) == 0 and (not (self.timer == 0))): 
 +                if (not self.looping):​ 
 +                    self.stop() 
 +                    return False 
 +                self.beat = -1 
 +                self.timer = 0 
 +             
 +            #On Beat 
 +            if (self.timer % self.tempo == 0): 
 +                self.beat = self.beat + 1
  
-<code python> +                #Remove expired notes from playing list 
-def playsong(mysong): +                i = 0 
-    ​for ​i in range(len(mysong)): +                while (i len(self.playingDurations)):​ 
-        if (mysong[i] == "​P"​): +                    ​self.playingDurations[i] = self.playingDurations[i] - 1 
-            ​bequiet()+                    if (self.playingDurations[i] <= 0): 
 +                        ​self.playingNotes.pop(i
 +                        self.playingDurations.pop(i) 
 +                    else: 
 +                        i = i + 1 
 +                         
 +                #Add new notes and their durations to the playing list 
 +                 
 +                """​ 
 +                #Old method runs for every note, slow to process on every beat and causes noticeable delay 
 +                ssong = song.split(";"​) 
 +                for note in ssong: 
 +                    snote = note.split(" ") 
 +                    if int(snote[0]) == beat: 
 +                        playingNotes.append(snote[1]) 
 +                        playingDurations.append(int(snote[2])) 
 +                """​ 
 +                 
 +                if (self.beat < len(self.notes)): 
 +                    if (self.notes[self.beat!None): 
 +                        for note in self.notes[self.beat]:​ 
 +                            self.playingNotes.append(note[0]) 
 +                            self.playingDurations.append(note[1]) 
 +                 
 +                #Only need to run these checks on beats 
 +                i 
 +                for pwm in self.pwms:​ 
 +                    if (i >= len(self.playingNotes)): 
 +                        pwm.duty_u16(0) 
 +                    else: 
 +                        #Play note 
 +                        pwm.duty_u16(self.duty) 
 +                        pwm.freq(tones[self.playingNotes[i]]) 
 +                    i = i + 1 
 +            ​ 
 + 
 +            #Play arp of all playing notes 
 +            if (len(self.playingNotes> len(self.pwms)):​ 
 +                self.pwms[len(self.pwms)-1].duty_u16(self.duty) 
 +                if (self.arpnote > len(self.playingNotes)-len(self.pwms)):​ 
 +                    self.arpnote = 0 
 +                self.pwms[len(self.pwms)-1].freq(tones[self.playingNotes[self.arpnote+(len(self.pwms)-1)]]) 
 +                self.arpnote = self.arpnote + 1 
 +                 
 +            return True
         else:         else:
-            ​playtone(tones[mysong[i]]) +            ​return False
-        sleep(0.3) +
-    bequiet()+
 </​code>​ </​code>​
  
-是这样的。首先,我们创建一个for循环来遍历myssong数组中的所有值。如果值等于P,则触发be quiet;​如果值不等于P,则触发playtone。注意,playtone需要一个数字频率值,因此我们必须从音调列表中获取每个音符的数字。如果我们只是播放tone(myssong [i]),它将失败,因为它将尝试播放字符串“E5”,而不是频率659,这是它需要的整数。 +示例代码:example.py
- +
-对于每个音调或暂停,系统维持0.3秒的睡眠状态。如果你想要更快的节奏,你可以降低时间。如果你想要慢节奏,那就加快节奏。 +
- +
-7.使用song参数触发playsong函数。+
  
 <code python> <code python>
-playsong(song) +from buzzer_music import music 
-</​code>​+from time import sleep
  
-运行此代码时,您将听到蜂鸣器播放熟悉的旋律。完整的代码应该是这样的:​+#Example songs
  
-<code python>​ +song '0 A#4 1 1;2 F5 1 1;4 D#5 1 1;8 D5 1 1;11 D5 1 1;6 A#4 1 1;14 D#5 1 1;18 A#4 1 1;20 D#5 1 1;22 A#4 1 1;24 D5 1 1;27 D5 1 1;30 D#5 1 1;32 A#4 1 1;34 F5 1 1;36 D#5 1 1;38 A#4 1 1;40 D5 1 1;43 D5 1 1;46 D#5 1 1;50 A#4 1 1;52 D#5 1 1;54 G5 1 1;56 F5 1 1;59 D#5 1 1;62 F5 1 1;64 A#4 1 1;66 F5 1 1;68 D#5 1 1;70 A#4 1 1;72 D5 1 1;75 D5 1 1;78 D#5 1 1;82 A#4 1 1;84 D#5 1 1;86 A#4 1 1;88 D5 1 1;91 D5 1 1;94 D#5 1 1;96 A#4 1 1;100 D#5 1 1;102 A#4 1 1;104 D5 1 1;107 D5 1 1;110 D#5 1 1;114 A#4 1 1;116 D#5 1 1;118 G5 1 1;120 F5 1 1;123 D#5 1 1;126 F5 1 1;98 F5 1 1'
-from machine import Pin, PWM +
-from utime import sleep +
-buzzer ​PWM(Pin(15))+
  
-tones = { +from machine import Pin
-"​B0":​ 31, +
-"​C1":​ 33, +
-"​CS1":​ 35, +
-"​D1":​ 37, +
-"​DS1":​ 39, +
-"​E1":​ 41, +
-"​F1":​ 44, +
-"​FS1":​ 46, +
-"​G1":​ 49, +
-"​GS1":​ 52, +
-"​A1":​ 55, +
-"​AS1":​ 58, +
-"​B1":​ 62, +
-"​C2":​ 65, +
-"​CS2":​ 69, +
-"​D2":​ 73, +
-"​DS2":​ 78, +
-"​E2":​ 82, +
-"​F2":​ 87, +
-"​FS2":​ 93, +
-"​G2":​ 98, +
-"​GS2":​ 104, +
-"​A2":​ 110, +
-"​AS2":​ 117, +
-"​B2":​ 123, +
-"​C3":​ 131, +
-"​CS3":​ 139, +
-"​D3":​ 147, +
-"​DS3":​ 156, +
-"​E3":​ 165, +
-"​F3":​ 175, +
-"​FS3":​ 185, +
-"​G3":​ 196, +
-"​GS3":​ 208, +
-"​A3":​ 220, +
-"​AS3":​ 233, +
-"​B3":​ 247, +
-"​C4":​ 262, +
-"​CS4":​ 277, +
-"​D4":​ 294, +
-"​DS4":​ 311, +
-"​E4":​ 330, +
-"​F4":​ 349, +
-"​FS4":​ 370, +
-"​G4":​ 392, +
-"​GS4":​ 415, +
-"​A4":​ 440, +
-"​AS4":​ 466, +
-"​B4":​ 494, +
-"​C5":​ 523, +
-"​CS5":​ 554, +
-"​D5":​ 587, +
-"​DS5":​ 622, +
-"​E5":​ 659, +
-"​F5":​ 698, +
-"​FS5":​ 740, +
-"​G5":​ 784, +
-"​GS5":​ 831, +
-"​A5":​ 880, +
-"​AS5":​ 932, +
-"​B5":​ 988, +
-"​C6":​ 1047, +
-"​CS6":​ 1109, +
-"​D6":​ 1175, +
-"​DS6":​ 1245, +
-"​E6":​ 1319, +
-"​F6":​ 1397, +
-"​FS6":​ 1480, +
-"​G6":​ 1568, +
-"​GS6":​ 1661, +
-"​A6":​ 1760, +
-"​AS6":​ 1865, +
-"​B6":​ 1976, +
-"​C7":​ 2093, +
-"​CS7":​ 2217, +
-"​D7":​ 2349, +
-"​DS7":​ 2489, +
-"​E7":​ 2637, +
-"​F7":​ 2794, +
-"​FS7":​ 2960, +
-"​G7":​ 3136, +
-"​GS7":​ 3322, +
-"​A7":​ 3520, +
-"​AS7":​ 3729, +
-"​B7":​ 3951, +
-"​C8":​ 4186, +
-"​CS8":​ 4435, +
-"​D8":​ 4699, +
-"​DS8":​ 4978 +
-}+
  
-song = ["​E5","​G5","​A5","​P","​E5","​G5","​B5","​A5","​P","​E5","​G5","​A5","​P","​G5","​E5"​]+#One buzzer on pin 0 
 +mySong = music(song, pins=[Pin(19)])
  
-def playtone(frequency):​ +#Four buzzers 
-    ​buzzer.duty_u16(1000) +#mySong = music(song, pins=[Pin(0),Pin(1),Pin(2),Pin(3)])
-    buzzer.freq(frequency) +
- +
-def bequiet():​ +
-    buzzer.duty_u16(0) +
- +
-def playsong(mysong)+
-    for i in range(len(mysong)): +
-        if (mysong[i] == "​P"​)+
-            bequiet() +
-        else: +
-            playtone(tones[mysong[i]]) +
-        sleep(0.3) +
-    bequiet() +
-playsong(song)+
  
 +while True:
 +    print(mySong.tick())
 +    sleep(0.04)
 </​code>​ </​code>​