J'ai pour projet de me fabriquer un petit piano DIY sympa et drole.
J'en suis aux essais sur table et j'ai actuellement un soucis.
Je produit le son avec un buzzer (c'est un actif il me semble) grâce à la fonction tone().
Lorsque je presse un bouton qui correspond à une note (il y en a 7), et que je reste appuyé dessus, le son saccade. C'est normal c'est fait comme cela dans le programme.
Ce qui m’embête plus, c'est que je ne veux pas que le son saccade lorsque je reste appuyé, j'aimerais un son continu, mais je ne trouve aucune solution.
Auriez-vous des solutions pour produire un son continu ?
Honnêtement je ne me suis pas cassé la tête pour le code, si vous avez des modifications à me faire part, je suis preneur
Plus tard, j'ajouterai un bouton pour changer d'octave et un écran pour savoir sur quelle octave on joue. Je précise que je ne suis pas du tout musicien, je fais cela pour m'amuser !
Cela fonctionne parfaitement, merci beaucoup.
Je ne comprends pas trop ce qui change du mien et surtout pourquoi ça change quelque chose mais bon ça fonctionne
La différence c'est la présence des "else" qui fait qu'une fois la touche trouvée, le code ne perd pas de temps à faire les autres tests. Un switch / case aurait certainement fait pareil.
Pour l'instant le spaghetti fonctionne très bien , je vais donc le laisser. Je changerais si par la suite j'ai des problèmes de délai.
Actuellement j'ai un autre problème, oui encore et ça m'énerve parce que je trouve pas pourquoi cela ne fonctionne pas.
Voici mon code :
int PIN_BUZZER = 9;
int bouton_do = 7;
int bouton_re = 6;
int bouton_mi = 5;
int bouton_fa = 4;
int bouton_sol = 3;
int bouton_la = 10;
int bouton_si = 8;
int bouton = 0;
int valeuroctave = 0;
void setup()
{
Serial.begin(9600);
pinMode(PIN_BUZZER, OUTPUT);
pinMode(bouton_do, INPUT);
pinMode(bouton_re, INPUT);
pinMode(bouton_mi, INPUT);
pinMode(bouton_fa, INPUT);
pinMode(bouton_sol, INPUT);
pinMode(bouton_la, INPUT);
pinMode(bouton_si, INPUT);
pinMode(bouton, INPUT);
attachInterrupt(0, fonction_octave, FALLING);
}
void fonction_octave()
{
Serial.println("Fonction_Octace");
valeuroctave == valeuroctave + 1;;
if(valeuroctave == 9);
{
valeuroctave = 0;
}
}
void loop()
{
Serial.print("bouton : ");
Serial.println(digitalRead(bouton));
Serial.println(valeuroctave);
switch(valeuroctave)
{
case 0 :
break;
case 1 :
break;
case 2 :
break;
case 3 :
break;
case 4 :
break;
case 5 :
break;
case 6 :
break;
case 7 :
if (digitalRead(bouton_do) == 0)
{
tone(PIN_BUZZER, 2093);
delay(200);
}
else {
if (digitalRead(bouton_re) == 0)
{
tone(PIN_BUZZER, 2350);
delay(200);
}
else {
if (digitalRead(bouton_mi) == 0)
{
tone(PIN_BUZZER, 2637);
delay(200);
}
else {
if (digitalRead(bouton_fa) == 0)
{
tone(PIN_BUZZER, 2794);
delay(200);
}
else {
if (digitalRead(bouton_sol) == 0)
{
tone(PIN_BUZZER, 3136);
delay(200);
}
else {
if (digitalRead(bouton_la) == 0)
{
tone(PIN_BUZZER, 3520);
delay(200);
}
else {
if (digitalRead(bouton_si) == 0)
{
tone(PIN_BUZZER, 3951);
delay(200);
}
else {
noTone(PIN_BUZZER);
}
}
}
}
}
}
}
break;
default:
break;
}
delay(200);
}
Comme vous pouvez le voir, j'utilise une interruption pour incrémenter une variable et changer les octaves selon cette variable. Seul soucis, j'entre bien dans la fonction puisque le texte est affiché, mais le calcul ne se fait pas.
Je ne sais pas ce que faisais cet égal ici mais dans tous les cas je l'ai enlevé et cela n'a rien changé
Je ne vois vraiment pas d'où cela peut venir, ma variable est bien initialisée, j'ai déjà fait ce genre d'opérations et cela fonctionnait.
Le message "Fonction_Octace" s'affiche alors que valeuroctave ne s'incrémente pas ? ce n'est pas possible, tu as dû oublier de recharger le programme ! Ou alors j'arrête le whisky !
valeuroctave n'est jamais changée dans loop() donc la variable est optimisée (comprendre constante dans le contexte).
En effet sa valeur est modifiée dans une fonction qui n'est pas appelée dans loop().
Il faut déclarer la variable valeuroctave volatile
volatile int valeuroctave = 0;
Et il ne faut pas utiliser Serial.print dans les routines d'interruption car les IT étant masquées on peut tomber dans un cas de blocage si le buffer d'émission est plein.
Je testerais cela ce soir, merci pour vos réponses.
Le Serial.print dans la fonction interruption était là juste histoire de vérifier que l'on passait bien dans la fonction, je compte par la suite enlever le moniteur de série.
Vous n’avez pas besoin d’interruption pour cela - et en plus ça vous complexifie la vie car effectivement pas possible de mettre un print dans l’ISR...
traitez simplement les touches appuyées toutes au même moment dans la loop... en commençant par tester les plus prioritaires si cela compte pour vous. Vous aurez ainsi une machine à état plus propre et extensible. Éventuellement réservez les interruptions pour quelque chose ne pouvant pas attendre un tour de loop et modifiant en cours de route ce qui se passe dans la loop
Si vous voulez aller plus loin et avoir des sons un peu plus sympas regardez la vidéo (en anglais) de Julian sur son penny organ utilisant des touches capacitives (avec un MPR121) en commençant éventuellement par son exploration du AD9833 et ses progrès et essais (il a une jolie collection de vidéos sur ce sujet et bcp d’autres, une bonne source de connaissances)