Dernière mise à jour le 15/01/2021

Présentation


Nous allons voir maintenant comment lire des données sur un PIC 18F4550 (ou autre) afin de renvoyer ces données à la cam OpenMV

Dans un premier temps, il faut “caler”, ou dirais-je rendre la communication I2C compatible entre la cam et le PIC pour arriver en sorte à ce que la cam puisse écrire des données sur le PIC qui une fois reçues, ce dernier les déposeras tour à tour dans un tableau (array) (tableau de 8×1) qu’on nommera Buffer[8][1].


Une bonne configuration entre la cam OpenMV et le PIC18F4550 est avant tout l’adressage. Oui sans adresse côté PIC il sera impossible de communiquer avec ce dernier. Pour plus de détails sur comment configurer le PIC en mode esclave, vous pouvez vous rendre dans cette rubrique PIC18F4550 (esclave) – OpenMV (maître) – mode I2C.


Pour faire “simple”, si vous configurez votre cam OpenMV avec pour adresse cAdrr = 0x02, il faudra configurer le PIC avec cAdrr = 0x04 (ajout de 1bit à droite donc décalage vers la gauche pour le PIC18F4550 !! – 0x02 << 1 donne 0x04).
ou
si vous configurez votre cam OpenMV avec cette fois-ci pour adresse cAdrr = 0x02 >> 1 (suppression de 1 bit à droite cette fois-ci réalisé au niveau de la cam, décalage à droite !, ce qui donne 0x01), alors côté PIC 18F4550 laisser cAdrr = 0x02).

C’est cette histoire de décalage qui va permettre de rendre compatible la cam OpenMV avec le PIC (plusieurs tests sont situé un peu plus bas pour voir ensemble le principe c’est beaucoup plus parlant).

Mode Lecture – Cam OpenMV vers PIC18F4550


Intéressons nous sur ces lignes de code côté OpenMV afin de réaliser la lectures des données situées dans le Buffer du PIC18F4550.

MAÎTRE – Programmation Python – Cam OpenMV STM32F765VI ARM

# Maître – OpenMV I2C – Lecture – Python – Electronique71.com

from pyb import I2C
import utime


i2c = I2C(2) # creation du bus I2C
i2c.init(I2C.MASTER, baudrate=100000) # initialisation du maître sur 100Khz


# 0x02 >> 1 : +1 bit à droite (décalage vers la gauche de l'adresse donne 0x04 pour PIC)
cAdrr = 0x02 >> 1
# si cAdrr = 0x02 côté cam OpenMV alors mettre cAdrr = 0x04 côté PIC18F4550 pour compatibilité !

utime.sleep_ms(500)# On attend un peu la fin de l'initialisation du bus I2C.

Buffer = bytearray(8)  # Création du Buffer (1 octet = 8bits)

print("Nettoyage Buffer !! -> " + str(i2c.recv(Buffer,cAdrr)))

while (True):

    # Lecture
    print(i2c.recv(Buffer,cAdrr))
    print("Fin de lecture!!")
    utime.sleep_ms(1000) # petite tempo de 1sec afin de voir l'affichage

Fonctionnement
Niveau initialisation, on y retrouve l’initialisation du bus I2C en mode “MASTER” (maître) sur 100Khz, puis, niveau adresse je reste toujours sur la même pour ne pas changer mes habitudes avec cAdrr = 0x02 >> 1, et s’enchaine tout de suite derrière une temporisation de 500ms afin de voir l’affichages des données.

Une autre chose à signaler, c’est la déclaration du Buffer sur un tableau de 1 octet (8 bits) c’est dans ce buffer que nous allons récolter toutes ces données du PIC.
Avant de se lancer dans toute la programmation on va déjà faire un nettoyage du Buffer pour commencer une extraction sur des bases saines !!


Dans la boucle “While”, nous affichons les données du PIC18F4550 en permanence via la fonction “recv” qui comporte deux arguments qui sont:


* Le buffer ou nous allons stocker les 8 bits;
* L’adresse qui correspond à l’esclave que nous voulons lire.


Le buffer, ici paramétré à 8 par l’intermédiaire de la variable bytearray(8), va réclamer 8 bit , c’est à dire qu’il va lancer 8 fois la lecture sur le PIC. Si vous mettez 7 alors il va lancer 7 fois etc.. etc..
Ici la programmation est réalisée sur 8 bits, car j’ai programme le PIC18F4550 sur un Buffer de 1 octet (8bits Buffer[8][1]).

Afin de voir ce qu’il se passe niveau terminal côté OpenCV, je vous ai fais une capture d’écran ou la boucle s’exécute toute les secondes.


Terminal OpenMV
Ci-dessous, une capture des données situées dans le buffer du PIC18F4550


Sans plus attendre, regardons maintenant la programmation côté PIC toujours en langage C (MikroC) et niveau réglage horloge cela donne ceci:


ESCLAVE – Programmation MikroC – PIC18F4550

// Esclave – PIC18F4550 – Lecture – MikroC – Electronique71.com

const cAdrr = 0x02; // cAdrr = 0x02 correspond à l'adresse de l'esclave
// Si cAdrr = 0x04 côté PIC alors mettre cAddr = 0x02 côté cam OpemMV pour compatibilité !

unsigned char iCount_Lecture;
unsigned char Data;
unsigned char VideBuffer;

// Tableau 2 dimensions pour envoyer donner vars cam OpenMV
unsigned char Buffer[8][1] = {
                                {0x00},  // bit 0
                                {0x01},  // bit 1
                                {0x02},  // bit 2
                                {0x03},  // bit 3
                                {0x04},  // bit 4
                                {0x05},  // bit 5
                                {0x06},  // bit 6
                                {0x07},  // bit 7
                              };

// Tableau 1 dimension pour envoyer donner vars cam OpenMV
//unsigned char Buffer[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};

void interrupt() // On contrôle chaque interruptions
{
  if (PIR1.SSPIF == 1)
  {
    // SSPSTAT.R_W  -> bit0 = 1: Lecture  ou  bit0 = 0: Ecriture
    if (SSPSTAT.R_W == 1)
    {
      if (BF_bit == 1) // On attend que le Buffer soit bien remplis avant d'envoyer !
      {
        // Lecture -> Maître (OpenMV) vers Esclave (18F4550)
        // On ajoute les différents bits du Buffer pour envoyer ver OpenMV
        SSPBUF = Buffer[0][iCount_Lecture]; 

        ++iCount_Lecture; // On ajoute les données dans un tableau
      }
    }
  }

  SSPCON1.CKP = 1; // On relache l'horloge pour lancer la suite
  PIR1.SSPIF = 0;  // On remet à zéro le drapeau d'interruption et on attent la prochaine !
}


void init()
{

  ADCON1 = 0xFF;      // On configure toutes les broches en numérique (0 ou 1)

  ADCON0.ADON = 0;   // On désactive le module de convertisseur analogique numérique

  CMCON = 0x07;      // On désactive le mode comparateur

  ADCON1.VCFG0 = 0;  // Bien penser à desactiver les tensions de références !
  ADCON1.VCFG1 = 0;

  TRISB = 0x03;      // Config les broches du PORTB - RB0 et RB1 comme entrée (SDA/SCL)
  PORTB = 0x00;
  LATB = 0x00;

  TRISD = 0x00;      // Config PORTD en sortie pour la lecture
  PORTD = 0x00;
  LATD = 0x00;

  TRISE = 0x00;      // Config MCLR
  PORTE = 0x00;
  LATE = 0x00;

  INTCON.GIE = 1;    // On active les interruptions globales 
  INTCON.PEIE = 1;   // On active les interruptions périphériques 
 
  PIE1.SSPIE = 1;    // On active le MSSP ( Module port série synch principal I2C ou SPI) 
  PIR1.SSPIF = 0;    // On met le drapeau d'interruption à zéro pour commencer 
 
  SSPCON1.SSPEN = 1; // On active les broches RB0 et RB1 en mode SDA et SCL
 
  // On active le mode 7 bits (0 à 7 = 8 bits) avec interruptions sur bit Start et Bit Stop 
  SSPCON1.SSPM0 = 0;
  SSPCON1.SSPM1 = 1;
  SSPCON1.SSPM2 = 1;
  SSPCON1.SSPM3 = 1;

  SSPADD = cAdrr;    // Configuration de l'adresse de l'esclave du PIC 18F4550

  SSPSTAT.SMP = 1;   //  vitesse de communication 100 Khz (standard)

  SSPCON2.SEN = 1;   // On active l'étirement de l'horloge

  SSPCON2.SEN = 1;   // On active l'étirement de l'horloge

  iCount_Lecture = 0;

  VideBuffer = SSPBUF; // On vide le Buffer correctement !

  Delay_ms(100);       // On attend un peu la fin de l'initialisation
}

void main()
{
  init(); // Initialisation du PIC18F4550

  while (1)
  {
    if ((P_bit == 1) && (iCount_Lecture >= 8))
    {
      iCount_Lecture = 0;   // On remet à "0" à 8
      VideBuffer = SSPBUF;  // On vide le buffer correctement !!
    }
  }
}

Fonctionnement
Dans cette configuration, le PIC réalise uniquement la récupération des élements du tableau Buffer[8][1] ou plus précisement Buffer[0][iCount_Lecture] ou on incrémente les lignes du Buffer une à une afin de récupérer les données et de les renvoyer au Maître (cam OpenMV).
Le tableau tout du moins le Buffer composé de 8×1 (8 élements qui stock 1 donnée) a été initialisé de 0 à 7 en héxadécimal.


1er envoi = Adresse:
Lorsque la cam OpenMV va faire une demande de lecture, la fonction “recv” vu précédemment va contenir un 1er octet qui correspondra TOUJOURS à l’adresse (cAdrr = 0x02 >> 2),


Dans ce premier octet d’envoi le bit de poids faible (bit0) sera à l’état “1” – il n’y a rien à faire de plus dans la fonction “recv” qui réalise tout le travail, tout du moins la seul chose à faire c’est de rentrer le Buffer dans cette fonction ainsi quel’adresse de l’esclave afin de stocker les données pour les lires sur le terminal.


Lorsque l’adresse est reconnue par le PIC18F4550, une interruption sera déclenchée à condition bien évidemment d’avoir pensé à activer les bits INTCON.GIE = 1 et INTCON.PEIE = 1 dans le registre INTCON du PIC. Le registre SSPSR quant à lui va recevoir le 1er octet qui comporte l’adresse.


Si l’adresse est reconnue par le PIC, le registre SSPSR va transférer l’octet reçu vers le buffer interne du PIC qui se nomme SSPBUF, et c’est à ce moment précis lorsque le SSPBUF est “rempli” (1 octet = 8bits) une interruption survient et met à l’état logique haut “1” le bit SSPIF du registre PIR1.


Nous nous retrouvons maintenant au niveau de la ligne SSPSTAT.R_W. Ce bit R_W (R=read/W=Write), permet de lire le bit de poids faible (bit0) afin de voir si celui-ci est à l’état logique haut “1” qui correspond à une lecture.
(Je tiens à le rappeler, mais ce bit change uniquement d’état sur l’envoi du 1er octet ! et non pas surs les autres octets situés sur le bus I2C)


Dans cette programmation, le code ne fait uniquement de récupérer chaque élements du tableau (Buffer[8][1]), afin de les copier dans le registre SSPBUF. Chaque fois qu’une demande de lecture est envoyées par la cam OpenMV, le PIC ne fait que de transmettre ses données et exécutera un total de 8 tour suite à la réclamation de la cam OpenMV via la fonction “bytearray(8)”.


J’ai crée une variable que j’ai nommée “VideBuffer”. Cette variable (optionnelle) permet de vider le registre SSPBUF mais n’est pas obligatoire. Dans certaine programmation nous devons créer ce genre de variable pour “vider” le Buffer alors j’ai gardé ce principe.

Schéma


Changement d’adresse



Comme évoqué dans la présentation, J’ai réalisé différents tests (8 au total) avec d’autres adresses à savoir de bien respecter que le bit0 doit être à un état logique bas “0”. Pour ne pas compliquer, je fais un décalage à gauche uniquement côté du PIC et non côté cam OpenMV (voir ci-dessous les différentes adresses)

Test Adresse OpenMV (cAdrr) Adresse 18F4550 (cAdrr) Compatibilité
1 0x04 (100b) 0x08 (1000b) OK
2 0x10 (10000b) 0x20 (100000b) OK
3 0x14 (10100b) 0x28 (101000b) OK
4 0xF0 (11110000b) 0xE0 (11100000b) OK
5 0xAA (10101010b) 0x54 (01010100b) OK
6 0x80 (10000000b) 0x00 (00000000b) NOK
7 0x40 (01000000b) 0x80 (10000000b) OK
8 0x6C (01101100b) 0xD8 (11011000b) OK

Comme vous pouvez le constater, il suffit de rajouter un “0” tout à droite, ce qui décale l’octet à gauche et donc supprime le dernier chiffre tout à gauche.

Test sur platine EasyPIC V7


Le câblage est réalisés sur le PORTC broche RC3(SCL) vers RB1(SCL du PIC18F4550) et RC4(SDA) vers RB0(SDA du PIC18F4550). En effet ce pont entre le PORTC permet de ramener les résistances de 4k7 sur le PORTB où sont reliés les broches SDA et SCL du PIC18F4550 situé sur la platine EasyPicV7. Ne pas oublier de placer les switchs (SW4) RC3 et RC4 en postion “ON” afin de mettre en circulation les résistances PULL-UP

Aucunes photos mise à part celle située en présentation….

Historiques


15/01/2021
-1er mise à disposition