En aquest cas el dispositiu mesura el corrent i mostra a la pantalla la potència consumida i el cost de l'energia acumulat des de la posada en marxa de l'aparell. Aquest dispositiu està pensat per a un ús durant un espai de temps reduït, no per a una mesura contínua.
El programa és el següent:
#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #include <xc.h> // Carrega el fitxer de funcions #include <math.h> #define _XTAL_FREQ 4000000 // La freqüència del rellotge és 4 MHz #define numEsp 2
unsigned int refer, mesura;
int Valor;
int Preu;
int comptaP = 0;
int temps = 1;
unsigned int suma = 0;
unsigned int sumatori = 0;
float mitjana, RMS;
unsigned int compta = 0;
char Digits[5]; // Variable amb el número dígit a dígit
// Digits[0] són les unitats
// Definició de les funcions que farem servir
void Esborra(void); // Esborra la pantalla i posa el cursor a l'inici
void EnviaL(char Caracter); // Envia un caràcter
void Cursor(char Filera, char Columna); // Posiciona el cursor
// (filera 1 a 2 i columna 1 a 32, segons pantalla)
void Llegir (void); // Llegeix la referència
void Escriure(char Nom);
void main (void) {
// Configuració d'entrades i sortides
TRISC = 0b11110000; // Posa els bits 0 a 3 del port C com a sortida
PORTC = 0; // i els altres quatre com a entrada
TRISA = 0xFF; // Tot el port A és d'entrada
__delay_ms(2000); // Esperem que arrenqui la pantalla
// Configuració de la comunicació amb la pantalla
BRGH = 1; // Configuració de velocitat
BRG16 = 0; // Paràmetre de velocitat de 8 bits
SPBRG = 25; // Velocitat de 9600 baud
SYNC = 0; // Comunicació asíncrona
TX9 = 0; // Comunicació de 8 bits
SPEN = 1; // Activa comunicació sèrie
TXEN = 1; // Activa comunicació
// Entrades analògiques
ANSEL = 0b00000000; // Desactiva totes les entrades analògiques
ANSELH = 0b00000011; // I activa AN8 i AN9
ADCON1 = 0b00010000; // Posa el conversor a 1/8 de la freqüència
// Configuració d'interrupció
INTCON = 0b01000000; // Habilitem la interrupció per PIE
// i deshabilitem les altres
PIE1 = 0b00000001; // Activa la interrupció per Timer 1
// Configuració del Timer 1
TMR1IF = 0; // Aquest bit es posarà a 1 quan el temporitzador acabi
// cal desactivar-lo des del programa
TMR1H = 253; // Inicialitza el Timer1
TMR1L = 143;
T1CON = 0b00000000; // Configuració de Timer1
// 00 - Factor d'escala de 1
// I el posem en marxa
Llegir();
// Preparem per a les lectures
ADCON0 = 0b10100101; // Activa el conversor connectat a AN9
// amb el resultat justificat per la dreta
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
// Descartem la primera lectura
GIE = 1; // Habilitem les interrupcions a nivell general
TMR1ON = 1; // Posa en marxa el temporitzador, per començar les mesures
Esborra();
while (1){ // Inici del bucle de programa
if(compta == 32){ // Quan ja tenim totes les mesures
comptaP=comptaP+1;
temps = temps + 1;
mitjana = (float)suma / compta; // Calculem la mitjana
RMS = (30 / numEsp) * 115 * 1.1107 * mitjana / 1023.0;
// Hem multiplicat per 100 per tenir dos decimals
// El 115 ve de multiplicar 5*230V/1000 *100
// A l'hora de mostrar-ho, posarem la coma convenientment
Valor = (int)round(RMS); // I el valor eficaç
PORTC = 0b00000000;
if (temps>60){
PORTC = 0b00000001; // Activa el bit 0 del port C i, per tant, encén el LED al cap d'un minut
}
if (temps>120){
PORTC = 0b00000011; // Activa els bits 0 i 1 del port C i, per tant, encén el LED al cap de dos minuts
}
if (temps>300){
PORTC = 0b00000111; // Activa els bits 0 1 i 2 del port C i, per tant, encén el LED al cap de cinc minuts
}
if (temps>600){
PORTC = 0b00001111; // Activa els bits 0 1 2 i 3 del port C i, per tant, encén el LED al cap de deu minuts
}
// Preparem per mostrar el valor
// Descomposem en dígits
sumatori=sumatori+Valor;
Cursor(1, 1);
Escriure(Valor);
// Afegim les unitats
EnviaL(' '); // Espai
EnviaL('k');
EnviaL('W');
suma = 0;
if (comptaP == 60){
// comptaP s'incrementa cada cop que compta = 32, és a dir, cada segon perquè compta arriba fins a 1600.
// El preu s'actualitzarà cada minut
Preu=(int)round(sumatori*0.0002387216);
// dividim el sumatori entre 60 per obtenir la potència mitja en un minut.
// 0.008594 és el preu mig del kW/h segons la 'Red Eléctrica de España'.
// Dividim entre 60 per obtenir kW/min. Multipliquem per 100 per donar el preu en centims.
// Per tant: 0,08594/60/60*100=0.0002387216
Cursor(2, 1);
Escriure(Preu);
// Afegim les unitats
EnviaL(' '); // Espai
EnviaL('C');
EnviaL('E');
EnviaL('N');
EnviaL('T');
comptaP = 0;
}
}
}
}
void __interrupt() temporit(void){
// No desactivem les interrupcions perquè només en tenim una que dura poc
if(TMR1IF){ // Comprovem que hi ha interrupció per Timer 1
TMR1ON = 0; // Aturem el Timer
TMR1H = 253; // Inicialitza el Timer1
TMR1L = 143;
TMR1ON = 1; // El tornem a engegar
TMR1IF = 0; // Tornem a posar el bit a zero
// Anem a llegir el corrent
if (compta<32){
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
mesura = ADRESH;
mesura = mesura << 8;
mesura = mesura | ADRESL;
if(mesura < refer){
suma = (suma + refer) - mesura; // Ho sumem
} else {
suma = (suma + mesura) - refer; // Ho sumem
}
}
compta++;
if (compta == 1590){
Llegir();
}
if (compta == 1600){
compta = 0;
}
}
}
void EnviaL(char Caracter){
TXREG = Caracter; // Agafa el caràcter i l'envia
__delay_ms(1); // Donem temps
while (TXIF == 0) // Esperem que s'acabi d'enviar
; // No fem res
}
void Esborra(void){
EnviaL(254); // Caràcter de control
EnviaL(1); // Esborra la pantalla i posa el cursor a l'inici
}
void Cursor(char Filera, char Columna) {
char Posicio = 0; // Variable per a calcular la posició
if (Filera == 2) {
Posicio = 64; // La primera columna de la segona fila és 64;
}
if (Columna > 0 && Columna < 33) { // Comprovem que sigui un valor raonable
Posicio = Posicio + Columna; // Sumem les adreces
Posicio = Posicio - 1; // Restem 1 perquè numera des de 0
}
Posicio = Posicio + 128; // Posa el bit de posicionat a 1
EnviaL(254); // Control de la posició del cursor
EnviaL(Posicio); // Canvia el cursor de lloc
}
void Llegir(void) {
ADCON0 = 0b10100001; // Activa el conversor connectat a AN8
// amb el resultat justificat per la dreta
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
// Descartem la primera lectura
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
refer = ADRESH;
refer = refer << 8;
refer = refer | ADRESL;
// Preparem per a les lectures
ADCON0 = 0b10100101; // Activa el conversor connectat a AN9
// amb el resultat justificat per la dreta
}
void Escriure(char Nom){
for (signed char j = 0; j < 5; j++){ // 5 dígits
Digits[j] = Nom % 10;
Nom = Nom / 10;
}
// Convertim a ASCII
for (signed char j = 0; j < 5; j++){ // 5 dígits
Digits[j] = Digits[j] + '0'; // Li sumem el codi ASCII de 0
}
// Eliminem zeros a l'esquerra
if(Digits[4] == '0') { // Mirem si el primer dígit és 0
Digits[4] = ' '; // Si ho és, hi posem un espai
if(Digits[3] == '0') { // Mirem si el segon dígit és 0
Digits[3] = ' '; // Si ho és, hi posem un espai
}
}
// Enviem a la pantalla
for (signed char j = 4; j >= 0; j--){ // 5 dígits
if(j == 1){
EnviaL(','); // Coma
}
EnviaL(Digits[j]); // Número
}
}

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.