jueves, 12 de enero de 2012

Conversor AD + proyecto ARES


Hola a todos de nuevo, esta práctica que os voy a mostrar a continuación es realmente parte de una práctica anterior, se trata de crear un conversor AD, así como cuando hicimos el LCD gráfico, sin embargo esta vez tengo que diseñar la placa, mediante el soporte que nos deja proteus llamado “ARES”.

Lo que haremos será, mediante el PIC18F4550 (tenéis su datasheet en la biblioteca) conectar un conversor AD, concretamente el MCP3204 (también en biblioteca)  mediante el SPI.
Para el control del MCP3204 haremos como con los LCD, utilizaremos una Librería ya creada, la cual os adjunto aquí, también vamos a usar un LCD alfanumérico, así que también os adjunto la librería de éste:

Librería del MCP3204:


////////////////// Driver for MCP3204 A/D Converter ////////////////////////
////                                                                     ////
////  adc_init()                                                          ////
////      Call after power up                                             ////
////                                                                       ////
////  value = read_analog_mcp( channel, mode )                             ////
////      Read an analog channel                                            ////
////      0 through 3 and select                                          ////
////      differential (0) or                                             ////
////      single (1) mode                                                  ////
////                                                                       ////
////  value = read_analog( channel )                                      ////
////      Read an analog channel                                           ////
////      0 through 7 in   single mode                                        ////
////                                                                       ////
////  convert_to_volts( value,  string )                                 ////
////      Fills in string with                                             ////
////      the true voltage in                                             ////
////      the form 0.000                                                   ////
////                                                                      ////
////////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2003 Custom Computer Services            ////
//// This source code may only be used by licensed users of the CCS C   ////
//// compiler.  This source code may only be distributed to other       ////
//// licensed users of the CCS C compiler.  No other use, reproduction  ////
//// or distribution is permitted without written permission.           ////
//// Derivative programs created using this software in object code     ////
//// form are not restricted in any way.                                ////
////////////////////////////////////////////////////////////////////////////

#ifndef MCP3204_CS
#define MCP3204_CLK  PIN_B1
#define MCP3204_DOUT PIN_C7
#define MCP3204_DIN  PIN_B0
#define MCP3204_CS   PIN_A0
#endif

void adc_init() {
   output_high(MCP3204_CS);
}

void write_adc_byte(BYTE data_byte, BYTE number_of_bits) {
   BYTE i;

   delay_us(2);
   for(i=0; i
      output_low(MCP3204_CLK);
      if((data_byte & 1)==0)
         output_low(MCP3204_DIN);
      else
         output_high(MCP3204_DIN);
      data_byte=data_byte>>1;
      delay_us(50);
      output_high(MCP3204_CLK);
      delay_us(50);
   }
}

BYTE read_adc_byte(BYTE number_of_bits) {
   BYTE i,data;

   data=0;
   for(i=0;i
      output_low(MCP3204_CLK);
      delay_us(50);
      shift_left(&data,1,input(MCP3204_DOUT));
      output_high(MCP3204_CLK);
      delay_us(50);
   }
   return(data);
}

long int read_analog_mcp(BYTE channel, BYTE mode) {
   int l;
   long int h;
   BYTE ctrl_bits;

   delay_us(200);

   if(mode!=0)
      mode=1;

   output_low(MCP3204_CLK);
   output_high(MCP3204_DIN);
   output_low(MCP3204_CS);

   if(channel==1)               // Change so MSB of channel #
      ctrl_bits=4;            //      is in LSB place
   else if(channel==3)
      ctrl_bits=6;
   else if(channel==4)
      ctrl_bits=1;
   else if(channel==6)
      ctrl_bits=3;
   else
      ctrl_bits=channel;

   ctrl_bits=ctrl_bits<<1;

   if(mode==1)                  // In single mode
      ctrl_bits |= 1;
   else                        // In differential mode
      ctrl_bits &= 0xfe;

   ctrl_bits=ctrl_bits<<1;      // Shift so LSB is start bit
   ctrl_bits |= 1;

   write_adc_byte( ctrl_bits, 7);   // Send the control bits

   h=read_adc_byte(4);
   l=read_adc_byte(8);

   output_high(MCP3204_CS);

   return((h<<8)|l);
}

long int read_analog( BYTE channel )   // Auto specifies single mode
{
   long int temp;

   if(channel<4)
      temp=read_analog_mcp( channel, 1);
   else
      temp=0;

   return temp;
}

void convert_to_volts( long int data, char volts[6]) {
   BYTE i, d, div_h, div_l;
   long int temp,div;
  
   div=4095/5.00;

   if(data>=4090)
      data=4095;

   for(i=0;i<=4;i++) {
     temp=data/div;
  
     volts[i]=(BYTE)temp+'0';

     if(i==0) {
       volts[1]='.';
       i++;
     }
     temp=div*(BYTE)temp;
     data=data-temp;
     div=div/10;
   }
   volts[i]='\0';
}





Seguidamente la librería para el control del LCD:







// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver.  Change these
// pins to fit your own board.

#define LCD_DB4   PIN_D4
#define LCD_DB5   PIN_D5
#define LCD_DB6   PIN_D6
#define LCD_DB7   PIN_D7
//
#define LCD_RS    PIN_D0
#define LCD_RW    PIN_D1
#define LCD_E     PIN_D2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW   1

//========================================

#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
 0xc,                    // Display on
 1,                      // Clear display
 6                       // Increment cursor
 };


//-------------------------------------
void lcd_send_nibble(int8 nibble)
{

// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));
 output_bit(LCD_DB7, !!(nibble & 8));

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;

output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);

output_low(LCD_E);

return(retval);
}
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);

 delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);

    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 60 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_LCD_RW
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
   address = lcd_line_two;
else
   address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      delay_ms(2);
      break;

    case '\n':
       lcd_gotoxy(1,2);
       break;

    case '\b':
       lcd_send_byte(0,0x10);
       break;

    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif

void lcd_setcursor_vb(short visible, short blink) {
  lcd_send_byte(0, 0xC|(visible<<1)|blink);
}



Este sería el programa principal



////////////////////////////////////////////////////////////////////////////////////
//   AUTOR: GABI                                     ENERO/2012


////////////////////////////////////////////////////////////////////////////////////

//   PROGRAMA:    Conversor AD CON MCP3204      VERSIÓN:    1.0
//   DISPOSITIVO: PIC 18F4550                           COMPILADOR:    CCSC
//   Entorno IDE: MPLAB                                 SIMULADOR:    Proteus 7
//   TARJETA DE APLICACIÓN: ___                         DEBUGGER:    ICD3

/////////////////////////////////////////////////////////////////////////////////                          
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//      
//      
// CREAR UN Conversor ad, mediante una conexión con MCP3204 y proyecto en ares. ///////
//      
//////////////////////////////////////////////////////////////////////////////////

#include
#fuses INTHS                 //oscilador interno
//#FUSES HS                   //no usamos oscilador externo
#FUSES MCLR                   //Master clear activado
#use delay(internal=4000000hz)   // Selecciona la velocidad del oscilador interno


#include    //otras librerías de LCD no me funcionaron.
#include


////////////////////////////////////////////////////////////////////////////////////
// VARIABLES GLOBALES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

float voltios;

char cad[6];

float  val;




////////////////////////////////////////////////////////////////////////////////////
// PRINCIPAL ///////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////







void main()

{

lcd_init();  //iniciamos el LCD y el cAD
adc_init();
for(;;)
{

val=read_analog(0);  //lectura del AD
DELAY_MS(50);
lcd_gotoxy(1,1); //centramos el LCD
convert_to_volts( val,cad );  //hacemos la conver
printf(lcd_putc," %s   Voltios",string);
lcd_gotoxy(1,2);
printf(lcd_putc,"Gabi");
DELAY_MS(150);

}

}



Como ya os dije al principio, la cosa no acaba aquí, ahora es el momento de crear una "maqueta 3D", mediante el soporte de ARES. Para eso primero tenemos que realizar un proyecto en isis que debe contener lo siguiente



Una vez tengamos todos estos componentes bien colocados, será el momento de pasar al ARES, para eso tendremos que ir a la aprte superior del soporte, en la ventana que os adjunto aquí.




Entonces nos tendrá que salir un entorno como este.



Es la primera vez que uso ARES, parece un soporte bastante más sencillo que el Layout de capturo, de hecho se parece bastante. Precisamente por eso voy a procurar “resumir” todo en los pasos más importantes.
Una vez entremos en el entorno, empezaremos por colocar el borde de nuestro proyecto. Es muy sencillo, solo tenemos que irnos a “2d graphics box mod” en la parte izquierda, como os muestro en la imagen.






Importante, teneis que tener en cuente en qué capa estáis trabajando, nosotros necesitamos hacerlo en “board edge”, para seleccionarla tenemos que, tras haber dado al 2d graphics, abajo a la izquierda nos saldrá una ventana con las capas. Necesitamos seleccionar “board edge” que está en amarillo.
Tras esto trazaremos nuestro borde.










El segundo paso será coger los componentes, esto es igual que con el proteus, primero vamos a la parte izquierda en la barra de herramientas y pulsamos éste botón.





Entonces nos irá pidiendo el nombre del componente, y sus encapsulados, recordad que tendréis que haberlos metido antes de pasar al ares, desde proteus. Sino no os saldrán.




Este sería un boceto de la colocación de los componentes.
Ahora vamos a una de las cuestiones más importantes, las medidas de las nets y los drills, esto que nos dio grandes quebraderos de cabeza en layout. Aunque he de decir que en ARES está todo más concurrido y bastante más claro, resulta más “casual” por decirlo de alguna manera.

Para eso tenemos que irnos a la función de la barra superior de herramientas que dice “design rule manager”. Que os muestro a continuación.




Nos saldrá una ventana como esta.


Por consejo de mis amigos lo he dejado tal y como está, al parecer  “T40” significa una broca de 1mm.
Y por otro lado, es importante saber que vamos a utilizar dos capas, la top (superior) y la bottton( inferior), podemos elegir el color de cada una etc. Una vez terminado esto, le daremos a OK y ya estaremos listos para comenzar a rutar.
Como pasaba con el Layout, existían 2 maneras de hacer los ruteos, por un lado de manera automática y por el otro de manera manual, cada uno tiene sus desventajas y ventajas, nosotros vamos a optar por la automática, ya que no queremos hacer un proyecto final, sino una práctica. Para eso nos vamos a la parte superior de la barra de herramientas y le damos a “Auto – router”.

Este sería el trabajo finalizado.



Aquí su simulación en proteus:




Ya para ultimar el proyecto es importante añadir un plano de masa, es muy sencillo, tan solo tenemos que irnos a “tools/ power plane Generator”, seleccionamos el color y demás y ya la tenemos colocada.

Ares también tiene una función de 3D, para eso solo tenemos que ir a “output/ 3d visualization”, y ahí nos aparecería nuestro layout en 3 dimensiones, podemos mover la cámara con el ratón, y hacer zoom con la rueda. Aquí os pongo un vídeo para que lo veais mejor.



Espero que os haya gustado esta entrada, un saludo y nos vemos!



DESCARGAR PROYECTO AQUÍ







No hay comentarios:

Publicar un comentario en la entrada