ENG-CANSAT-FEATHER-M0-SKETCH

De MCHobby - Wiki
Sauter à la navigation Sauter à la recherche

Forewords

The ATSAMD21 is still a newcomer in the Arduino-compatible world. Most of sketch and libraries would work on ATSAND21 but somes things have to be pointed out!

Le notes here under would apply to the M0 boards.

Analog reference

If you want to use the ARef for a voltage reference under 3.3v, the line code to use is analogReference(AR_EXTERNAL) with AR_EXTERNAL and not EXTERNAL.

Pins and pull-up

The old way of activating the pull-up resistor was:

pinMode(pin, INPUT)
digitalWrite(pin, HIGH)

Because the pullup-selection register was the same register than output-selection register.

For the M0 (as for many plateform), the code to use is:

pinMode(pin, INPUT_PULLUP)

Serial ou SerialUSB

99.9% of Arduino Sketch does use Serial.print for debugging purpose (or serial output). On the official SAMD/M0 Arduino, this instruction use the Serial5 port which is not exposed on a Feather.

Instead, the USB port on official Arduino M0 is called SerialUSB.

Adafruit did fix this on the Adafruit M0 by redirecting Serial call to USB calls. So, when using a Feather M0 everything appears to work to properly without requiring any changes.

If you want to use an official M0 without the need to change all the Serial.print() call to SerialUSB.print() , then place the following code:

#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL)
   // required for Serial operations on Zero based board
   #define Serial '''SERIAL_PORT_USBVIRTUAL'''
#endif

just before the first function definition in the code.

Example:

FEATHER-M0-ArduinoIDE-Croquis-01.png
Crédit: AdaFruit Industries www.adafruit.com

AnalogWrite / PWM on Feather M0

After looking through the SAMD21 datasheet, we've found that some of the options listed in the multiplexer table don't exist on the specific chip used in the Feather M0.

For all SAMD21 chips, there are two peripherals that can generate PWM signals: The Timer/Counter (TC) and Timer/Counter for Control Applications (TCC). Each SAMD21 has multiple copies of each, called 'instances'.

Each TC instance has one count register, one control register, and two output channels. Either channel can be enabled and disabled, and either channel can be inverted. The pins connected to a TC instance can output identical versions of the same PWM waveform, or complementary waveforms.

Each TCC instance has a single count register, but multiple compare registers and output channels. There are options for different kinds of waveform, interleaved switching, programmable dead time, and so on.

The biggest members of the SAMD21 family have five TC instances with two 'waveform output' (WO) channels, and three TCC instances with eight WO channels:

  • TC[0-4],WO[0-1]
  • TCC[0-2],WO[0-7]

And those are the ones shown in the datasheet's multiplexer tables.

The SAMD21G used in the Feather M0 only has three TC instances with two output channels, and three TCC instances with eight output channels:

  • TC[3-5],WO[0-1]
  • TCC[0-2],WO[0-7]

En suivant les signaux vers les broches rendues disponibles sir le Feather M0, les broches suivantes ne seront pas capable de produire de signal PWM:

  • broche analogique A5

Les broches suivantes peuvent être configurées en sortie PWM (sans aucun conflit) aussi longtemps que les broches SPI, I2C et UART gardent leurs fonctions protocole:

  • Broches digitales 5, 6, 9, 10, 11, 12 et 13
  • Broches analogiques A3 et A4

Si seules les broches SPI gardent leur fonctions protocole, vous pouvez également faire du PWM sur les broches suivantes:

  • TX (broche digitale 1)
  • SDA (broche digitale 20)

analogWrite() et gamme de valeur PWM

Sur un AVR (Arduino Uno), si vous utilisez l'instruction analogWrite(pin, 255) sur une sortie PWM alors cela conduit à un signal HAUT en permanence sur la broche.

Sur un Cortex ARM, le signal PWM sera fixé à 255/256. Par conséquent, il y aura toujours une très petite 'implusion à 0v'. Si vous avez besoin que le signal soit continuellement HIGH alors il faudra ajouter un test qui remplace l'instruction analogWrite(pin, 255) par digitalWrite(pin, HIGH)

Fichier d'entête manquant

Vous pourriez avoir du code qui utilise des bibliothèques non supportée sur un coeur M0. Par exemple, si vous avez du code contenant la ligne suivante:

#include <util/delay.h>

alors vous obtiendrez une erreur mentionnant

fatal error: util/delay.h: No such file or directory
  #include <util/delay.h>
                         ^
compilation terminated.
Error compiling.

Ce qui permet de localiser la ligne (et fichier) où s'est produit l'erreur. Il suffira alors de l'inclure dans une structure #ifdef comme celle présentée ci-dessous:

#if !defined(ARDUINO_ARCH_SAM) && !defined(ARDUINO_ARCH_SAMD) && !defined(ESP8266) && !defined(ARDUINO_ARCH_STM32F2)
 #include <util/delay.h>;
#endif

Les lignes ci-dessous font en sorte de ne pas inclure le fichier d'entête pour d'autres architectures.

Si l'instruction #include se trouve directement dans votre croquis Arduino alors vous pouvez essayer de retirer cette ligne.

Lancer le Bootloader

Sur la plupart des AVRs (Arduino Uno), le simple fait de presser le bouton reset avec le microcontrôleur branché en USB permet de démarrer manuellement le bootloader. Le bootloader termine automatiquement sont exécution au bout de quelques secondes.

Sur le M0, vous aurez besoin de double cliquer le bouton reset. Vous verrez la LED rouge pulser, ce qui indique que le bootloader est actif. Une fois dans ce mode, il n'y a pas de "time out", le M0 reste en mode bootloader indéfiniment. Cliquez une nouvelle fois sur le bouton "reset" pour redémarrer le microcontrôleur.

Alignement en mémoire

Cela à moi de chance de vous arriver... mais autant être tenu informé.

Si vous avez utilisé des plateformes 8 bits alors vous savez probablement qu'il est possible de réaliser des typecast de variables. Par exemple:

uint8_t mybuffer[4];
float f = (float)mybuffer;

Mais vous ne pouvez pas garantir que cela fonctionnera sur une plateforme 32 bits parce que mybuffer pourrait ne pas être aligné sur 2 ou 4 octets (voir alignement en mémoire sur Wikipedia).

Un ARM Cortex-M0 peut uniquement accéder directement aux données par bloc de 16-bit (tous les deux ou 4 octets). Essayer d'accéder à un octet impaire (octets en position 1 ou 3) provoquera une erreur matérielle et un arrêt du MCU.

Heureusement, il existe une solution simple... utiliser la fonction memcpy !

uint8_t mybuffer[4];
float f;
memcpy(f, mybuffer, 4)

Conversion en virgule flottante (dtostrf)

Tout comme pour les AVR arduino, la bibliothèque M0 ne propose un support "complet" permettant de convertir une valeur en virgule flottante vers une chaine de caractères.

Les fonctions comme sprintf ne feront pas la conversion de valeur en virgule flottante. Par chance, la bibliothèque standard AVR-LIBC inclus la fonction dtostrf qui est capable de gérer cette conversion pour nous.

Malencontreusement, les bibliothèques run-time du M0 ne dispose pas de cette fonction dtostrf! Vous pourriez rencontrer quelques fils de discussions mentionnant #include <avr/dtostrf.h> pour obtenir la fonction dtostrf. Mais si cela compile, le fonction ne fonctionne pas sur un M0.

A la place, voyez le fil de discussion suivant pour trouver une fonction dtostrf fonctionnelle que vous pourrez inclure dans votre code:

Combien de RAM disponible?

Un ATSAMD21G18 dispose de 32K de RAM mais vous pourriez avoir besoin de surveiller sa consommation pour des raisons propres à votre projet. Vous pouvez le faire à l'aide de cette fonction:

extern "C" char *sbrk(int i);

int FreeRam () {
  char stack_dummy = 0;
  return &stack_dummy - sbrk(0);
}

Merci a ce fil de discussion sur les forums Arduino pour ce truc!

Stocker des données en FLASH

Si vous utilisez un AVR (Arduino), alors vous avez probablement déjà utilisé PROGMEM qui permet au compilateur de savoir que vous voulez placer le contenu d'une variable (ou chaine de caractère) dans la mémoire Flash (afin d'économiser de la RAM).

Sur un ARM, c'est un peu plus facile. Il suffit d'ajouter le mot const devant le nom de la variable:

const char str[] = "Ma treesss lonnnnguuuue chaiiiinnnnneeee";

Cette chaîne de caractère est maintenant en FLASH. Vous pouvez manipuler la chaîne de caractère comme si c'était des données en RAM, le compilateur fera automatiquement une lecture depuis la mémoire FLASH et vous n'aurez pas besoin d'utiliser de fonction spécialement conçue pour les manipulation progmem.

Vous pouvez vérifier l'emplacement de stockage des données en affichant leur adresse de stockage:

Serial.print("Address of str $"); Serial.println((int)&str, HEX);

Si l'adresse est:

  • égale ou supérieure à $2000000 alors c'est stocker en SRAM.
  • entre $0000 et $3FFFF alors c'est stocké en FLASH

Written by Meurisse D. from MC Hobby - License: CC-SA-BY.