[Suite] Essayez l'accès au registre PLC avec Python

Dans "Essayer l'accès au registre PLC en Python", j'ai essayé l'accès aux mots de base par SLMP en Python. Cette fois, je vais implémenter la manipulation des données lors de la lecture et de l'écriture d'un périphérique bit avec du code binaire en Python.

Méthode d'accès au périphérique Bit

SLMP propose deux méthodes d'accès continu aux périphériques bit.

Dans le cas d'un accès en unités 1 point, il s'agit d'une représentation de code BCD à 4 bits comme indiqué ci-dessous. Voici un exemple de communication au moment de la lecture.

image.png

Pour l'accès par unités de 16 points, 1 bit est une représentation binaire de 1 point. Voici un exemple de communication au moment de la lecture.

image.png

Bien entendu, les unités à 16 points sont plus avantageuses pour la lecture et l'écriture de masse en continu.

La commande de communication utilisée est la même que lors de l'accès aux mots, mais comme les données binaires sont compactées comme décrit ci-dessus, la conversion des données est nécessaire pour les traiter comme des données de tableau telles qu'une liste en Python.

C'est assez ennuyeux, et en particulier dans le cas d'unités à 16 points, si vous essayez d'extraire un bit à la fois, vous craignez que cela affecte la vitesse de traitement en Python. Ici, implémentons-le en utilisant l'opération bit de numpy.

Accès en unités 1 point

en train de lire

Lire avec la commande Lire (0401h) de la même manière que l'accès par mot. Cependant, la sous-commande est différente de «0001h».

Si le tableau de données reçu est extrait comme [0x00, 0x01, 0x00, 0x11, ...], alors [0, 0, 0, 1, 0, 0, 1, 1, ...] Doit être développé comme .

L'exemple de code ci-dessous développe la séquence de code BDC. L'argument data et la valeur de retour sont tous deux le ndarray de numpy (dtype = uint8).

Étant donné que les données de tableau peuvent être calculées dans un lot à l'aide de numpy, le traitement en boucle dans la syntaxe Python n'est pas nécessaire et un traitement à grande vitesse peut être attendu, en particulier lorsque la quantité de données est importante.

import numpy as np

# ex. data = np.array([0x12, 0x34, 0x56], 'u1')

def decode_bcd(data):
    """
    Decode 4bit BCD array
      [0x12,0x34,...] --> [1,2,3,4,...]
    """
    binArrayH = (data >> 4) & 0x0F
    binArrayL = data & 0x0F

    binArray = np.empty(data.size * 2, 'u1')
    binArray[::2] = binArrayH
    binArray[1::2] = binArrayL

    return binArray

l'écriture

Le modèle est l'inverse de la lecture. Pack en code BCD. Si les données d'origine sont un nombre impair, les 4 derniers bits sont inutilisés, remplissez-les donc avec 0.

def encode_bcd(data):
    """
    Encode 4bit BCD array
      [1,2,3,4,...] --> [0x12,0x34,...]
Si le nombre d'entrées est impair, remplissez les 4 derniers bits avec 0
    """
    binArrayH = (data[::2] & 0x0F) << 4
    binArrayL = data[1::2] & 0x0F
    binArray = np.zeros_like(binArrayH)

    if data.size % 2 == 0:
        binArray = binArrayH | binArrayL
    else:
        binArray[:-1] = binArrayH[:-1] | binArrayL
        binArray[-1] = binArrayH[-1]

    return binArray

Accès par unités de 16 points

en train de lire

Comme pour l'accès aux mots, la commande Lecture (0401h) lit et les sous-commandes sont les mêmes. Puisque le contenu est constitué de données de mots, il s'agit d'une commande de communication.

Comme le montre l'exemple de communication ci-dessus, les données de 4 octets reçues «[34h, 12h, 02h, 00h]» sont

[<M107>, ..., <M100>, <M115>, ..., <M108>, <M123>, ..., <M116>, <M131>, ..., <M124>]
                    ^                    ^                    ^

Il sera étendu par bits et développé dans un tableau de données de 16 * 4 = 32 points.

La chose déroutante ici est que ** les adresses sont stockées dans l'ordre inverse par octet **. En d'autres termes, dans l'exemple ci-dessus, le LSB du premier octet "34h" est la valeur de l'adresse de début lorsque la commande de lecture est envoyée, et la valeur des données dont l'adresse est incrémentée vers le MSB. Et pour le 2ème octet 12h, cette fois le LSB est la valeur de" start address +8 "...

L'exemple de code ci-dessous utilise unpackbit de numpy pour développer chaque bit de données dans un tableau unidimensionnel. numpy.packbits, [numpy.unpackbits](https://docs.scipy.org/doc/numpy /reference/generated/numpy.unpackbits.html) est une fonction qui convertit un nombre décimal ⇔ un tableau de nombres binaires.

Là où l'ordre de LSB et MSB doit être inversé, le miso est que l'ordre dans la direction de la colonne est inversé en spécifiant la tranche après avoir arrangé une fois en deux dimensions et développé les bits.

def unpack_bits(data):
    """
Développez les chaînes de bits stockées dans l'ordre de LSB dans un tableau
    [<M107 ... M100>, <M115 ... M108>] --> [<M100>, ... ,<M107>, <M108>, ... ,<M115>]
    """

    #Afin d'inverser l'ordre des données après décompression des bits, sous la forme d'un pseudo tableau bidimensionnel,
    #Assurez-vous que les données de bit sont stockées pour chaque octet
    #   ex. [1,2,3] --> [[1],[2],[3]]
    byteArray2D = data.reshape((data.size, 1))

    #Développer les données de bits
    #   ex. [[1],[2],[3]] --> [[0,0,0,0,0,0,0,1],[0,0,0,0,0,0,1,0],[0,0,0,0,0,0,1,1]]
    byteArray2D_bin = np.unpackbits(byteArray2D, axis=1)
            
    #Après avoir inversé l'ordre dans le sens de la colonne, revenez au tableau unidimensionnel
    return byteArray2D_bin[:, ::-1].flatten()

l'écriture

Le modèle est l'inverse de la lecture. Packs 0/1 données de tableau à 1 dimension dans une chaîne d'octets

def pack_bits(data):
    """
Pack d'un tableau de données binaires dans une chaîne d'octets stockée dans l'ordre à partir de LSB
    [<M100>, ... ,<M107>, <M108>, ... ,<M115>]  --> [<M107 ... M100>, <M115 ... M108>]
    """
    #Assurez-vous que le nombre de données est un multiple de 8
    size8 = -(-data.size // 8) * 8

    #Remplissez 0 lorsque la dernière taille est insuffisante
    byteArray_bin = np.zeros(size8, 'u1')
    byteArray_bin[:size8] = data

    #Converti en un tableau bidimensionnel pour inverser l'ordre des données tous les 8 bits
    byteArray2D_bin = byteArray_bin.reshape((size8//8, 8))

    #Pack de données de bits
    return np.packbits(byteArray2D_bin[:, ::-1])

Les références

Recommended Posts

[Suite] Essayez l'accès au registre PLC avec Python
Essayez l'accès au registre PLC en Python
Essayez de gratter avec Python.
Essayez la sortie Python avec Haxe 3.2
Essayez d'exécuter Python avec Try Jupyter
Essayez de gratter avec Python + Beautiful Soup
Essayez d'exploiter Facebook avec Python
Essayez la décomposition de valeurs singulières avec Python
Essayez l'invite http avec un accès http interactif
Essayez la reconnaissance faciale avec python + OpenCV
Essayez la simulation de contrôle de fréquence avec Python
Essayez Python
Essayez de reproduire un film couleur avec Python
Essayez de vous connecter à qiita avec Python
Essayez une formule utilisant Σ avec python
Essayez d'utiliser Python avec Google Cloud Functions
Essayez le scraping HTML avec la bibliothèque Python
Essayez d'appeler Python depuis Ruby avec une économie
Essayez de dessiner une carte avec python + cartopy 0.18.0
Essayez d'attribuer ou de changer avec Python: lambda
[Pour les débutants] Essayez le web scraping avec Python
Accédez à l'API Web avec Python et enregistrez / acquérez des données IoT (dweet.io, Requests, HTTPie)
FizzBuzz en Python3
Accédez au pont léger HPS-FPGA de Cyclone V avec Python
Grattage avec Python
Essayez-le avec JupyterLab en Python japonais Word Cloud.
Grattage avec Python
Python avec Go
Essayez d'exécuter Google Chrome avec Python et Selenium
Essayez de résoudre le diagramme homme-machine avec Python
Essayez de dessiner une courbe de vie avec python
Twilio avec Python
Intégrer avec Python
Jouez avec 2016-Python
Python> essayez: / sauf:
Essayez de créer un code de "décryptage" en Python
AES256 avec python
Testé avec Python
Essayez de générer automatiquement des documents Python avec Sphinx
python commence par ()
avec syntaxe (Python)
Essayez de travailler avec Mongo en Python sur Mac
[Python3] [Ubuntu16] [Docker] Essayez la reconnaissance faciale avec OpenFace
Bingo avec python
Essayez de créer un groupe de dièdre avec Python
Zundokokiyoshi avec python
Excel avec Python
Essayez de détecter les poissons avec python + OpenCV2.4 (inachevé)
Micro-ordinateur avec Python
Cast avec python
Essayez de résoudre le livre des défis de programmation avec python3
Faisons un outil de veille de commande avec python
Essayez de traduire avec Python tout en conservant la mise en page PDF
Essayez facilement Amazon EMR / Cloud Dataproc avec Python [mrjob]
Essayez de résoudre le problème d'affectation du médecin de formation avec Python
Installez le sélénium sur votre Mac et essayez-le avec python
Essayez de déboguer Python sur Raspberry Pi avec Visual Studio.
Essayez d'implémenter la mémoire associative par hop field network en Python