mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

liaison i2c

Sun Feb 18, 2018 10:55 am

Bonjour,
Je débute aussi bien avec Linux qu’avec Python 3.5 sur Raspberry pi3.
J’ai un petit souci en voulant utiliser le petit circuit comprenant une horloge DS3231 et une mémoire E²prom AT24C32.
Sudo i2cdetect –y 1
Ce qui est conforme à mon attente.
L’adresse 0x68 correspond à l’horodateur et l’adresse 0x57 à la mémoire e2prom.

Commençons par la mémoire.
Je fais un petit test pour vérifier le bon fonctionnement en écrivant la lettre ‘A’ à l’adresse 0x20.
I2cset –y 1 0x57 0x20 0x41 b
Et pour vérifier :
I2cdump –y –r 0x00-0xff 1 0x57 b
Et là rien d’écrit.

Avez-vous une idée sur la ou les instructions que je n’aurai pas ou mal exécutées.
Merci d’avance.
Cdlt

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Sun Feb 18, 2018 7:18 pm

I2cdump –y –r 0x00-0xff 1 0x57 b
Il y a typo! (-y 1)


i2cdump -y 1 0x57 b

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Mon Feb 19, 2018 9:02 am

bonjour danjperron,

Non il n'y a pas d'erreur pour la fonction i2cdump elle se rédige bien de cette façon, celle que tu me propose ne fonctionne pas.
Je précise la carte est une Raspberry pi3. il semblerait que, en fonction des modèles, les instructions aient variées. je ne sais pas pourquoi.
Je ne connais pas l'historique, je ne suis qu'un débutant aussi bien en Linux que en Python

Merci pour ta remarque mais ça doit venir d'ailleurs.

Ne doit on pas “notifier” au système la présence du composant ?
du genre :
echo ds3231 0x68 | sudo tee /sys/class/i2c-adapter/i2c-1/new_device
Une bonne idée serait bien venue.

Cdlt

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Mon Feb 19, 2018 11:44 pm

Non il n'y a pas d'erreur pour la fonction i2cdump
Oui c'est vrai. l'erreur est de moi!

Le problème c'est que l'address est 16 bits donc plus grande que 256 alors il faut tricher!

Pour écrire 0x65 = 'A' à l'adresse 0x20 il faut donc envoyer 3 octets 0x00 0x20 0x65 (0x0020 donc 0x00 0x20)

i2cset -y 1 0x50 0x00 0x20 65 i

et pour lire l'adresse 0x20

i2cset -y 1 0x50 0x00 0x20 ; i2cget -y 1 0x50


J'ai vérifié avec un 24LC1025. Désolé je n'ai pas the AT24C32!

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Tue Feb 20, 2018 4:20 am

Voici une classe en python pour lire et écrire un octet à la fois.

Code: Select all

import smbus

class i2c_eerom:

  def __init__(self, i2c_bus,i2c_address):
     self.i2c_address= i2c_address
     self.bus = smbus.SMBus(i2c_bus)

  def  writeByte(self, mem_address, byteValue):
    self.bus.write_i2c_block_data(self.i2c_address,\
                                   (mem_address >> 8) & 0xff,\
                                  [mem_address & 0xff ,\
                                   byteValue])

  def readByte(self, mem_address):
    self.bus.write_i2c_block_data(self.i2c_address,\
                                  mem_address >> 8,\
                                  [mem_address & 0xff])
    return self.bus.read_byte(self.i2c_address)
ex:

Code: Select all

import i2c_eerom
eerom = i2c_eerom.i2c_eerom(1,0x50)
eerom.writeByte(0,1)
eerom.readByte(0)
Pour lire plus d'un octet à la fois il faudra utiliser le IOCTL puisque le smbus ne permet pas de ne pas avoir de 'cmd' pour lire un bloc de data.

viewtopic.php?f=32&t=134997&p=898853&hi ... tl#p898853

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Tue Feb 20, 2018 10:14 am

bonjour,

Je voulais essayer ce circuit comprenant l'horloge DS3231 et la mémoire AT24C32.
https://image.noelshack.com/fichiers/20 ... it-i2c.jpg
l'adresse de la mémoire est bien de 7 bits + R/W ce qui fait 8 bits.
L'organisation est de 8 pages 4096 b (A0, A1, A2) non sélectionnable par soft, ce qui me contrarie car je n'avais pas compris cela dans le descriptif du fournisseur.

Donc pour en revenir à mon problème, je n'ai pas avancé d'un pouce.

cette après-midi je vais tester le programme python en 8 bits pour voir si?

Cdlt

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Tue Feb 20, 2018 12:25 pm

@mandrin N'oublie pas que ton adresse I2C sera 0x57 et que la classe i2c_eerom est dans un fichier i2c_eerom.py qui doit être sous le même répertoire que le fichier principal.

Si tu utilises la classe dans le même fichier que celui qui exécute il faut enlever un i2c_eerom ex: eerom=i2c_eerom(1,0x57).

En passant le système SMBus permet seulement d'envoyer et de recevoir 32 bytes à la fois!

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Tue Feb 20, 2018 4:17 pm

merci pour ce complément.
Je t'avoue qu'il me faut plus de temps pour avaler ta class.

La je ne suis pas à l'aise.
Cdlt

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Thu Feb 22, 2018 3:22 am

Et bien je me suis amusé.


J'ai ajouté writeBlock et readBlock dans la classe i2c_eerom. Le SMBus d'ou provient le I2C ne permet que 32 octets à la fois sous le I2C. J'ai donc utiliser 16 octets pour la pagination au lieu de 32 puisque nous utilisons le premier octet pour le valeur basse de l'address du AT24C32. Ce qui veut dire qu'il n'y a que 31 octets de disponible.

Voici ma classe qui est sous le fichier i2c_eerom.py

Code: Select all

import time
import smbus

class i2c_eerom:

  def __init__(self, i2c_bus,i2c_address):
     self.i2c_address= i2c_address
     self.bus = smbus.SMBus(i2c_bus)

  def  writeByte(self, mem_address, byteValue):
    self.bus.write_i2c_block_data(self.i2c_address,\
                                   (mem_address >> 8) & 0xff,\
                                  [mem_address & 0xff ,\
                                   byteValue])

  def readBlock(self, mem_address, count):
    value = []
    #ajustons la premiere adresse
    self.bus.write_i2c_block_data(self.i2c_address,\
                                  mem_address >> 8,\
                                  [mem_address  & 0xff])
    #ok lecture des octets
    for i in range(count):
       value.append(self.bus.read_byte(self.i2c_address))
    return value

  def readByte(self, mem_address):
    self.bus.write_i2c_block_data(self.i2c_address,\
                                  mem_address >> 8,\
                                  [mem_address & 0xff])
    return self.bus.read_byte(self.i2c_address)


  def writeBlock(self, mem_address, blocValeur):
     # combien d'octet à transferer
     byteSize= len(blocValeur)
     blocList=blocValeur
     # est-ce un bytearray ou une liste
     if isinstance(blocValeur,list):
        #ok c'est une liste
        pass
     elif isinstance(blocValeur,bytearray):
        #alors créons un liste
        blocList = list(blocValeur)
     elif isinstance(blocValeur, bytes):
        blocList = list(blocValeur)
     else:
        raise IOError("Le data n'est pas une liste,un bytearray ou des bytes")
     #ok maintenant verifions l'offset pour la page
     #le système SMBus ne permet que 32 bytes à la fois mais puisque
     #nous utilisons un octet pour l'adresse basse il ne reste que 31 octets
     #La pagination de eerom at24C32 est de 32 octets alors le meilleur multiple
     #est 16   donc la pagination sera de 16 octets
     pagination = 16
     #nombre d'octet a transférer
     octetTotal = len(blocList)
     #voici le bloc de transfer
     blocIndex=0;
     while octetTotal > 0 :
        #alignement avec la pagination
        pageOffset = mem_address % pagination
        reste = pagination - pageOffset
        if reste > octetTotal:
           reste = octetTotal

        #ok c'est la commande i2c pour ecrire la page sur le eerom
        self.bus.write_i2c_block_data(self.i2c_address,\
                                  mem_address >> 8,\
                                  [mem_address & 0xff]+blocList[blocIndex:blocIndex+reste])
        time.sleep(0.01) #important de laisser le write se compléter
        blocIndex += reste
        mem_address += reste
        octetTotal -= reste
Et voici mon exemple avec quoi je me suis amusé.
Je récupère du net les 4096 décimales de π (PI) que j'écris dans le eerom.
Ensuite je les relis et affiche.
Ceci devrait te donner un bon exemple comment l'utiliser.
P.S. Le data pour le writeBlock peut être une liste, un bytearray ou des bytes.

Voici mon exemple Pi4096.py qui roule sous python3

Code: Select all

#!/usr/bin/python3
import time
from urllib.request import urlopen
import i2c_eerom

eerom = i2c_eerom.i2c_eerom(1,0x50)

UFormat='latin-1'
eeromByteSize= 4096


print("- Extraction des décimales de Pi d'une page web")

html = urlopen('http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html')
PiString = html.read(eeromByteSize+500).decode(UFormat).replace('\n','')

#trouvons le 3.1415
depart = PiString.find('3.1415')

#créons un bloc de bytes de 4096 charactères représentant Pi

bytePi = PiString[depart : depart + eeromByteSize].encode(UFormat)

#maintenant enregistrons les 4096 valeurs décimales de Pi

print("- Enregistrement des 4096 premier charactères de Pi sur l'eerom")
print("  P.S. comptez 10ms par octet donc ~40 secondes pour un AT24C32")
print("  Avec writeBlock, 16 octets sont écris en même temps alors c'est 16 fois plus rapide")
#ceci est pour writeByte
#for i in range(len(bytePi)):
#   eerom.writeByte(int(i),bytePi[i])
#   time.sleep(0.010)  #très important. Un délais pour l'écriture

#ceci est writeBlock
eerom.writeBlock(0,bytePi)


# maintenant nous allons lire le mémoire et envoyer l'info sur l'écran

print("- Lecture de l'eerom et l'affichage de son contenu")


#ceci est par readByte()
#byteLu= bytearray()
#
#for i in range(eeromByteSize):
#   byteLu.append(eerom.readByte(i))

#ceci est par readBlock()
byteLu= bytearray(eerom.readBlock(0,eeromByteSize))

# creons une fonction pour lire un byte array sur l'écran
def  byteDump( lebytearray):
   for i in range(0,len(lebytearray),16):
      print("\n{:04X} : ".format(i),end='')
      reste = len(lebytearray) - i
      if reste > 16:
        reste = 16
      for h in range(reste):
         print("{:02X} ".format(lebytearray[i+h]),end='')

      for h in range(16 - reste):
         print("   ",end='')

      print(" ",end='')
      for h in range(reste):
         valeur = lebytearray[i+h]
         if (valeur > 127) or ( valeur < 32):
           print(".",end='')
         else:
           print(chr(valeur),end='')
   print()


byteDump(byteLu)

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Thu Feb 22, 2018 9:47 am

Bonjour,

C'est beau les gens qui s'amusent pendant que d'autres "rament".
( Q: Dis papa c'est loin le Canada? R:Tais toi et rames!!)

En tous cas je vais avoir du mal à décortiquer tout ça.
Pour l'instant je bute sur def writeByte et readByte

Code: Select all

def  writeByte(self, mem_address, byteValue):
    self.bus.write_i2c_block_data(self.i2c_address,\
                                   (mem_address >> 8) & 0xff,\
                                  [mem_address & 0xff ,\
                                   byteValue])
Quelques commentaires sur les manipulations d'adresses seraient les bien venus.
Ingurgiter Python+Linux, pour commencer à utiliser ma Raspberry pi 3, ça fait beaucoup d'un seul coup. De plus il y a des copains qui mettent des "class" la dedans!

Merci quand même, j'apprécie le soutiens.

Bon avec tout çà je retourne bosser la doc python ET le programme de pi().

Amicalement

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Thu Feb 22, 2018 12:30 pm

def writeByte(self, mem_address, byteValue):
self.bus.write_i2c_block_data(self.i2c_address,\
(mem_address >> 8) & 0xff,\
[mem_address & 0xff ,\
byteValue])

Ok le Raspberry Pi passe par le SMBus pour le I2C. Ce I2c n'est pas exactement 100%. Il y a des limites avec le nombre de données que tu peux envoyer.

la fonction write_i2c_block_data a trois paramètres. Le premier c'est l'adresse I2C de la composante,le deuxième c'est la commande et la dernier c'est une liste de données.
Si tu convertis cette fonction en écriture et lecture I2C c'est :

parametre 1 -> envoi d'un octet I2c pour l'addresse + write
parametre 2 -> envoi d'un octet de commande qui pour nous est le MSB de l'addresse interne du eerom
parametre 3 -> envoie des données qui est pour nous sera séparé en deux parties. Le premier octet contient l'adresse LSB interne du AT24C32 et le deuxième octet sera la donnée à enregistrer dans le eerom.


la fonction readByte est séparer en deux.
La première partie est de sélectionner l'adresse interne du eerom . C'est le write_I2cBlock
Et la deuxième partie n'est qu'un read_byte qui va lire directement l'adresse interne du eerom sélectionné.


Bon je sais que c'est beaucoup mais le writeBlock de ma classe est plus compliqué puisqu'il faut tenir compte de la pagination interne du eerom qui permet d'écrire en même temps 32 bytes. Chaque écriture oblige un délais de 10 ms.


Si tu veux je peux écrire les commandes en 'C' si tu le maîtrises mieux.

Bonne lecture. N'oublie de lire le pdf technique du eerom.


As-tu essayé mon exemple au moins ?

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Thu Feb 22, 2018 5:47 pm

Bonjour danjperron

D'abord merci pour tes conseils et explication qui me mettent sur la bonne voie même si j'ai de la peine à suivre.

Non je n'ai pas encore essayé ton exemple car je pioche dans la doc pour comprendre et certains points n'y sont pas développés.
Pour cette partie :
mem_address >> 8,[mem_adresse &0xf]
quel est l’effet de
>> 8

dans cette adresse ?

Peut être qu’en C je comprendrai mieux ?

Pour le volume à écrire dans l'eeprom j'ai 27 octets toute les 10 minutes que je devrai transférer dans la feuille de calcul d'un tableur toutes les 24 heures.
Donc j'ai intérêt à bien comprendre cette opération pour le futur.

Amicalement

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Thu Feb 22, 2018 6:20 pm

Re bonjour danjperron

je viens de trouver ça:
>> Binary Right Shift

Enfin je vais pouvoir continuer.

Merci encore
Amicalement

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Thu Feb 22, 2018 7:08 pm

mem_address >> 8 et mem_address & 0xff
Ok Pour commencer C'est la même chose en C alors je pense qu'il est mieux de rester en Python ;-)

La valeur 0xff est en hexadécimal et équivaut à 255 en base 10. Le préfixe 0x impose l'hexadécimal tout comme le préfixe 0b impose le binaire.


La puce utilise un addressage de 16 bits même si c'est seulement 12 bits (2 puissance 12 = 4096)

il faut donc envoyer 16 bits pour l'adresse. Avec le I2c il n'y a que 8 bits possible à la fois donc nous allons envoyer deux fois 8 bits.


Il faut penser en binaire! Une adresse 16 bits est donc 0bxxxxxxxxxxxxxxxx représentant un chiffre binaire et x peut prendre 0 ou 1.

donc pour envoyer deux octets nous allons envoyer les premiers 8 bits les plus significatifs suivit des 8 autres.

Donc si nous déplaçons vers la droite de 8 bits nous allons avoir les 8 bits pour envoyer. mem_address>> 8
Et si nous masquons les 8 bits les plus significatif nous allons avoir les autres 8 bits pour envoyer. mem_address & 0xff ce qui veut dire mem_address ET 0b0000000011111111



ex:
Je veux écrire dans l'adresse 3024. il faut donc convertir l'adresse 16 bits en deux de 8 bits

la valeur décimale 3024 équivaut à 0000101111010000 en binaire

Donc 3024>>8 me donnera en binaire un déplacement vers la droite de 8 bits soit 0b00001011 ce qui donne une valeur de 11 en base dix.
Et 3024& 0xff sera 0b0000101111010000 et 0b0000000011111111 = 0b11010000 ce qui donne une valeur de 208 en base dix.

et pour vérifier le tout il reste à faire l'opération inverse soit (11 * 256)+208 = 3024

& est un ET arithmétique
| est un OU arithmétique
% est un modulus arithmétique (le reste d'une division)
^ est un OU exclusif arithmétique
>> est un déplacement binaire vers la droite (MSB vers LSB) (division 2 puissance N)
<< est un déplacement binaire vers la Gauche (LSB vers MSB) (multiplication 2 puissance N)
~ est une inversion binaire. ( 0 devient 1 et vice versa)

En passant je pourrais utiliser ceci aussi
premier Octet (mem_address // 256) le double // spécifie une division de nombre entier. Nous oublions les décimales.
deuxieme octet ( mem_address % 256) un modulus c'est le reste après un division de nombre entier.

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Fri Feb 23, 2018 10:28 am

Bonjour dannjperron,

Merci pour tes explications très détaillées.

Dans l'exemple du 20/2 afin de bien suivre les explications de base, avant d'aller plus loin,
j'ai un petit soucis dont je ne saisi pas la raison.
Voici une copie d'écran:
https://image.noelshack.com/fichiers/2 ... mage3.png
Pour mémoire la copie de la class i2c_eerom.py
import smbus

class i2c_eerom: ## page 193 2-python et 126 1-python

def __init__(self, i2c_bus,i2c_address): #definition du bus et adresse
self.i2c_address= i2c_address # adresse de 16 bits
self.bus = smbus.SMBus(i2c_bus) # N° du bus

def writeByte(self, mem_address, byteValue):
self.bus.write_i2c_block_data(self.i2c_address,\
(mem_address >> 8) & 0xff,\
[mem_address & 0xff ,\
byteValue])

def readByte(self, mem_address):
self.bus.write_i2c_block_data(self.i2c_address,\
mem_address >> 8,\
[mem_address & 0xff])
return self.bus.read_byte(self.i2c_address)
L'erreur concerne la dernière ligne de l'addresse.
A la ligne précédente ne manquerait il pas quelque chose comme & 0xff ?
Si j'ai bien compris !
Merci de m'éclairer.
Amicalement.

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Fri Feb 23, 2018 11:39 am

L'erreur c'est un IO Erreur donc la puce ne répond pas

As-tu changé l'adresse pour 0x57 si tu as pris mon exemple?

Si tu veux utiliser la classe il faut créé l'object

Code: Select all

import time
import i2c_eerom

eerom = i2c_eerom.i2c_eerom(1,0x57)
maintenant eerom.read_byte(0

Avec Python tu peux tout essayer à la main.

Exemple pour simuler de lire l'adresse 0 du AT24C32

- ouvre une session python3. Pour le i2c le sudo n'est pas nécessaire si tu utilises une version récente de stretch

Code: Select all

python3
- importe la librairie SMbus
- crée un object I2c avec l'adresse du bus
- envoie l'addresse que tu veux lire
- et lis le byte de la mémoire.

Code: Select all

[email protected]:~ $ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170124] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import smbus
>>> bus=smbus.SMBus(1)
>>> bus.write_i2c_block_data(0x57,0,[0])
>>> bus.read_byte(0x57)
0
>>> bus.write_i2c_block_data(0x57,123 >>8,[123 &0xff])
>>> bus.read_byte(0x57)
0
>>> bus.write_i2c_block_data(0x57,123 >>8,[123 &0xff,12])
>>> bus.write_i2c_block_data(0x57,123 >>8,[123 &0xff])
>>> bus.read_byte(0x57)
12
>>> 
Dans cet exemple j'écris aussi à l'adresse 123 la valeur de 12 et je la relie et elle donne maintenant 12. Utiliser Python en console te permet de vérifier les commandes une par une ce qui est très pratique.

Voici l'utilisation de ma classe à la main avec la console python3

Code: Select all

[email protected]:~ $ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170124] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import i2c_eerom
>>> eerom = i2c_eerom.i2c_eerom(1,0x57)
>>> eerom.readByte(0)
0
>>> eerom.writeByte(0,1)
>>> eerom.readByte(0)
1
>>> eerom.readBlock(0,16)
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> eerom.writeBlock(4,[ 1 , 2 , 3, 4])
>>> eerom.readBlock(0,16)
[1, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0]
>>> 
P.S. j'ai changé l'adresse 0x50 pour 0x57

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Sat Feb 24, 2018 8:24 am

Suite:

J'ai bien changé l'adresse en 0x57

La puce ne réponds pas dans python, mais elle répond à la console avec l'instruction suivante.
i2cset -y 1 0x57 0x00 0x20 ; i2cget -y 1 0x57
Pour progresser dans tes exemples, l'enregistrement des 4096 octets de pi() s'est très bien enregistré et lu par le programme python 'Pi4096.py'.

Une petite merveille !
Je ne pensais pas que le traitement ce soit si long.

A cette occasion cela concerne une page de la mémoire AT24C32. Or cette mémoire contient 4 pages de 4096 octets. Est-il possible d'adresser les autres pages par soft. Sur le circuit imprimé les adresses de ces pages sont sélectionnées par une résistance de pull up au +VCC à shunter au GND pour en changer (A0, A1, A2).

Maintenant il ne me reste plus qu'a continuer a découvrir tout çà pour en comprendre les mécanismes.

Merci encore
Amicalement.

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Sat Feb 24, 2018 1:55 pm

Et non la puce at24C32 ne contient que 4096 octets. Les broches A0,A1 et A1 ne sont la que pour ajouter d'autres AT24C32.

Ses broches spécifient à qu'elle adresse la puce va répondre.

Si tu as besoin de plus de mémoire il est possible de simplement ajouter une puce eerom dans ton circuit.
Moi J'ai vérifié ma classe avec une puce 24LC1025 qui est complèetement compatible avec le AT24C32 mais elle contient deux pages de 64K octets.
La broche A2 change la page et A0,A1 spécifient l'adresse I2C de la puce. En fait Le Pi voit deux adresses soit 0x50 et 0x54. (A0=0 et A1=0)

As-tu essayer le mode console avec python3 et essayer ligne par ligne ce que j'ai écris au post précédent?

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Sun Feb 25, 2018 11:09 am

Bonjour dannjperron

Ok merci pour la question de l'adressage de A0..A2.

En manuel pour explorer le programme et avant de le modifier pour mes propres besoins, je vérifie si j'ai bien compris cet adressage.
Après avoir appliqué le programme Pi4096.py, si je lis la mémoire AT24C32 avec l’instruction suivante :
i2cset -y 1 0x57 0x00 0x00;i2cdump -y -r 0x00-0x0f 1 0x57 b
Je devrai retrouver la première ligne du nombre pi() à savoir de 0x00 à 0x0f :
3.14159265358979
Or la lecture de ces 16 octets ne me donne pas le même résultat :
6473434336496661
Il semblerait que l’adresse ne soit pas la même. Mais où suis-je donc ?

I2cset positionne le pointeur à l’adresse 0x0000 de la mémoire 0x57
I2cdump lit les octets 0x00 à 0x0f de la même adresse dans la même mémoire.
Est-ce bon ou non?
Là je patauge.
J'exagère peut être un peu mais il n'y a pas grand chose dans les tutos sur ce sujet.
Merci encore
Amicalement

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Sun Feb 25, 2018 3:27 pm

Ok comme je t'ai dit au premier "post" les eeroms n'utilisent pas un octet pour l'adresse mais deux! donc il est impossible d'utiliser i2cdump de cette façon.

Il faut utiliser i2cget puisqu'il est possible de ne pas envoyer de commande. Le problème c'est que c'est octet par octet et donc plus long.

J'ai ajusté l'horloge du I2C à 400Khz pour le PI3 et cela prend environ 21 secondes pour répondre.

Code: Select all

[email protected]:~ $ i2cset -y 1 0x57 0x00 0x00; value=$(for i in {0..4095}; do i2cget -y 1 0x57;done); echo $value | xxd -r -p; echo ""
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745530506820349625245174939965143142980919065925093722169646151570985838741059788595977297549893016175392846813826868386894277415599185592524595395943104997252468084598727364469584865383673622262609912460805124388439045124413654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767889525213852254995466672782398645659611635488623057745649803559363456817432411251507606947945109659609402522887971089314566913686722874894056010150330861792868092087476091782493858900971490967598526136554978189312978482168299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610213596953623144295248493718711014576540359027993440374200731057853906219838744780847848968332144571386875194350643021845319104848100537061468067491927819119793995206141966342875444064374512371819217999839101591956181467514269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672218256259966150142150306803844773454920260541466592520149744285073251866600213243408819071048633173464965145390579626856100550810665879699816357473638405257145910289706414011097120628043903975951567715770042033786993600723055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816909152801735067127485832228718352093539657251210835791513698820914442100675103346711031412671113699086585163983150197016515116851714376576183515565088490998985998238734552833163550764791853589322618548963213293308985706420467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325974636673058360414281388303203824903758985243744170291327656180937734440307074692112019130203303801976211011004492932151608424448596376698389522868478312355265821314495768572624334418930396864262434107732269780280731891544110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201855810072936065987648611
[email protected]:~ $
Explication;

- i2cset
Sélectionne l'adresse 00x00 commande et 0x00 pour data (il faut 16 bits)
- value=$(
C'est une fonction bash pour ecécuter ce qui a entre les paranthèses et d'enregistrer ce qui va en console dans la variable value
- for i in {0..4095}
C'est la loop bash pour executer de 0 à 4095 les commandes entre le do et le done
- i2cget -y 1 0x57
Lire un octet de la puce i2c à l'adresse 0x57 sans envoyer de commande.
- echo $value
Envoi à la console le contenu de la variable value qui contient les valeurs en hexadécimales du contenu des mémoires 0 à 4095
- xxd -r -p
J"utilise un pipe pour convertir les valeurs hexadécimales en ascii
- echo ""
Ajout de fin de ligne

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Sun Feb 25, 2018 4:22 pm

J'ai trouvé sur le net une application qui lit les eeroms.

https://www.richud.com/wiki/Rasberry_Pi ... OM_Program


ok pour compiler

Code: Select all

wget http://darkswarm.org/eeprog-0.7.6-tear5.tar.gz
tar -xzf eeprog-0.7.6-tear5.tar.gz
cd eeprog-0.7.6-tear12
J'ai modifié Makefile pour installer eeprog dans /usr/bin

Attention ce n'est pas des espaces mais des "tab"

Code: Select all

...
...
install: eeprog
        install -p eeprog $(PREFIX)
        install -ps eeprog $(PREFIX)/eeprog-tear

...
...

uninstall:
        $(RM) $(PREFIX)/eeprog
        $(RM) $(PREFIX)/eeprog-tear
 ...
 ...
 
Je compile et installe avec,

Code: Select all

make
sudo make install
et il reste à tester

Code: Select all

[email protected]:~ $ eeprog -f -16 -r 0:4096 /dev/i2c-1  0x57
eeprog 0.7.6-tear12, a 24Cxx EEPROM reader/writer
Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved.
Copyright (c) 2011 by Kris Rusocki - All rights reserved.
  Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit
  Operation: read 4096 bytes from offset 0, Output file: <stdout>
  Reading 4096 bytes from 0x0
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653[email protected]Pi3:~ $ 

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Mon Feb 26, 2018 8:50 am

Bonjour,
Avec tout ça le vais en avoir pour quelques jours à digérer.

En voulant reprendre un ancien petit programme qui tournait, afin d'en intégrer une partie, je découvre que des fonctions qui s'exécutaient correctement initialement ne marchent plus.

Un petit retour sur les fondamentaux, comme ont dit, est nécessaire.

Si en plus tu m'envoie dans le cercle vertueux des compilations etc, alors là!

C'est çà les copains!

Assez de plaisanterie, laisse moi quelques jours pour digérer çà et je ne manquerai pas de te relancer.

Amicalement

mandrin
Posts: 65
Joined: Tue Feb 06, 2018 4:49 pm

Re: liaison i2c

Fri Mar 02, 2018 6:30 pm

Bonjour dannjperron

Fin du repos, la crêpe est de retour.

Pour revenir sur l'application sur le net qui lit les eeroms,
Ou doit se trouver le dossier ?
eeprog-0.7.6
Car la partie
install: eeprog
etc
ne fonctionne pas. C'est probablement dû a l'emplacement du fichier.
*----------------*
Dans un petit programme qui enregistre dans la mémoire e2prom le résultat des mesures toutes les 10 minutes durant la journée soit 144 lignes de 30 valeures par ligne limité à 2 valeures.
En utilisant le programe i2c_eerom.py de Pi4096.py précédents
Données transférées du programme appelant dans i2c_eerom.py:
100 16 # mem_address,date.hour
la valeur 100 correspond à 16h 40 minutes
adres_eerom=date.hour*6+date.minute//10 # calcul de l'adresse eerom en fonction de l'heure \
qui produit l'enregistrement des mesures
et la valeur 16 correspond a date.hour
Partie du programme appellée:
def writeByte(self, mem_address, byteValue):
self.bus.write_i2c_block_data(self.i2c_address,\
(mem_address >> 8) & 0xff,\
[mem_address & 0xff ,\
byteValue])
La première ligne de données transférées par le programme appelant se passe bien.
La deuxième ligne ne passe pas et je ne comprend pas pourquoi.
Il n'y a pas de différence entre les deux a part la valeur
101 40 # mem_address,date.minute
la valeur 101 correspond à
adres_eerom+=1
c'est la même adresse mais implémentée de 1 pour l'octet suivant et la valeur 40 correspond a date.minute
En clair j'enregistre à l'adresse 100 l'heure des mesures et c'est bon , et à l'adresse 101 les minutes, cette dernière me déclenche l'anomalie suivante:
Traceback (most recent call last):
File "Viadrus.py", line 139, in <module>
store_mesures()
File "Viadrus.py", line 111, in store_mesures
eerom.writeByte(mem_address,date.minute)
File "/home/pi/Dossier_raspi/i2c_eerom2.py", line 15, in writeByte
byteValue])
OSError: [Errno 121] Remote I/O error
C'est la même boucle que pour la première ligne
Je ne vois pas pourquoi.
Je précise ce programme doit fonctionner en Python et non en console.
Amicalement.

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Fri Mar 02, 2018 6:47 pm

Pour revenir sur l'application sur le net qui lit les eeroms,
Ou doit se trouver le dossier ?
eeprog-0.7.6
Car la partie
install: eeprog
Oui la compilation ce fait dans "~/eeprog-0.7.6-tear12"

Si tu as de la misère avec l'installation tu peux tout simplement copier eeprog dans /usr/local/bin

cd eeprog-0.7.6-tear12
sudo cp eeprog /usr/local/bin

P.S. je suppose que tu as réussi à compiler.


Pour le problème de date je n'ai aucune idée ce que tu passes dans la fonction puisque tu ne nous as pas donné la partie du code la plus importante ce qui veut dire la structure que tu envoies.

"date" vient de qu'elle structure ou objet?

danjperron
Posts: 3032
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: liaison i2c

Fri Mar 02, 2018 7:43 pm

Code: Select all

def writeByte(self, mem_address, byteValue):
self.bus.write_i2c_block_data(self.i2c_address,\
(mem_address >> 8) & 0xff,\
[mem_address & 0xff ,\
byteValue])
La première ligne de données transférées par le programme appelant se passe bien.
La deuxième ligne ne passe pas et je ne comprend pas pourquoi.
Il n'y a pas de différence entre les deux a part la valeur
Veux-dire "self.bus.write_i2c_block_data(self.i2c_address,\" comme deuxième ligne ?

Si c'est le cas et bien c'est normal. En python les blocs de commandes ce font par la position de la colonne (identation).

il aurait fallut que tu écrives

Code: Select all

  def  writeByte(self, mem_address, byteValue):
     self.bus.write_i2c_block_data(self.i2c_address,\
                                 (mem_address >> 8) & 0xff,\
                                  [mem_address & 0xff ,\
                                  byteValue])
Au cas qu'il y a un problème avec la transcription de i2c_eerom.py voici le lien pour la télécharger.

Code: Select all

cd
wget https://dl.dropboxusercontent.com/s/wex9mv0oinx7zhn/i2c_eerom.py

Return to “Français”

Who is online

Users browsing this forum: No registered users and 4 guests