Proyecto de trabajo. Vumetro pasando código de Arduino a C18 [PIC18f26k22]

Hola a todos.

Bueno estoy haciendo un proyecto de trabajo. Consiste en que la salida de audio de un amplificador (LM380) entre al PIC18F26k22. Quiero que el micro haga la función de un vumetro; más aparte que se transmita (solo) una comunicación serial a la PC como comprobar los valores salidos.

Nada fácil ¡¿Eh?!

Permitidme explicarles que es lo que hice para dar una rápida solución a esto. Utilice el arduino, el siguiente código dice lo siguiente.

Se toma los valores del audio y las va sumando (1000 por segundo), de tal forma que el resultado lanzado se divide entre 1000 lanzando el promedio en la terminal.

Código:
void loop() {
  Serial.flush();
  temp = 0;
  prom = 0;
  cuenta = 0;
  while (temp < 1000) {
     sensorValue = analogRead(sensorPin);
     cuenta = (float)cuenta + sensorValue;
     temp++;
  }
  prom = ((cuenta) / 1000);
  Serial.println(prom);

El voltaje promedio es el que se utilizó para determinar el rango de los 10 led's de salida.

De 0 a 85 prenderá el LED 1.
De 86 a 170 el LED 2.
De 171 a 255 el LED3.
De 256 a 340 el LED4.
De 341 a 425 el LED5.
De 426 a 510 el LED6.
De 511 a 595 el LED 7.
De 596 a 680 el LED 8.
De 681 a 765 el LED 9.
De 766 a 850 el LED 10.

Bueno. esto fue lo que hice en el fabuloso Arduino.

Ahora estoy de novato con el C18, ya que en el trabajo manejan ese PIC y la programación igual.

Estoy leyendo el Data de ese PIC y les dejo lo que eh echo y con ayuda de varios blogs, foros y páginas que me eh encontrado en la red (Aún no esta completo) pero me gustaría que lo revisarán y dieran su opinión y sugerencias en mi programa.

Código:
/*
 * File:   vumetro_mainp18.c
 * Author: R. Giskard Raventlov
 *
 * Created on 29 de junio de 2016, 00:01 AM
 */

//LIBRERÍAS

#include <p18f26k22.h> // Librería del microcontrolador que se va a utilizar.
#include <usart.h>

//CONFIGURACIÓN DE BITS DEL PIC.

// CONFIG1H
#pragma config FOSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKOUT function on OSC2)
#pragma config PLLCFG = ON // 4X PLL Enable (Oscillator multiplied by 4)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config MCLRE = EXTMCLR // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-003FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (004000-007FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (008000-00BFFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (00C000-00FFFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-003FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (004000-007FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (008000-00BFFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (00C000-00FFFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000800-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (004000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)

//TERMINA CONFIGURACIÓN DE BITS DEL PIC.

void main(void) {

    // CONFIGURACIÓN DEL OSCILADOR INTERNO.
    OSCCONbits.IDLEN = 0; // Entra en modo de suspensión con instrucción.
    OSCCONbits.IRCF = 0b111; // Frecuencia del oscilador a 16 MHz (HFINTOSC).
    OSCCONbits.HFIOFS = 1; // Frecuencia de HFINTOSC es estable.

    //CONFIGURACIÓN DEL MODULO ADC.
    ANSELAbits.ANSA3 = 1; //Entrada digital del buffer desactivada.
    ADCON0bits.CHS = 0b00011; // Seleción del canal AN3 (RA3).
    ADCON0bits.GO_DONE = 1; // Se pone a 1 para iniciar el proceso de conversión.
    ADCON0bits.ADON = 1; // ADC está activado.
    ADCON1bits.PVCFG = 0b00; //Voltage positivo a 5V.
    ADCON1bits.NVCFG = 0b00; //Voltage negativo a 0V.
    ADCON2bits.ADFM=1; // Se justifica hacia la derecha.
    ADCON2bits.ADCS = 0b100; //Se divide entre 4 los 16MHz.

    // CONFIGURACIÒN DEL UART.
    
    /* Configuración de pines TX y RX. */
    ANSELCbits.ANSC6 = 0; //Entrada digital del buffer activada.
    ANSELCbits.ANSC7 = 0; //Entrada digital del buffer activada.
    TRISCbits.TRISC6 = 1; // Tx como entrada.
    TRISCbits.TRISC7 = 1; // Rx como entrada.

    /* Estatus y control del registro de trasmisión. */
    TXSTA1 = 0b00100010;
    /* TXSTA1.TRMT = 1 // Registro de tranmision de cambio vacío.
     * TXSTA1.BRGH = 0 // Baja velocidad en la trasmisiòn de datos.
     * TXSTA1.SYNC = 0 // Se activa el modo Asincrono.
     * TXSTA1.TXEN = 1; // Habilitar la transmisiòn.
     */
    /* Estatus y control del registro de recepción.*/
    RCSTA1 = 0b10010000;
    /* RCSTA1.SPEN = 1 // Habilita el puerto serial.
     * RCSTA1.CREN = 1 // Habilita la recepción continua.
     */
    /* Rango de control del registro BAUD. */
    
    

    BAUDCON1bits.BRG16 = 0;

}

Difícil empezar, pero no imposibles.
Soy novato en este foro, esté es mi segunda entrada, mismo tema. Espero sus ataques (En serio)
 
Estoy leyendo el Data de ese PIC y les dejo lo que eh echo y con ayuda de varios blogs, foros y páginas que me eh encontrado en la red (Aún no esta completo) pero me gustaría que lo revisarán y dieran su opinión y sugerencias en mi programa.
Aún no hay programa, lo único que has escrito es una configuración inicial extendida. :rolleyes:
Y digo extendida, porque todo eso que escribiste se puede simplificar bastante.

No es necesario que configures cada registro bit por bit.
Si ya sabes que valor debe tener cada bit de determinado registro, puedes darle un valor total.

Por ejemplo:
TRISC = 0b11000000; // RB7 y RB6 como entradas.

Lo mismo para la palabra de configuración:
#pragma config FOSC = INTIO7, PLLCFG = ON, PRICLKEN = ON, etc.

Y si quieres, puedes crear otro renglón para no extender tanto uno solo.

Por ahora, esa es mi opinión.
 
Vale, le sigo en este hilo.

¡Bueno al grano! Me gustaría que le echarán un vistazo a mi código (da la "BUILD SUCCESSFUL") y que me dierán su punto de vista bueno (corrigieran) en donde tenga fallas de organización... de una manera se pudiera decirse.

Código:
Código:
/*
 * File:   vumetro_mainp18.c
 * Author: COP
 *
 * Created on 22 de junio de 2016, 06:08 PM
 */

/* LIBRERÍAS */

#include <p18f26k22.h>
#include <stdio.h>
#include <delays.h>
#include <adc.h>

/* CONFIGURACIÓN DE BITS DEL PIC. */
// CONFIG1H
#pragma config FOSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKOUT function on OSC2)
#pragma config PLLCFG = ON // 4X PLL Enable (Oscillator multiplied by 4)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config MCLRE = EXTMCLR // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
/* TERMINA CONFIGURACIÓN DE BITS DEL PIC. */

/* DEFINICIONES */
#define nPromedio 1000
#define led1 PORTBbits.RB0
#define led2 PORTBbits.RB1
#define led3 PORTBbits.RB2
#define led4 PORTBbits.RB3
#define led5 PORTBbits.RB4
#define led6 PORTBbits.RB5
#define led7 PORTBbits.RB6
#define led8 PORTBbits.RB7
#define led9 PORTCbits.RC0 
#define led10 PORTCbits.RC1
#define ledok PORTCbits.RC2
#define leder PORTCbits.RC3
/* TERMINA LAS DEFINICONES */

/* VARIABLES */
unsigned int resultado;
unsigned int sum_resultado;
unsigned int cuenta;
unsigned int prom_resultado;
/* TERMINA VARIABLES */
void main(void) {

    // CONFIGURACIÓN DEL OSCILADOR INTERNO.
    OSCCON = 0b01110100;
    /* Entra en modo de suspensión con instrucción.
     * Frecuencia del oscilador a 16 MHz (HFINTOSC)
     * Frecuencia de HFINTOSC es estable */

    //CONFIGURACIÓN DE LOS PUERTOS.
    ANSELA = 0b00000010;
    TRISA = 0b11111111;
    TRISB = 0b00000000;
    TRISC = 0b00000000;
    // CONFIGURACIÓN DEL CONVERTIDOR ADC.
    OpenADC(ADC_FOSC_4 & 
            ADC_RIGHT_JUST & 
            ADC_16_TAD, ADC_CH1 & 
            ADC_INT_OFF & 
            ADC_REF_VDD_VSS, 0b00000000);
    Delay10TCYx(2); // RETARDO DE 20ms.
    
    while(cuenta < nPromedio){ // Mientras la cuenta sea menor a 1000.
        ConvertADC(); // Empieza la conversión.
        while(BusyADC()); //Espera para que se complete la conversión.
        resultado = ReadADC(); //Capturando el resultado.
        sum_resultado = (float)sum_resultado + resultado; //Se va sumando el valor hasta que cuente 1 seg.
        //sum_resultado + = (float) resultado;
        cuenta++; //Incrementa cuenta.
        Delay10TCYx(2); //Retardo
        //PORTB = resultado;
    }
    prom_resultado = ((sum_resultado) / nPromedio); // Se obtiene el promedio; la suma del resultado durante 1 seg sobre 1000.
    Delay10TCYx(2); //Retardo
    
    if ((prom_resultado>=0)&&(prom_resultado<67)){
        led1 = 1;
        led2 = 0;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 0;
        leder = 1;
}
    else if (prom_resultado>=67 && prom_resultado<134){
        led1 = 1;
        led2 = 1;
        led3 = 0;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 0;
        leder = 1;
    }
    else if (prom_resultado>=134 && prom_resultado<201){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 0;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 0;
        leder = 1;
    }
    else if (prom_resultado>=201 && prom_resultado<268){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 0;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 0;
        leder = 0;
    }
    else if ( prom_resultado>=268 && prom_resultado<335){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 1;
        led6 = 0;
        led7 = 0;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 0;
        leder = 1;
    }
    else if ( prom_resultado>=335 && prom_resultado<402 ){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 1;
        led6 = 1;
        led7 = 0;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 0;
        leder = 1;
    }
    /*LED VERDE*/
    else if (prom_resultado>=402 && prom_resultado<500){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 1;
        led6 = 1;
        led7 = 1;
        led8 = 0;
        led9 = 0;
        led10 = 0;
        ledok = 1;
        leder = 0;
    }
    else if (prom_resultado>=500 && prom_resultado<750){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 1;
        led6 = 1;
        led7 = 1;
        led8 = 1;
        led9 = 0;
        led10 = 0;
        ledok = 1;
        leder = 0;
    }
    else if (prom_resultado>=750 && prom_resultado<810){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 1;
        led6 = 1;
        led7 = 1;
        led8 = 1;
        led9 = 1;
        led10 = 0;
        ledok = 1;
        leder = 0;
    }
    /*FIN DEL RANGO OK (LED VERDE)*/
    
    else if (prom_resultado>=1000){
        led1 = 1;
        led2 = 1;
        led3 = 1;
        led4 = 1;
        led5 = 1;
        led6 = 1;
        led7 = 1;
        led8 = 1;
        led9 = 1;
        led10 = 1;
        ledok = 0;
        leder = 1;
    }
}

Yo pienso que

Código:
ConvertADC(); // Empieza la conversión.
while(BusyADC()); //Espera para que se complete la conversión.

No van a dentro de

Código:
while(cuenta < nPromedio){

Pero no estoy segúro aún así voy a investigar por cuenta propia pero si me quieren echar una mano con su opinión (repito) sería de mucha ayuda.
 
¡Yuju! :D encontré la solución al fin, lo tenía enfrente de mi nariz. :oops:

Primero. Entré a la librería adc.h para saber como se configuraban el módulo ADC correctamente, descubrí que cada peripheral library (MPLAB x ide V.3.30) funcionaba definiendo USE_AND_MASKS (manda 0xFF "1" y limpia los bits de registro.) Quedando de la siguiente manera.
Código:
#define USE_AND_MASKS

void init_ADC (void){
    OpenADC(ADC_FOSC_16 && 
        ADC_RIGHT_JUST && 
        ADC_4_TAD, ADC_CH0 &&
        ADC_INT_OFF &&
        ADC_REF_VDD_VDD &&
        ADC_REF_VDD_VSS, 0x00);

La configuración de arriba dice lo siguiente: Selecciona el FOSC a 16MHz; justificado de lado derecho; el TAD es FOSC/4 y selección del canal 0 (RA0), interrupciones apagadas y voltajes de referencia positivo y negativos como predeterminados a la hoja de datos técnicos; el último número en hex se trata sobre el registro ADCON1. :)

Una vez configurada el convertidos, a mandar a declarar la conversión en una función para mayor comodidad y sugerencia.
Código:
unsigned int analogicSensors( unsigned char ch ){
    select_ADC(ch); 
    //SelChanConvADC( ADC_CH1 );
    Delay10TCYx(2);
    ADCON0bits.GO=1; 
    //ConvertADC(); // Empieza la conversión.
    while(ADCON0bits.GO); 
    //while (BusyADC()); //infinite loop
       resultado = ADRESH; resultado<<=8; resultado+=ADRESL;
    //resultado = ReadADC(); //Capturando el resultado.
    return resultado;
:unsure: no me acuerdo muy bien el porque en C18. Pero el problema con el el canal fue un dolor de cabeza, ya que faltaba definir le para poder llamarla en el Void principal después.
Código:
#define select_ADC(ch) { ADCON0 &= 0b11000011;  ADCON0 |= (ch<<2); }
Código:
 ANSELA = 0b00000010;
    TRISA = 0b11111111;
    TRISB = 0b00000000;
    TRISC = 0b00000000;
    init_ADC ();
    while(1){
        val= analogicSensors(0);
        //ADCVal = ((5 * val) / 1023);
        PORTB = val>>8;
        //PORTC = val>>2;
        Delay10TCYx(50);
    }
Aquí la función analogicSensors debe de albergar al canal y guarecerse en una variable para ser igualada al PORTB. De lo contrario les generára errores variados.

Vaya... no soy bueno en explicar lo que eh echo. :oops:

Quiero agradecer a todos por su colaboración en este tema y en especial al moderador por dar su opinion. Quiero dar por cerrado esté hilo, si no antes leer lo que opinan de mi código. Lo se es muy sencillo pero me demore 12 días en busquedas, lecturas y pruebas y errores. :D
 
Atrás
Arriba