ENG-CANSAT-FEATHER-M0-SPI
Forewords
One of the most exciting feature of the M0 Express board is this small FLASH chip wired on the SPI bus. That memory could be used to provide lot of services like storing files, python script and many more.
You can see that additional FLASH chip like a small SD card continously wired on the board. This flash memory is available through a library very similar to the Arduino's SD card. You can even read and write the files on the CircuitPython filesystem (Circuit Python use this Flash to store the Python Script and files)!
You will need to install the Adafruit SPI Flash Memory library in Arduino IDE to use the SPI Flash with your Arduino sketch. Click on the link below to download the library source code, open the zip file and copy the file files into a subfolder named Adafruit_SPIFlash (remove the '-master' added by GitHub on the front of the folder name). Place this new library next to your other Arduino libraries:
Once the library installed, start your Arduino IDE to access the various examples available in the library:
- fatfs_circuitpython
- fatfs_datalogging
- fatfs_format
- fatfs_full_usage
- fatfs_print_file
- flash_erase
Thoses exemples would allow you to format the Flash memory with the FAT filesystem (the same filesytem than used on SD card), read and write files like we do with SD card.
Format the Flash memory
The example fatfs_format will format the SPI FLASH with a brand new FileSystem. WARNING: this sketch will erase all the data stored in the FLASH memory, including any data, python script!.
The sketch is useful when you need to erase ALL the items to start a fresh setup. This sketch would also allow you to recover the board when the file system is corrupted.
The sketch fatfs_format and exemples here under are not compatible with the CircuitPython file system!. If you need to share data between Arduino and CircuitPython then you should have a look to the example fatfs_circuitpython described here below. |
To execute the formatting sketch, just load the Arduino IDE and updload it on the Feather M0 board. Then open the serial monitor (at 115200 baud). You should see a message requiring a confirmation before formatting the Flash.
If you do not see the message, close the serial monitor, press the reset button then open the serial monitor again.
Crédit: AdaFruit Industries www.adafruit.com
Type in OK in the serial monitor and press the "send" button to confirm the format operation of the Flash memory. It is necessary to type the OK in capital!
Once done, the sketch would start to format the SPI Flash memoryt. The formating procedure need 1 minute to get complete. The sketch will display a message when done. Great, you have a drand new file system.
Error while formatting
If you can't get the Flash memory formated and receive the following error:
Adafruit SPI Flash FatFs Format Example Flash chip JEDEC ID: 0x1401501 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This sketch will ERASE ALL DATA on the flash chip and format it with a new filesystem! Type OK (all caps) and press enter to continue. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Partitioning flash with 1 primary partition... Couldn't read sector before performing write! Error, f_fdisk failed with error code: 1
Then you will need to use an older library version (until a fixed version is released).
See this thread on the Adafruit forums.
Datalogging example
A common usage of the SPI Flash memory is the datalogging. The example fatfs_datalogging shows some datalogging/writing operation. Open the sketch into Arduino IDE then upload the Feather M0 board. Next, open the serial monitor (at 115200 baud) and you should see a message displayed every minutes when the sketch writes a new line in the SPI Flash file system.
See the content of the loop() function to understand how to write into a file:
// Open the datalogging file in write mode. the FILE_WRITE mode will
// open the file for appending (it will add the data a the end
// of the file).
File dataFile = fatfs.open(FILE_NAME, FILE_WRITE);
// Check if the file is open and write datas.
if (dataFile) {
// Grab the data from sensors. In this sample
// the data would be a random number.
int reading = random(0,100);
// Write a new line in the file.
// The user can use the same functions as print function
// sending data to the serial monitor.
// EG: to write 2 CSV entries (coma separated):
dataFile.print("Sensor #1");
dataFile.print(",");
dataFile.print(reading, DEC);
dataFile.println();
// The file must be closed at the end of writing operation.
// This is the right way to ensure that data are writtebn
// into the file.
dataFile.close();
Serial.println("New value written to the file!");
}
Comme vous le feriez avec la bibliothèque Arduino de la carte SD, vous pouvez créer un objet File en appelant la fonction open en indiquant le nom de fichier et le mode d'accès (le mode FILE_WRITE, écrit de nouvelles données en fin de fichier). Notez cependant qu'à la place d'appeler la fonction global open, c'est la méthode fatfs.open() de l'objet système_de_fichier nouvellement créé qu'il faut appeler (voyez les valeurs de configurations juste après #define).
Une fois le fichier ouvert, il suffit simplement d'appeler les fonctions print et println sur l'objet fichier pour écrire des données en fin de fichier. C'est exactement comme envoyer des données vers le moniteur série pour y afficher du texte, des valeurs numériques et autres types de donnée.
Assurez-vous d'avoir correctement fermé le système de fichier pour être certain que les données soient enregistrées correctement dans le fichier!
Lecture et affichage de fichiers
L'exemple fatfs_print_file ouvrira un fichier (le fichier data.csv par défaut, le fichier créé par l'exemple fatfs_datalogging présenté ci-dessus) et affiche tout son contenu dans le moniteur série. Ouvrez l'exemple fatfs_print_file et téléversez le sur votre carte Feather M0, puis ouvrez le moniteur série (à 115200 baud).
Vous devriez voir le croquis afficher le contenu du fichier data.csv (si la mémoire flash ne contient pas de fichier data.csv alors vous pouvez ouvrir l'exemple datalogging ci-dessus pour le créer).
Voyez le contenu de la fonction setup() pour comprendre comment s'effectue la lecture du fichier:
// Ouvrir le fichier en lecture et vérifier s'il est correctement ouvert
// Le mode FILE_READ ouvre le fichier en lecture.
File dataFile = fatfs.open(FILE_NAME, FILE_READ);
if (dataFile) {
// Le fichier a été ouvert.
// Afficher le contenu caractère par caractère jusqu'à
// la fin du fichier.
Serial.println("Fichier ouvert, contenu affiché ci-dessous:");
while (dataFile.available()) {
// Utilisé la fonction read() pour lire le prochain caractère.
// Il est également possible d'utiliser des fonctions telles
// que readUntil, readString, etc.
// Voyez l'exemple fatfs_full_usage pour plus de détails.
char c = dataFile.read();
Serial.print(c);
}
}
Tout comme pour l'écriture de donnée dans l'exemple datalogging, il est nécessaire de créer un objet File en appelant la fonction open de l'objet fatfs. Cependant, cette fois, le mode utilisé est FILE_READ, indiquant que l'on désire lire le système de fichier.
Après avoir ouvert le fichier en lecture, la fonction available permet de facilement savoir si des données sont disponibles dans le fichier. Ensuite, la fonction read permet de lire un caractère depuis le fichier. La combinaison de ces deux fonctions permet de réaliser facilement une boucle de lecture qui vérifie la disponibilité de donnée puis la lecture et l'affichage de celle-ci (un caractère à la fois).
Il existe également des fonctions de lecture avancées que vous pouvez voir dans l'exemple fatfs_full_usage ou soit dans la documentation de la classe SD d'Arduino (la bibliothèque Flash SPI implémente les mêmes fonctions).
Exemple complet d'utilisation de la Flash
Vous pouvez vous référer à l'exemple fatfs_full_usage pour une démonstration complète concernant la lecture et l'écriture de fichiers. Cet exemple utilise toutes les fonction de la bibliothèque et démontre des opérations tels que le test d'existence d'un fichier, la création de répertoire, effacement de fichier, effacement de fichier, etc.
Rappelez vous que la bibliothèque SPI flash est conçue pour exposer les mêmes fonctions et mêmes interfaces que la la bibliothèque SD d'Arduino. Par conséquent, les code et exemples stockant des données sur une carte SD seront très facile à adapter pour fonctionner avec la bibliothèque SPI flash. Créez simplement un objet fatfs comme dans les exemples ci-dessus et utilisez la fonction open sur cet objet (en lieu et place de la fonction globale). Une fois que vous avez obtenu une référence sur un fichier, toutes les fonctions et utilisations sont identiques entre la bibliothèque SPI flash et la bibliothèque SD d'Arduino!
Lire et écrire des fichiers CircuitPython
L'exemple fatfs_circuitpython montre comment lire et écrire des fichiers sur la mémoire flash de sorte qu'ils puissent être accéssible depuis CircuitPython/MicroPython. Cela signifie que vous pouvez exécuter un programme CircuitPython sur votre carte pour y stocker des données, puis utiliser un croquis Arduino qui utilise cette bibliothèque pour interagir avec ces mêmes données.
Notez qu'avant d'utiliser l'exemple fatfs_circuitpython vous devez avoir chargé CircuitPython sur votre carte. Voyez ce guide pour charger la dernière version de CircuitPython afin que le système de fichier CircuitPython soit écrit et initialisé sur la puce Flash. Une fois CircuitPython chargé sur la carte, vous pouvez exécuter le croquis fatfs_circuitpython.
Pour exécuter le croquis, il faut le charger dans Arduino IDE et le téléverser sur la carte Feather M0. Ensuite, il faut ouvrir le moniteur série à 115200 baud. Vous devriez voir des messages s'afficher lorsqu'il essaye de lire et écrire des fichiers sur la mémoire Flash.
Plus spécifiquement, l'exemple cherche les fichiers boot.py et main.py (puisque CircuitPython exécute ces fichiers au démarrage) et affiche leur contenu. Puis il ajoute une ligne à la fin du fichier data.txt présent sur la carte (le fichier est créé s'il n'existe pas encore). Après avoir exécuté le croquis, vous pouvez recharger CircuitPython sur la carte et charger et lire le fichier data.txt depuis CircuitPython!
Voyons un peu le code du croquis pour comprendre comment lire et écrire des fichiers CircuitPython. Pour commencer une instance de la classe Adafruit_M0_Express_CircuitPython est crée en lui passant un instance de la classe SPIFlash (permettant d'accéder à la mémoire Flash):
#define FLASH_SS SS1 // broche SSP de la Flash
#define FLASH_SPI_PORT SPI1 // port SPI surlequel est branché la mémoire Flash
Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Utiliser le bus SPI matériel
// Il est possible d'utiliser d'autres broches comme bus SPI (SPI logiciel)!
//Adafruit_SPIFlash flash(SCK1, MISO1, MOSI1, FLASH_SS);
// Pour finir, créer un objet Adafruit_M0_Express_CircuitPython qui offre un accès
// à une interface de type Carte SD pour interagir avec les fichiers stockés dans
// le système de fichier Flash de CircuitPython.
Adafruit_M0_Express_CircuitPython pythonfs(flash);
En utilisant la classe Adafruit_M0_Express_CircuitPython vous obtenez un objet de type système de fichier compatible avec en lecture et écriture avec le formattage de la mémoire Flash de CircuitPython. C'est très important pour l'interopérabilité entre CircuitPython et Arduino étant donné que CircuitPython dispose d'un partitionnement spécifique et d'un agencement particulier de la mémoire flash qui n'est pas compatible avec des bibliothèque plus "simple" (que vous pourriez rencontrer dans les autres exemples).
Une fois l'instance de la classe Adafruit_M0_Express_CircuitPython créée (instance appelée pythonfs dans le croquis) vous pouvez interagir avec elle comme s'il s'agissait de la bibliothèque carte SD d'Arduino. Vous pouvez ouvrir des fichiers en lecture ou écriture, créer des répertoires, effacer des fichiers et répertoires et plus encore.
Voici un croquis qui vérifie la présence du fichier boot.py et affiche sont contenu (un caractère à la fois):
// Vérifie si le fichier boot.py existe puis affiche le contenu.
if (pythonfs.exists("boot.py")) {
File bootPy = pythonfs.open("boot.py", FILE_READ);
Serial.println("Afficher boot.py...");
while (bootPy.available()) {
char c = bootPy.read();
Serial.print(c);
}
Serial.println();
}
else {
Serial.println("Pas de fichier boot.py...");
}
Notez l'appel de la fonction exists qui vérifie la présence du fichier boot.py, puis l'utilisation de la fonction open pour ouvrir celui-ci en mode lecture (read en anglais). Une fois fichier ouvert vous obtenez une référence vers un objet de la classe File qui permet de lire et écrire dans le fichier comme s'il s'agissait d'un périphérique Serial (encore une fois, toutes les fonctions de la classe File sont identiques à celle de la classe carte SD).
Dans ce cas, la fonction available retournera le nombre d'octets (bytes) restant à lire jusqu'à la fin du fichier -et- la fonction read lit un caractère à la fois (pour l'afficher sur le moniteur série).
L'écriture d'un fichier est tout aussi simple, voici comment le croquis ajoute des données dans le fichier data.txt:
// Créer et ajouter des données dans le fichier data.txt
// puis ajouter un retour à la ligne.
// Le code CircuitPython pourra, plus tard, ou consulter
// le contenu de ce fichier!
File data = pythonfs.open("data.txt", FILE_WRITE);
if (data) {
// Ajouter une nouvelle ligne de donnée:
data.println("Un bonjour a CircuitPython de la part d Arduino!");
data.close();
// Voir les autre exemples fatfs comme fatfs_full_usage
// et fatfs_datalogging pour plus d'exemples concernant
// les interactions avec les fichiers.
Serial.println("Nouvelle ligne ajoutée au fichier data.txt!");
}
else {
Serial.println("Erreur, ne sais pas ouvrir le fichier en écriture!");
}
Cette fois encore, la fonction open est utilisée pour ouvrir le fichier si ce n'est que cette fois, le fichier est ouvert en lecture (write en anglais). Dans ce mode, le fichier est ouvert en ajout (les données sont ajoutées en fin de fichier) si ce dernier existe. A noter le mode écriture crée le fichier si celui-ci n'existe pas. Une fois le fichier ouvert, les fonctions tels que print et println peuvent être utilisées pour écrire des données dans le fichier (juste comme envoi des données vers le moniteur série). Une fois le traitement terminé, la fonction close ferme le fichier!
Voilà, nous en avons terminé avec les opérations fondamentales de lecture et d'écriture. Voyez l'exemple fatfs_full_usage pour un apercu des fonctionnalités avancées tels que la création de répertoire, effacement de fichiers et répertoires, obtention de la taille d'un fichier, etc! Rappelez vous que pour interagir avec les fichiers CircuitPython, il faudra utiliser la classe Adafruit_Feather_M0_CircuitPython comme indiqué dans l'exemple ci-dessus!
Accéder à la Flash SPI
Arduino n'est malheureusement pas capable d'exposer un périphérique de stockage (dit "mass storage" en anglais). Par conséquent, il faut utiliser CircuitPython qui, lui, est capable de faire cela pour nous. Voici la technique à utiliser.Here's the full technique:
- Démarrer le bootloader de votre carte Express. Faites un glisser/déposer de la dernière version du fichier uf2 circuitpython.
- Après un moment, vous devriez voir apparaître le lecteur CIRCUITPY contenant un fichier boot_out.txt. Voilà, le système de fichier est initialisé sur la Flash SPI.
- Ouvrez maintenant Arduino IDE et téléversez l'exemple fatfs_circuitpython disponible dans la bibliothèque SPI d'Adafruit. Ouvrez la console série pour démarrer le croquis. Voilà, le système de fichier CircuitPython sera correctement monté et le fichier data.txt créé et initialisé.
Crédit: AdaFruit Industries www.adafruit.com
- Revenons sur notre ordinateur, redémarrez le bootloader de la carte Express --ET-- re-glissez/re-déposez circuitpython.uf2 sur le lecteur BOOT rendu accessible par le bootloader. Voilà, CircuitPython est résintallé sur la carte Express.
- Au bout d'un moment, le lecteur CIRCUITPY redevient accessible. Celui-ci expose a nouveau le système de fichier MicroPython de la Flash SPI. Vous pouvez maintenant voir le fichier data.txt, l'ouvrir et en consulté le contenu!
Crédit: AdaFruit Industries www.adafruit.com
Une fois que votre croquis de datalogging Arduino fonctionne comme attendu, vous pouvez simplifier la procédure en copiant CURRENT.UF2 depuis le lecteur BOOT pour faire une copie de sauvegarde de votre programme Arduino. Vous pourrez ensuite charger CircuitPython pour accéder au système de fichier de la Flash SPI et enfin recopier votre CURRENT.UF2 sur le lecteur BOOT de la carte Express pour réactiver votre croquis Arduino!
Written by Meurisse D. from MC Hobby - License: CC-SA-BY.