Auteur Sujet: Teensy 3.1, 3.2 - Sonorisation locomotive  (Lu 93656 fois)

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #45 le: janvier 09, 2018, 11:44:22 am »
1) Ok, pour l'instant, j'ai installé, pour les essais, le petit haut-parleur directement sur la sortie du Teensy (avec un condensateur de 10 MicroF placé en série) :
le son est faible, mais suffisant pour vérifier le son.
Par la suite, je mettrais effectivement un LM386 ou une petite carte intégrant un LM386.

2) J'aimerai utiliser "EncodeAudio" (8 bits-8kHz) pour piloter le DAC mais, "EncodeAudio" fournit du "const unsigned char" et le DAC n'accepte que de l' "int" (AnalogWrite (n°pin, int ->  0 to 256) ?

 3) A priori, la résolution du DAC peut être spécifiée :  analogWriteResolution ( 8 ) ;  // analogWrite value 0 to 256 (8 by default)

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #46 le: janvier 10, 2018, 11:56:48 am »
2) J'aimerai utiliser "EncodeAudio" (8 bits-8kHz) pour piloter le DAC mais, "EncodeAudio" fournit du "const unsigned char" et le DAC n'accepte que de l' "int" (AnalogWrite (n°pin, int ->  0 to 256) ?

analogWrite n'a pas le même prototype sur Arduino/AVR et sur Arduino/ARM. Sur Arduino/ARM (Due, Zero, Teensy 3), les deux arguments sont des uint32_t. Donc pas de soucis pour lui passer un 8 bits non signé.

Citer
3) A priori, la résolution du DAC peut être spécifiée :  analogWriteResolution ( 8 ) ;  // analogWrite value 0 to 256 (8 by default)

Oui, j'ai regardé dans le code et ça fait ce que tu veux
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #47 le: janvier 11, 2018, 12:01:27 am »
J'ai essayé d'utiliser la fonction "IntervalTimer", mais, je dois certainement très mal m'y prendre pour implémenter la fonction de lecture du tableau "son" et l'envoi de l'échantillon vers la pin A14 ( DAC ).
IntervalTimer myTimer;
  int SoundArray[sizeof(SoundArray)] ;
  int StartLok[] PROGMEM = { // from EncodeAudio
  39, 26, 26, 62, 80, 97, 90,
  };
 
    void ReadSound(int SoundArray[sizeof(SoundArray)]){ // Déclaration Fonction : lit un échatillon et l'envoi sur le DAC pin A14
          for(int i = 0; i < sizeof(SoundArray); i++){
          analogWrite(A14, SoundArray[i]);
          Serial.println(SoundArray[i]);
          return void;
          }
  }
void setup(){
       Serial.begin(9600);
       analogWriteResolution(8);  // analogWrite value 0 to 256 (8 by default)
}

void loop(){
       for(int i = 0; i < sizeof(StartLok); i++){
       SoundArray[i] = StartLok[i]
       }
       myTimer.begin(ReadSound(SoundArray[sizeof(SoundArray)]), 125); // 125 MicroS -> 8 kHz

Teensy_Sound_PWM_V2:2: error: 'SoundArray' was not declared in this scope
 int SoundArray[sizeof(SoundArray)] ;                      ^

Teensy_Sound_PWM_V2:7: error: 'SoundArray' was not declared in this scope
     void ReadSound(int SoundArray[sizeof(SoundArray)]){ // Déclaration Fonction : lit un échatillon et l'envoi sur le DAC pin A14                                   

Teensy_Sound_PWM_V2:7: error: 'SoundArray' was not declared in this scope
     void ReadSound(int SoundArray[sizeof(SoundArray)]){ // Déclaration Fonction : lit un échatillon et l'envoi sur le DAC pin A14                                       

Teensy_Sound_PWM_V2: In function 'void ReadSound(...)':
Teensy_Sound_PWM_V2:8: error: 'SoundArray' was not declared in this scope
           for(int i = 0; i < sizeof(SoundArray); i++){

Teensy_Sound_PWM_V2:11: error: expected primary-expression before 'void'
           return void;

Teensy_Sound_PWM_V2:11: error: return-statement with a value, in function returning 'void' [-fpermissive]
Teensy_Sound_PWM_V2:11: error: expected ';' before 'void'
Teensy_Sound_PWM_V2:11: error: declaration does not declare anything [-fpermissive]
Teensy_Sound_PWM_V2: In function 'void loop()':
Teensy_Sound_PWM_V2:21: error: 'SoundArray' was not declared in this scope
 int SoundArray[sizeof(SoundArray)] ;

Teensy_Sound_PWM_V2:22: warning: comparison between signed and unsigned integer expressions
         for(int i = 0; i < sizeof(StartLok); i++){
               
'SoundArray' was not declared in this scope

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #48 le: janvier 11, 2018, 07:57:08 am »
Bonjour

int SoundArray[sizeof(SoundArray)] ; n’est pas une déclaration qui a du sens. Étant donné que la taille du tableau est déterminée à partir de la taille du tableau qui n’est pas connue  ???
D’ailleurs la déclaration de l’argument de ReadSound n’est pas non plus légale.

Par ailleurs ce que fait ReadSound contredit le commentaire puisqu’elle envoie tous les échantillons et non pas un seul. Comme a dit je ne sais plus qui « si les commentaires ne correspondent pas au programme alors les deux sont faux »

Ensuite je ne vois pas où l’intervalTimer est lié à la fonction ReadSound, voir https://www.pjrc.com/teensy/td_timing_IntervalTimer.html
« Modifié: janvier 11, 2018, 08:05:55 am par Jean-Luc »
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #49 le: janvier 11, 2018, 10:46:02 am »
Bonjour et merci pour tes commentaires :
1) Création de la fonction ReadSound : elle est censée (c'est ce que j'ai essayé de faire!) avoir pour argument un tableau d'échantillons de son dont je ne connais pas à priori la taille.
Cette fonction devrait pouvoir en effet s'appliquer sur n’importe quel tableau de son (donc avec des tailles variables).

2) Ok, à vrai dire, je suis un peu perdu avec les déclarations car le  tableau de son généré par EncodeAudio est un "unsigned char" alors que AnalogWrite n'admet que les "int".

3) Ok, en y réfléchissant, tu as raison.

4) Je pensais que l'instruction suivante suffisait :
       myTimer.begin(ReadSound(SoundArray[sizeof(SoundArray)]), 125); // 125 MicroS -> 8 kHz

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #50 le: janvier 11, 2018, 01:59:23 pm »
D'après ce que j'ai compris, IntervalTimer va te servir à appeler à une fréquence définie (8kHz ici) une fonction qui va envoyer un échantillon et un seul. Là tu envoies tout le tableau, donc les 8kHz ne vont pas être respectés  :).

Par ailleurs cette fonction ne peut pas prendre d'argument. Donc il faut que tu aies une variable qui donne l'index de l'échantillon courant (appelons le echantillonCourant). La fonction appelée par IntervalTimer va lire l'échantillon à l'index echantillonCourant, l'envoyer au DAC, et incrémenter echantillonCourant. Si echantillonCourant est égal à la taille du tableau, deux solutions, on recommence au début (le son est joué en boucle) ou on arrête. À cet effet, on peut décider qu'une valeur spéciale d'echantillonCourant, disons -1, signifie qu'il n'y a pas de son à jouer.

Le begin soit être appelé dans setup je pense.

Par ailleurs, le son à jouer est dans StartLok ? tu le recopies en plusieurs exemplaires dans SoundArray ? c'est le but ? Parce que si c'est le cas, ta boucle ne fait pas ça, elle ne remplit que les sizeof(Starlok), le reste de SoundArray reste non initialisé. Ensuite sizeof ne renvoie pas la taille d'un tableau mais le nombre d'octets occupés en mémoire. Si tu veux avoir le nombre d'éléments d'un tableaux d'entiers, il faut écrite sizeof(StartLok)/sizeof(int) si StartLok est un tableau d'int.

Bref, si tu veux jouer ce qu'il y a dans StartLok en boucle, tu n'as pas besoin de le copier dans SoundArray (le programme non testé et non compilé mais avec indentation correcte) :

IntervalTimer myTimer;
int StartLok[] PROGMEM = { // from EncodeAudio
  39, 26, 26, 62, 80, 97, 90
};
int echantillonCourant = 0;
 
void SendSound()
{
  analogWrite(A14, StartLok[echantillonCourant++]);
  if (echantillonCourant >= sizeof(StartLok)/sizeof(int)) {
    echantillonCourant = 0;
  }
}

void setup()
{
   analogWriteResolution(8);
   myTimer.begin(SendSound, 125);
}

void loop()
{
}
« Modifié: janvier 11, 2018, 02:39:26 pm par Jean-Luc »
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #51 le: janvier 11, 2018, 03:43:54 pm »
Merci pour ta patience.
Je vais analyser tout cela.

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #52 le: janvier 11, 2018, 09:05:27 pm »
Merci, ça marche super bien.
En faisant varier les microseconds dans
myTimer.begin(function, microseconds); le son de la locomotive accélère ou ralenti.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #53 le: janvier 12, 2018, 01:03:49 pm »
Excellente nouvelle  :)
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #54 le: janvier 13, 2018, 02:14:16 pm »
1) sur la base du template que tu m'as donné, j'ai créé un fonction par son (je pense que ce sera plus lisible lorsque le son sera intégré dans le décodeur "NmraDcc".

2) Il y a certes plus de mémoires dans le Teensy (256 k), mais c'est malgré un peu juste. Je pense que pour être vraiment à l'aise, il faudrait entre 2 à 4 Mo. Il faut donc optimiser la taille des tableaux "son".
Le code en 3) donne le résultat de compilation :
Le croquis utilise 199700 octets (76%) de l'espace de stockage de programmes. Le maximum est de 262144 octets.
Les variables globales utilisent 3468 octets (5%) de mémoire dynamique, ce qui laisse 62068 octets pour les variables locales. Le maximum est de 65536 octets.

Même en déclarant les tableaux "son" en "const"
De plus  sur le Teensy, contrairement à l'arduino, ce n'est pas évident de gérer" manuellement" la mémoire Flash.

3)
IntervalTimer myTimer;

const int StartLokBR99[] PROGMEM = { // from EncodeAudio
  39, 26, 26, 62, 80, 97, 90, 59
};

const int BrakeLokBR99[] PROGMEM = { // from EncodeAudio
122, 143, 160, 164, 159, 143, 138, 131
};

const int SiffletLokBR99[] PROGMEM = { // from EncodeAudio
12, 68, 109, 132, 167, 195, 167, 142, 137, 174, 184,
};
 
const int MarcheLokBR99[] PROGMEM = { // from EncodeAudio
124, 128, 134, 124, 100, 100, 113, 110, 118, 145,
};

const int ClocheLokBR99[] PROGMEM = { // from EncodeAudio
130, 123, 118, 123, 128, 128, 128, 130, 135, 132, 130,
};

const int StandbyLokBR99[] PROGMEM = { // from EncodeAudio
130, 134, 135, 131, 124, 121, 122, 125, 129, 131

unsigned int echantillonCourant = 0;
 
void BrakeLok(){
        analogWrite(A14, BrakeLokBR99[echantillonCourant++]);
        if (echantillonCourant >= sizeof(BrakeLokBR99)/sizeof(int)) {
        echantillonCourant = 0;
        }
}

 void SiffletLok(){
        analogWrite(A14, SiffletLokBR99[echantillonCourant++]);
        if (echantillonCourant >= sizeof(SiffletLokBR99)/sizeof(int)) {
        echantillonCourant = 0;
        }
}

void StartLok(){
        analogWrite(A14, StartLokBR99[echantillonCourant++]);
        if (echantillonCourant >= sizeof(StartLokBR99)/sizeof(int)) {
        echantillonCourant = 0;
        }
}

  void MarcheLok(){
        analogWrite(A14, MarcheLokBR99[echantillonCourant++]);
        if (echantillonCourant >= sizeof(MarcheLokBR99)/sizeof(int)) {
        echantillonCourant = 0;
        }
}
void StandbyLok(){
        analogWrite(A14, StandbyLokBR99[echantillonCourant++]);
        if (echantillonCourant >= sizeof(StandbyLokBR99)/sizeof(int)) {
        echantillonCourant = 0;
       }
}

void ClocheLok (){
        analogWrite(A14, ClocheLokBR99[echantillonCourant++]);
        if (echantillonCourant >= sizeof(ClocheLokBR99)/sizeof(int)) {
        echantillonCourant = 0;
        }
}
void setup(){
       analogWriteResolution(8);
       myTimer.begin(StartLok, 500);
       myTimer.begin(BrakeLok, 125);
       myTimer.begin(SiffletLok, 125);
       myTimer.begin(ClocheLok, 125);
       myTimer.begin(StandbyLok, 125);
}

void loop()
{
}


Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #55 le: janvier 13, 2018, 08:57:37 pm »
De plus  sur le Teensy, contrairement à l'arduino, ce n'est pas évident de gérer" manuellement" la mémoire Flash

C’est à dire ?
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #56 le: janvier 13, 2018, 11:17:29 pm »
Si j'ai bien compris, sur le teensy, il n y a pas d'équivalent de la bibliothèque EEPROM.h.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #57 le: janvier 13, 2018, 11:23:13 pm »
Cordialement

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #58 le: janvier 13, 2018, 11:26:10 pm »
Je suis assez étonné de l’occupation mémoire de ce programme. Il n’y a qu’une poignée de pauvres tableaux de quelques éléments.
« Modifié: janvier 13, 2018, 11:39:11 pm par Jean-Luc »
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #59 le: janvier 14, 2018, 02:11:52 pm »
Ok, je vais voir pour EEPROM.

Mes fichiers son en *.wav (8 bits PCM) avant conversion par EncodeAudio prennent au total environ 110 Ko.