Nous programmons le passage par passage. MicroPython sur esp8266 (sonoff) avec OTA. Partie 1

Bonjour à tous.


En cours de réparation, la tâche s'est posée de faire un interrupteur de passage. Bien sûr, je voulais le faire de la manière la plus simple et la plus pratique, en ajoutant des fonctions de contrôle de base à partir du téléphone. J'ai choisi la technologie la plus simple et la plus pratique pour cela (bien sûr, à mon avis) - MicroPython, et j'ai commencé à le faire. J'ai pris la planche finie sur esp8266 et alloué une heure de temps libre pour cela. Mais, comme cela arrive avec des projets pas très populaires et non rodés, la tâche a traîné un peu.


En fin de compte, le design que j'ai trouvé le plus pratique, il s'avère, ne fonctionne pas du tout. J'ai dû passer un peu de temps à analyser cela, en plus j'ai décidé de décrire l'ensemble du processus avec suffisamment de détails. Le volume de l'article a commencé à augmenter rapidement, j'ai donc décidé de le diviser en parties et de jeter tous les détails inutiles à mon avis.


La première partie se compose de trois parties:


  1. Considérations théoriques sur la sélection du support le plus simple pour le développement d'un interrupteur de passage,
  2. Lancement pratique du firmware de base sélectionné sur l'équipement sélectionné, pièges,
  3. Développement de firmware

Choisir l'environnement de développement le plus simple


Pour une maison intelligente comme «faites-le vous-même si vous avez une minute de temps libre», en plus des articles classiques (par exemple, la stabilité), la liste des exigences d'équipement obligatoires ajoute également une facilité de développement, d'installation et d'assistance. Les appareils sont nécessaires pour y connecter facilement les capteurs ou dispositifs de commande nécessaires. Qu'il existait des moyens pratiques et faciles de communiquer avec l'ensemble du système. Il est nécessaire de garantir la facilité d'écriture du micrologiciel sur cet appareil, en tenant compte du fait que l'appareil peut être situé là où il sera difficile de s'y rendre. Et bien sûr, la facilité de développement, cela est particulièrement critique pour le bricolage, lorsque, par exemple, 2 ans après avoir travaillé sans défaillance de l'ensemble du système
du coup je veux ajouter quelques ajustements au firmware. Pour effectuer ces corrections, vous devez vous rappeler comment ce système fonctionne, ce qui peut parfois prendre plus de temps que l'ajustement lui-même.


Prenons un exemple banal: vous devez effectuer un simple commutateur d'intercommunication avec la possibilité de le contrôler, y compris à partir d'un PC. Ces derniers temps, cette tâche était assez compliquée, il fallait prendre une sorte de microcontrôleur (les plus populaires étaient avr ou pic), et pour écrire le firmware, en règle générale, vous devez lire la documentation pour cela. Si vous voulez tout faire hors de la boîte, vous devez séparer la carte, où mettre AC / DC, un microcontrôleur et une interface de communication. Après LUT (ou commander des cartes de circuits imprimés), soudez tout, achetez un programmeur et flash firmware. Et puis après 2-3 ans, si nécessaire, pour réparer quelque chose, chercher tout l'équipement et tout apprendre à partir de zéro ...


Pour simplifier ce processus, des solutions toutes faites ont commencé à apparaître sur le marché. La solution la plus réussie est Arduino. Cette solution est fournie par l'IDE, le chargeur de démarrage avec la fonction de mise à jour, qui vous permet de travailler avec l'appareil exclusivement via l'interface standard sans utiliser de programmeurs. Il permet de faire du firmware, n'ayant que
une compréhension très superficielle de la façon dont tout est organisé là-bas. Un ensemble de modules externes permet de connecter des appareils sans fer à souder. Mais de toute façon, pour effectuer des modifications, vous devez installer le logiciel Arduino, stocker le firmware quelque part.


Notre commutateur pass-through s'avérera être assez grand, il contiendra une carte Arduino + AC / DC + module relais. Et si vous avez besoin de faire des ajustements, vous devrez vous rappeler douloureusement où se trouve le code et réinstaller le logiciel Arduino.


Afin de vous épargner le besoin de compiler le code source (c'est-à-dire d'installer un logiciel supplémentaire et de le stocker), la solution la plus logique semble être d'utiliser des interprètes ou de compiler directement le code sur le microcontrôleur lui-même. Heureusement, des projets sont maintenant apparus qui permettent de le faire. Par exemple, NodeMCU, l'interpréteur de langage lua pour le microcontrôleur esp8266: le micrologiciel lui-même prend en charge le système de fichiers, ce qui vous permet de télécharger / lire des scripts vers / depuis l'appareil. Un autre projet assez sérieux est Micropython, une version allégée de python spécialement conçue pour les microcontrôleurs. Il en sera question.


MicroPython est une implémentation de l'un des langages de programmation python les plus populaires aujourd'hui. Il prend en charge un grand nombre d'architectures et de SoC (bare-arm, CC3200, esp8266, esp32, nRF, pic16bit, stm32). Le projet se développe activement et dispose d'un grand nombre de modules supplémentaires.


Le microprocesseur esp8266 est très adapté en tant que partie matérielle, car les modules de commutation wifi économiques qui y sont construits sont vendus sur le marché. Ils contiennent tout ce dont nous avons besoin: AC / DC, un microcontrôleur avec une interface de communication intégrée (wifi). Disponible sous la marque Sonoff. Les microprocesseurs esp8266 ne contiennent pas de mémoire, ils sont soudés séparément et peuvent avoir une taille différente. Pour Sonoff Basic, ils ont mis des modules de 1 Mo.


Démarrage du firmware de base sur esp8266. Sonoff Basic.


En l'absence de pièges, il serait possible de procéder immédiatement à une programmation en python. Mais, malheureusement, il y a un certain nombre de problèmes qui doivent être résolus, afin de programmer et de modifier le firmware, c'était très facile et simple. Bien sûr, nous sommes intéressés à le faire via le wifi, sans utiliser d'appareils supplémentaires à l'exception d'un ordinateur portable.


Le premier écueil, bien sûr, est le firmware de base qui est enregistré sur votre carte. Si vous avez acheté une carte de débogage, vous y trouverez très probablement NodeMCU, si Sonoff Basic, puis un firmware propriétaire. Pour préparer cette carte pour vous-même, vous devez y écrire le firmware nécessaire. Dans certains microcontrôleurs, il est nécessaire d'acheter
un programmeur spécial, dans notre cas, nous avons eu de la chance, il vous suffit d'obtenir un convertisseur USB <-> UART. Si vous travaillez avec des microcontrôleurs, cela vous sera utile plus d'une fois, et leur prix est généralement de l'ordre de 3 $.


Il n'y a pas de peigne pour Sonoff Basic qui vous permet de vous connecter via UART, et nous en avons besoin pour programmer l'appareil. Pour programmer simplement l'appareil, il n'est pas nécessaire de prendre le fer à souder entre vos mains, il suffit de pencher les contacts et d'écrire le firmware. Étant donné que d'autres travaux se feront via le wifi, nous n'aurons plus besoin de ces contacts. Mais nous implémentons un commutateur de passage, ce qui signifie que nous avons besoin de soudure,
au moins trois jambes.


Pour Sonoff Basic, il n'y a qu'un seul connecteur GPIO libre et 2 connecteurs RX, TX. Étant donné que nous avons besoin de RX, TX nous-mêmes une fois (pour flasher le firmware), à ​​l'avenir, ils peuvent être reprogrammés en GPIO, car esp8266 le permet. Mais dans ce cas, nous devons abandonner le débogage via UART, heureusement nous avons déjà prévu de le faire, car le débogage via wifi, du point de vue de la commodité, est beaucoup plus simple.


Étant donné que la version de MicroPython peut changer au cours du processus, nous souhaitons déboguer la méthode de mise à jour via wifi. OTA vient à la rescousse. OTA est un firmware qui vous permet de reprogrammer un appareil. Cela fonctionne tout simplement. Après avoir allumé l'appareil, le micrologiciel détermine s'il doit être reprogrammé, si nécessaire, lance un programme spécial
le programme de mise à jour wifi, sinon, lance le firmware de l'utilisateur. L'implémentation peut être différente, le micrologiciel peut se remplacer ou écrire dans une zone libre de la mémoire. Vous pouvez également déterminer si vous souhaitez exécuter le programme de copie de différentes manières. Par exemple, considérez le cxumma d'un micrologiciel personnalisé s'il ne converge pas,
puis passez de force au clignotement. Vous pouvez lire les données du GPIO ou écrire des informations sur la nécessité de démarrer la mise à jour ailleurs.


En tant que programme de mise à jour, le projet MicroPython fait référence au projet yaota8266. Yaota8266 prétend flasher l'appareil et signer chaque paquet. Il convient de noter que la clé publique est intégrée dans le firmware lui-même, c'est pourquoi cela n'a aucun sens de télécharger le firmware déjà assemblé, car il est nécessaire d'y coudre votre clé.
Il n'y a pas de fonction pour modifier la clé privée dans l'image assemblée, donc dans notre cas, il est plus facile d'assembler le firmware vous-même. Une caractéristique intéressante est que la fonction de vérification de signature est, mais est commentée dans le code, c'est-à-dire en fait, nous obtenons des difficultés sans aucun gain de sécurité. La version de base de yaota8266 ne va pas,
Heureusement, il existe des fourches sur github qui résolvent ce problème, et elles ajoutent la possibilité de déterminer si le flashage doit être effectué en fonction de l'écriture dans la zone RTC, ce qui permet de basculer MicroPython en mode bootloader.


Même après avoir inclus toutes les corrections, notre micrologiciel OTA écrira avec des erreurs, mais fonctionnera avec succès sur les cartes de débogage NodeMCU. Cela est dû à des délais d'attente. Lors de la mise à jour à partir de la machine hôte, des paquets UDP sont envoyés et une réponse est attendue si l'enregistrement en flash prend plus de temps que d'habitude, un délai d'attente se produit et le paquet est envoyé à nouveau. L'avantage est facile à corriger,
augmentant simplement les délais d'attente dans le code du client ota.


Le bundle OTA + MicroPython sur Sonoff présente également des bizarreries intéressantes. L'un d'eux est lié au fait que les fonctions standard pour travailler avec SPI Flash dans esp-sdk fonctionnent sur des blocs 4k, et cette taille de bloc a été choisie pour implémenter le système de fichiers FAT. À son tour, en raison du fait que SPI Flash n'est que de 1 Mo, dont ~ 300 Ko est le micrologiciel OTA, ~ 500 Ko est le micrologiciel MicroPython, il reste moins de 200 Ko pour le système de fichiers, c'est-à-dire moins de 50 blocs. Cependant, la bibliothèque sélectionnée qui implémente fatfs ne peut pas créer FS où il y a moins de 50 blocs. Il existe plusieurs façons de résoudre le problème: réduire la taille du bloc (FAT vous permet de définir 512), corriger la bibliothèque FatFs, utiliser SPI FS (en espérant qu'il n'y ait pas de telles bizarreries). J'ai choisi de réduire le bloc à 512.


Les microcontrôleurs utilisent SPI Flash - il s'agit de mémoire NOR et / ou NAND. La particularité de cette mémoire est qu'il n'y a pas de concept "d'écrire des données". Vous pouvez uniquement réinitialiser la valeur (à 0xff) ou définir les bits souhaités sur "0". SPI Flash est généralement une mémoire NOR, il a pour fonction de réinitialiser n'importe quel octet à 0xff, tandis que NAND ne peut être réinitialisé que par blocs. C'est-à-dire si la taille minimale du bloc de réinitialisation est de 4k, pour écrire
1 octet de mémoire, il est nécessaire de lire le bloc entier, de le réinitialiser à 0xFF, puis d'écrire le bloc en définissant l'octet souhaité à la valeur souhaitée. Les fabricants de SPI Flash ont approximativement le même ensemble d'API pour le travail, mais, comme la pratique l'a montré, la commande pour écrire un octet de SPI Flash peut différer. Quelque part, il sera automatiquement réinitialisé avant d'écrire dans 0xFF, quelque part non.


Si vous changez la section FAT en 512 octets, il y a une chance d'obtenir un système cassé si un Flash SPI spécifique ne prend pas en charge la réinitialisation automatique des octets lors de l'enregistrement. Et c'était juste un tel souvenir que j'ai rencontré dans Sonoff Basic. La rumeur veut qu'ils y installaient Winbond 25q80bv, mais maintenant PUYA 25q80h, qui a un bloc de nettoyage minimum de 256 octets. La solution semble
simple, il vous suffit d'effacer deux pages où elles seront écrites avant d'écrire le bloc FAT, mais l'implémentation est compliquée par le fait que sdk-esp ne supporte que la suppression dans les blocs 4k. Étant donné que l'écriture à la FAT sera très rare pour notre commutateur,
seulement lors de la mise à jour des scripts du firmware, vous pouvez faire le mauvais chemin et mettre à jour le bloc de 512 octets en blocs de 4k. La documentation de cette mémoire indique que la mémoire peut supporter 100000 cycles de réécriture, c'est-à-dire un contournement similaire du problème nous réduira cette valeur de 4 fois, c'est-à-dire jusqu'à 25 000.


MicroPython a une console par défaut, elle s'appelle REPL et fonctionne via le port COM. Nous ne sommes pas très satisfaits de cet état de fait, car nous voulons communiquer avec l'appareil via le wifi. Heureusement dans MicroPython, WebRepl est également fourni en standard, mais il ne démarre pas automatiquement. Vous pouvez enregistrer l'exécution automatique dans boot.py, mais j'ai décidé de l'exécuter directement à partir de _boot.py, le fichier système, il est cousu dans le fichier du firmware lui-même.


Après le premier démarrage, notre firmware créera un système de fichiers, lancera webrepl et créera un point d'accès. Vous pouvez vous y connecter et prescrire les paramètres de connexion à votre réseau local, ou, comme je l'ai fait, configurer le réseau à l'aide du port com, après quoi seul le wifi doit être utilisé.


Pour les essais, vous pouvez utiliser le client webrepl écrit en javascript. Le client peut être lancé dans un navigateur sur la page correspondante du projet. Une autre option consiste à utiliser le projet mpfshell, il fournit des fonctions plus pratiques pour travailler avec l'appareil.


Ainsi, après avoir surmonté tous ces pièges, vous pouvez passer directement à la programmation du commutateur.


Développement de firmware


Pour développer le firmware, nous devons avoir une idée approximative du fonctionnement de GPIO. En général, cela peut être compris de manière purement intuitive:


  1. Si nous définissons le mode de sortie (OUT), la jambe produit soit GND soit Vcc.
  2. Si nous réglons le mode d'entrée (IN), alors la jambe "pend dans l'air", auquel cas le microcontrôleur peut donner n'importe quoi
  3. Pour que le microcontrôleur ne donne rien, la jambe peut être tirée à la valeur souhaitée à l'aide du microcontrôleur intégré
    résistances de pull-up PULL_UP ou PULL_DOWN.

Vous devez également avoir une idée de ce que sont les interruptions: dans notre cas, c'est le code qui doit être exécuté si une sorte d'événement se produit: un bouton a été enfoncé / relâché ou un message est venu du réseau local sur la nécessité d'éteindre / allumer l'appareil.


Pour commencer, écrivons un programme de commutation simple (pas de pass-through) en Python.


from machine import Pin class SW: def __init__(self, portin, portout): self.pin = Pin(portin , Pin.PULL_UP) #  self.pout = Pin(portout, Pin.OUT) #  #  self._auto(),       self.pin.irq(trigger=Pin.IRQ_RISING|Pin.IRQ_FALLING, handler=self._auto) self.value = 0 def _auto(self, _=0): if self.value: res = self.pin.value() else: res = not self.pin.value() self.pout.value(res) def change(self, val=2): """   0, ,  1, ,  2  """ if val == 2: self.value = not self.value else: self.value = val self._auto() sw = SW(14, 12) 

J'ai nommé ce fichier switch.py ​​et lui ai ordonné de s'exécuter dans boot.py:


 from switch import sw 

Après avoir démarré le firmware, j'ai obtenu un objet sw, si j'exécute sw.change (), un changement de programme se produira
passer à une autre position. Lorsqu'une broche libre est court-circuitée à Vcc dans le microcontrôleur
le relais s'allume ou s'éteint, respectivement.


La prochaine étape sera le lancement du client MQTT et la possibilité de basculer le commutateur depuis le téléphone.

Source: https://habr.com/ru/post/fr438624/


All Articles