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

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #120 le: avril 04, 2018, 09:35:08 pm »
J'ai l'impression qu'il ne doit pas être possible de sortir le son issu de la SPI Flash vers le DAC du Teensy (pin A14).

Sur le site PRJC : https://www.pjrc.com/store/teensy3_audio.html , le Teensy est couplé à une carte audio qui elle possède un lecteur SD et un emplacement permettant de souder une SPI Flash. Cette carte possède en particulier un DAC qui doit être mis en œuvre grâce à la bibliothèque Audio.h (PlayFlashRaw).
Le Teensy pilote la carte audio par un bus I2C (SDA - SCL) et le bus série (Tx - Rx).
IL semble que la bibliothèque PlayRawFlash ne puisse ne mettre en œuvre que le DAC de la carte audio.
Y at-il une possibilité que le son de la SPI Flash puisse attaquer la sortie DAC A14 du Teensy?

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #121 le: avril 16, 2018, 11:27:37 am »
Mais oui

Lire le fichier de la flash et sortir le son sur le DAC sont deux choses séparées. Il n'y a aucune raison que ça ne fonctionne pas.
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #122 le: mai 01, 2018, 09:11:55 pm »
Bon, après un certain nombre de discussion et d'essai sur le forum PRJC, tout marche ! ! !
A la base, il y avait un problème de synchro entre le flux de données sur la liaison "Arduino" et le script Python.
Le sketch Arduino (CopyFromSerialMC.ino) permet de charger dans la SPI Flash les données de fichier "son" sont remontées par le script Python (rawfile-uploader-mc.py)
Le sketch Arduino est lancé et démarre, puis, il s'arrête et attend le caractère "c" que le fournit le script Python lorsque celui-ci est lancé (fenêtre de commande Windows).
Ci-joint, les codes en question :
CopyFromSerialMC.ino
/*
 * This is free and unencumbered software released into the public domain.
 * ARDUINO / Teensy Modified Monitor Control added.....Apr2018......
 * Anyone is free to copy, modify, publish, use, compile, sell, or
 * distribute this software, either in source code form or as a compiled
 * binary, for any purpose, commercial or non-commercial, and by any
 * means.
 *
 * In jurisdictions that recognize copyright laws, the author or authors
 * of this software dedicate any and all copyright interest in the
 * software to the public domain. We make this dedication for the benefit
 * of the public at large and to the detriment of our heirs and
 * successors. We intend this dedication to be an overt act of
 * relinquishment in perpetuity of all present and future rights to this
 * software under copyright law.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * For more information, please refer to <http://unlicense.org>
 * -------------------------------------------------------------------------
 *
 * This is example code to 1) format an SPI Flash chip, and 2) copy raw
 * audio files (mono channel, 16 bit signed, 44100Hz) to it using the
 * SerialFlash library.  The audio can then be played back using the
 * AudioPlaySerialflashRaw object in the Teensy Audio library.
 *
 * To convert a .wav file to the proper .RAW format, use sox:
 * sox input.wav -r 44100 -b 16 --norm -e signed-integer -t raw OUTPUT.RAW remix 1,2
 *
 * Note that the OUTPUT.RAW filename must be all caps and contain only the following
 * characters: A-Z, 0-9, comma, period, colon, dash, underscore.  (The SerialFlash
 * library converts filenames to caps, so to avoid confusion we just enforce it here).
 *
 * It is a little difficult to see what is happening; aswe are using the Serial port
 * to upload files, we can't just throw out debug information.  Instead, we use the LED
 * (pin 13) to convey state.
 *
 * While the chip is being formatted, the LED (pin 13) will toggle at 1Hz rate.  When
 * the formatting is done, it flashes quickly (10Hz) for one second, then stays on
 * solid.  When nothing has been received for 3 seconds, the upload is assumed to be
 * completed, and the light goes off.
 *
 * Use the 'rawfile-uploader.py' python script (included in the extras folder) to upload
 * the files.  You can start the script as soon as the Teensy is turned on, and the
 * USB serial upload will just buffer and wait until the flash is formatted.
 *
 * This code was written by Wyatt Olson <wyatt@digitalcave.ca> (originally as part
 * of Drum Master http://drummaster.digitalcave.ca and later modified into a
 * standalone sample).
 *
 * Enjoy!
 *
 *     // xxxx ... MONITOR CONTROL ADDED ........Apr 2018.........
 *
 */

#include <SerialFlash.h>
#include <SPI.h>

const int FlashChipSelect = 10; // digital pin for flash chip CS pin
//const int FlashChipSelect = 21; // Arduino 101 built-in SPI Flash
// I coul;dn't get #define CSPIN 6 to work so put in the FlashChipSelect = 6 line .....xxxxxxxxxxxxxxxxxxxx

//Buffer sizes
#define USB_BUFFER_SIZE      256   // was 128
#define FLASH_BUFFER_SIZE    8192  //was 4096

//Max filename length (8.3 plus a null char terminator)
#define FILENAME_STRING_SIZE      13

//State machine
#define STATE_START      0
#define STATE_SIZE      1
#define STATE_CONTENT    2

//Special bytes in the communication protocol
#define BYTE_START      0x7e
#define BYTE_ESCAPE      0x7d
#define BYTE_SEPARATOR    0x7c


//SPI Pins (these are the values on the Audio board; change them if you have different ones)
//#define MOSI               11 //7
//#define MISO              12
//#define SCK               14
// #define CSPIN              6
//#define CSPIN           21  // Arduino 101 built-in SPI Flash


void setup(){
 
   pinMode(13, OUTPUT);    // Teensy LED pin
   
  Serial.begin(9600);  //Teensy serial is always at full USB speed and buffered... the baud rate here is required but ignored
 
  delay(1000);
 
  Serial.println("Enter char...  c  ...to Start Erase and Copy Files Sketch");

  while(Serial.read() != 'c');

  Serial.println("Erase and Copy Sketch Started");
 
   
  //Set up SPI
  SPI.setMOSI(11);  // uncomment these if using the alternate pins
  SPI.setMISO(12);  // these are the standard pins for the Teensy 3.2 & Audio Adaptor board conbination
  SPI.setSCK(14);
 

 if (!SerialFlash.begin(FlashChipSelect)) {
    while (1) {
      Serial.println("Unable to a access SPI Flash chip");
      delay(1000);
    }
  }
 
// Double flash LED a few times to warn Erase is about to begin ..........
  for(uint8_t i = 0; i < 3; i++){
    delay(100);
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
  delay(100);
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    delay(1000);
  }
                 
  //We start by formatting the flash...
  uint8_t id[5];
  SerialFlash.readID(id);
  SerialFlash.eraseAll();
 
  //Flash LED at 1Hz while formatting
  while (!SerialFlash.ready()) {
    delay(500);
    digitalWrite(13, HIGH);
    delay(500);
    digitalWrite(13, LOW);
  }

  //Quickly flash LED a few times when completed, then leave the light on solid
  for(uint8_t i = 0; i < 10; i++){
    delay(100);
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
  }
  digitalWrite(13, HIGH);
 
  delay(1000);
 
  Serial.println("Full Erase Has Completed...Now Unplug USB & Plug in USB again to reset COMMS");
  Serial.println("Close Arduino Serial Monitor");
  Serial.println("Run Python rawfile-uploader-mc script from a new CMDline or batch file.");
  Serial.println("Teesny LED goes out when Copy Files has completed");
 
  //We are now going to wait for the upload program
  while(!Serial.available());
 
  SerialFlashFile flashFile;
 
  uint8_t state = STATE_START;
  uint8_t escape = 0;
  uint8_t fileSizeIndex = 0;
  uint32_t fileSize = 0;
  char filename[FILENAME_STRING_SIZE];
 
  char usbBuffer[USB_BUFFER_SIZE];
  uint8_t flashBuffer[FLASH_BUFFER_SIZE];
 
  uint16_t flashBufferIndex = 0;
  uint8_t filenameIndex = 0;
 
  uint32_t lastReceiveTime = millis();
 
    // .... We assume the serial receive part is finished when we have not received something for 3 seconds
    // ..... parenthesis added around this bit on line below........... (lastReceiveTime + 3000) > millis()....reads better...
 
  while(Serial.available() || (lastReceiveTime + 3000) > millis()){
    uint16_t available = Serial.readBytes(usbBuffer, USB_BUFFER_SIZE);
    if (available){
      lastReceiveTime = millis();
    }

    for (uint16_t usbBufferIndex = 0; usbBufferIndex < available; usbBufferIndex++){
      uint8_t b = usbBuffer[usbBufferIndex];
     
      if (state == STATE_START){
        //Start byte.  Repeat start is fine.
        if (b == BYTE_START){
          for (uint8_t i = 0; i < FILENAME_STRING_SIZE; i++){
            filename[i] = 0x00;
          }
          filenameIndex = 0;
        }
        //Valid characters are A-Z, 0-9, comma, period, colon, dash, underscore
        else if ((b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '.' || b == ',' || b == ':' || b == '-' || b == '_'){
          filename[filenameIndex++] = b;
          if (filenameIndex >= FILENAME_STRING_SIZE){
            //Error name too long
            flushError();
            return;
          }
        }
        //Filename end character
        else if (b == BYTE_SEPARATOR){
          if (filenameIndex == 0){
            //Error empty filename
            flushError();
            return;
          }
         
          //Change state
          state = STATE_SIZE;
          fileSizeIndex = 0;
          fileSize = 0;
         
        }
        //Invalid character
        else {
          //Error bad filename
          flushError();
          return;
        }
      }
      //We read 4 bytes as a uint32_t for file size
      else if (state == STATE_SIZE){
        if (fileSizeIndex < 4){
          fileSize = (fileSize << 8) + b;
          fileSizeIndex++;
        }
        else if (b == BYTE_SEPARATOR){
          state = STATE_CONTENT;
          flashBufferIndex = 0;
          escape = 0;
         
          if (SerialFlash.exists(filename)){
            SerialFlash.remove(filename);  //It doesn't reclaim the space, but it does let you create a new file with the same name.
          }
         
          //Create a new file and open it for writing
          if (SerialFlash.create(filename, fileSize)) {
            flashFile = SerialFlash.open(filename);
            if (!flashFile) {
              //Error flash file open
              flushError();
              return;
            }
          }
          else {
            //Error flash create (no room left?)
            flushError();
            return;
          }
        }
        else {
          //Error invalid length requested
          flushError();
          return;
        }
      }
      else if (state == STATE_CONTENT){
        //Previous byte was escaped; unescape and add to buffer
        if (escape){
          escape = 0;
          flashBuffer[flashBufferIndex++] = b ^ 0x20;
        }
        //Escape the next byte
        else if (b == BYTE_ESCAPE){
          //Serial.println("esc");
          escape = 1;
        }
        //End of file
        else if (b == BYTE_START){
          //Serial.println("End of file");
          state = STATE_START;
          flashFile.write(flashBuffer, flashBufferIndex);
          flashFile.close();
          flashBufferIndex = 0;
        }
        //Normal byte; add to buffer
        else {
          flashBuffer[flashBufferIndex++] = b;
        }
       
        //The buffer is filled; write to SD card
        if (flashBufferIndex >= FLASH_BUFFER_SIZE){
          flashFile.write(flashBuffer, FLASH_BUFFER_SIZE);
          flashBufferIndex = 0;
        }
      }
    }
  }

  //Success!  Turn the light off.
  digitalWrite(13, LOW);
}

void loop(){
  //Do nothing.
}

void flushError(){
  uint32_t lastReceiveTime = millis();
  char usbBuffer[USB_BUFFER_SIZE];
  //We assume the serial receive part is finished when we have not received something for 3 seconds
  // ..... parenthesis added around this bit on line below........... (lastReceiveTime + 3000) > millis()....reads better...
  while(Serial.available() || (lastReceiveTime + 3000) > millis()){
    if (Serial.readBytes(usbBuffer, USB_BUFFER_SIZE)){
      lastReceiveTime = millis();
    }
  }
}

rawfile-uploader-mc.py
#!/usr/bin/python
#
# Uploads raw audio files to Teensy + Audio board with SPI Flash on board.  To use this program, first
# load the 'CopyFromSerial' example sketch.  When it first runs, it will format the SPI flash chip
# (this may take a long time for larger chips; a 128MB chip that I am using can take almost 10 minutes,
# but smaller 16MB ones should be faster).
#
# While the chip is being formatted, the LED (pin 13) will toggle at 1Hz rate.  When the formatting is
# done, it flashes quickly (10Hz) for one second, then stays on solid.  When nothing has been received
# for 3 seconds, the upload is assumed to be completed, and the light goes off.
#
# You can start this program immediately upon plugging in the Teensy.  It will buffer and wait until
# the Teensy starts to read the serial data from USB.
#
###################

import serial, sys, os, time

if (len(sys.argv) <= 2):
print("Usage: '" + sys.argv[0] + " <port> <files>' where:\n\t<port> is the TTY USB port connected to Drum Master\n\t<files> is a list of .RAW files (bash globs work).")
sys.exit()

#Special bytes
BYTE_START = "\x7e"
BYTE_ESCAPE = "\x7d"
BYTE_SEPARATOR = "\x7c"

#Flash size (in MB).  Change this to match how much space you have on your chip.
FLASH_SIZE = 8

totalFileSize = 0;
for i, filename in enumerate(sys.argv):
if (i >= 2):
totalFileSize = totalFileSize + os.path.getsize(filename)

flashSizeBytes = FLASH_SIZE * 1024 * 1024
if (totalFileSize > flashSizeBytes):
print("Too many files selsected.\n\tTotal flash size:\t" + "{:>14,}".format(flashSizeBytes) + " bytes\n\tTotal file size:\t" + "{:>14,}".format(totalFileSize) + " bytes")
sys.exit()
#ser = serial.Serial(sys.argv[1], 9600, timeout=0, writeTimeout=None)
ser = serial.Serial(sys.argv[1])
ser.write("c")
print("Uploading " + str(len(sys.argv) - 2) + " files...")
for i, filename in enumerate(sys.argv):
if (i >= 2):
startTime = time.time();
sys.stdout.write(str(i - 1) + ": ")
sys.stdout.write(filename)
sys.stdout.flush()


f = open(filename, "rb")
fileLength = os.path.getsize(filename)
try:
encoded = []
#Start byte
encoded.append(BYTE_START)
#Filename
for byte in os.path.basename(filename):
encoded.append(byte)
#End of filename
encoded.append(BYTE_SEPARATOR)

#File length (uint32_t)
encoded.append(chr((fileLength >> 24) & 0xFF));
encoded.append(chr((fileLength >> 16) & 0xFF));
encoded.append(chr((fileLength >> 8) & 0xFF));
encoded.append(chr((fileLength >> 0) & 0xFF));
encoded.append(BYTE_SEPARATOR)

#Binary data, with escaping
for byte in f.read():
if byte == BYTE_START or byte == BYTE_ESCAPE:
encoded.append(BYTE_ESCAPE)
encoded.append(chr(ord(byte) ^ 0x20))
else:
encoded.append(byte);

#Write end of data byte
encoded.append(BYTE_START)
ser.write("".join(encoded))

finally:
f.close()

endTime = time.time();
print(" (" + str(round(fileLength / 1024 / (endTime - startTime), 2)) + " KB/s)");

print("All files uploaded")

Pour la lecture du son à partir de la SPI Flash vers le DAC (convertisseur Numérique -> Analogique), ci-joint un petit sketch "Teensy" - le choix du fichier à lire est réalisé en tapant sur une touche du clavier :
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

//#define FLASH_CHIP_SELECT 10

const int FLASH_CHIP_SELECT = 10; 
// GUItool: begin automatically generated code
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=228,273
AudioOutputAnalog        dac1;           //xy=751,337
AudioConnection          patchCord1(playFlashRaw1, 0, dac1, 0);
// GUItool: end automatically generated code
int lu;
void setup() {
    Serial.begin(9600);
    while (!Serial && millis()<500 );
    AudioMemory(50);
    analogReference(EXTERNAL);

//************************************
//  Set up SPI Teensy without audio Card
  SPI.setMOSI(11); //7
  SPI.setMISO(12);
  SPI.setSCK(14);
//************************************
    delay(2000);
    if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1){
            Serial.println ("Cannot access SPI Flash chip");
            delay (10000);
        }
    }
}
void playFile(const char *filename)
{
  SerialFlashFile ff = SerialFlash.open(filename);
  Serial.print("Playing file: ");
  Serial.println(ff);

  playFlashRaw1.play(filename);
  // Simply wait for the file to finish playing.
  while (playFlashRaw1.isPlaying()) {
   }
}   

void loop() {
if ( Serial.available() ) {
    lu = Serial.read();
    Serial.println(lu);
  }
//  else {
//    Serial.println("Rien");
//  }
switch (lu) {
  case 'a': {
    playFile("A0A814.TRW");
    break;
   }
  case 'z':{ 
    playFile("A1A814.TRW");
    break;
   }   
  case 'e':{   
    playFile("A2A814.TRW");
    break;
   }   
  case 'r':{ 
    playFile("A3A814.TRW");
    break;
   }   
  case 't':{ 
    playFile("A4A814.TRW");
    break;
   }   
  case 'y':{ 
    playFile("A5A814.TRW");
    break;
   }   
  case 'u':{ 
    playFile("A6A814.TRW");
    break;
   }       
  case 'i':{ 
    playFile("A7A814.TRW");
    break;
   }   
  case 'o':{ 
    playFile("A8A814.TRW");
    break;
   }   
//  default:
//    // statements
//  }
  }
}

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #123 le: mai 22, 2018, 11:29:03 pm »
Bonjour,
Le code ci-dessous fonctionne bien.
Il est possible de jouer en boucle le son sélectionné en appuyant sur les touches "a", "z", "e"," r", "t", "y", "u", "i", "o", ou "p" à partir du moniteur série.
Le son tourne en boucle tant que je n'ai pas appuyé sur une autre touche.

Je souhaiterai que lorsque j'appuie sur la touche : 'e' Horn, ce fichier soit lu une seule fois et qu'ensuite, le fichier lu précédemment soit repris en boucle.
Exemple :
1) 't' Driving en boucle (par appui sur 't')
2) 'e' Horn (par appui sur 'e') : Ce fichier ne doit être lu qu'une seule fois.
3) Reprise de la lecture du fichier précédent en boucle, c'est à dire 't'Driving dans cet exemple, mais cela peut être un autre fichier.

Je ne vois pas trop par quel mécanisme, je pourrai obtenir ce résultat ?

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
    //A0A8B14.TRW = 'a' Engine start - Pantograph up
    //A1AB814.TRW = 'z 'Compressor + air release
    //A2AB814.TRW = 'e 'Horn
    //A3AB814.TRW = 'r' Start driving
    //A4AB814.TRW = 't' Driving
    //A5AB814.TRW = 'y' Brake
    //A6AB814.TRW = 'u' Compressor - Air release + engine start
    //A7AB814.TRW = 'i' Uncoupling
    //A8AB814.TRW = 'o' Stop driving
    //A9AB814.TRW = 'p' Stand-by engine

const int FLASH_CHIP_SELECT = 10; 
// GUItool: begin automatically generated code
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=228,273
AudioOutputAnalog        dac1;           //xy=751,337
AudioConnection          patchCord1(playFlashRaw1, 0, dac1, 0);
// GUItool: end automatically generated code

int lu;

void setup() {
    Serial.begin(9600);
    while (!Serial && millis()<500 );
    AudioMemory(50);
    analogReference(EXTERNAL);

//************************************
//  Set up SPI Teensy without audio Card
  SPI.setMOSI(11); //7
  SPI.setMISO(12);
  SPI.setSCK(14);
//************************************
    delay(2000);
    if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1){
            Serial.println ("Cannot access SPI Flash chip");
            delay (10000);
        }
    }
}
void playFile(const char *filename)
{
  SerialFlashFile ff = SerialFlash.open(filename);
  Serial.print("Playing file: ");
  Serial.println(ff);

  playFlashRaw1.play(filename);
  // Simply wait for the file to finish playing.
  while (playFlashRaw1.isPlaying()) {
   }
}   

void loop() {
if ( Serial.available() ) {
    lu = Serial.read();
    Serial.println(lu);
  }
  else {
    Serial.println("Rien");
  }

switch (lu) {
  case 'a':{
    playFile("A0AB814.TRW");
    break;
   }
  case 'z':{ 
    playFile("A1AB814.TRW");
    break;
   }   
  case 'e':{   
    playFile("A2AB814.TRW");
    break;
   }
  case 't':{ 
    playFile("A4A814.TRW");
    break;
   }   
  case 'y':{ 
    playFile("A5AB814.TRW");
    break;
   }   
  case 'u':{ 
    playFile("A6AB814.TRW");
    break;
   }       
  case 'i':{ 
    playFile("A7AB814.TRW");
    break;
   }   
  case 'o':{ 
    playFile("A8AB814.TRW");
    break;
   } 
  case 'p':{ 
    playFile("A9A814.TRW");
    break;
   }     
    //  default:
    // statements
  }
}

Nota : A0A8B14.TRW est un fichier "son" avec l'extension "TRW" compatible avec la bibliothèque du Teensy.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #124 le: mai 23, 2018, 02:10:12 pm »
Bonjour Benoit,

Dans le programme que tu viens de poster, on s'aperçoit que :

  • la fonction play attend que le son soit terminé avant de retourner
  • la variable lu n'étant pas réinitialisée après utilisation pour le switch...case, le son est relancé en boucle

Donc, si tu veux que le son s'arrête, il suffit de mettre lu à un caractère qui n'apparaît pas dans le switch à la fin de loop

Ensuite ce que tu veux faire c'est plutôt avoir le horn superposé avec le bruit de machine ? Dans ce cas, il faut plutôt avoir plusieurs canaux et un mixer.
« Modifié: mai 23, 2018, 02:14:28 pm par Jean-Luc »
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #125 le: mai 23, 2018, 09:04:41 pm »
Ok, merci Jean-Luc.

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #126 le: mai 24, 2018, 09:12:46 pm »
Bon, voilà, ça marche bien. C'est un peu béton, mais ça marche.
Je pense que ce code pourrait être transcrit pour un Arduino en utilisant des fichiers codés en PWM.
Pour l'instant, je n'utilise pas encore le mixage de deux fichiers "son": Il faut que je regarde sur le site PRJC Teensy.
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

    //A0A8B14.TRW = 'a' Engine start - Pantograph up
    //A1AB814.TRW = 'z' Compressor + air release
    //A2AB814.TRW = 'e' Horn
    //A3AB814.TRW = 'r' Start driving
    //A4AB814.TRW = 't' Driving
    //A5AB814.TRW = 'y' Brake
    //A6AB814.TRW = 'u' Compressor - Air release + engine start
    //A7AB814.TRW = 'i' Uncoupling
    //A8AB814.TRW = 'o' Stop driving
    //A9AB814.TRW = 'p' Stand-by engine

const int FLASH_CHIP_SELECT = 10; 
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySerialflashRaw  playFlashRaw1;  //xy=228,273
AudioOutputAnalog        dac1;           //xy=751,337
AudioConnection          patchCord1(playFlashRaw1, 0, dac1, 0);
// GUItool: end automatically generated code

int lu;     // Données lu liaison série
int Oldlu;  // Données lu liaison série

void setup() {
    Serial.begin(9600); // Initialisation liaison série
    while (!Serial && millis()<500 );
    AudioMemory(50);// Réservation espace mémoire
    analogReference(EXTERNAL);//Configurer Amplitude 3,3V pour le DAC

//************************************
//  Set up SPI Teensy without audio Card
  SPI.setMOSI(11); //7
  SPI.setMISO(12);
  SPI.setSCK(14);
//************************************
    delay(2000);
    if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1){
            Serial.println ("Cannot access SPI Flash chip");
            delay (10000);
        }
    }
}
    void playFile1(const char *filename)// Fonction lecture fichier audio
    {
      SerialFlashFile ff = SerialFlash.open(filename);
      Serial.print("Playing file1: ");
      Serial.println(ff);
      playFlashRaw1.play(filename);
     // Simply wait for the file to finish playing.
     while (playFlashRaw1.isPlaying()) {
     }
    }
   
void loop() {
if ( Serial.available() ) {
    lu = Serial.read();
    Serial.println(lu);
  }
  else {
    Serial.println("Rien");
  }

switch (lu) {
   case 'a':{  // Fichier à lire en boucle 
     Oldlu = 'a';   
     playFile1("A0AB814.TRW");
     break;
   }
   case 'z':{  // Fichier à lire en boucle 
      Oldlu = 'z';  // Lecture en boucle 
      playFile1("A1AB814.TRW");
      break;
   }   
           case 'e':{   // Fichier à lire une seule fois   
           playFile1("A2AB814.TRW");
           lu=Oldlu; // reprise fichier précédent
           Serial.println(lu);
           break;
           }
    case 't':{  // Fichier à lire en boucle 
     Oldlu = 't';
     playFile1("A4A814.TRW");
     break;
    }   
    case 'y':{  // Fichier à lire en boucle 
     Oldlu = 'y';
     playFile1("A5AB814.TRW");
      break;
    }   
    case 'u':{  // Fichier à lire en boucle 
      Oldlu = 'u'; 
      playFile1("A6AB814.TRW");
     break;
    }       
    case 'i':{  // Fichier à lire en boucle   
      Oldlu = 'i';
      playFile1("A7AB814.TRW");
      break;
    }   
    case 'o':{  // Fichier à lire en boucle 
      Oldlu = 'o'; 
      playFile1("A8AB814.TRW");
      break;
    } 
    case 'p':{  // Fichier à lire en boucle 
      Oldlu = 'p'; 
      playFile1("A9A814.TRW");
      break;
   }     
  }
}

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #127 le: mai 29, 2018, 09:50:58 pm »
Bonjour,
Si j'utilise à la place du Teensy, un arduino pour lire des fichiers "son" à partir d'une SPI Flash,
comment devrais-je procéder pour :
 - Écrire dans la SPI Flash à partir d'un fichier "son" qui est situé sur le PC
 - Lire ce fichier "son" sur l'arduino (à partir de son nom de fichier)
Merci

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #128 le: mai 29, 2018, 09:59:00 pm »
Si la SPI FLASH est une Carte SD, c’est facile d’y écrire des fichiers avec un PC.
Pour les restituer avec un Arduino, j’explique mon projet ici :
http://forum.locoduino.org/index.php?topic=157.60
Cordialement,
Dominique

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #129 le: mai 29, 2018, 10:31:40 pm »
Non ce n'est pas une carte SD

- Écrire dans la SPI Flash à partir d'un fichier "son" qui est situé sur le PC

Il est fort possible que le sketch que tu as utilisé sur Teensy fonctionne également. Idem pour le programme côté PC

Citer
- Lire ce fichier "son" sur l'arduino (à partir de son nom de fichier)

Là par contre je doute que Audio fonctionne sur Arduino.
« Modifié: mai 29, 2018, 11:00:09 pm par Thierry »
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #130 le: mai 29, 2018, 11:55:44 pm »
Je vais essayer avec la librairie Teensy Audio.h : on ne sait jamais !
Sinon, je pense utiliser le principe suivant : (j'avais comparé plusieurs techniques plus avant dans ce sujet) :
2) Arduino + EncodeAudio + Bibliothèque <PCM.h> + sortie PWM
Avantages :
Qualité de son moyenne mais acceptable pour réaliser du bruitage (8 bits – 8kHz)
Fichiers « son » codé avec EncodeAudio -> fichiers « son » de petite taille
Inconvénients :
Essentiellement lié au fait que l’arduino ne possède que peu de mémoire (Flash ou RAM)

Les"sons" seront chargés dans une  SPI Flash Winbond 25Q64BVSIG (8 Mo).
Je pourrais essayer d'augmenter la résolution et la fréquence d'échantillonnage.
Je vais essayer également de tout faire tenir sur un Arduino Nano (commande moteur, éclairages diverses, bruitage) car même en travaillant à l'échelle 1, il n'y a pas tellement de place (en particulier sur la BR80= petite locomotive à vapeur 030).
Il faut que je case dans la locomotive :

 1 - Un Arduino Nano
 2 - Un pont en H (pour les moteurs)
 3 - une minicarte avec la SPI Flash Winbond 25Q64BVSIG
 4 - Une petite carte amplificatrice (son)
 5 - Un haut-parleur
 6 - Une carte de décodage Dcc + alimentation 5V + alimentation 16 V (pour les moteurs)




Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3039
  • 100% Arduino et N
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #131 le: mai 30, 2018, 07:00:24 am »
Le Teensy 3.2 (18x36 mm) est plus petit qu’un Nano donc pour gagner de la place...
Le Pro Mini a une taille équivalente (18x33 mm) et la partie USB n’est plus nécessaire une fois le projet terminé.

Mais côté mémoire je vois mal comment se contenter de 32k de flash (AtMega328) par rapport aux 256k du Teensy, surtout pour la Ram (2k contre 64k).
Cordialement,
Dominique

Thierry

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 810
    • Voir le profil
« Modifié: mai 30, 2018, 10:38:25 am par Thierry »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #133 le: mai 30, 2018, 11:57:16 am »
Du coup je ne comprends pas trop

Comme dit Dominique le Teensy est plus petit qu'un Nano. Il est beaucoup plus puissant (calcul, mémoire). Il a une sortie DAC qui évite la circuiterie externe pour lisser la PWM, il a un support en terme de bibliothèques audio qui est plus avancé, il est complètement compatible avec l'infrastructure logicielle Arduino. Et enfin tu as commencé à prototyper des choses qui marchent dessus.

Pourquoi essayer de faire entrer au chausse pied tes fonctions dans un Nano ?

D'ailleurs ça risque bien de ne pas rentrer, si tu veux par exemple mixer le bruit moteur, le klaxon et le freinage, et je ne parle pas de la fréquence du SPI qui est limité à 8MHz alors que sur Teensy tu peux monter à 24MHz.

Thierry, sur l'ESP 32 il n'y a pas de sortie DAC et la PWM est logicielle. Les STM32 ont un support Arduino limité.
Cordialement

Benoit92

  • Full Member
  • ***
  • Messages: 200
    • Voir le profil
Re : Re : Teensy 3.1, 3.2 - Sonorisation locomotive
« Réponse #134 le: mai 30, 2018, 01:24:15 pm »
Le Teensy 3.2 (18x36 mm) est plus petit qu’un Nano donc pour gagner de la place...
Le Pro Mini a une taille équivalente (18x33 mm) et la partie USB n’est plus nécessaire une fois le projet terminé.

Mais côté mémoire je vois mal comment se contenter de 32k de flash (AtMega328) par rapport aux 256k du Teensy, surtout pour la Ram (2k contre 64k).
C'est vrai, mais la bibliothèque NmraDcc (qui permet de décoder les trames DCC) n'est pas compatible avec le Teensy.
Donc, je suis obligé de rester sur Arduino pour assurer le décodage de la trame DCC.
J'ai déjà monté l'Arduino Nano sur une locomotive mais je n'assure que les fonctions commande moteur (pont H), éclairages et feux.

ESP32 ou Arduino Nano : je n'ai pas de préférence : j'ai déjà  5 Nano acheté pour 10,00 € chez Aliexpress.