Diseño Brujula 3 ejes

Tema en 'R/C ELECTRÓNICA' iniciado por niuton, 20 Ene 2010.

  1. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Hola a todos pues en este hilo vamos poniendo los avances del desarrollo de la brújula con los sensores MEMSIC.

    yo tengo hecho el prototipo en PCB y SCH así que lo adjunto aquí por si os sirven.

    Adjunto un archivo RAR con los esquemas y el pcb para que se vaya haciendo jejeje, si alguien hace algo más pues que lo vaya poniendo y entre todos hacemos funcionar este bichito .

    Como no puedo subir el archivo .RAR con el SCH y PCB completo y listo para transferir a la placa, les pongo el link: PCB Y SCH.

    En esta pagina aparece como hacer las placas por el método de la plancha. yo la he hecho así y me a dado muy buen resultado, con papel satinado de 150gr y la plancha a un poco menos del maximo, se imprime en impresora laser el PCB y se coloca en la placa, luego se pone encima la plancha y a presionar al mismo tiempo que se desplaza la plancha por toda la superficie, eso durante 5min. Se prepara en un plato con agua caliente se mete la placa esperando a que se empape y con la ayuda de la yema de los dedos se va quitando el papel. al final los restos que queden se utiliza un cepillo de dientes y listo. Por ultimo se mete en el ácido y placa hecha.
     

    Adjuntos:

    • SCH.JPG
      SCH.JPG
      Tamaño de archivo:
      16 KB
      Visitas:
      250
    • PCB.JPG
      PCB.JPG
      Tamaño de archivo:
      19,4 KB
      Visitas:
      162
    #1 niuton, 20 Ene 2010
    Última edición: 22 Ene 2010
  2. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Bueno ya he soldado el magnetómetro a la placa, pero me faltan los condensadores que no los consigo por ningún sitio. los de 1uF y 10uF no polarizados.

    En cuanto los consiga podré conectarlo al PIC y sacar información.

    os dejo unas fotos con las soldaduras, no costó mucho soldarlo y he comprobado si existen cortocircuitos y no hay. Sólo falta qeu funcione :wink2::

    BYE
     

    Adjuntos:

  3. acristóbal Gurú FPV

    acristóbal
    Registrado:
    9 Oct 2006
    Mensajes:
    3.710
    Me Gusta recibidos:
    0
    Hola niuton, me parece interesante tu proyecto por lo barato que sale y lo que se podría conseguir.

    Querría saber que datos puedes conseguir de este sensor:
    Esta claro que la dirección en el plano horizontal la puedes conseguir ya que es como unabrújula normal, pero los ángulos verticales (si lo colocásemos en un avión o heli, el ángulo de cabeceo y el ángulo de alabeo) se pueden conseguir??
    Estos datos estarían libres de variaciones por efectos de aceleraciones y movimientos.

    Si eso se consiguiera, se podría sustituir la cabeza sensora del copilot y atener además el dato del heading (no se como se llama en español) que es diferente del rumbo.

    Suerte con el proyecto.
     
  4. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Hola acristobal,

    No es decir que entienda mucho, pero creo que solo sería posible la dirección en el plano eso es lo que pretendo conseguir.
    Para conseguir la inclinación sería necesario un acelerómetro, pero eso sería poco robusto ya que solo funcionaría bien en estacionario, en el momento que existiese fuerzas de aceleraciones ya no serían fiable los datos. para solucionar esto sería necesario incluir además giróscopos, pero este sensor tiene el inconveniente de una deriva. como solución global para obtener el PITCH y ROLL sería necesario fusionar los datos del acelerometro y giróscopo mediante alguna técnica como filtro de Kalman y los datos obtenidos serían fiables. ufff terminé :rolleyes:.

    ¿que permite la cabeza sensora del Copit?, ¿qué es el heading?

    un saludo y gracias.
     
  5. acristóbal Gurú FPV

    acristóbal
    Registrado:
    9 Oct 2006
    Mensajes:
    3.710
    Me Gusta recibidos:
    0
    Ok, que pena.

    El Heading es la dirección a la que apunta el morro del avión.
    La cabeza sensora del copilot es un dispositivo con 4 sensores de radiación infrarroja (temperatura) para determinar el horizonte en dirección de cabeceo y de alabeo, con este dispositivo el avión es capaz de mantenerse horizontal por si solo.
     
  6. Ariel Miembro Activo

    Ariel
    Registrado:
    29 May 2009
    Mensajes:
    1.841
    Me Gusta recibidos:
    0
    Bueno , prueba numero 1 superada. soldar el chip de memsic , que mas pequeño no puede ser , y para rematar las soldaduras no quedan a la vista.

    Al fin le encontré una función a la plancha de casa jejejej

    pues me a quedado perfecto , ya que no hay continuidad entre ninguno de los pines y me dan una medida de resistencias distintas todos los pines con respecto a masa, o sea que todos están haciendo contacto correctamente.
    Ver el archivo adjunto 11854



    Como va el tema de los condensadores esos? has probado poner unos de tantalio o unos cerámicos normales? supongo que solo disminuirá la precisión de la lectura, aunque en el pdf dice que los utiliza para realizar el SET/RESET del sensor.

    Adjunto el pdf correcto para este encapsulado , por que el que puse en el post del pedido es para otro tipo.
    Ver el archivo adjunto 11855

    Ahora el tema de la alimentación , segun entiendo en el pdf , se pueden alimentar ambos pines (Vdd y Vda ) con 1,8v hasta 5,25V . por que no alimentarlos con 5v a ambos uniendo los pies?

    lo que me confunde es que incluso en el esquema propuesto salen separado.
    Ver el archivo adjunto 11856

    Bueno , voy a ir preparando un pic en una placa para conectarlo y empezar a hacer alguna rutinita para sacarle los datos.
    ¿que pic usas tu niutron? lo pregunto por que tengo muchos y por usar el mismo y compartir códigos.
    Yo programo en C18, aunque no soy un experto , por que lo mio era el ensamblador, no me terminaba de convencer el C hasta que me toco hacer unos senos y cosenos jejejej.

    Bueno , no me enrollo mas , Saludos
    Ariel
     
  7. jlezana Miembro Activo

    jlezana
    Registrado:
    29 Sep 2008
    Mensajes:
    1.114
    Me Gusta recibidos:
    0
    pero como has soldado eso... jejej

    Interesante proyecto..

    Saludos
    J. Lezana
     
  8. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Buenoo!!!!!:icon_eek: que buena pinta tiene eso Ariel. amí me dan mucho miedo este tipo de encapsulado por que nunca se si están bien soldados :locos: y luego te vuelves loco jejeje.

    bueno yo ya tengo soldado todos los componentes y los condensadores lo que pasa que no he podido poner las fotos y la verdad que he estado liado con la lectura de un ADC por I2C que me tiene amargado :sad: y no le he dedicado tiempo a la brujula.

    Yo tengo el 18F452 a 20MHz en una placa que es el que utilizo para probar y uso el CCS C, uso este por que tiene muchas de las funciones de comunicación implementadas. Si todo va bien este finde probaré la placa con el PIC a ver si realizo la comunicación I2C.

    El tema de los condensadores he conseguido los de tantalo, y en la alimentación yo he diferenciado 5v para I2C y 3.3v para circuito, por que disponía de las dos pero se pueden colocar las dos directas a 5v sin problemas.

    El tema de compartir código sin problemas los mejores proyectos salen en equipo jejeje :biggrin:.

    Un circuito que necesito realizar para evitar problemas que tengo como es el caso del puerto I2C voy a realizar un analizador lógico para I2C que estube buscando y he encontrado uno muy fácil de hacer y creo que es útil, aunque no tenga mucho que ver con la brújula pero por si sirve :rolleyes2:.

    http://www.f6fbb.org/LogicAnalyzer/index.html

    Bueno pues esto es toda la informació que tengo hasta ahora ariel a ver si esto sigue por buen camino jejejeej, ya me cuentas.

    BYE
     
  9. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Necesito ayuda, al final voy a odiar el protocolo I2C.

    Bueno cuento lo que pasa: he conectado el magnetometro mediante I2C al 18F452 con dos resistencias de pull up de 4k7. He hecho una rutina facil solo para saber que el chip responde con un ACK, pero cual es mi frustración que no hace nada, me explico.

    Insertar CODE, HTML o PHP:
    #include <18F452.h>
    #fuses HS, NOWDT, NOPROTECT, NOLVP
    #use delay(clock = 20000000)
    
    #use rs232(baud = 19200, xmit = PIN_C6, rcv = PIN_C7)
    
    #use I2C(MASTER, SDA = PIN_C4, SCL = PIN_C3, FAST, FORCE_HW) 
    
    void main(void) {
       int8 rack=0;
    while(true){
       i2c_start();            // si se recibe acknowledged,
       rack = i2c_write(address);  // el dispositivo esta preparado.
       i2c_stop();
       
       printf("\r\nACK = %u", rack);
       delay_ms(300)
    }   
       return rack;
    }
    Si no me equivoco en CCS C cuando se recibe un ACK el valor devuelto es 0, pero yo siempre recibo el 1. otra cosa es que se quedaba muchas veces como pillado el micro y cuando quito los cables del I2c que conecta al chip se desbloquea. Como no entendía por que pasa esto me puse a hacer medidas con el polimetro en las señales SCL y SDA y miden 5v y la otra 3v ¿eso es así o debería ser 5v y 5v?.

    Llevo todo el fin de semana con esto, haber si sabéis qué solución o que está pasando.

    Bye
     
  10. Ariel Miembro Activo

    Ariel
    Registrado:
    29 May 2009
    Mensajes:
    1.841
    Me Gusta recibidos:
    0
    Hola niuton.

    el I2C tiene que estar siempre en 1 (+5V) ambas señales. asi que si tienes 3V es por que alguno esta tirando hacia abajo y el contrario hacia arriba,.

    no se si me explico.

    si el CLK del pic esta a cero y el CLK del MMS a uno , al final se queda en 3.
    quita las resistencias y asegurate de que los 4 pines (2 del pic y 2 del mms) esten en treestate , osea que ni uno ni cero ,en alta impedancia.

    cuando un dispositivo I2c maestro crea un pulso de start , en ese mismo momento cambia de alta impedancia a cero durante un tiempo que no recuerdo pero creo qeu 8 veces el clock y al terminar ese pulso negativo se vuelve a colocar en alta impedancia para que el pulso negativo del esclavo (ASK) no se vea interferido por el.

    por otro lado lei que 4k7 es para distancias de 10 pulgadas y para menos lo correcto es 10K.

    ahora me toca a mi . el CCS se lo puedo poner al MPLAB como tengo el C18? me le puedes pasar? por que veo que es prácticamente igual y como es mas popular al final es mas fácil encontrar ejemplos y códigos por la red que con el C18.

    Yo aun no he preparado el placa para hacer pruebas, pero le tengo casi lista, me falta encontrar tiempo nada mas.

    un saludo y suerte con el I2c, y agradece que no es el protocolo 1wire, que ese si me dio un buen dolor de cabeza en asembler :blink:
     
  11. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Bueno ariel, pues sigo con malas noticias :frown: hoy he realizado algunos cambios en la placa como cambiar las resistencas a 10K y l alimentación del sensor a 5v las dos señales VDD y VDA que yo tenia una a 3v3 y otra a 5v.

    Con estos cambios he conseguido que al inicializar el micro en el puerto I2C las dos señales tenga una tensión de 5v y encuanto se manda una señal de escritura i2c_write(0x60) el PIC se queda bloqueado a la espera del ack del sensor que nunca llega. En ese caso cuando que está bloqueado vuelvo a medir las señales SCL y SDA marcando una tension de 2.9v y 2v respectivamente.

    como se puede conocer si esta en alta impedancia una patilla del pic ¿con el polimetro?.

    bueno pues no se de que puede ser. He probado con todas las direcciones y el resultado es el mismo.

    bye
     
  12. Ariel Miembro Activo

    Ariel
    Registrado:
    29 May 2009
    Mensajes:
    1.841
    Me Gusta recibidos:
    0
    Hola Niuton , ten paciencia que seguro que al final es alguna tontería.

    si los voltajes esos slos estas midiendo con el polímetro y no con un osciloscopio , puede que estén pasando dos cosas:
    que lo que estas midiendo es un voltaje continuo o que es estas midiendo pulsos de 5 voltios , lo cual te dara en el polimetro un voltage intermedio.

    si el pic y el sensor están en tristate ambos , te tendría que medir 5v ya que las resistencias de pullup subirían el voltaje y lo demás es como si no estuviera.

    si quieres medir independientemente un pin para saber si esta en tristate con el polímetro , utiliza una R de 10k por ejemplo conectada al pin y el otro extremo lo conmutas entre 0 y 5v mientras mides el pin con el polímetro el cual te tiene que medir lo mismo (0 y 5v), como si no estuviera conectado a nada,simplemente eso.

    un saludo y ánimo.

    PD , estoy terminando un diseño que me han encargado y cando termine me pongo con el sensor.
     
  13. Ariel Miembro Activo

    Ariel
    Registrado:
    29 May 2009
    Mensajes:
    1.841
    Me Gusta recibidos:
    0
    Bueno , ya eh logrado que el sensor me de su señal de acknowledge.

    pero hay una cosa que no me queda claro en la forma de leer y escribir los datos ya que el pdf no trae un simple grafico de la cadena i2c y el texto me confunde un poco.

    Insertar CODE, HTML o PHP:
    EXAMPLE OF TAKE MEASUREMENT
    First cycle: START followed by a calling to slave
    address [0110xx0] to WRITE (8th SCL, SDA keep low).
    [xx] is determined by factory programming, total 4
    different addresses are available.
    Second cycle: After a acknowledge signal is received
    by master device (MEMSIC device pulls SDA line low
    during 9th SCL pulse), master device sends
    “[00000000]” as the target address to be written into.
    MEMSIC device should acknowledge at the end (9th
    SCL pulse). Note: since MEMSIC device has only one
    internal register that can be written into, so user
    should always use “[00000000]” as the write address.
    Third cycle: Master device writes to internal MEMSIC
    device memory the code “[00000001]” as a wake-up
    call to initiate a data acquisition. MEMSIC device
    should send acknowledge.
    A STOP command indicates the end of write
    operation.
    A minimal 5ms wait period should be given to
    MEMSIC device to finish a data acquisition and return
    a valid output. The TM bit (Take Measurement bit in
    control register) will be automatically reset to “0” after
    data from A/D converter is ready. The transition from
    “1” to “0” of TM bit also indicates “data ready”. The
    device will go into sleep mode afterwards. Analog
    circuit will be powered off, but I2C portion will continue
    be active and data will not be lost.
    Fourth cycle: Master device sends a START
    command followed by calling MEMSIC device address
    with a WRITE (8th SCL, SDA keep low). A
    acknowledge should be send by MEMSIC device at
    the end.
    Fifth cycle: Master device writes to MEMSIC device a
    “[00000000]” as the starting address to read from
    which internal memory. Since “[00000000]” is the
    address of internal control register, reading from this
    address can serve as a verification operation to
    confirm the write command has been successful. Note:
    the starting address in principle can be any of the 5
    addresses. For example, user can start read from
    address [0000001], which is X channel MSB.
    Sixth cycle: Master device calls MEMSIC device
    address with a READ (8th SCL cycle SDA line high).
    MEMSIC device should acknowledge at the end.
    Seventh cycle: Master device cycles SCL line, first
    addressed memory data appears on SDA line. If in
    step 7, “[00000000]” was sent, internal control register
    data should appear (in the following steps, this case is
    assumed). Master device should send acknowledge at
    the end.
    Eighth cycle: Master device continues to cycle the
    SCL line, next byte of internal memory should appear
    on SDA line (MSB of X channel). The internal memory
    address pointer automatically moves to the next byte.
    Master acknowledges.
    Ninth cycle: LSB of X channel.
    Tenth cycle: MSB of Y channel.
    Eleventh cycle: LSB of Y channel.
    Twelfth cycle: MSB of Z channel.
    Thirteenth cycle: LSB of Z channel.
    Master ends communications by NOT sending
    ‘Acknowledge’ and also followed by a ‘STOP’
    command.
    No me queda claro si hay que enviar la cadena siguiente:

    1- [start][7bit de direccion del sensor][0 write o 1 read][ack][byte direccion][ack][byte dato][stop]

    o en dos pasos de esta forma:

    1- [start][7bit de direccion del sensor][0 write o 1 read][ack][byte direccion][ack][stop]
    2- [start][7bit de direccion del sensor][0 write o 1 read][ack][byte dato][ack][stop]

    De momento ya me responde el sensor a la primer cadena ( [start][7bit de direccion del sensor][0 write o 1 read][ack] ) en la que le identifico con su direccion.
    Me ha costado un poco por que el pic es el 18f1330 de solo 18 pines y le tengo conectado a un LCd , un sensor de temperatura y a una entrada analógica y ya no me quedan pines jejeje , sumado que uno de los puertos no me leía el dato y he tenido que usarlo como Clock del i2c ya que solo necesita escribir y eso funcionaba bien.

    bueno , mañana mas , les mantendré al tanto.

    Saludos.
    Ariel
     
  14. Ariel Miembro Activo

    Ariel
    Registrado:
    29 May 2009
    Mensajes:
    1.841
    Me Gusta recibidos:
    0
    Solucionado.

    Ya esta funcionando . os dejo un video de los datos en el LCD y el codigo fuente que he utilizado.

    el código esta en MC C18 , pero supongo que fácilmente se puede traducir al de CCS . yo no he podido hacer funcionar el pluging para el MPLAB asi que al final lo hice en C18.

    Las rutinas de I2c las he creado yo , por que las que vienen en c18 nunca me funcionan y al final se pierde mas tiempo que haciéndolas uno mismo(al menos a mi me pasa eso).
    main.c
    Insertar CODE, HTML o PHP:
    
    #include <p18f1330.h>
    #include <delays.h>
    #include <stdio.h>
    //#include <usart.h>
    #include <adc.h>
    #include <adc.h>
    //#include <math.h>
    #include <i2c.h>
    
    #pragma config OSC=HS //INTIO2 //, FSCM=OFF//FOSC = ECIO_EC,FCMEN = OFF,IESO = OFF //CONFIG1H
    #pragma config PWRT = ON,BOR = OFF,BORV = 0 //CONFIG2L
    #pragma config WDT = OFF,WDTPS = 32768 //CONFIG2H
    
    #pragma config MCLRE = ON//CONFIG3H
    #pragma config STVREN = OFF,XINST = OFF,DEBUG = OFF//CONFIG4L
    #pragma config CP0 = OFF,CP1 = OFF//CONFIG5L
    #pragma config CPB = OFF,CPD = OFF//CONFIG5H
    #pragma config WRT0 = OFF,WRT1 = OFF//CONFIG6L
    #pragma config WRTB = OFF,WRTC = OFF,WRTD = OFF//CONFIG6H
    #pragma config EBTR0 = OFF,EBTR1 = OFF//CONFIG7L
    #pragma config EBTRB = OFF//CONFIG7H
    
    //-----------  DEFINICIONES ----------
    
    #define     CLK_FREQ         25000000
    #define     fn_delay(us)     ((CLK_FREQ / 4000000) * ( us / 10))
    #define     delay_us(us)     Delay10TCYx(fn_delay(us))
    #define     ADDRESS_CHIP    0b00110000
            
    
    //--------- FUNCIONES -----------
    #include <lcd_18.c>
    #include <1wire.c>
    #include <i2c.c>
    #include <mis_funciones.c>
    
    //-----------------------  variebles globales ---------------------------
    int    adval=0,volt_decimal=0,volt_entero=0,time=0,min=0,seg=0;
    char str[];
    unsigned char Temp_LSB,Temp_MSB,Temp,COUNT_REMAIN,COUNT_PER;
    int MSBxMi=4000,MSByMi=4000,MSBzMi=4000,MSBxM=0,MSByM=0,MSBzM=0,MSBx,LSBx,MSBy,LSBy,MSBz,LSBz,i_byte,i;
    
    
    //--------------------------MAIN-------------------------------------------
    void main(void){
        INTCON=   0b01100000;
        INTCONbits.GIE=0;
        CVRCON= 0b00000000;
        ADCON1 = 0x07; //0b00001100; // for digital inputs
        CMCON = 0x07; //0b00000111; // for digital input    TRISA = 0X00;
        TRISA = 0b00000010;
        TRISB = 0b0;
        PORTB = 0xFF;
        T0CON=0b00001000;    //configura el timer0
        T1CON=0b01000110;
    
    OpenADC(    ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_0_TAD,ADC_CH1 & ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS,0b1101);
    lcd_init();
    lcd_clear();
    
    I2C_CLK = 1;
    I2C_CLK_TRIS = 0;
    I2C_DATA_TRIS = 1;
    
    //volt_decimal = i2c_write_2_byte(0b00000000,0b00000100);  // descomentar para enviar un RESET al sensor memsic 
    //delay_ms(500);
    //volt_decimal = i2c_write_2_byte(0b00000000,0b00000010);  // descomentar para enviar un SET al sensor memsic  
    delay_ms(100);
    
    while(1){
        volt_decimal = i2c_write_2_byte(0b00000000,0b00000001);  // inicia convercion
        delay_ms(50);
        volt_decimal = i2c_write_1_byte(0b00000001);  // voy a leer desde posicion 1 (MSB x)
    
        //proceso de  lectura de os datos x,y,z 
        i2c_send_start_and_address_id(ADDRESS_CHIP);
        send_read();
        send_clk_test_ack();
        MSBx = i2c_read_byte();
        send_clk_and_ack();
        LSBx = i2c_read_byte();
        send_clk_and_ack();
        MSBy = i2c_read_byte();
        send_clk_and_ack();
        LSBy = i2c_read_byte();
        send_clk_and_ack();
        MSBz = i2c_read_byte();
        send_clk_and_ack();
        LSBz = i2c_read_byte();
        send_stop();
        
        
    
    
    MSBx = MSBx * 255 + LSBx;
    MSBy = MSBy * 255 + LSBy;
    MSBz = MSBz * 255 + LSBz;
    
    if (MSBx > MSBxM) MSBxM = MSBx;
    if (MSBy > MSByM) MSByM = MSBy;
    if (MSBz > MSBzM) MSBzM = MSBz;
    if (MSBx < MSBxMi) MSBxMi = MSBx;
    if (MSBy < MSByMi) MSByMi = MSBy;
    if (MSBz < MSBzMi) MSBzMi = MSBz;
    
        itoa((MSBx-MSBxMi)/10,str);
        lcd_puts(str);
    lcd_puts_ram("  ");
    lcd_goto(7);
        itoa((MSBy-MSByMi)/10,str);
        lcd_puts(str);
    lcd_puts_ram("  ");
    lcd_goto(14);
        itoa((MSBz-MSBzMi)/10,str);
        lcd_puts(str);
    lcd_puts_ram("  ");
    
    lcd_goto(40);
    MSBx = MSBx - MSBxMi;
    MSBy = MSBy - MSByMi;
    MSBz = MSBz - MSBzMi;
    MSBx = MSBx / ((MSBxM-MSBxMi)/6);
    MSBy = MSBy /( (MSByM-MSByMi)/6);
    MSBz = MSBz / ((MSBzM-MSBzMi)/6);
    
    lcd_putch('x');
    for (i=0;i<MSBx;i++) lcd_putch(0xFF);
    for (i=0;i<(6-MSBx);i++) lcd_putch(' ');
    
    lcd_putch('y');
    for (i=0;i<MSBy;i++) lcd_putch(0xFF);
    for (i=0;i<(6-MSBy);i++) lcd_putch(' ');
    
    lcd_putch('z');
    for (i=0;i<MSBz;i++) lcd_putch(0xFF);
    for (i=0;i<(6-MSBz);i++) lcd_putch(' ');
    
    
        
    }    
    }
    
    
    
    
    
    i2c.c
    Insertar CODE, HTML o PHP:
    //****************************************************************************
    //                            i2c.c
    //
    // rutinas para enviar y recivir datos por el buss I2C 
    // 
    
    
    #define     I2C_DATA_WRITE        LATAbits.LATA2           // Register select
    #define     I2C_DATA_READ        PORTAbits.RA2           // Register select
    #define     I2C_DATA_TRIS          TRISAbits.TRISA2        // TRIS 
    
    #define     I2C_CLK                LATAbits.LATA0           // Register select
    #define     I2C_CLK_TRIS          TRISAbits.TRISA0        // TRIS 
    
    void i2c_data_LO(void){
        I2C_DATA_WRITE = 0;
        I2C_DATA_TRIS = 0;    }
    void i2c_data_HI(void){
        I2C_DATA_TRIS = 1;    
        I2C_DATA_WRITE = 1;}
        
    void send_start(void){
        i2c_data_HI();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        i2c_data_LO();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        I2C_CLK = 0;
    }
    void send_stop(void){
        i2c_data_LO();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        i2c_data_HI();
        delay_us(5);
    }
    void send_read(void){   // SDA uno en el pulso de CLK
        i2c_data_HI();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        I2C_CLK = 0;
        delay_us(5);
    }
    void send_write(void){  // SDA cero en el pulso de CLK
        i2c_data_LO();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        I2C_CLK = 0;
        delay_us(5);
    }
    int send_clk_test_ack(void){
        int ask=0;
        i2c_data_HI();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        ask = !I2C_DATA_READ; 
        I2C_CLK = 0;
        delay_us(5);
        return ask;
    }
    int send_clk_and_ack(void){
        int ask=0;
        i2c_data_LO();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        I2C_CLK = 0;
        delay_us(5);
        i2c_data_HI();
        return ask;
    }
    int test_data(){
        int _bit;
        i2c_data_HI();
        delay_us(5);
        I2C_CLK = 1;
        delay_us(5);
        _bit = I2C_DATA_READ; 
        I2C_CLK = 0;
        delay_us(5);
        return _bit;
        }
    
    int i2c_send_start_and_address_id(int address_chip){
        int i;
        send_start();
        for(i=6; i>=0; --i) {
            if(test_bit(address_chip, i))
                send_read();  
                else send_write();  
            }
    }    
    int i2c_read_byte(){
        int i,i_byte=0;
        for(i=7; i>=0; --i) {
            if (test_data()) i_byte = i_byte + potencia(2,i);
            }
        return i_byte;
    }
    
    int i2c_write_1_byte(unsigned char address){
        int address_chip=0b00110000,i,ack,ack2;
        send_start();
        for(i=6; i>=0; --i) {
            if(test_bit(address_chip, i))
                send_read();  
                else send_write();  
            }
        send_write();
        ack = send_clk_test_ack();
        for(i=7; i>=0; --i) {
            if(test_bit(address, i))
                send_read();  
                else send_write();  
            }
        ack2 = send_clk_test_ack();
        send_stop();
        return ack&ack2;
    }
    
    int i2c_write_2_byte(unsigned char address,unsigned char data){
        int address_chip=0b00110000,i,ack,ack2,ack3;
        send_start();
        for(i=6; i>=0; --i) {
            if(test_bit(address_chip, i))
                send_read();  
                else send_write();  
            }
        send_write();
        ack = send_clk_test_ack();
        for(i=7; i>=0; --i) {
            if(test_bit(address, i))
                send_read();  
                else send_write();  
            }
        ack2 = send_clk_test_ack();
        for(i=7; i>=0; --i) {
            if(test_bit(data, i))
                send_read();  
                else send_write();  
            }
        ack3 = send_clk_test_ack();
        send_stop();
        return ack&ack2&ack3;
    }
        
        
    
    lcd_18.c
    Insertar CODE, HTML o PHP:
    /*
     *   LCD interface example
     *   Uses routines from delay.c
     *   This code will interface to a standard LCD controller
     *   like the Hitachi HD44780. It uses it in 4 bit mode, with
     *   the hardware connected as follows (the standard 14 pin 
     *   LCD connector is used):
     *   
     *   PORTB bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
     *   PORTB bit 5 is connected to the LCD RS input (register select)
     *   PORTB bit 4 is connected to the LCD EN bit (enable)
     *   
     *   To use these routines, set up the port I/O (TRISA, TRISB) then
     *   call lcd_init(), then other routines as required.
     *   
     */
    
    #define LEE_P       PORTB
    #define ESCRIBE_P    LATB
    #define TRIS_P      TRISB
    
    #define LCD_RS LATBbits.LATB4   // Register select
    #define LCD_EN LATBbits.LATB5   // Enable
    
    
    
    void LCD_STROBE(void)
    {
       LCD_EN = 1;
       Delay10TCYx(2);         //4 us
       LCD_EN = 0;
    }
    
    /* write a byte to the LCD in 4 bit mode */
    void
    lcd_write(unsigned char c)
    {
       ESCRIBE_P = (LEE_P & 0xF0) |  (c >> 4);
       LCD_STROBE();
       ESCRIBE_P = (LEE_P & 0xF0) |  (c & 0x0F);
       LCD_STROBE();
       Delay1KTCYx(10);         //2 Ms
    }
    
    /*
     *    Clear and home the LCD
     */
    
    void
    lcd_clear(void)
    {
       LCD_RS = 0;  
       lcd_write(0x1);
       Delay1KTCYx(1);            //200 Us
    }
    
    /* write a string of chars to the LCD */
    
    void
    //lcd_puts(auto const rom char * s)
    lcd_puts( char * s)
    {
       LCD_RS = 1;   // write characters
       while(*s)
          lcd_write(*s++);
    }
    
    /* write a string of chars to the LCD */
    
    void
    //lcd_puts(auto const ram char * s)
    lcd_puts_ram(const rom char * s)
    {
       LCD_RS = 1;   // write characters
       while(*s)
          lcd_write(*s++);
    }
    
    /* write a string of chars to the LCD de la rom*/
    
    void
    lcd_puts_rom(auto const rom char * s)
    {
       LCD_RS = 1;   // write characters
       while(*s)
          lcd_write(*s++);
    }
    
    /* write one character to the LCD */
    
    void
    lcd_putch(char c)
    {
       LCD_RS = 1;   // write characters
       ESCRIBE_P = (LEE_P & 0xF0) |  (c >> 4);
       LCD_STROBE();
       ESCRIBE_P = (LEE_P & 0xF0) |  (c & 0x0F);
       LCD_STROBE();
       Delay1KTCYx(10);      //2 Ms tiempo para escribir un dato
    }
    
    /*
     * Go to the specified position
     */
    
    void
    lcd_goto(unsigned char pos)
    {
    unsigned char t;
       LCD_RS = 0;
       t=(unsigned char)(0x80+pos);
       lcd_write(t);
    }
       
    /* initialise the LCD - put into 4 bit mode */
    
    void
    lcd_init(void)
    {
       LCD_RS = 0;            // write control bytes
       LCD_EN= 0;
       Delay1KTCYx(100);      //20 ms power on delay
       ESCRIBE_P= 0x3;         // attention!
       LCD_STROBE();
       Delay1KTCYx(25);      // 5 Ms
       LCD_STROBE();
       Delay1KTCYx(25);      //5 Ms
       ESCRIBE_P = 0x2;      // set 4 bit mode
       LCD_STROBE();
       lcd_write(0x28);      // 4 bit mode, 1/16 duty, 5x8 font
       lcd_write(0b00001100);      // display on, blink curson on
       lcd_write(0x06);      // entry mode
       lcd_clear();
    }
    
    mis_funciones.c
    Insertar CODE, HTML o PHP:
    
    //     Mis funciones varias 
    //************************************************************
    //*****************  FUNCIONES *******************************
    //************************************************************
    
    #define        audio_out    LATAbits.LATA4            
    
    void DelayFor18TCY( void )
        {
        Nop();Nop();Nop();Nop();Nop();Nop();Nop();
        Nop();Nop();Nop();Nop();Nop();
    
        }
    void DelayPORXLCD (void)
        {
        Delay1KTCYx(200); // Delay of 15ms
        // Cycles = (TimeDelay * Fosc) / 4
        // Cycles = (15ms * 16MHz) / 4
        // Cycles = 60,000
        return;
        }
    void DelayXLCD (void)
        {
        Delay1KTCYx(6); // Delay of 5ms
        // Cycles = (TimeDelay * Fosc) / 4
        // Cycles = (5ms * 16MHz) / 4
        // Cycles = 20,000
        return;
        }
    //-----------------------------convertX-------------------------------
    // digitaliza la señal en el canal CHANNEL le resta el VALMINIMO y le aplica la GANANCIA, 
    // luego lo muestra en la posicion POSICION con la LETRAANTERIOS y la LETRA_POSTERIOR.
    // con el FORMATO (ENTERO o DECIMAL) y si SIGNO es 1 no deja que muestre un valor negativo(se qeuda en cero).
    int convertX(unsigned char channel,float ganancia,unsigned int valminimo){
        unsigned int jdec;
        int jent;
        switch (channel){
            case 0:        SetChanADC(ADC_CH0); break;    
            case 1:        SetChanADC(ADC_CH1); break;    
            case 2:        SetChanADC(ADC_CH2); break;    
            case 3:        SetChanADC(ADC_CH3); break;    
            default: SetChanADC(ADC_CH0);
            }    
        ConvertADC(); // Start conversion
        while( BusyADC() ); // Wait for ADC conversion
        Delay1KTCYx(10);
        jent = ReadADC(); // Read result and put in temp
        jent =  jent - valminimo; 
        if(jent < 0 ) jent = 0;
        jent = (int)((float)jent * ganancia);
        return jent;
    }
    
    
    void beep(unsigned int tiempo,unsigned int tono){
        
        int song;
                for(song=0;song<tiempo;song++){
                audio_out = 1;
                Delay10TCYx( tono );
                audio_out = 0;
                Delay10TCYx( tono );
                }
    }
    
    
    void delay_ms(int ms)
    {
        ms *=4;
        do { delay_us(250); } while (--ms);
    }
    
    
    
    Bueno , este foro cada ves tiene mas limitaciones, y eso que esta lleno de publicidades, ahor ano te deja subir un fichero , asi qeu lo he pegado como CODE.

    este es el video:
    [vimeo]9606509[/vimeo]

    Me queda pendiente convertir a un vector los tres valores y asi controlar los 3 sevos. solo es algo de matematicas y calibracion.

    un saludo y suerte con buestros projectos.
     
    #14 Ariel, 21 Feb 2010
    Última edición: 21 Feb 2010
  15. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Felicidadesss!!!!!!!!!!!!!!!!:wink2:.

    Yo tambien tengo buenas noticias ya he conseguido hacer funcionar el I2C con la brujula, y todo era culpa de mi placa de desarrollo, al final he cogido otra vieja que tenia y solo necesite conectarla para que funcionasee jejejej, pero al final me vuelvo lokoooo :locos: el el I2C.

    bueno pues yo no pongo videos yo coloco la trama que he sacado con mi nuevo analizador jejejeje, que al final lo construí y me esta dando muy buenos resultados.

    Codigo en CCS C

    Insertar CODE, HTML o PHP:
    #include <18F452.h>
    #fuses HS, NOWDT, NOPROTECT, NOLVP
    #use delay(clock = 20000000)
    
    #use rs232(baud = 19200, xmit = PIN_C6, rcv = PIN_C7)
    
    #use I2C(MASTER, SDA = PIN_C4, SCL = PIN_C3, FAST, FORCE_HW) 
    
    int8 ack = 1, no_ack = 0;
    
    void main( int8 address_R, int8 address_W ) {
       
       enable_interrupts(GLOBAL);
       enable_interrupts(INT_SSP);
    
       i2c_start();
       i2c_write(64);
       i2c_write(0x00);  
       i2c_write(0x01);               
       i2c_stop();
    
       i2c_start();
       i2c_write(65);
       datos_MSB_x = i2c_read(ack);           
       datos_LSB_x = i2c_read(ack);
       datos_MSB_y = i2c_read(ack);
       datos_LSB_y = i2c_read(ack);             
       datos_MSB_z = i2c_read(ack);
       datos_LSB_z = i2c_read(no_ack); 
       i2c_stop();
    }
    
    Bueno no he podido escribir hasta hoy debido a que el foro estaba caído o en mantenimiento.

    bueno pues ya que lo tenemos funcionando solo falta lo que dices los calculos matemáticos. mira estas notas que explica la calibración y medidas.

    Calibración

    Ángulo

    Bye
     

    Adjuntos:

  16. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Hola de nuevo, ¿que tal van los avances?

    yo no he podido avanzar por que mi placa de desarrollo está mal como ya vi con el I2C y me he tenido que meter con un dsPIC30F y con el compilador CCS C no se puede trabajar por que tiene muchos bug con los dsPIC porque lo he vivido en primera persona :sad:, así que me he tenido que meter con el C30 y me está costando.

    ¿ariel has trabajado con el dsPIC30F y el C30? a ver si me puedes aclarar algunas dudas.

    Estoy utilizanado un cristal XT 7.37MHz y PLL16 y lo estoy haciendo con el VISUAL INITIALIZER pero creo que no lo esta haciendo bien, por que me pone 29MHZ en vez de 119MHZ.

    Bye
     
  17. Ariel Miembro Activo

    Ariel
    Registrado:
    29 May 2009
    Mensajes:
    1.841
    Me Gusta recibidos:
    0
    Lo siento , pero no voy apoder ayudarte , simplemente por que nunca he utilizado el C30 y no tengo ni idea de que es el VISUAL INITIALIZER jejejej

    pero tengo pensado ponerme a estudiar el C30 ya que tengo algunos dsPIC por qui y me gustaría probarlos.

    Por que te comlicas la vida con los dsPIC ? utiliza cualquier f18 y estas sobrado de velocidad. al menos a mi me pasa que tengo que meter delays por todos lados sino no me funciona nada por que lo hace todo tan rapido que no le da tiempo ni a los protocolos I2c , SPI ni 1Wire.

    Yo he dejado un momento en Stanby este proyecto por que me he metido con el WiiMotionPlus para hacer el HeadTracking y me queda un poco para terminarlo. si te interesa pásate por el nuevo tema que he creado.

    Un saludo
    Ariel
     
  18. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Hola ariel, interesante el WII motion, eso el objetivo final es que al girar la cabeza la camara realice el mismo movimiento ¿no?.

    bueno pues el meterme con el dsPIC no es otra por que el objetivo final es montarlo en un helicoptero y realizar tareas de control, por lo que necesito filtrado y realizar SIN y COS, por lo que el 18 se queda corto.

    bueno pues irá despacito y con buena letra, seguiré ese wii que parece iteresante.

    BYE
     
  19. niuton Nuevo Miembro

    niuton
    Registrado:
    30 Nov 2009
    Mensajes:
    56
    Me Gusta recibidos:
    0
    Funcionando

    Hola a todos, se dice que mas vale tarde que nunca, pues despues de un parón de unos mese, he retomado el tema de la brujula y ya he finalizado consiguiendo calcular el ángulo.

    La brujula que funcionaba por I2C nos proporcionaba las lecturas magnéticas en cada eje. Pero antes de utilizarlo es necesario calibrar el magnetometro.

    yo estos calculos los hago fuera del PIC y en el PIC opero con el resultado.

    * calcular el OFFSET y SENSIBILIDAD:

    Mx_Sensitivity=(Mx_max-Mx_min)/2
    My_Sensitivity=(My_max-My_min)/2
    Mz_Sensitivity=(Mz_max-Mz_min)/2
    Mx_Offset=(Mx_max+Mx_min)/2
    My_Offset=(My_max+My_min)/2
    Mz_Offset=(Mz_max+Mz_min)/2

    Se debe de encontrar el valor máximo y mínimo en cada eje y la solución es mover el sensor en todas las direcciones y coger el valor máximo y minimo en cada eje.

    * Con estos datos ya los utilizamos dentro del PIC.

    Dentro del PIC los unicos cálculos son los de normalizar las medidas de cada eje. Para ello se utiliza estas formulas:

    Mx_cal(Mx-Mx_Offset)/Mx_Sensitivity
    My_cal(My-My_Offset)/My_Sensitivity
    Mz_cal(Mz-Mz_Offset)/Mz_Sensitivity

    Con estos valores ya se puede calcular los grados referidos al Norte Magnetico:

    Angulo = Atan(My_cal/Mx_cal)


    NOTA: el eje Z no se usa por que no se está compensando la inclinación.

    Bueno pues espero que le sirva a alguien, amí me ha servido ;).

    Bye

    PD: El siguiente proyecto será meterme con el GPS a ver si encuentro algo.
     

Compartir esta página