MicroPython-Hack-piezo

De MCHobby - Wiki
Sauter à la navigation Sauter à la recherche


MCHobby investit du temps et de l'argent dans la réalisation de traduction et/ou documentation. C'est un travail long et fastidieux réalisé dans l'esprit Open-Source... donc gratuit et librement accessible.
SI vous aimez nos traductions et documentations ALORS aidez nous à en produire plus en achetant vos produits chez MCHobby.

Ce que nous faisons

Jusqu'à maintenant nous avons contrôlé la lumière, le mouvement et les électrons. Attaquons nous maintenant au son.

Mais le son est un phénomène analogique, bien que notre PyBoard dispose d'une sortie analogique, nous ne disposons pas d'une mémoire suffisamment grande pour y stocker un morceau de musique (a moins d'utiliser une carte SD).

Nous allons donc aller droit au but et produire directement des sons. Une fois encore, nous allons nous appuyer sur l'incroyable vitesse de traitement de la PyBoard pour imiter le comportement analogique. Pour y arriver, nous allons raccorder un composant piezo sur une des broches PWM de la PyBoard.

Un piezo fait un petit « clic » chaque fois qu'il est traversé par un courant. Si nous envoyons des impulsions à la bonne fréquence (par exemple, 440 fois par seconde pour obtenir un La (A)) ces « clics » combinés produiront une note. Essayons donc d'expérimenter cette particularités et de faire jouer « A vous dirais-je maman » sur notre PyBoard.

Sélection du Timer et Channel

Dans ce montage, nous allons utiliser la capacité qu'a la PyBoard de manipuler la fréquence de ses Timers pendant que l'on génère un signal PWM, de la sorte nous allons pouvoir produire des notes et même les changer à la volée.

Nous allons utiliser la broche (Y2) pour piloter le Buzzer en PWM. Comme nous l'avons déjà fait par le passé, il nous faut identifier le Timer et le Channel qui y correspond.

 
Crédit: MicroPython micropython.org

En examinant le graphique de référence de la carte PyBoard (ci-dessous), nous pouvons constater que la broche Y2 est est connectée sur le canal 2 ( dit channel 2) du Timer 8. Regarder le graphique, vous noterez la terminologie TIM8 CH2 pour Y2.

Le montage

Le matériel nécessaire

Résistance de 100 Ohms (brun-noir-brun)
x1

Piezo buzzer
x1

 

Tous ces éléments sont disponible sur shop.mchobby.be

schéma

 

Le montage

 
Made with - réalisé avec - Fritzing fritzing.org

Le code

Voici un script élémentaire qui permet de jouer une mélodie.

La mélodie est encodée dans une chaîne de caractère.

# Commande élémentaire d'un Piezo Buzzer à l'aide de MicroPython PyBoard
# Simple Piezo Buzzer driving with MicroPython Pyboard 
#   http://shop.mchobby.be/product.php?id_product=57
#
# Voir Tutoriel - See our french tutorial
#   http://wiki.mchobby.be/index.php?title=MicroPython-Hack-piezo
# Voir les tutoriels "Pyb Discovery Kit" / see the "Pyb Discovery Kit" tutorials 
#   http://wiki.mchobby.be/index.php?title=MicroPython.Pyboard.Discovery 
#
from pyb import Pin, Timer, udelay

# Configurer les broches PWM pour la sortie sur buzzer
p2 = Pin("Y2") # Broche Y2 avec timer 8 et Channel 2
tim = Timer(8, freq=3000)
ch = tim.channel(2, Timer.PWM, pin=p2)

# Notes/tonalite simple avec frequence correspondantes
notes = { ' ' : 0,   # silence,
          'c' : 261, # Do
          'd' : 294, # Ré 
          'e' : 329, # Mi
          'f' : 349, # Fa
          'g' : 392, # Sol
          'a' : 440, # La
          'b' : 493, # Si 
          'C' : 523 # Do
        }

# Jouer une mélodie:
#   Liste de Note + Rythme (separe par des virgules)
#   Premier caractere = la note/tonalite
#   Second caractere = rythme (manquant=defaut=1)
tune = "c,c,g,g,a,a,g2,f,f,e,e,d,d,c2, 4"
tune2 = "c2,c,d3,c3,f3,e3,c2,c,d3,c3,g3,f3, 4"
tempo = 300

# Jouer une frequence donnee (donc une note)
def play_freq( freq ):
    if freq == 0: 
        ch.pulse_width_percent( 0 )
    else:
        tim.freq( freq )
        ch.pulse_width_percent( 30 )

# jouer les notes abcdef... pendant une duree donnee
def play_note( note, duration ):
    # Transforme la note en frequence
    freq = notes[ note ]
    play_freq( freq )
    # Transforme la duree en temp (1=1000micros, 2=2000micros, etc)
    udelay( duration * 1000 ) # temps en micro-second

# Joue toutes les notes connues (du dictionnaire, test play_tone) 
def test_notes():
    note_duration = 2
    for note, freq in notes.items():
        print(note)
        play_note( note, tempo * note_duration )
        pyb.delay(300)

# Joue une mélodie encodée dans une chaine de caractere
def play_tune( tune_string ):
    tune_list = tune_string.split( ',' )
    duration = 1
    for tune_item in tune_list:
        # print( tune_item )
        if len( tune_item )>1:
            try:
                duration = int( tune_item[1:] )
            except:
                raise ValueError( 'Invalid duration %s for note %s' % (tune_item[1:], tune_item[0]) )
        else:
            duration = 1

        # Jouer la note
        play_note( tune_item[0], tempo * duration )
        # Pause entre 2 notes
        play_freq( 0 )
        udelay( (tempo * 1000) // 2 )   

# test_notes()
play_tune( tune ) # A vous dirais-je maman
# play_tune( tune2 ) # Joyeux anniversaire 

# Pour forcer le silence
# play_note( ' ', 1 )

Cela ne fonctionne pas?

Voici 3 choses à essayer.

Pas de son?

Etant donné la taille et la forme d'un piezo (un gros cylindre). Il est facile de le placer dans le mauvais trou sur le breadboard.

Vérifiez son emplacement.

Arrêter la mélodie

Je n'arrive plus à penser pendant que ma PyBoard joue une mélodie

Il suffit de débrancher le piezo pendant que vous êtes occupé.

Ensuite, chargez votre nouveau programme et rebranchez le piezo

Une autre mélodie

Fatigué d'entendre « A vous dirais- je maman » ?

Le code est écrit de telle sorte qu'il vous sera facile d'ajouter vos propres mélodies.

Jetez un coup d'œil sur la section ci-dessous.

Faire encore mieux

Modifier la vitesse

Il est possible de modifier la vitesse de la mélodie en modifiant la valeur de la variable tempo.

Le temps de chaque note est calculé à l'aide de variables de telle sorte que nous pouvons modifier le son de chaque note ainsi que le temps de chaque note.

Pour changer la vitesse d'une mélodie, il ne faut changer qu'une ligne.

tempo = 300

Utiliser une valeur plus grande pour ralentir la mélodie et une plus petite valeur pour l'accélérer.

Adapter les notes

Si vous trouvez que les notes ne correspondent pas bien à la mélodie, cela peut également être corrigé. Contrairement à de nombreuses plateformes, sur la PyBoard, vous pouvez indiquer directement la fréquence de la note (comme la fréquence à laquelle oscille une corde de guitare).

Pour ajuster une note, il suffit de modifier sa fréquence correspondante dans le dictionnaire notes. Chaque note étant identifié par son code dans la codification anglosaxone (nous employons Do pour le "Do" mais les anglosaxons utilisent la lettre "c").

Par exemple c = Do = 261 Hertz.

notes = { ' ' : 0,   # silence,
          'c' : 261, # Do
          'd' : 294, # Ré 
          'e' : 329, # Mi
          'f' : 349, # Fa
          'g' : 392, # Sol
          'a' : 440, # La
          'b' : 493, # Si 
          'C' : 523 # Do
        }

Utiliser une classe

Dans le code ci-dessous, nous allons transformer le code présenté ci-dessus en classe (plus pratique à manipuler) et présenter une seconde mélodie :-) .

# Commande d'un Piezo Buzzer à l'aide de MicroPython PyBoard
# Drive a Piezo Buzzer with MicroPython Pyboard 
#   http://shop.mchobby.be/product.php?id_product=57
#
# Voir Tutoriel - See our french tutorial
#   http://wiki.mchobby.be/index.php?title=MicroPython-Hack-piezo
# Voir les tutoriels "Pyb Discovery Kit" / see the "Pyb Discovery Kit" tutorials 
#   http://wiki.mchobby.be/index.php?title=MicroPython.Pyboard.Discovery 
#
from pyb import Pin, Timer, udelay

class Piezo:
    """ Driver piezo buzzer wired on a PWM Pin
    
    Use the Pin Y2 by default, wire the piezo with a 100 Ohms resistor """
    notes = { ' ' : 0,   # silence,
              'c' : 261, # Do
              'd' : 294, # Ré 
              'e' : 329, # Mi
              'f' : 349, # Fa
              'g' : 392, # Sol
              'a' : 440, # La
              'b' : 493, # Si 
              'C' : 523 # Do
            }

    def __init__(self, tempo=300, pin="Y2", timer=8, channel=2 ):
        """ initialzation 
        :param tempo: tempo of tune. Lower the value to go faster
        :param pin: name of the piezo pin
        :param timer: timer attached to the pin (to control PWM signal
        :param channel: channel to use with the timer """

        self._tempo = tempo
        self.p = Pin( pin )
        self.tim = Timer( timer, freq=3000 )
        self.ch  = self.tim.channel( channel, Timer.PWM, pin=self.p )

    def get_tempo( self ):
        return self._tempo

    def set_tempo( self, value ):
        self._tempo = value

    tempo = property( get_tempo, set_tempo )

    def play_tone(self, freq ):
        """ play a given tone (frequency) on the piezo """
        if freq == 0: 
            self.ch.pulse_width_percent( 0 )
        else:
            self.tim.freq( freq )
            self.ch.pulse_width_percent( 30 )

    def no_tone( self ):
        self.play_tone( 0 )

    def play_note(self, note, duration ):
        """ Play a note identified by a letter for a given duration """
        # Transforme la note en frequence
        freq = self.notes[ note ]
        self.play_tone( freq )
        # Transforme la duree en temp (1=1000micros, 2=2000micros, etc)
        udelay( duration * 1000 ) # temps en micro-second

	# Joue une mélodie encodée dans une chaine de caractere
    def play_tune( self, tune_string ):
        """ play a tune stored within a comma separated string. 
            each item being a note letter + duration digit (1 digit acting as time multiplier).
            If the duration digit is missing then it is replaced by the value 1 

            :param tune_string: eg "c2,c,d3,c3,f3,e3,c2,c,d3,c3,g3,f3, 4" where the space is a blank sound """
    	tune_list = tune_string.split( ',' )
    	duration = 1
    	for tune_item in tune_list:
    	    # print( tune_item )
    	    if len( tune_item )>1:
    	        try:
    	            duration = int( tune_item[1:] )
    	        except:
    	            raise ValueError( 'Invalid duration %s for note %s' % (tune_item[1:], tune_item[0]) )
    	    else:
    	        duration = 1

    	    # Jouer la note
    	    self.play_note( tune_item[0], self._tempo * duration )
    	    # Pause entre 2 notes
    	    self.no_tone()
    	    udelay( (self._tempo * 1000) // 2 )   


# a Tune is stored within a comma separated string. 
#  * Each item being a note letter + duration digit (acting as tempo time multiplier).
#  * If the duration digit is missing then it is replaced by the value 1 
#
piezo = Piezo( tempo = 300 )
piezo.play_tune( "c,c,g,g,a,a,g2,f,f,e,e,d,d,c2, 4" )
piezo.tempo = 150
piezo.play_tune( "c2,c,d3,c3,f3,e3,c2,c,d3,c3,g3,f3, 4" )

Internet

Tableau des notes selon Arduino

 * Le calcul de la tonalité est fait en suivant
 * l'opération mathématique suivante:
 *
 * timeHigh = période/2 = 1/(2*FrequenceTonalité)
 *
 * Où les différentes tonalités sont spécifiées dans la table suivante:
 *
 * note Fréquence Période timeHigh
 * Do c 261 Hz    3830    1915
 * Ré d 294 Hz    3400    1700
 * Mi e 329 Hz    3038    1519
 * Fa f 349 Hz    2864    1432
 * Sol g 392 Hz   2550    1275
 * La a 440 Hz    2272    1136
 * Si b 493 Hz    2028    1014
 * Do C 523 Hz    1912    956



Source: Micro Python Intro écrit par/written by Damien P.George

Traduit par Meurisse D. pour MCHobby.be - Translated by Meurisse D. for MCHobby.be

Toute référence, mention ou extrait de cette traduction doit être explicitement accompagné du texte suivant : «  Traduction par MCHobby (www.MCHobby.be) - Vente de kit et composants » avec un lien vers la source (donc cette page) et ce quelque soit le média utilisé.

L'utilisation commercial de la traduction (texte) et/ou réalisation, même partielle, pourrait être soumis à redevance. Dans tous les cas de figures, vous devez également obtenir l'accord du(des) détenteur initial des droits. Celui de MC Hobby s'arrêtant au travail de traduction proprement dit.

Traduit avec l'autorisation de micropython.org - Translated with the authorisation of micropython.org