Outils pour utilisateurs

Outils du site


communication_protocole_i2c

Communication avec le protocole I2C

Ressources

Seulement 2 fils, les appareils sont définis par des adresses.

  • I2C sur fr.wikipedia.org Les libs font le boulot, pas besoin d“apprendre la page par coeur. Par contre, le § sur les résistances de pull-up est important.
  • I2C par Nick Gammon This post describes how the I2C (Inter-Integrated Circuit, or “Two-Wire”) interface works, with particular reference to the Arduino Uno which is based on the ATmega328P microprocessor chip. A lot of the details however will be of more general interest.

Installation sur une Pi

From https://gist.github.com/ribasco/c22ab6b791e681800df47dd0a46c7c3a

sudo nano /boot/config.txt
 
# Find the line containing dtparam=i2c_arm=on
# Add i2c_arm_baudrate=<new speed> (Separate with a Comma)
dtparam=i2c_arm=on,i2c_arm_baudrate=400000

Reboot Raspberry Pi
Create a simple test script to verify the speed

Switch to home directory

cd ~

Create shell script

nano i2cspeed.sh

Copy and paste the following lines of code

#!/bin/bash
var="$(xxd /sys/class/i2c-adapter/i2c-1/of_node/clock-frequency | awk -F': ' '{print $2}')"
var=${var//[[:blank:].\}]/}
printf "%d\n" 0x$var

Change file permissions

chmod +x i2cspeed.sh

Execute test script

./i2cspeed.sh

Installation sur Arduino

smbus2

Exemple à revérifier

Exemple entre Raspberry Pi et Arduino Leonardo

Contexte: Le codeur 4000 points est complétement marabouté! La Leonardo ne peut pas être Slave en SPI, il faut faire la comm entre Pi et Arduino en I2C.

Code python pour la Pi en master

from time import time, sleep
from smbus2 import SMBus
 
addr = 44
bus = SMBus(1)
sleep(0.1)
E = 0
 
def request():
    global E
    try:
        b2 = bus.read_i2c_block_data(addr, 0, 2)
        b = bytearray(b2)
        pos = (b[0] << 8) + b[1]
    except IOError:
        pos = None
        E += 1
    return pos
 
t = time()
n = -1
e = 0
nbr = 1000
tempo = 0.03
pos = 0
while n < nbr:
    n += 1
    pos1 = request()
    # #if n % 200 == 0:
        # #print(pos1)
    if pos1 != pos:
        pos = pos1
        print(pos)
    sleep(tempo)
d = ((((time() - t)/nbr) - tempo))*1000
print("Temps de transmission", round(d, 2), "ms")
print("Nombre d'erreur:", E)
bus.close()
"""
freq = 100 000 Hz avec adaptateur
Temps de transmission 0.93 ms
Nombre d'erreur: 2
freq = 100 000 Hz avec adaptateur et pull up
Temps de transmission 1.02 ms
Nombre d'erreur: 2
"""

Code pour Arduino Leonardo

#include <Wire.h>
#include <Encoder.h>
 
// Interrupt
const int ENC_Z = 7;
// Objet Encoder
Encoder myEnc(0, 1);
// I2C
const byte MY_ADDRESS = 44;
// Variable globale
long val = 0;
int hi = 0;
int lo = 0;
 
void index_ISR(){
    myEnc.write(0);
}
 
void setup() {
    //Serial.begin(115200);
    // I2C
    Wire.begin (MY_ADDRESS);
    Wire.onRequest(requestEvent);
 
    pinMode(ENC_Z, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(ENC_Z), index_ISR, RISING);
}
 
void loop() {
    val = myEnc.read();
    delayMicroseconds(500);
    //Serial.print("loop");
    //Serial.println(val);
    //delay(100);
    }
 
void requestEvent ()
    {
    //val = myEnc.read();
    byte buf [2];
    buf [0] = val >> 8;
    buf [1] = val & 0xFF;
    Wire.write (buf, 2);
    }

Pull-up Resistors

On tire le signal vers le + avec une résistance sur SDA et SDL:

communication_protocole_i2c.txt · Dernière modification : 2022/09/07 09:33 de serge