Lo scopo di questo tutorial è quello di fornire una soluzione per rilevare la tensione di rete con un microcontrollore. In questo esempio ho scelto il PIC16F628A ma potete scegliere qualsiasi altro microcontrollore.

Per isolare la rete dal microcontrollore ho utilizzato un foto accoppiatore e nello specifico ho scelto l' SFH620A. Lo schema elettrico è il seguente:

Schema elettrico

Funzionamento.

Quando sul morsetto J1 è presente la tensione di rete, nel semiperiodo positivo dell'onda, l'uscita V1 sul collettore del transistor interno al fotoaccoppiatore commuterà da 5V a 0V  come evidenziato nel grafico. Questo avverrà non appena la corrente nel fotodiodo sarà sufficiente per  saturare il transistor interno. La corrente necessaria dipende dal CTR del fotoaccoppiatore e tenendo conto che il valore minimo si attesta intorno 13, allora il transistor saturerà quando la tensione in ingresso arriverà a circa 10V.

Poichè all'interno del fotoaccoppiatore sono presenti 2 foto diodi in antiparallelo, la commutazione avverrà anche durante il semiperiodo dell'onda negativa.

Da quanto descritto si intuisce che le commutazioni avvengono in circa 10 msec (ogni T/2), con T periodo dell'onda sinusoidale pari all'inverso della frequenza T=1/f.

Sapendo che ogni commutazione avviene in 10 msec circa, possiamo attivare un'uscita del microcontrollore (LED D1) sul primo fronte di discesa rilevato e caricare un timer con un valore superiore a T/2.

Ogni volta che il microcontrollore rileverà un fronte di discesa ricaricherà il timer al suo valore massimo  impedendo il suo azzeramento fino a quando non verranno rilevati più fronti.

Quando non ci saranno più commutazioni per più di 20-30 msec allora il timer si azzererà e l'uscita LED D1 si porterà a 0. Spero di essere stato chiaro, in caso contrario potete contattarmi.

Codice C:

/*
 * File:   main.c
 * Author: v.primoceri
 *
 * Created on 14 ottobre 2021, 14.04
 * XC8 compiler Microchip V 2.31
 * */


#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
 
 
#define DivTimer1 3 //
#define DivTimer0 5000 //

#define LED1 PORTBbits.RB3
#define ST_MAINS_VOLTAGE_DETECTION 1
#define ST_WAIT 0

#define _XTAL_FREQ 10000000 //Frequenza quarzo
#include "xc.h"
#include <pic16f628a.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

volatile unsigned int IncTimer1=0;
volatile unsigned int IncTimer0=0;
volatile unsigned char Main_Voltage_Detection=0;
volatile unsigned char Timeout_Main_Voltage_Detection=0;
unsigned char State;

void __interrupt () isr(void){
    
    if((INTCONbits.INTF)&&(INTCONbits.INTE)) {//Fronte di discesa su RB0
        
       if(State==ST_WAIT) {
             Main_Voltage_Detection=1;
          }
       
        IncTimer1=DivTimer1;
        INTCONbits.INTF=0;
    }
//----------------------------------------------------------------------------    
    
    
if(INTCONbits.TMR0IF){//Timer0
        
        if(--IncTimer0==0){//ogni secondo
             
              IncTimer0=DivTimer0;////Variabile per divisione contatore per ottenere 1 sec
             //....
          }

              TMR0=5;
              TMR0IF=0;
    }
    
//----------------------------------------------------------------------------    
     if(PIR1bits.TMR1IF==1){// interrupt ogni 20 millesec 
                   
          if(IncTimer1>0){
             if(--IncTimer1==0){
             
                   Timeout_Main_Voltage_Detection=1;
                 }
              
              }
        
           TMR1=0x9E58;//40536
           PIR1bits.TMR1IF=0; 
           
    }//Fine      if(PIR1bits.TMR1IF==1){
    
}

int main(void) {
    
     OPTION_REGbits.PSA=0;//0 = Prescaler is assigned to the Timer0 module
     OPTION_REGbits.T0CS=0;//0= Internal instruction cycle clock (FOSC/4)
     OPTION_REGbits.T0SE=0;//=0 Increment  on low-to-high transition
     OPTION_REGbits.PS=0;// prescaler 1:2
     OPTION_REGbits.INTEDG=0;//0 = Interrupt on falling edge of RB0/INT pin
     INTCONbits.T0IE=0;//Timer0 Overflow Interrupt Enable bit
     INTCONbits.GIE=1;//Global Interrupt Enable bit
     INTCONbits.PEIE=1;//Disables all peripheral interrupts
     INTCONbits.T0IF=0;//Timer0 Overflow Interrupt Flag bit
     INTCONbits.INTE=1;//Se=1 abilta INT0
     INTCONbits.RBIE=0;//
     CMCON=0b00000111;//Comparatori spenti
     VRCON=0b00000000;//Vref off
     T1CON=0b00000001;//Timer1 ON 
     TMR1=0x9E58;//40536 -->65536 -25000=40536   per 20 msec
     PIE1bits.TMR1IE=1;//Interrupt abilitato
     T2CON=0b00000000;//Timer2  OFF
     PIR1bits.TMR1IF=0;
     PORTB=0b00000000; 
     TRISB=0b00000001;
     PORTA=0b00000000; 
     TRISA=0;
     TMR0=5;//impostare per 1 sec

     IncTimer0=DivTimer0;
     State=ST_WAIT;
  
    while(1){
    
           switch (State){
           
               case ST_WAIT:
               
                    if(Main_Voltage_Detection==1){
                          Main_Voltage_Detection=0;
                          LED1=1;
                          State=ST_MAINS_VOLTAGE_DETECTION;
                    }
               break;
               
               case ST_MAINS_VOLTAGE_DETECTION:
                 
                  if(Timeout_Main_Voltage_Detection==1){
                       Timeout_Main_Voltage_Detection=0;
                       LED1=0;
                       State=ST_WAIT;
                    }
               break;
               
           }    
        
    }
    return 0;
}

Grazie per la vostra attenzione al prossimo tutorial.

Saluti V.Primoceri.

 

No comments

Leave your comment

In reply to Some User