Cette page vous affiche les différences entre la révision choisie et la version actuelle de la page.
robotics:electronics:shield_arduino_ls7366r [2012/05/23 18:07] ldo [Mise en oeuvre] |
robotics:electronics:shield_arduino_ls7366r [2014/10/03 14:38] (Version actuelle) gdo [Typon] |
||
---|---|---|---|
Ligne 61: | Ligne 61: | ||
{{:robotics:electronics:typon.jpg|}} | {{:robotics:electronics:typon.jpg|}} | ||
- | ====== Test ====== | ||
- | Dans un premier temps, nous avons fait un petit programme de test pour communiquer avec le compteur. Nous avons utilisé une Arduino uno (ou duemilanove 2009) et un compteur LS7366R. | ||
- | Nous générons une horloge sur la sortie PD3 (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 LS7366 | + | Vous pouvez télécharger le typon au format Kicad ici : {{:robotics:electronics:counter_shield.kicad_pcb.zip|}} |
- | vérifier que la valeur inscrite dans le registre MDR0 est correcte | + | ====== Implementation ====== |
- | test 2 : test comptage sens positif (B=1) | + | ===== Fonctions de base ===== |
- | Il faut mettre 5V sur l'entrée B du compteur. | + | 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. |
+ | <code c> | ||
+ | |||
+ | /* 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; | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ===== 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 3 : test comptage sens negatif (B=0) | + | * test 1 : test communication avec le LS7366R. Vérifier que la valeur inscrite dans le registre MDR1 est correcte |
- | Il faut mettre l'entrée B du compteur à la masse. | + | * 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. | ||
- | <code> | + | <code c> |
/* | /* | ||
* main.c | * main.c | ||
Ligne 82: | Ligne 140: | ||
* Author: ldo | * Author: ldo | ||
* | * | ||
- | * Arduino duemilanove 2009 | + | * Arduino duemilanove 2009 ou ARDUINO UNO |
* Atmega328P 16MHz | * Atmega328P 16MHz | ||
*/ | */ | ||
- | #include<avr/io.h> /* pour les definitions des registres */ | + | #include <avr/io.h> /* pour les definitions des registres */ |
#include <avr/interrupt.h> /* pour les interruptions */ | #include <avr/interrupt.h> /* pour les interruptions */ | ||
+ | #include <avr/delay.h> | ||
+ | |||
+ | #include "spi.h" | ||
/* SPI port */ | /* SPI port */ | ||
- | #define DDR_SPI DDRB /* SPI port B */ | + | #define DDR_SPI DDRB /* SPI on port B */ |
#define PORT_SPI PORTB | #define PORT_SPI PORTB | ||
- | #define DD_SS 2 /* SS/ : PB2 */ | + | #define DD_SS 1 /* SS/ : PB1 */ |
#define DD_MOSI 3 /* MOSI : PB3 */ | #define DD_MOSI 3 /* MOSI : PB3 */ | ||
#define DD_MISO 4 /* MISO : PB4*/ | #define DD_MISO 4 /* MISO : PB4*/ | ||
#define DD_SCK 5 /* SCK : PB5 */ | #define DD_SCK 5 /* SCK : PB5 */ | ||
- | /* LS7366R opcode list */ | ||
- | #define CLR_CNTR 0x20 /* clear CNTR register to zero */ | ||
- | #define READ_MDR0 0x48 /* read MDR0 */ | + | /* generation d'une horloge pour simuler l'entrée A du compteur */ |
- | //#define READ_MDR1 | + | void |
- | #define READ_CNTR 0x60 /* transfer CNTR to OTR */ | + | generation_horloge(void) |
- | //#define READ_OTR 0x68 | + | |
- | + | ||
- | #define WRITE_MDR0 0x88 /* write serial data into MDR0 */ | + | |
- | #define WRITE_MDR1 0x90 /* write serial data into MDR1 */ | + | |
- | + | ||
- | //#define LOAD_OTR 0xE4 /* load CNTR to OTR in "parallel" */ | + | |
- | + | ||
- | #define CONF_MDR0 0x00 /* non-quadrature count mode */ | + | |
- | #define CONF_MDR1 0x03 /* 1-byte counter mode */ | + | |
- | + | ||
- | void initPort(void) | + | |
{ | { | ||
- | /* configuration des ports : '1' pour sortie */ | + | _delay_ms(15); /* attente 15 ms */ |
- | DDRD = 0b11111111; /* PORTD en sortie */ | + | PORTD ^= (1 << 5); /* inverse PD5 */ |
} | } | ||
- | void SPI_MasterInit(void) | + | /* test communication */ |
+ | void | ||
+ | test_communication(char data) | ||
{ | { | ||
- | DDR_SPI = (1 << DD_MOSI) | (1 << DD_SCK) | (1 << DD_SS); /* set MOSI, SCK and SS/ output */ | + | data = read(READ_MDR1); |
- | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); /* Enable SPI, Master, set clock rate fck/16 */ | + | if (data == _1_BYTE) |
+ | { | ||
+ | PORTD |= (1 << 4); // PD4 = 1 | ||
+ | } | ||
} | } | ||
- | char SPI_MasterTransmit(char data) | + | /* test comptage sens positif (B=1) */ |
+ | void | ||
+ | test_comptage_positif(signed char data) | ||
{ | { | ||
- | SPDR = data; /* load byte to data register */ | + | if (data > 100) |
- | while (!(SPSR & (1 << SPIF))) | + | { |
- | ; /* wait for transmission complete */ | + | PORTD |= (1 << 4); // PD4 = 1 |
- | data = SPDR; /* load received byte */ | + | } |
- | return data; | + | else |
+ | { | ||
+ | PORTD &= ~(1 << 4); // PD4 = 0 | ||
+ | } | ||
} | } | ||
- | void clr(char op_code) | + | /* test comptage sens negatif (B=0) */ |
+ | void | ||
+ | test_comptage_negatif(signed char data) | ||
{ | { | ||
- | PORT_SPI |= (1 << DD_SS); | + | if (data < -100) |
- | PORT_SPI &= ~(1 << DD_SS); /* slave select */ | + | { |
- | SPI_MasterTransmit(op_code);/* send command */ | + | PORTD |= (1 << 4); // PD4 = 1 |
- | PORT_SPI |= (1 << DD_SS); /* slave unselect */ | + | } |
+ | else | ||
+ | { | ||
+ | PORTD &= ~(1 << 4); // PD4 = 0 | ||
+ | } | ||
} | } | ||
- | void write(char op_code, char data) | + | void |
+ | init_port(void) | ||
{ | { | ||
- | PORT_SPI |= (1 << DD_SS); | + | /* configuration des ports : '1' pour sortie */ |
- | PORT_SPI &= ~(1 << DD_SS); /* slave select */ | + | DDRB = 0xFF; /* PORTB en sortie */ |
- | SPI_MasterTransmit(op_code);/* send command */ | + | PORTB = 0x00; |
- | SPI_MasterTransmit(data);/* send command */ | + | DDRD = 0xFF; /* PORTD en sortie */ |
- | PORT_SPI |= (1 << DD_SS); /* slave unselect */ | + | PORTD = 0x00; |
} | } | ||
- | char read(char op_code) | + | void |
+ | init(void) | ||
{ | { | ||
- | char data; | + | init_port(); |
- | PORT_SPI |= (1 << DD_SS); | + | SPI_master_init(); |
- | PORT_SPI &= ~(1 << DD_SS); /* slave select */ | + | _delay_ms(100); |
- | data = SPI_MasterTransmit(op_code);/* send command */ | + | |
- | data = SPI_MasterTransmit(0x00);/* start dummy transmission to read data from LS7366R */ | + | |
- | PORT_SPI |= (1 << DD_SS); /* slave unselect */ | + | |
- | return data; | + | |
} | } | ||
- | void attente(void) | + | int |
+ | main(void) | ||
{ | { | ||
- | unsigned int i = 0; | + | signed char data; |
- | while (i < 48000) | + | init(); |
- | { | + | |
- | asm("nop"); | + | |
- | i++; | + | |
- | } | + | |
- | } | + | |
- | int main(void) | + | // configuration du LS7366R |
- | { | + | write(WRITE_MDR0, NON_QUADRATURE); |
- | char data; | + | write(WRITE_MDR1, _1_BYTE); |
+ | clr(CLR_CNTR); | ||
- | initPort(); | + | while (1) |
- | PORTD = 0x00; | + | { |
+ | /* lecture du compteur */ | ||
+ | data = read(READ_CNTR); | ||
- | SPI_MasterInit(); | + | test_communication(data); |
+ | //test_comptage_positif(data); | ||
+ | //test_comptage_negatif(data); | ||
+ | } | ||
- | /* configuration du LS7366R */ | + | return 1; |
- | write(WRITE_MDR0, CONF_MDR0); | + | } |
- | write(WRITE_MDR1, CONF_MDR1); | + | </code> |
- | clr(CLR_CNTR); | + | |
- | while (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. |
- | /* generation d'une horloge pour simuler l'entrée A du compteur */ | + | |
- | attente(); /* attente 15 ms */ | + | |
- | PORTD ^= (1 << 3); /* inverse PD3 */ | + | |
- | /* lecture du compteur */ | + | <code c> |
- | data = read(READ_CNTR); | + | void |
+ | test_quadrature_x1(signed char data) | ||
+ | { | ||
+ | if (data > 0) | ||
+ | { | ||
+ | PORTD |= (1 << 4); // PD4 = 1 | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | PORTD &= ~(1 << 4); // PD4 = 0 | ||
+ | } | ||
+ | } | ||
- | /* test communication */ | + | int |
- | /*data = read(READ_MDR0); | + | main(void) |
- | if (data == CONF_MDR0) | + | { |
- | { | + | signed char data; |
- | PORTD = 0xFF; | + | |
- | }*/ | + | |
- | /* test comptage sens positif (B=1) */ | + | init(); |
- | if (data < 50) | + | |
- | { | + | |
- | PORTD |= (1 << 2); /* PD2 = 1 */ | + | |
- | } | + | |
- | else | + | |
- | { | + | |
- | PORTD &= ~(1 << 2); /* PD2 = 0 */ | + | |
- | if (data > 100) | + | // configuration du LS7366R |
- | { | + | write(WRITE_MDR0, X1_QUADRATURE); |
- | clr(CLR_CNTR); | + | write(WRITE_MDR1, _1_BYTE); |
- | } | + | clr(CLR_CNTR); |
- | } | + | |
- | /* test comptage sens negatif (B=0) */ | + | while (1) |
- | /* if (data > -50) | + | { |
- | { | + | /* lecture du compteur */ |
- | PORTD=0xFF; | + | data = read(READ_CNTR); |
- | } | + | |
- | else | + | |
- | { | + | |
- | PORTD=0x00; | + | |
- | if (data<-100) | + | |
- | { | + | |
- | clr(CLR_CNTR); | + | |
- | } | + | |
- | }*/ | + | |
- | } | + | |
- | return 1; | + | test_quadrature_x1(data); |
+ | } | ||
+ | |||
+ | return 1; | ||
} | } | ||
+ | |||
</code> | </code> |