Commit c7d4e505fed556852b85e511636efe1c5ce33a7e

Authored by Geoffrey PREUD'HOMME
1 parent f85fc947

Encore des avancements dans le CR

Showing 2 changed files with 49 additions and 15 deletions   Show diff stats
... ... @@ -60,16 +60,23 @@ La température mesurée (et convertie via le convertisseur ADC), est comparée
60 60  
61 61 ## Stockage des données
62 62  
63   -Les accès à la RAM nécessitant plus d'instructions et donc étant plus gourmands en énergie, on stockera le maximum d'informations dans les registres, de préférences les données étant lues/écrites les plus fréquemment. On y stockera donc :
  63 +Les accès à la RAM nécessitant plus d'instructions et donc étant plus gourmands en énergie, on stockera le maximum d'informations dans les registres, de préférences les données étant lues/écrites les plus fréquemment. On y utilisera donc :
64 64  
65   -- **4 registres** : les 4 digits de l'afficheur 7 segments en cours d'affichage. Ces informations devant être récupérées 4 fois toutes les quelques millisecondes, on ne calculera leur représentation que lors de leur changement et on les stockera dans ces registres.
66   -- **1 registre (dont 4 bits inutilisés)** : afficheur 7 segment actuellement en cours d'affichage. Cela permet d'alterner les 4 dans l'ordre. Pour économiser un registre d'utilisation générale, on utilisera le fait que le port C est considéré comme un registre et sauvegarde les états qui lui sont envoyés.
67   -- **3 registres** : Stockage du temps. Le compteur de temps le plus grand mais à la fois diviseur de la période de changement de mode veille et d'une heure sur l'Atmega 2560 est deux secondes. On comptera le temps de la semaine avec cette période de deux secondes. Il y a alors $\frac{7 \times 24 \times 60 \times 60 }{ 2 }$ $=302400$ valeurs possibles pour ce compteur de temps. On a donc besoin de 3 registres $\left( 2^{8 \times 2} = 65536 < 302400 < 16777216 = 2^{8 \times 3} \right)$ pour stocker cette valeur. Afin de simplifier, sur le premier registre on utilisera 3 bits pour stocker le jour de la semaine, 5 bits pour l'heure du jour, on utilisera le deuxième registre pour stocker la minute de l'heure, et le troisième registre pour stocker le nombres de fois qu'il y a eu 2 secondes dans la minute actuelle. Cela permet de simplifier les calculs et d'éviter de faire des opérations sur des entiers de 24 bits *(on aurait pu utiliser un registre supplémentaire pour stocker le jour de la semaine et éviter des opérations, mais on voulait s'amuser avec des masques et des divisions)*.
  65 +- `d3`, `d2`, `d1` et `d0` : les 4 digits de l'afficheur 7 segments en cours d'affichage. Ces informations devant être récupérées 4 fois toutes les quelques millisecondes, on ne calculera leur représentation que lors de leur changement et on les stockera dans ces registres.
  66 +- `PORTC` : afficheur 7 segment actuellement en cours d'affichage. Cela permet d'alterner les 4 dans l'ordre. Pour économiser un registre d'utilisation générale, on utilisera le fait que le port C est considéré comme un registre et sauvegarde les états qui lui sont envoyés.
  67 +- `t2`, `t1` et `t0` : stockage du temps actuel. Il y a $7 \times 24 \times 60 \times 60$ $=604800$ valeurs possibles pour ce compteur de temps. On a donc besoin de 3 registres $\left( 2^{8 \times 2} = 65536 < 604800 < 16777216 = 2^{8 \times 3} \right)$ pour stocker cette valeur. Afin de simplifier, sur le premier registre on utilisera 3 bits pour stocker le jour de la semaine, 5 bits pour l'heure du jour, on utilisera le deuxième registre pour stocker la minute de l'heure, et le troisième pour stocker les secondes de la minute. Cela permet de simplifier les calculs et d'éviter de faire des opérations sur des entiers de 24 bits.
  68 +- `etat` et `compteur` : ils permettent de stocker l'état actuel du menu.
  69 +- `reference` : contient la température désirée actuelle (c'est à dire pour le mode de l'heure actuelle). Étant comparée toutes les 10 secondes avec la température réelle et le calcul de sa valeur nécessitant de connaître le temps actuel, le mode associé à ce temps et la température associée à ce mode, on a jugé avantageux de le stoceker dans un registre qui sera mis à jour au besoin.
  70 +- `temp` : registre dédié à certaines opérations temporaires. Il n'a pas de rapport (la plupart du temps) avec la température.
68 71  
69   -TODO Il manque des registres
  72 +Notes :
  73 +- Nous aurions pu utiliser un registre distinct pour stocker le jour de la semaine et éviter des opérations, mais on voulait s'amuser avec des masques et des divisions.
  74 +- Nous aurions pu utiliser une période Watchdog plus grande afin de minimiser les opérations. Mais on verra par la suite que nous n'avons pas pu utiliser le Watchdog du tout.
70 75  
71 76 Les associations de chaque heure de la semaine à son mode (jour/nuit) seront stockées dans la RAM. Bien qu'en théorie nous n'avons besoin que de $\frac{ \text{nb jours/semaine} \times \text{nb heures/jour} \times \text{nb bits pour stocker le mode} }{ \text{nb bits stockables sur une adresse} }$ $=\frac{7 \times 24 \times 1 }{ 8 }$ $=\frac{168}{8}$ $=21$ adresses pour stocker ces informations, on préfèrera utiliser une adresse par heure de la semaine, soit $168$ adresses. Bien que l'on perd en espace mémoire disponible, on garde en rapidité d'éxecution (et donc en énergie), en effet il n'est pas nécessaire d'utiliser des masques pour récupérer la valeur des bits individuels. Dans notre cas le microprocesseur n'abritera aucun autre programme avec qui il devra partager la RAM, et la consommation énergétique ne change pas selon le nombre d'adresses utilisées, il n'y a donc que des avantages à utiliser cette technique.
72 77  
  78 +Enfin, on stockera les températures des deux modes dans la RAM également, car on y accède que toutes les heures (ou lors de leur modification), le registre `reference` agissant comme intermédiaire.
  79 +
73 80 # Configuration des interfaces
74 81  
75 82 ## Interruptions externes
... ... @@ -198,19 +205,39 @@ On utilise le fait qu&#39;une décrémentation depuis la valeur 0 effectue un dépas
198 205  
199 206 ## Fonction d'agissement
200 207  
201   -TODO
  208 +Ces fonctions permettent de prendre des actions en fonction du temps.
  209 +
  210 +- `agir1s` : déclenchée toutes les secondes, elle met à jour les registres de temps, et appelle les fonctions `agir10s` et `agirHeure`
  211 +- `agir10s` : déclenchée toutes les dix secondes, elle change l'état de veille si l'appareil est en veille. Dans tous les cas, elle déclenche une conversion analogique numérique pour lire le capteur de température.
  212 +- `agirHeure` : elle recharge depuis la RAM le mode actuel, et met à jour le registre `reference` contenant la température à utiliser.
  213 +
  214 +Voici à titre d'exemple une de ces fonctions (bien qu'elles soient toutes radicalement différentes) :
202 215  
203 216 ## Interruptions
204 217  
205   -TODO
  218 +Les fonctions que nous avons vues jusqu'à lors sont appelées uniquement par les interruptions, étant donné qu'il n'y a pas de programme principal. Voici les différentes interruptions qui sont déclenchées.
206 219  
207   -## Timer
  220 +### Timer
208 221  
209   -## Watchdog
  222 +Déclenchée toutes les ~4 ms, elle change le digit de l'afficheur 4 × 7 segments actuellement affiché en modifiant la configuration du port C, et cenvoie sur le port A les données du registre `dX` correspondant.
  223 +
  224 +### Watchdog
  225 +
  226 +Déclenché toutes les secondes, il se contente d'appeler la fonction `agir1s`. Cependant, on s'est rendu compte que la fréquence d'appel était ~100× plus élevé que ce qui devrait être. N'ayant pas réussi à corriger ce comportement (que l'on a pu aussi constater en TP), nous avons dû trouver un autre moyen de procéder.
  227 +
  228 +En effet, nous avons utilisé le timer, et un registre supplémentaire, `tt`, qui est incrémenté à chacune de ses interruptions. Le timer ayant une fréquence exacte de $\frac{16 MHz}{256^2}=244.140625 Hz$;, dès que `tt` a depassé `244` on appelle donc `agir1s`.
  229 +
  230 +D'un point de vue énergétique, cette approche est beacoup moins efficace car elle rajoute des instructions supplémentaires à l'interruption du timer, qui est la fonction « critique » du système car appelée 244 fois par secondes.
  231 +
  232 +### ADC
  233 +
  234 +Cette interruption est déclenchée à chaque fois qu'une conversion analogique→numérique est terminée. Elle est donc déclenchée à peu près toutes les 10 secondes car les conversions ne sont demandées que depuis la fonction `agir10s`. Elle s'occupe d'activer ou de désactiver la chaudière en fonction de la température récupérée lors de la conversion, en se basant sur le registre `reference`. Par exemple, la chaudière est éteinte si la température dépasse de plus de 0,5 degrés la température de référence. Dans le code, on vérifiera si `ADCH > reference + 5`, car 0,1°C correspond à une unité. On remarque que l'on peut obtenir un dépassement si jamais `reference > 250`, ce qui n'est pas censé arriver car on ne propose à l'utilisateur que de choisir une température entre 5,5 et 30,0°C, `reference` est donc compris entre 5 et 250. Si jamais la température est comprise dans l'intervalle, le port G conserve l'état de la chaudière actuel.
  235 +
  236 +*Note : Pour la présentation orale vous pourrez constater dans le code que cette interruption en déclenche une autre afin d'avoir un retour immédiat sur nos actions.*
210 237  
211   -## ADC
  238 +### Boutons
212 239  
213   -## Boutons
  240 +À chaque bouton est associé une interruption, et chacun d'entre elle appelle une fonction d'état selon la valeur actuelle de compteur. Par exemple, si l'état actuel est `veilleHeure` et que le bouton Valider est pressé, la fonction `etatMenuAssoc` est appelée. Pour les boutons Incrémenter et Décrémenter, le registre `compteur` est incrémenté ou décrémenté respectivement avant d'appeler la fonction d'état.
214 241  
215 242 # Conclusion
216 243  
... ...
principal.txt
... ... @@ -49,7 +49,7 @@
49 49  
50 50 ; Nommage des adresses RAM utilisées
51 51  
52   -.equ assocs = 0x0200 ; Association des modes aux heures
  52 +.equ assocs = 0x0200 ; Association des modes aux heures (tableau de taille 168 octets)
53 53 .equ tempJour = 0x02a8 ; Température du mode jour
54 54 .equ tempNuit = 0x02a9 ; Température du mode nuit
55 55  
... ... @@ -290,6 +290,8 @@ a10sVeilleTemp:
290 290 agirHeure:
291 291 ; Recharge la température de référence
292 292 temp <- (t2 / 0b00100000) * 24 + (t2 & 0b00011111)
  293 + ; ↑ numéro du jour de la semaine
  294 + ; ↑ heure actuelle
293 295 if assocs[temp] = 0x00 alors reference <- tempJour
294 296 if assocs[temp] = 0x01 alors reference <- tempNuit
295 297 ret
... ... @@ -598,13 +600,18 @@ eteindreChaudiere:
598 600 PORTG@IO <- 0x00
599 601 reti
600 602  
601   -; Interruption timer
  603 +; Interruption timer (~4 ms)
602 604 timer:
  605 + ; Notre composant requiert d'envoyer 0 sur PC7-4
  606 + ; afin d'activer le digit qui y est connecté
  607 +
603 608 ; Affiche le digit suivant sur l'afficheur 7seg
604   - temp <- PORTC@IO
605   - lsr temp
  609 + temp <- PORTC@IO ; On lis l'état précédent du port
  610 + lsr temp ; On change de digit
  611 + ; Il y a 4 digits et 8 bits, on doit donc boucler plus tôt
606 612 si temp < 0b00001111 alors temp <- 0b11110111
607 613 PORTC@IO <- temp
  614 + ; On envoie le registre correpspondant
608 615 si temp = 0b11110111 alors PORTA@IO <- d3
609 616 si temp = 0b01111011 alors PORTA@IO <- d2
610 617 si temp = 0b00111101 alors PORTA@IO <- d1
... ...