Outils pour utilisateurs

Outils du site


robotics:electronics:shield_arduino_ls7366r

Présentation des LS7366R

Le LS7366R est un compteur 32 bits spécialisé pour les horloges en quadrature (type codeur incrémentaux). Il peut être configuré en compteur 1, 2 3 ou 4 octets. Il dispose également d'une entrée index. Il communique avec un microcontrolleur via une liaison SPI.

Entrées / Sorties

A et B : Les sorties A et B du codeur incrémental (idéalement en quadrature de phase) doivent être directement connectées aux entrées A et B du codeurs.

INDEX : L'entrée INDEX est une entrée programmable du compteur. Elle peut être directement reliée à la sortie INDEX du codeur incrémental (si celui-ci en a un) ou alors au microcontrolleur. Cette entrée peut avoir plusieurs fonctionnalités. Elle permet de charger le registre d'entrée ou de sortie ou alors de remettre le compteur à zéro.

FCKO et FCKI : Entrées pour connecter un oscillateur. Pour un filtrage correct des entrées, il faut que Ff > 4fQA avec Ff : fréquence interne de l'ocilateur et fQA : frequence max du signal A en quadrature.

CNT_EN : Permet le comptage quand cette entrée est à 1.

LFLAG et DFLAG : sorties programmables qui permettent d'annoncer un dépassement du compteur ou fonction de comparaison.

MOSI : entrée de la liaison SPI. les données sont reçues sur cette entrée.

MISO : sortie de la liaison SPI. les données sont envoyées sur cette sortie.

SS/ : sélectionne le compteur pour activer la liaison SPI., MOSI : utilisés pour la liaison SPI.

SCK : horloge du signal SPI.

Registres

CNTR : registre qui contient la valeur courante du compteur. Ce registre peut être directement lu mais pour éviter les problèmes de comptage, il est préférable d'utiliser OTR.

OTR : registre de sortie indiquant la valeur de CNTR. Ce registre peut être directement lu via la liaison SPI sans perturber le comptage. Il faut tout d'abord charger CNTR dans OTR (LOAD CNTR) puis lire OTR (READ OTR).

DTR : registre d’entrée qui contient la valeur de chargement de CNTR. La valeur contenue dans DTR peut être transférée dans CNTR logiciellement ou matériellement grâce à un signal sur INDEX.

STR : registre d’information sur l'état du compteur (dépassement et état du compteur, comparaison, direction de comptage et signe de la valeur)

IR : registre interne qui permet de sélectionner le registre et les actions lors des communications SPI.

MDR0 : registre qui configure le mode de quadrature, le mode de comptage et le mode d'indexage.

MDR1 : registre qui configure la taille du compteur et l’utilisation des flags.

Communication

L'horloge SCK générée par le micro permet d'avoir une liaison synchrone entre le micro et le LS7366 utilisé en esclave. Chaque transmission est composée de trames de 1 à 5 octets de données. La longueur des trames est automatiquement ajustée en fonction de la configuration du compteur. Chaque transmission débute par le passage à 0 de la ligne SS/. Elle débute par un octet d'instruction, les octets suivants sont considérés comme des données. La transmission se termine quand SS/ repasse à 1 (ligne au repos). Les données sont reçues sur l'entrée MOSI , le MSB en premier sur un état haut d'horloge. Les données sortantes sont envoyées sur la sortie MISO, le MSB en premier, sur un état bas d'horloge SCK.

Mise en oeuvre

Nous réalisons un robot avec deux moteurs à courant continu que nous voulons asservir. Les moteurs ont chacun un codeur incrémental en quadrature (sortie A et B) et nous souhaitons également mettre deux roues codeuses indépendantes. Cela fait donc 4 codeurs à traiter. Pour cela, nous utilisons une carte ARDUINO UNO et une shield moteur ARDUINO pour le contrôle des moteurs (2 x 2A basée sur un L298). Sur le principe des shield ARDUINO, nous avons donc fait une carte avec les 4 compteurs LS7366R communiquant via la liaison SPI.

Shéma fonctionnel

Nous utilisons 4 compteur LS7366R et un oscillateur à quartz 40 MHz. Voici le schéma de la shield LS7366R.

Typon

Pour l'instant, nous avons réaliser la carte avec des composants traditionnels. Il serait interressant de la refaire avec des composants CMS pour réduire sa taille et pouvoir laisser libre les borniers de la shield moteur.

Vous pouvez télécharger le typon au format Kicad ici : counter_shield.kicad_pcb.zip

Implementation

Fonctions de base

Nous avons écrite quelques fonctions de base pour le compteur. Ces fonctions permettent de lire et d'écrire dans les registres de configuration et compteur.

/* LS7366R opcode list */
#define CLR_CNTR	0x20	/* clear CNTR register to zero */
 
#define READ_MDR0	0x48	/* read MDR0 */
#define READ_MDR1       0x50    /* read MDR1 */
#define READ_CNTR	0x60	/* transfer CNTR to OTR */
 
#define WRITE_MDR0	0x88	/* write serial data into MDR0 */
#define WRITE_MDR1	0x90	/* write serial data into MDR1 */
 
/* configuration MDRO */
#define NON_QUADRATURE  0x00    /* non-quadrature count mode */
#define X1_QUADRATURE   0x01    /* x1 quadrature count mode */
 
/* configuration MDR1 */
#define _1_BYTE	0x03	/* 1-byte counter mode */
 
 
/* remise a zero du compteur */
void
clr(char op_code)
{
  PORT_SPI |= (1 << DD_SS);
  PORT_SPI &= ~(1 << DD_SS); /* slave select */
  SPI_master_transmit(op_code);/* send command */
  PORT_SPI |= (1 << DD_SS); /* slave unselect */
}
 
/* ecriture (envoi d'une commande) */
void
write(char op_code, char data)
{
  PORT_SPI |= (1 << DD_SS);
  PORT_SPI &= ~(1 << DD_SS); /* slave select */
  SPI_master_transmit(op_code);/* send command */
  SPI_master_transmit(data);/* send command */
  PORT_SPI |= (1 << DD_SS); /* slave unselect */
}
 
/* lecture */
char
read(char op_code)
{
  char data;
  PORT_SPI |= (1 << DD_SS);
  PORT_SPI &= ~(1 << DD_SS); /* slave select */
  data = SPI_master_transmit(op_code);/* send command */
  data = SPI_master_transmit(0x00);/* start dummy transmission to read data from LS7366R */
  PORT_SPI |= (1 << DD_SS); /* slave unselect */
  return data;
}

Tests

Mode compteur

Dans un premier temps, nous avons fait un petit programme de test pour tester le mode compteur. Nous avons utilisé une ARDUINO UNO (ou duemilanove 2009) et un compteur LS7366R.
Nous générons une horloge sur la sortie PD5 (30 Hz) à mettre sur l'entrée A du compteur.
MDR0 = 0x00 non quadrature count mode (horloge sur A et direction sur B)
MDR1 = 0x03 : comptage sur 1 octet

  • test 1 : test communication avec le LS7366R. Vérifier que la valeur inscrite dans le registre MDR1 est correcte
  • test 2 : test comptage sens positif (B=1). Il faut mettre 5V sur l'entrée B du compteur.
  • test 3 : test comptage sens négatif (B=0). Il faut mettre l'entrée B du compteur à la masse.
/*
 * main.c
 *
 *  Created on: Feb 28, 2012
 *      Author: ldo
 *
 *	Arduino duemilanove 2009 ou ARDUINO UNO
 *	Atmega328P 16MHz
 */
 
#include <avr/io.h>	/* pour les definitions des registres */
#include <avr/interrupt.h> /* pour les interruptions */
#include <avr/delay.h>
 
#include "spi.h"
 
/* SPI port */
#define DDR_SPI DDRB	/* SPI on port B */
#define PORT_SPI PORTB
#define DD_SS	1	/* SS/ : PB1 */
#define DD_MOSI 3	/* MOSI : PB3 */
#define DD_MISO	4	/* MISO : PB4*/
#define DD_SCK 5	/* SCK : PB5 */
 
 
/* generation d'une horloge pour simuler l'entrée A du compteur */
void
generation_horloge(void)
{
  _delay_ms(15); /* attente 15 ms */
  PORTD ^= (1 << 5); /* inverse PD5 */
}
 
/* test communication */
void
test_communication(char data)
{
  data = read(READ_MDR1);
  if (data == _1_BYTE)
    {
      PORTD |= (1 << 4); // PD4 = 1
    }
}
 
/* test comptage sens positif (B=1) */
void
test_comptage_positif(signed char data)
{
  if (data > 100)
    {
      PORTD |= (1 << 4); // PD4 = 1
    }
  else
    {
      PORTD &= ~(1 << 4); // PD4 = 0
    }
}
 
/* test comptage sens negatif (B=0) */
void
test_comptage_negatif(signed char data)
{
  if (data < -100)
    {
      PORTD |= (1 << 4); // PD4 = 1
    }
  else
    {
      PORTD &= ~(1 << 4); // PD4 = 0
    }
}
 
void
init_port(void)
{
  /* configuration des ports : '1' pour sortie */
  DDRB = 0xFF;  /* PORTB en sortie */
  PORTB = 0x00;
  DDRD = 0xFF; /* PORTD en sortie */
  PORTD = 0x00;
}
 
void 
init(void)
{
  init_port();
  SPI_master_init();
  _delay_ms(100);
}
 
int
main(void)
{
  signed char data;
 
  init();
 
  // configuration du LS7366R
  write(WRITE_MDR0, NON_QUADRATURE);
  write(WRITE_MDR1, _1_BYTE);
  clr(CLR_CNTR);
 
  while (1)
    {
      /* lecture du compteur */
      data = read(READ_CNTR);
 
      test_communication(data);
      //test_comptage_positif(data);
      //test_comptage_negatif(data);
    }
 
  return 1;
}

Mode quadrature

Nous avons fait un petit programme pour tester le mode quadrature x1. Les sorties A et B du codeur sont reliées aux entrées A et B du compteur. Nous comptons toujours sur 1 octet.

void
test_quadrature_x1(signed char data)
{
  if (data > 0)
    {
      PORTD |= (1 << 4); // PD4 = 1
    }
  else
    {
      PORTD &= ~(1 << 4); // PD4 = 0
    }
}
 
int
main(void)
{
  signed char data;
 
  init();
 
  // configuration du LS7366R
  write(WRITE_MDR0, X1_QUADRATURE);
  write(WRITE_MDR1, _1_BYTE);
  clr(CLR_CNTR);
 
  while (1)
    {
      /* lecture du compteur */
      data = read(READ_CNTR);
 
      test_quadrature_x1(data);
    }
 
  return 1;
}
robotics/electronics/shield_arduino_ls7366r.txt · Dernière modification: 2014/10/03 14:38 par gdo