Introduction: Raspberry Pi Thumb Harp (EN/FR)

Code


EN :

As part of an Embedded System project at Polytech Paris-UPMC, we are in charge of creating an instrument.
This instrument must be autonomous, powered by a battery, and must be able to determine the frequency of a signal and convert it autonomusly. We decided that our input signal will be a vibration. In order to generate this vibration we opted for a string instrument.

To summarize, our project breaks down as follows:

By plucking a string, a vibration is generated and sensed by an accelerometer. This vibration is digitized with an analog-to-digital converter and then analyzed with a Fourier transform to determine the frequency.From this frequency we generate a sound that will be sent to the audio card of the Raspberry Pi.

Our application is coded in C language.

FR :

Dans le cadre d'un projet à Polytech Paris-UPMC, nous sommes chargés de réaliser un instrument. Cet instrument devra être autonome, alimenté par des piles ou une batterie, et devra être capable d'analyser un signal en fréquence et la convertir en totale autonomie.

Nous avons choisi de réaliser un instrument qui produit différent son en fonction d'une vibration. Afin de générer cette vibration nous avons opté pour le choix d'un instrument à cordes.

Pour résumer de façon concise, notre projet se décompose de la manière suivante : En excitant une corde, une vibration est générée et captée par un accéléromètre. Cette vibration est numérisée avec un convertisseur analogique-numérique, puis analysée avec une transformer de Fourrier pour en déterminer la fréquence. A partir de cette fréquence nous générons un son qui sera envoyé à la carte audio de la Raspberry Pi. Afin de créer différentes fréquences de vibration nous avons opté de placer plusieurs cordes de tension et de longueurs différentes afin de créer plusieurs fréquences et donc générer plusieurs sons. Notre application est codée en langage C.

Step 1: What You'll Need / Matériel

EN :

- Raspberry Pi 2
- MCP 3008 Analog-to-digital converter

- Polulu 5V Voltage regulator

- OP Amp TL082

- 5V & 2,5V Voltage references

- ICL7660 Voltage converter ( converts 5V to -5V for the op amp )

- ADXL335 Accelerometer

- Régulateur 5V S7V7F5

- 6 AA batteries 1,2V 2000mAh

- Resistors ,capacitors & cables (see the analog portion for more details )

- Rubber bands

- Soft plastic

(not the stuff from the picture)

FR :

- Raspberry Pi 2
- Convertisseur analogique numérique MCP 3008

- Régulateur de tension 5V Polulu

- Amplificateur TL082

- Référence de tension 5V et 2,5V

- Convertisseur de tension ICL7660 qui transforme 5V en -5V (Pour le TL082)

- Accéléromètre ADXL335

- Régulateur 5V S7V7F5

- 6 piles AA de 1,2V 2000mAh

- Résistances & capacités

- Connecteurs, nappe, etc..

- Élastiques (ou cordes)

- Plastique souple

Step 2: Mecanical Part / Partie Mécanique

EN:

Our strings are simple rubber bands. For them to vibrate at different frequencies, we play on the size of the strings as well as on their tension. To simplify, the longer a string is, the lower its frequency, and the more tense a string is, the higher its frequency is. In reality it is more complex than that, because the material of the string has an impact on its vibration, and the strings can vibrate in several modes. To tune the instrument, we use a printf () in C code to display the frequency on the terminal. We then change the tension of the strings until the frequency gap between each string is sufficient to avoid confusion.

We use a piece of flexible plastic on which is attached the sensor and the strings. Because we wanted to use only one sensor, that was the solution we developed. Between each string there is a binding. These allow us to isolate the strings between them and prevent the vibration of one string from vibrating another and gives us a false result. The whole is suspended on a plate of wood with hinges.


FR:

Nos cordes sont de simples élastiques. Pour qu'elles vibrent à des fréquences différentes, nous jouons sur la taille des cordes ainsi que sur leur tension. Pour simplifier, plus une corde est grande, plus sa fréquence de vibration sera basse, et plus une corde est tendu, plus sa fréquence est haute. C'est en réalité plus compliqué que sa, car la matière de la corde à un impact sur sa vibration, et les cordes peuvent vibrer selon plusieurs modes. Pour accorder l'instrument, nous utilisons un printf() dans le code C pour afficher la fréquence sur le terminal. Nous changeons ensuite la tension des cordes jusqu’à ce que l'écart entre chaque corde soit suffisant afin d’éviter toute confusion. Nous utilisons un support plastique souple sur lequel sont fixés le capteur et les cordes. Étant donné que nous ne voulions utiliser qu'un seul capteur, c'est la solution que nous avons élaborée. Entre chaque fixation de corde sur notre support plastique, il y a une isolation métallique verticale. Celle-ci nous permet d'isoler les cordes entre elles et éviter que la vibration d'une corde en fasse vibrer une autre et nous donne de faux résultat à l’acquisition. Le tout est suspendu sur un support en bois avec des charnières.

Step 3: Electronic Circuit / Partie Électronique Analogique

EN:

The ADXL335 accelerometer allows us to capture the dynamic acceleration produced by the vibration of the strings on its support, represented by the voltage at its terminals, or rather by the voltage difference with its rest value.

The sensor's output has a continuous voltage component and we don't want to amplify it. A high-pass filter (which may be a simple capacitance) is then used, and then the sinusoidal component is amplified.

In addition, the MCP3008 can digitalize an analog input between 0 and 5V. We therefore use an adder circuit with our voltage reference 2.5V so that it is centered before sending it to the converter. A 5V voltage reference is used for the Vref input of the MCP3008 as it must be as stable as possible to ensure proper conversion. We use batteries and the voltage regulator to supply power to our circuit. The 2,5V voltage reference can be used to supply the power needed by the sensor since it does not uses much. We also use a negative voltage converter circuit around the ICL7660 because our op amps need a -5V input.

There is also an anti-aliasing filter at 1KHz upstream of the converter.


FR :

L'accéléromètre ADXL335 nous permet de capter
l'accélération dynamique que produit la vibration des cordes sur son support. Cette vibration est représentée par la tension aux bornes de l’accéléromètre, ou plutôt par la différence de tension par rapport à sa tension de repos. La sortie du capteur a donc une composante continue (offset de repos) qu'on ne souhaite pas amplifier.

On utilise donc un filtre passe-haut (qui peut être une simple capacité), puis on amplifie la composante sinusoïdale. De plus, le MCP3008 peut numériser une entrée analogique comprise entre 0 et 5V. On utilise alors un montage additionneur avec notre référence de tension 2,5V pour rehausser le signal avant de le transmettre au convertisseur.

On utilise une référence de tension 5V pour l'entrée Vref du MCP3008 car elle doit être la plus stable possible pour assurer une conversion correcte. Nous utilisons des piles suivis d’un régulateur de tension pour alimenter notre circuit. La référence de tension 2,5V peut servir à alimenter notre capteur car celui-ci consomme très peu de courant. Nous utilisons aussi un montage de conversion de tension autour du ICL7660.

Il y a aussi un filtre anti-repliement à 1KHz en amont du convertisseur.

Step 4: Signal Acquisition / Acquisition Du Signal

MCP3008 Datasheet

EN:

We use the analog-to-digital converter MCP3008 to digitize the signal received by the sensor.
Port correspondence :

MOSI (19) -> DIN ; MISO(21) -> DOUT

SCLK(23) -> CLK ; CEO(24) -> CS-SHDN

The ADC and the RPi communicate via the SPI bus (Serial Peripheral Interface). We use the WiringPi library, a GPIO interface library for Raspberry PI. For more details on how to use this library, click on this link.

SPI Transmission: The master generates the clock. At each clockstroke the master and the slave exchange one bit. For more information, see the MCP3008 datasheet (page 21).

To enable the SPI bus on the Raspberry, use the raspi-config command.

FR :

Nous utilisons le convertisseur analogique-numérique MCP3008 pour numériser le signal reçu par le capteur.

Correspondance des ports :

MOSI (19) -> DIN ; MISO(21) -> DOUT
SCLK(23) -> CLK ; CEO(24) -> CS-SHDN

La communication entre le CAN et la RPi ce fait grâce au bus SPI (Serial Peripheral Interface).

Pour la communication SPI, nous utilisons la bibliothèque WiringPi, une bibliothèque d'interface GPIO pour la Raspberry PI. Pour plus de détails sur l'utilisation de cette bibliothèque, voir ce lien (en anglais).

Transmission SPI : Le maître génère l'horloge. A chaque coup d'horloge le maître et l'esclave s'échangent un bit. Pour plus d'informations, voir la datasheet du MCP3008 (page 21).


Pour activer le bus SPI sur la Raspberry, utilisez la commande raspi-config.

Step 5: FFT

EN:

To determine which string has been pinched, we use a discrete Fourier transform on the digitized signal. We
thus obtain the spectral representation (the unit is no longer the time but the frequency) of the signal, and as the strings vibrate differently, they will have different spectrum. We use the GNU scientific library for the FFT (Fast Fourier Transform) algorithm. However, the function gsl_fft which performs the transformation on an array has no information on the time interval between two values and by extension on the frequency interval between two output values.

To ensure the coherence of this transform, we must absolutely control the time interval between two acquisition (which corresponds to the inverse of the sampling frequency Fe), and for this we use a posix timer. Moreover, only half of the result table is of interest to us, and the index of the medium corresponds to the frequency Fe / 2. To find the frequency corresponding to the amplitude of result [i], result [i] x (Fe / 2)) / result_size []. Finally, we look for the index of the maximum value of the result table, to which we apply the above formula to determine the dominant frequency of the signal.


FR:

Pour déterminer quelle corde à été pincée, nous utilisons une transformée de Fourier discrète sur le signal numérisé. On obtient ainsi la représentation spectrale (l'unité n'est plus le temps mais la fréquence) du signal, et comme les cordes vibrent différemment, elles auront des spectres différents. Nous utilisons la bibliothèque scientifique GNU(en anglais) pour l'algorithme de FFT (Fast Fourier Transform). Cependant, la fonction gsl_fft qui réalise la transformation sur un tableau, n'a pas d'information sur l'intervalle de temps entre deux valeurs, et par extension sur l'intervalle de fréquence entre deux valeurs en sortie.

Pour assurer la cohérence de cette transformée, il faut donc absolument maitriser l'intervalle de temps entre deux acquisition (qui correspond à l'inverse de la fréquence d’échantillonnage Fe), et pour cela nous utilisons un posix timer. De plus, seulement la moitié du tableau résultat nous intéresse, et l'indice du milieu correspond à la fréquence Fe/2. Pour retrouver la fréquence correspondant à l'amplitude de résultat[i], il faut faire (résultat[i] x (Fe/2)) / taille_resultat[]. Finalement, nous recherchons l'indice de la valeur maximale du tableau résultat, auquel nous appliquons la formule si dessus pour déterminer la fréquence dominante du signal.

Step 6: Pthreads & Timers

EN :

At the C code level, we use pthreads and a posix timer to parallelize our application. The pthreads are execution threads which are processed in "pseudo-parallel". We control the time interval between acquisitions with the posix timer, and the Fast Fourier Transform is made in a different thread. For the fourier transform, we use a big array, that we constantly filled by the posix timer function, and when it is at least half full, the function calls the FFT threads on this half of the array.

FR :

Au niveau du code C, nous utilisons des pthreads et un posix timer pour paralléliser notre application. Les pthreads sont des fils d’exécutions qui sont traités en "parallèle". Nous contrôlons l'intervalle de temps entre chaque acquisition du signal avec un posix timer, et la transformée de Fourier se fait dans un fil d'exécution différent.

Step 7: Sound Generation / Génération Du Son

EN:

To generate a sound, we use ALSA (Advanced Linux Sound Architecture). This architecture provides audio and MIDI functionality for Linux. After initializing the sound card, we fill a buffer with sinusoids of different frequencies according to the string that was plucked, then we send this buffer to the sound card, with the snd_pcm_writei () function. You can also use ALSA to play pre-recorded sound; We chose to generate sound from sinus because we wanted to study later the mathematical part of sound design (sum of cos, harmonics of different amplitudes etc ...).


FR:

Pour générer un son, nous utilisons ALSA (Advanced Linux Sound Architecture). Cette architecture procure des fonctionnalités audio et MIDI pour Linux.

Après avoir initialisé la carte son, nous remplissons un buffer avec des sinusoïdes de fréquences différentes en fonction de la corde qui à été pincée,puis nous envoyons ce buffer à la carte son, avec la fonction snd_pcm_writei().

Vous pouvez aussi utiliser ALSA pour jouer des sons préenregistrés; Nous avons choisi de générer du son à partir de sinus car nous voulions nous pencher plus tard sur la partie mathématique du design d'un son (sommes de cosinus pour faire des accords, harmoniques d'amplitudes différentes etc...).

Step 8: Conclusion

EN:

We had a lot of fun doing this project, and a video is coming soon. Do not hesitate to take and improve our little project.

Do not spend too much time on the mechanical part, the heart of the project was to pick up and use a vibration, and the strings are just one way to do it, but it can be a lot more things! For example, you can use the sensor as a kind of musical stethoscope that will play different sound by hitting the surface on which it's on. Be Creative!

If you made it this far, thank you very much!


FR:

Nous nous sommes bien amusez en réalisant ce projet, et une vidéo arrive bientôt. N’hésitez pas à reprendre et à améliorer notre petit projet.

Ne passez pas trop de temps sur la partie mécanique, le cœur du projet était de capter et traiter une vibration, et les cordes sont un moyen de faire vibrer le capteur, mais son utilisation n'est pas limitée aux cordes. Par exemple, vous pouvez utiliser le capteur comme une sorte de stéthoscope musical qui jouerait différents sons en frappant la surface sur laquelle il est. Soyez créatifs !

Si vous êtes arrivez jusqu'ici, merci beaucoup !

Step 9: Demo