Comment vraiment réduire une esquisse

9

Je veux faire un croquis aussi petit que possible, à des fins de test. Le problème est que lorsque je compile l'esquisse BareMinimum (avec une configuration et une boucle vides), j'obtiens 466 octets pour l'Uno et 4 242 pour le Leonardo. Existe-t-il un moyen d'écrire votre propre code qui n'a pas de fonctions supplémentaires (à savoir Timer0 pour millis()et delay()). J'aimerais également pouvoir désactiver les fonctions clavier / souris du Leonardo.

Le docteur
la source
4
Cela ne devrait-il pas être étiqueté leonardo et non uno (et se concentrer sur une seule planche)? Ce sont des questions distinctes.
asheeshr
Je souligne simplement qu'une esquisse compilée vierge est grande pour de nombreuses cartes, en particulier celles basées sur USB natives
TheDoctor
J'aimerais également pouvoir désactiver les fonctions clavier / souris du Leonardo. est la deuxième question.
asheeshr

Réponses:

3

Vous devriez pouvoir créer votre propre définition de carte avec un fichier boards.txt personnalisé selon https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification . Comme je le vois, il y a plusieurs fonctionnalités USB dans la définition de Leonardo. J'espère que l'inclusion de la compilation du 4K est basée sur ces drapeaux et non sur le type de processeur.

Où le boards.txt utiliserait le téléchargement, les sections du chargeur de démarrage de Leonardo et la construction de l'uno.

Tout cela suppose que la construction de la bibliothèque principale n'utilise pas d'indicateurs spécifiques au processeur pour inclure les fonctions USB.

Si vous obtenez un tel travail. poster en arrière, je suis sûr que d'autres seraient intéressés.


J'ai récemment rencontré cette limitation d'utilisation 4K sur une démo de bibliothèque qui a en fait maximisé l'UNO et a dû mettre en place un

#if !defined(__AVR_ATmega32U4__)
...

autour d'un grand morceau de fonctionnalités supplémentaires dans le croquis pour s'adapter sur le Leonardo.

J'avais supposé (à tort) que ce 4K était parce que j'incluais encore Serial.print qui était sur le CDC de l'USB sur le Leo. Mais je vois après un vidage mémoire d'un croquis vide qu'ils sont toujours là.

C:\Users\mflaga\AppData\Local\Temp\build8958339595868119500.tmp>avr-objdump -d sketch_feb13a.cpp.elf > sketch_feb13a.cpp.elf.lst

Ce qui est logique. Comme le Leonardo nécessite toujours le client USB-CDC (le 4K) pour détecter la connexion 1200 Baud d'AVR-DUDE comme pour exécuter le redémarrage à distance.


Par conséquent, faire un boards.txt personnalisé sans USB dans la construction, doit également avoir

leonardo.upload.use_1200bps_touch=true

supprimé.

Une fois chargé sur la cible, cela nécessiterait que le téléchargement soit synchronisé avec une réinitialisation manuelle de la cible. Comme la capacité de redémarrage à distance est perdue.

mpflaga
la source
mis à jour pour expliquer pourquoi 4K est toujours compilé, même si Serial.print est omis.
mpflaga
3

J'ai récemment voulu faire exactement cela. Puisqu'il n'y a pas de bonne façon de le faire, j'ai fini par écrire un correctif pour le plugin arduino de texte sublime Stino pour faire exactement cela. Il a ensuite été accepté, il devrait donc être dans toutes les installations Stino à jour.

Cela ajoute une nouvelle option à Stino:

entrez la description de l'image ici

L'utilisation de ce mode produit des résultats de compilation tels que les suivants:

Pour un Uno:

Taille d'esquisse binaire: 172 octets (sur un maximum de 32256 octets, 0,53%).
Estimation de l'utilisation de la mémoire: 0 octet (sur un maximum de 1024 octets, 0,00%).

Pour un leonardo

Taille d'esquisse binaire: 240 octets (sur un maximum de 28672 octets, 0,84%).
Estimation de l'utilisation de la mémoire: 0 octet (sur un maximum de 2 560 octets, 0,00%).

En fait, programmer le leonardo avec la sortie compilée ci-dessus est probablement une mauvaise idée, car cela pourrait casser la fonctionnalité de réinitialisation automatique, mais vous pourriez , si vous le vouliez. Pointe du chapeau à mpflaga pour l'avoir noté dans sa réponse.

Notez que les rapports de mémoire sont en fait incorrects, mais c'est un problème distinct .

Le code utilisé pour ce qui précède est:

int main()
{
    while (1)
    {

    }
}

Quelques notes:

  • Vous n'écrit pas un « Sketch » plus, pas que vous jamais réellement n'écrire un croquis. Vous écrivez des programmes . Période. Peu m'importe ce que les wackos Arduino veulent dire, ils ne parviennent pas à redéfinir les termes.
  • Toute la gestion des interruptions est manuelle. Cela signifie non milis()ou similaire.
  • Vous pouvez toujours utiliser les bibliothèques série Arduino et ainsi de suite, si vous le souhaitez. Vous devez #include <Arduino.h>.
  • Vous définissez main. Vous ne revenez jamais de main. Si vous voulez des trucs de configuration, cela précède le while (1).
Connor Wolf
la source
@jfpoilpret Vous appelez cela un IDE? Plus comme un bloc-notes avec des macros ...
Ron
@ Ron-E Je ne l'appelle pas un IDE, Arduino IDE est son nom, donc j'ai juste utilisé son nom, même s'il ne vaut pas ce nom.
jfpoilpret
2
@FakeName Un langage incorrect n'est pas autorisé sur les sites Stack Exchange (voir: stackoverflow.com/help/behavior ). Je l'ai édité dans ce cas, mais essayez de vous abstenir d'utiliser des explications sur ce site à l'avenir. Merci.
Peter Bloomfield
2

Bien que cela dépende de votre esquisse, vous pouvez légèrement réduire la taille en réutilisant le code avec des méthodes.

Prenez ce code:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

  val = digitalRead(10);
}

1,322 octets sur Arduino Uno. Maintenant, rétrécissons un peu:

int led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  for(uint8_t i = 0; i < 8; i++) {
    blink(HIGH);
    blink(LOW);
  }    
  val = digitalRead(10);
}

void blink(uint8_t state) {
  digitalWrite(led, state);   // turn the LED to the right state
  delay(1000);                // wait for a second
}

1,194 octets. C'est environ une diminution de 10%!

Quoi qu'il en soit, bien qu'il ne réduise pas considérablement une esquisse, il peut parfois être l'itinéraire le plus simple lorsque vous avez deux octets au-dessus de la limite, ou si vous souhaitez simplement créer une esquisse plus compacte sans perdre aucune fonctionnalité. Ce n'est pas pour toutes les situations, mais je le trouve parfois utile.

Pingouin anonyme
la source
Généralement, si vous extrayez du code dans des fonctions, le compilateur fera le travail dur et fera le reste pour vous.
Cybergibbons
@Cybergibbons Pouvez-vous définir cela [pour les utilisateurs qui ne le connaissent pas]?
Anonymous Penguin
3
Si vous décomposez du code en fonction et que ce n'est pas efficace, généralement le compilateur le mettra en ligne pour vous. Cependant, un compilateur ne décompose jamais le code en fonctions. Par conséquent, il est presque toujours préférable d'écrire plus de fonctions.
Cybergibbons
1
De plus, mettre le code en fonctions le rend beaucoup plus facile à lire et à comprendre
En utilisant l'accès direct au port, la taille est réduite à 646 octets. En utilisant uniquement avr-libc (pas de noyau Arduino), il descend à 220 octets.
Edgar Bonet
0

@annonomus pingouin, bien sûr que nous pouvons Bien que le code compile en 1180 octets flash + 13 octets de RAM pour un uno sur mon ordinateur, nous pouvons l'améliorer :) donc défi de golf accepté et aussi quelques conseils utiles puisque nous sommes dans le métier de apprentissage.

Étape 1: diminuez les exigences variables. Utiliser un int pour un port led semble un peu exagéré, nous n'avons certainement pas 65535 ports IO adressables sur l'arduino :) Nous le changeons donc en octet juste pour le plaisir. Nous le changerons plus tard en #define, mais pour montrer l'impact de l'utilisation de types de variables trop grands.

byte led = 13;
int val;

void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Compile en 1172 octets + 13 octets de RAM. Cela permet d'économiser 8 octets de flash en raison d'un nombre réduit d'opérations nécessaires pour l'octet au lieu d'un entier. Je m'attendrais à 12 octets de RAM, mais d'accord. Pas tant que ça, mais chaque octet enregistré est bon.

Étape 2: changez la variable en définit quand cela a du sens. Par exemple, l'octet mené n'est pas nécessaire, la broche ne se dessoudera pas.

#define LED 13
int val;

void setup() {                
  pinMode(LED, OUTPUT);     
}

void loop() {
  blink();
  val = digitalRead(10);
}

void blink() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Compile en 1142 octetsflash + 11 octets de RAM. Déjà 38 octets enregistrés. Cela est dû à moins d'opérations de registre nécessaires pour récupérer la valeur int. Nous avons également enregistré 2 octets de RAM. (se demandant toujours pourquoi l'octet n'a pas été compilé en 1 octet de moins de ram .....)

Étape 3: optimisez le code. Je vois 2 retards. Je me demande si je le change en 1 retard, cela économiserait de l'espace, mais je dois déterminer la valeur de la broche LED et la basculer (inverser). Nous pouvons le faire avec digitalRead (), mais cela économisera-t-il de l'espace?

#define LED 13
int val;
void setup() {                
  pinMode(LED, OUTPUT);     
}
void loop() {
  blink();
  val = digitalRead(10);
}
void blink() {
  digitalWrite(LED, !digitalRead(LED));   // toggle the led based on read value
  delay(1000);               // wait for a second and spare yourself the other delay
}

Compile en 1134 octets + 11 octets de RAM. Yay! encore 8 octets. Cela fait un total de 46 octets et 2 lignes de code en moins.

Un autre conseil général sur la diminution de la taille des codes. N'utilisez pas la classe String. C'est ÉNORME, apprenez à gérer les tableaux de caractères, strcpy (), strcmp (). Si vous n'avez que quelques opérations de base sur les chaînes, l'utilisation de la classe String ne fait que gaspiller de l'espace à la fois sur le flash et la RAM.

Patrick Deelman
la source