J'ai étudié les options de sommeil de l'ATmega328 et lu quelques articles à ce sujet, et j'aimerais comprendre s'il y a plus d'options.
Je voudrais donc obtenir un courant aussi faible que possible, afin que tout ce qui est inférieur à 100uA soit bon - tant que je peux écouter uart et les interruptions pour le réveil.
J'utilise un PCB personnalisé (pas l'UNO), avec ATmega328p.
Mettre la puce en veille profonde:
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu ();
ne le réveillerait pas avec une communication série, selon cela .
Vous aurez besoin de le mettre en IDLE
mode, pour écouter en série, mais cela consommerait quelques mA -bad.
J'ai trouvé ce lien où vous pouvez connecter dans le matériel la série à l'interruption - ce qui est dangereux pour que vous puissiez perdre des données, et en plus, j'ai besoin de ces 2 broches d'interruption.
J'ai également lu cet article de Gammon , où vous pouvez désactiver certaines choses, afin que vous puissiez dormir en veille avec une puissance beaucoup plus faible - mais il n'a pas mentionné comment vous obtenez exactement cela:
power_adc_disable();
power_spi_disable();
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_twi_disable();
Donc, en fin de compte, existe-t-il une option pour obtenir moins de 0,25 mA au moins et écouter également le port série, sans aucune manipulation matérielle? Par exemple, vous vous réveillez avec une longue entrée de données série ?
Réponses:
Un conseil que nous fabriquons fait cela.
En veille, l'interruption de bas niveau INT0 est activée
La routine de service d'interruption INT0 définit un indicateur et désactive l'interruption
Au réveil, nous vérifions le drapeau (il existe d'autres sources d'interruption)
Du côté des communications, nous utilisons un protocole de message qui a un caractère de début
>
et un caractère de fin\r
. par exemple>setrtc,2015,07,05,20,58,09\r
. Cela donne une protection de base contre la perte de messages, car les caractères entrants ne sont pas traités jusqu'à ce que a>
soit reçu. Pour réveiller l'appareil, nous envoyons un message factice avant la transmission. Un seul personnage le ferait, mais nous envoyons>wakeup\r
hehe.L'appareil reste éveillé pendant 30 secondes après la réception du dernier message en cas de nouveaux messages. Si un nouveau message est reçu, la temporisation de 30 secondes est réinitialisée. Le logiciel d'interface PC envoie un message factice toutes les secondes pour garder l'appareil éveillé pendant que l'utilisateur le connecte pour la configuration, etc.
Cette méthode ne pose absolument aucun problème. La carte avec quelques périphériques utilise environ 40 µA pendant le sommeil. Le courant réel consommé par l'ATMega328P est probablement autour de 4uA.
Mise à jour
À regarder la fiche technique montre que la broche RX est également la broche d'interruption de changement de broche 16 (PCINT16)
Ainsi, une autre méthode sans fils peut être
Avant de dormir: définissez le bit de masque d'interruption de changement de port dans PCMSK2 pour PCINT16, désactivez l'indicateur de port de changement de broche 2 dans PCIFR, activez l'interruption du port de changement de broche 2 (PCINT16-PCINT23) en définissant PCIE2 dans PCICR.
Configurez un ISR pour l'interruption du port de changement de broche 2 et continuez comme auparavant.
La seule mise en garde avec l'interruption de changement de port est que l'interruption est partagée entre toutes les 8 broches activées pour ce port. Donc, si vous avez activé plus d'un changement de broche pour le port, vous devez déterminer qui a déclenché l'interruption dans l'ISR. Ce n'est pas un problème si vous n'utilisez aucune autre interruption de changement de broche sur ce port (PCINT16-PCINT23 dans ce cas)
Idéalement, c'est ainsi que j'aurais conçu notre planche, mais ce que nous avons fonctionne.
la source
Le code ci-dessous réalise ce que vous demandez:
J'ai utilisé une interruption de changement de broche sur la broche Rx pour remarquer quand les données série arrivent. Dans ce test, la carte se met en veille s'il n'y a pas d'activité au bout de 5 secondes (la LED "éveillé" s'éteint). Les données série entrantes provoquent l'interruption du changement de broche pour réveiller la carte. Il recherche un nombre et clignote la LED "verte" ce nombre de fois.
Courant mesuré
Fonctionnant à 5 V, j'ai mesuré environ 120 nA de courant pendant le sommeil (0,120 µA).
Message d'éveil
Un problème est cependant que le premier octet arrivant est perdu en raison du fait que le matériel série s'attend à une baisse du niveau sur Rx (le bit de démarrage) qui est déjà arrivé au moment où il est complètement réveillé.
Je suggère (comme dans la réponse de geometrikal) que vous envoyiez d'abord un message "éveillé", puis que vous vous arrêtiez un court instant. La pause consiste à s'assurer que le matériel n'interprète pas l'octet suivant comme faisant partie du message d'éveil. Après cela, cela devrait bien fonctionner.
Comme cela utilise une interruption par changement de broches, aucun autre matériel n'est requis.
Version modifiée utilisant SoftwareSerial
La version ci-dessous traite avec succès le premier octet reçu en série. Il le fait en:
Utilisation de SoftwareSerial qui utilise des interruptions de changement de broche. L'interruption provoquée par le bit de démarrage du premier octet série réveille également le processeur.
Réglage des fusibles pour utiliser:
Inspiré par FarO dans un commentaire, cela permet au processeur de se réveiller en 6 cycles d'horloge (750 ns). À 9600 bauds, chaque temps de bit est de 1/9600 (104,2 µs), donc le retard supplémentaire est insignifiant.
La consommation d'énergie pendant le sommeil a été mesurée à 260 nA (0,260 µA), ce qui représente une très faible consommation lorsqu'elle n'est pas nécessaire.
Notez qu'avec les fusibles réglés comme ça, le processeur fonctionne à 8 MHz. Vous devez donc en informer l'IDE (par exemple, sélectionnez "Lilypad" comme type de carte). De cette façon, les retards et SoftwareSerial fonctionneront à la bonne vitesse.
la source