Aide Aide programmation Arduino

V

Vik'TheBike

Nouveau
Une question pour la gestion de tempo sans utilser l'instruction 'delay' mais avoir qqch d'assez simple dans le programme...

On ne pourrait pas utiliser une fonction avec un paramètre d'entrée qui serait le temps en ms et un paramètre de sortie qui serait un bit à changer d'etat quand la tempo est finie...
Une sorte d'instruction 'MonDelay' mais qui ne bloquerait pas le uC dans une boucle d'attente inutile...
Je ne sais pas si je me fais bien comprendre...
L'idée etant de ne pas avoir ces longues phrases "if (preciousMillis-Millis < maTempo) {}...à tout bout de champ dans le programme principal... 8-)
Tu peux écrire une telle fonction, je pense que tu as les connaissances nécessaires.
Sinon tu peux rechercher une librairie qui propose déjà cette fonction, je suis sûr que ça existe quelque part.

edit : un indice, si tu lis l'anglais : https://playground.arduino.cc/Main/SketchList/#Timing_code
 
W

wika58

Compagnon
Et re une question sur la declaration des variables...:rolleyes::oops:

Dans le code ci-dessus,
...
int delayMilliSeconds(int timerNumber,unsigned long delaytime){
unsigned long timeTaken;
...
Là je suis un peu perdu...
a) un int devant une fonction
b) une declaration dans les paramètres d'entrée de la fonction
c) une declaration en début du code de la fonction...

:7grat::7hus5::smt100
 
F

furynick

Compagnon
Par définition une variable consomme de la mémoire, même si c'est une constante.
C'est juste la durée de présence en mémoire qui va changer mais pour le moment tu n'as pas besoin de chercher à optimiser ta conso mémoire.

Pour du timing tu as grosso modo 3 solutions :
1. La fonction delay, extrêmement simple mais bloquant donc il ne se passera rien d'autre pendant ce temps (tu verras les interruptions plus tard)
2. Le delta de millis dans un if, comme tu l'as évoqué c'est assez lourd mais très efficace. Préfères toutefois inverser la logique pour éviter un calcul à chaque passage dans la condition : static unit32_t next = millis() + TIMEOUT; if (millis() >= next) {next += TIMEOUT;}, tu passeras dans la condition toutes les TIMEOUT millisecondes.
3. Les timers étant la solution ultime, c'est un peu comme une alarme, tu définis une fonction qui sera exécutée à intervalles réguliers. Un peu plus complexe à mettre en œuvre mais tu as l'impression que c'est magique. C'est le uC qui fait des choses tout seul.
 
F

furynick

Compagnon
a) une fonction va obligatoirement renvoyer une valeur et cette valeur a obligatoirement un type. Lorsque cette valeur est de type void elle est obligatoirement vide (void en anglais).
Dans ce cas là fonction renvoie une valeur de type int et tu dois avoir l'instruction return en fin de fonction.
b) une fonction prend obligatoirement un ou plusieurs paramètres, tout comme pour le retour ça peut être un seul paramètre de type void (choix par défaut et implicite lorsque tu ne précise rien entre les parenthèses). Ici la fonction prend deux paramètres, ce seront des variables locales à ta fonction dont les valeurs auront été fixées lors de l'appel à cette fonction. Ça s'appelle le passage par valeur. Tu verras peut être le passage par référence plus tard.
c) c'est simplement la déclaration d'une variable locale à la fonction.
 
F

fredcoach

Compagnon
Par définition une variable consomme de la mémoire, même si c'est une constante.
Pas obligatoirement. Le compilateur peut décider de mettre la valeur de la constante comme paramètre de l'instruction qu'il écrit en assembleur, comme s'il s'agissait d'un nombre donné dans le source. Si tu écris var = var + 10, il ne va pas créer une variable pour y stocker la valeur 10. Il peut faire de même pour une const
 
W

wika58

Compagnon
Hello..
Bonne nouvelle...:roxxx:
J'ai enfin un contact avec un des profs de l'univ de Lausanne.
J'ai fouillé sur le site de l'univ et j'ai trouvé les adresses mail des 2 profs.
Je leur ai fait un mail cette nuit et ce matin j'avais une réponse de Mr. Nicoud... qui s'occupe plus de la partie théorique.
Il m'a répondu que Mr. Rochat allait me répondre pcq c'est lui qui s'occupe de la technique...

A suivre et bonne journée.
 
F

furynick

Compagnon
@wika58 : yep, c'est ça
@fredcoach : c'est assez complexe et ça dépend des mécanismes d'optimisation du compilo. Ceci dit, il y a deux façons de déclarer des constantes :
  1. #define VAR "valeur" - dans ce cas on est sûr que la mémoire dynamique ne sera pas utilisée mais ça peut poser problème car c'est le compilateur qui va déterminer le type de la variable s'il n'y a pas de distinction spécifique
  2. const uint8_t var = 8; - dans ce cas c'est une variable typée clairement identifiée, le compilateur décidera de comment stocker et utiliser la valeur
Il est préférable d'utiliser la deuxième notation pour éviter des problèmes de typage lors de la manipulation de cette constante avec d'autres variables.
 
F

fredcoach

Compagnon
@wika58 : yep, c'est ça
@fredcoach : c'est assez complexe et ça dépend des mécanismes d'optimisation du compilo. Ceci dit, il y a deux façons de déclarer des constantes :
  1. #define VAR "valeur" - dans ce cas on est sûr que la mémoire dynamique ne sera pas utilisée mais ça peut poser problème car c'est le compilateur qui va déterminer le type de la variable s'il n'y a pas de distinction spécifique
  2. const uint8_t var = 8; - dans ce cas c'est une variable typée clairement identifiée, le compilateur décidera de comment stocker et utiliser la valeur
Il est préférable d'utiliser la deuxième notation pour éviter des problèmes de typage lors de la manipulation de cette constante avec d'autres variables.
Tout à fait d'accord.
Tant que le compilateur allouait systématiquement de la mémoire pour une variable même constante, la première notation présentait un intérêt, au prix du risque d'erreurs potentielles. Maintenant que le compilateur peut décider de ne pas allouer de mémoire, la première notation ne présente plus d'intérêt et il faut clairement privilégier la deuxième.
 
5

59JAG

Ouvrier
moi j aime bien declarer des #define surtout pour faire des macro pour manipuler les bit sur le port
exemple: #define PIN_A1 ((PORTC &_BV(1)) >> 1)
 
W

wika58

Compagnon
Oui ben ca c'est mon calvaire pour le moment... :hang:
Si tu pouvais un peu developper/expliquer ton exemple... :prayer:
 
Dernière édition:
S

speedjf37

Compagnon
Bonjour,
moi j aime bien declarer des #define surtout pour faire des macro pour manipuler les bit sur le port
exemple: #define PIN_A1 ((PORTC &_BV(1)) >> 1)
Les # sont des directives pour le pré processus de compilation.
Le #define ne fait que remplacer le texte cité après l'alias , c'est carrément du traitement de texte.

Les #if #else #endif sont des opérateurs de compilation conditionnelle
Cela peut aussi utiliser les #define avec #ifdef etc

Jf
 
V

Vik'TheBike

Nouveau
Tout à fait, et pour ajouter à ce que dit @speedjf37 , je dirai qu'il est important de ne pas parler de variable lorsqu'il s'agit de #define, ce ne sont pas des variables, mais bien du code (du texte).

On devrait noter:
#define ALIAS valeur

plutôt que
#define VARIABLE valeur
 
W

wika58

Compagnon
Donc quand on définit toutes les affectations de pin en debut de programme, l'instruction
#define PinLed 4
est bien la bonne pratique...?
 
F

furynick

Compagnon
... et non
comme dit plus haut, les #define sont traités par le pré-processeur.
En (très) gros, le processus de compilation se décompose en deux gros traitements :
  1. Le pré-processeur va générer le code source final adapté à la situation
  2. Le compilateur va transformer le code source final en langage machine
Par exemple on a le code suivant (blink test ultra basique)

Le pré-processeur va transformer ça en

En soi ça ne pose aucun problème, mais dans le cas suivant on pourrait avoir un pb :
Le résultat affiché sera 169 et à priori le compilateur ne bronchera pas (c'est peut-être plus le cas aujourd'hui mais ça illustre la problématique) !!

En typant la constante comme ci-après, normalement le compilateur devrait sortir une alerte parce qu'il y a une potentielle incompatibilité de type.

C'est assez vicieux comme erreur et le compilateur peut ne rien voir ou être paramétré pour ne pas être sensible à ce type de problème.
C'est pour cette raison qu'il est fortement conseillé d'utiliser des constantes typées plutôt que des #define.
 
F

furynick

Compagnon
Hormis les constantes, les #define restent extrêmement utiles pour rendre le code portable (multi-architecture) ou pour limiter les réécritures de code (macro).
 
W

wika58

Compagnon
Merci d'avoir pris le temps d'expliquer en détail...
Pas sûr de tout comprendre à la première lecture... mais j'en ferai une seconde...
 
G

gégé62

Compagnon
switch case...
ça c'est magique, je l'utilise souvent, dès que le type de programme s'y prête, un truc séquentiel....ça décompose le sketch en différentes situations possibles et ça simplifie beaucoup la lecture, donc le travail....
 
F

fredcoach

Compagnon
ça c'est magique, je l'utilise souvent, dès que le type de programme s'y prête, un truc séquentiel....ça décompose le sketch en différentes situations possibles et ça simplifie beaucoup la lecture, donc le travail....
Attention, le switch case façon C est dangereux, même si je l'aime beaucoup.
Il y a un petit mot à la fin du case qu'il ne faut pas oublier et dont l'absence n'est pas détectée puisqu'elle est légale.
C'est pourquoi des compilateurs C à très haute sureté interdisent le switch.
 
W

wika58

Compagnon
Oui ça j'ai vu... le break...

Mais sinon ça a l'air pas mal et dans le cours MOOC ils l'utilisent pour en faire une machine d'état...
 
G

gégé62

Compagnon
oui il ne faut pas oublier les break, mais bon, je ne comprends pas qu'on les interdise. Je suppose qu'on peut obtenir le même résultat avec des if et une sorte de flag qui prend plusieurs valeurs selon les cas, mais déjà dans la plupart des sketches il y a beaucoup de if en général, imbriqués ou non, et je trouve que d'avoir les différentes séquences définies par les "case" du switch permet de mieux les voir. C'est comme si on les encadrait ...
 
F

furynick

Compagnon
Il ne s'emploie pas tant que ça le switch-case mais c'est clairement très pratique et améliore considérablement la lisibilité pour peu qu'on n'oublie pas le break ... on qu'on utilise son absence à bon escient ce qui peut se révéler extrêmement pratique pour les conditions additives qui seraient ingérables avec de simples if
 
F

fredcoach

Compagnon
Tout à fait d'accord, j'utilise moi-même assez souvent le switch. Cependant, il est vrai qu'il présente un risque d'erreur et dans certaines applications (aéronautique) c'est déjà trop! Mais je pense qu'on pourrait supprimer ce risque sans être aussi radical.
 
W

wika58

Compagnon
Oui et on parle tjrs de l'utilisation de l'Arduino dans nos projets DIY pour l'atelier... bien sûr... :rolleyes:
 
C

coredump

Compagnon
Pour ceux qui aiment les switchs:

void
send(short *to, short *from, int count)
{
int n=(count+7)/8;
switch(count%8) {
case 0:
do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n>0);
}
}
 
F

furynick

Compagnon
Il picote celui là, une boucle imbriquée dans le switch j'aurais pas tenté.
 

Sujets similaires

W
Réponses
122
Affichages
12 593
Philippe85
P
N
Réponses
3
Affichages
956
jpbbricole
jpbbricole
lolo
Réponses
0
Affichages
498
lolo
T
Réponses
1
Affichages
334
Teddy55
T
D
Réponses
0
Affichages
285
dodochef
D
osiver
Réponses
14
Affichages
40 333
osiver
osiver
P
Réponses
0
Affichages
233
Ptitleud
P
Dudulle
Général langage MMBASIC
Réponses
8
Affichages
1 209
Dudulle
Dudulle
J
Réponses
12
Affichages
660
Robert
R
P
Réponses
33
Affichages
20 503
wika58
W
T
Réponses
2
Affichages
29 728
Tristan l'apprenti
T
esloch
Réponses
0
Affichages
393
esloch
esloch
Haut