Viewing 8 posts - 1 through 8 (of 17 total)
  • Author
  • #9702

    Goodmorning everyone.
    I am making a circuit to control a fan and a relay on a power supply that I have finally finished.
    Having a VoltAmpere module on the display and wanting to use it, for the management of the relay that switches the secondary of the transformer and of the fan according to the heat sink temperature, I used a small 12F683 and the PROTON BASIC. Very simple SW, created, simulated with proteus, all right.
    The problem is that in reality, or realized (on millefori) but also on breadboard, does not work. Of course the circuit has been checked and is correct, but the part that manages the fan does not work.
    The working part, composed of the analog port GP0 reads the output voltage (divided 10) and if higher than 12V, switches the relay (on port GP4) which supplies 24Vac all’ power supply:perfect.
    The NOT working part is composed of the GP1 port, also analog, which reads an LM335 and after conversion to ° C, manages the fan in PWM 50Hz (GP2 port), already studied, verified and working. The range is <30° fan OFF, between 30 and 50 ° fan running from minimum to maximum speed. If you exceed 50 °, fixed PWM output a “1” then maximum speed and a red LED flash (port GP5) indicates this event. All this simulated, it works perfectly, in reality NO.
    The PWM, I do not create it with the dedicated module but with the TIMER1 which generates an interrupt every 200uS and appropriate counts.
    The flashing of the red led, I create it with the TIMER 0 which generates an interrupt every 10mS and appropriate counts.
    See TIMER 1 ON, TIMER 0 OFF and vice versa.
    I can't figure out where the problem is but I can't even figure out how to verify the SW as in the simulation, it works.
    I enclose the FW quite simple to interpret.

    '*  Name    : alim_12F683.BAS                                      *
    '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
    '*  Notice  : Copyright (c) 2020 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 21/10/2020                                        *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :                                                   *
    ;**** Added by Fuse Configurator ****
    ; Use the Fuse Configurator plug-in to change these settings
    Device = 12F683
    Declare Reminders Off
    @ CONFIG_REQ = 0 ; Override Compiler's configuration settings
    Declare Reminders On
    ;**** End of Fuse Configurator Settings ****
    On_Hardware_Interrupt GoTo Isr
    Xtal 8
    Symbol OUT          = GPIO.2        ' OUT PWM 50Hz
    Symbol TMR1IF       = PIR1.0        ' Timer1 interrupt Flag
    Symbol TMR1IE       = PIE1.0        ' TMR1 Overflow Interrupt Enable
    Symbol TMR0IF       = INTCON.2      ' Timer0 Interrupt Flag
    Symbol TMR0IE       = INTCON.5      ' nome del bit di attivazione Timer0
    Symbol TMRSET       = 99            ' periodo di conteggio per 10 millisecondi
    Symbol ADON         = ADCON0.0      ' A/D ON bit
    Symbol RELE         = GPIO.4        ' attiva rele
    Symbol MINTEMP      = 30            ' valore minimo di temperatura
    Symbol MAXTEMP      = 50            ' valore massimo di temperatura
    Symbol MAXDUTY      = 100           ' valore massimo di duty cycle
    Symbol LED          = GPIO.5        ' lampeggio LED timer
    Declare Adin_Res = 10
    Declare Adin_Tad = FRC
    Declare Adin_Stime = 50
    ' ******************************************************************************
    ' Definizione variabili
    ' ******************************************************************************
    Dim tlong As Dword                  ' variabile di calcolo di una media
    Dim tempo_totale As Word            ' calcolo del periodo di tempo trascorso
    Dim cnt4sec As Byte                 ' contatore di periodo per i secondi
    Dim v_adc1 As Dword                 ' Utilizzata per ADC
    Dim timer As Byte                   ' Variabile conteggio per durata PWM ON
    Dim duty As Byte                    ' Durata PWM
    Dim var1 As Byte                    ' Variabile temporanea
    Dim chnl As Byte                    ' valore selezione canale analogico
    Dim temperatura As Byte             ' Temperatura
    Dim V_out As Word                   ' Tensione uscita alimentatore
    Dim delta As Byte                   ' Coefficiente aumento duty da 20° a 50°
    ' *****************************************************************************
    '             MAIN program
    ' *****************************************************************************
    GoSub init
     While 1 = 1                       ' INIZIO Ciclo
         GoSub leggi_adc_van0
         GoSub leggi_adc_t
         If temperatura > MINTEMP Then      ' se la temperatura e' oltre i 30°
                If temperatura < MAXTEMP Then
                  Clear TMR0IE
                  TMR1IE = 1                      ' se e' minore di MAXTEMP
                  TMR1IF = 0
                  GoSub leggi_adc_van0
                      If temperatura <= MAXTEMP Then    ' <= 50°
                          delta=(temperatura -30)*3
                          duty = temperatura + delta    ' il duty viene controllato
                                                        ' dalla temperatura
                        Else                            ' altrimenti se T > 50°
                          TMR1IE = 0
                          Set OUT
                      End If
                End If 
                  If temperatura >= MAXTEMP Then    ' Se T>50°
                      Clear TMR1IE                  ' Ferma TMR1
                      Clear TMR1IF
                      Clear T1CON.0
                      Set OUT                       ' Uscita fissa a 1 FAN max velocità
                      Set TMR0IE                    ' Accendi TMR0
                      Clear TMR0IF                  ' clear flag TMR0
                      Set T1CON.0
                      Clear LED 
                      Clear TMR0IE
                      Clear TMR0IF 
                  End If
               GoSub leggi_adc_t             ' presenta la tensione
               DelayMS 500
              duty = 0                      ' ferma le ventole
              GoSub leggi_adc_t             ' legge temperatura
              DelayMS 250                   ' aspetta un po
         End If
    ' *****************************************************************************
    '             Init
    ' *****************************************************************************
     DelayMS 20
     DelayMS 20
     DelayMS 20
     DelayMS 20
      T1CON	 = %00000001
      TMR1IF = 0
      TMR1H	 = 0xFE
      TMR1L	 = 0x6F
      TMR1IE = 0
      INTCON = %11000000  '0xC0
      Clear TMR0IE              'Ferma TMR0
     Clear RELE
     Clear OUT
     Clear duty
     Clear timer
     Clear cnt4sec
     Clear LED
    leggi_adc:                      ' Legge ADC
          For var1 = 1 To 128               ' Ciclo 32 letture ADC
            v_adc1 = ADIn chnl              ' lettura canale prefissato
            DelayUS 5
            tlong = tlong + v_adc1
          Next var1
          tlong = tlong / 128              ' valore medio delle 20 letture
          tlong = (tlong * 5000) / 1023    ' VDD=4,923V  Valore finale in 0,1 mV
                                           ' VDD 4,923 misurata sul circuito reale: 
                                           ' in teoria dovrebbe essere 5,000
                                           ' Dipende dalla tolleranza del 7805
    leggi_adc_van0:                     ' Lettura tensione uscita alimentatore
                                        ' su VAN0
      chnl = 0                          ' assegna per la lettura dal canale 0
      DelayMS 50
         GoSub leggi_adc                   ' legge il canale
         DelayMS 20
      tlong=tlong / 10
      If V_out>120 Then
         Set RELE
      End If
      If V_out <110 Then
         Clear RELE
      End If 
    leggi_adc_t:                        ' Legge valore Temperatura su VAN1
      chnl = 1                          ' assegna per la lettura dal canale 1
      DelayMS 50
      GoSub leggi_adc
      Clear var1
      DelayMS 50
      tlong=(tlong-2731)                ' Conversione temperatura
     ' If tlong <= 20 Or tlong >= 1000 Then
     '   tlong=20
     ' End If
      tlong = tlong / 10                ' converte in ASCII di 5 cifre
      temperatura = tlong
    ' *****************************************************************************
    '             Interrupt Service Routine
    ' *****************************************************************************
      Context Save                    ' salva i registri
    ' ******************* TIMER 1 *************************************************  
      If TMR1IF = 1 Then              ' interrupt ogni 200uS   TIMER1
         TMR1IF =  0                  ' azzera il flag
         TMR1H  =  $FE                
         TMR1L  =  $6F
          If timer < duty Then        ' Se il periodo e minore del Duty
             OUT = 1                  ' Uscita alta
             OUT = 0                  ' altrimenti bassa
          End If
        If timer > 99 Then            ' Se il tempo ha contato 100
           timer = 0                  ' azzera
        Else                          ' oppure
          Inc timer                   ' si aumenta
        End If
      End If
    ' *******************  TIMER 0  ***********************************************  
        If TMR0IF = 1 Then                ' Interrupt per TIMER0
            TMR0IF = 0                    ' rimuove il  flag
            TMR0  =  TMRSET               ' carica 99 su TMR0 per interrupt a 10mS
            Inc cnt4sec                   ' aggiorna il contatore
                                          ' dopo mezzo secondo e interrupt ON
                If TMR0IE = 1 Then        ' ammesso che e' abilitato il TMR0
                  If cnt4sec < 50 Then    ' e che il cnt4sec e <50  500mS
                    LED = 1               ' uscita alta LED ON
                  Else                    ' altrimenti
                    LED = 0               ' uscita bassa LED OFF
                End If
        End If
        If cnt4sec >= 100 Then           ' passato un secondo.....
          cnt4sec = 0                   ' azzera il cnt4sec
        End If
      End If
      Context Restore                    ' recupero dei registri
    ' *************************************************************************



    In my opinion you don't want to use 32 bit for reading the analogue channel, you always want to get a lean reading better suited for the micro in use. If you used a word you could get the average of 64 samples. The delay is also just a lost period, Reading takes place correctly with the hardware and the proper command.
    As for compiling the Configuration, it is better if you use the Proton IDE plugin. At the most, make sure it doesn't have WDTE or MCLRE enabled.

    Symbol NUMSAMPLE 40
    $if NUMSAMPLE > 63
    $ error NUMSAMPLE exceed the maximum
    Dim Tlong As Word
    Sub readADC()
          For var1 = 1 To NUMSAMPLE               ' Ciclo 32 letture ADC
            v_adc1 = ADIn chnl              ' lettura canale prefissato
            tlong = tlong + v_adc1
          Next var1

    For what concerns the PWM, I found a’ idea from the network which obviously uses only on timer0, therefore we would have a maximum frequency of Fosc / 256 = 3906,25 Theoretical Hz a 4 MHz. To do this you only need

    If TMR0IF = 1 Then                  ' Interrupt per TIMER0
      TMR0IF = 0                        ' rimuove il  flag
      If OUT = 1 Then
        Clear OUT
        TMR0  =  -PULSE                 ' carica il periodo basso
        Set OUT
        TMR0 = PULSE                    ' carica il periodo  basso
    End If

    If you don't need a whole byte of resolution then you can go up in frequency, only that he begins to lose readiness in recalculating the periods. If you are interested I will do the necessary storage.

    As for what the simulator shows you and what happens to reality, there are several factors such as oversights (talking about my experiences) to electrical connections and disturbances that the simulator does not take into account. For this you should take into account the debugging method in the software which signals where it is in the program. For this the quickest way would be to use the serial and a pin assigned to do the job. But with interrupts enabled, it would be better if you disable the GIE to send the message.
    Otherwise if you need to keep the maximum speed then it is better to use a pin to signal a certain point in a certain event, for that you just need to keep an eye on the oscilloscope. It would be better if you have an analog type analyzer
    logic analizer
    The price is moderate and should not exceed 10 €. Of course this guy only has eight inputs.
    Then you could probe all the pins and see if it matches what you want.


    Hi Picmicro…
    First of all, i solved the main problem…..
    Now it works fine: i took another PIC from the drawer and this works perfectly with the same FW… PIC perhaps the analog input AN1 ko is faulty, I'll check it out later before throwing it out. However, both PICs are new…. mah!
    The LM335 provided a correct voltage, but the outputs of the PIC always fixed to zero.
    I'm analyzing your suggestions:
    when we get to the sub line that reads the ADC tlong = (tlong * 5000) / 1023 even doing alone 32 readings, the WORD is not enough anymore that's the reason that made me use a DWORD.
    For PWM, with TIMER1, i get interrupt every 200uS and then counting 100, I generate about 50Hz, I don't have to get higher frequencies to control the 12V fan.
    I could get the 200uS even with the TIMER 0 but now this project was born like this.
    Ok for the logic analyzer, me information.


    For curiosity, the logic analyzer you showed, what SW in the PC works with?


    I use that of saeles
    However, there is also another rather satisfactory brand, the Kingst for a more elaborate model.
    At the end you can also make one Research to online stores and are found from € 8 upwards,
    Glad you found the flaw, as far as the program is concerned, nothing subversive, I just wanted to make you aware of some methods. Basically, for regulation based on temperature it is sufficient to have a value that responds to regulation. Especially if you don't need to view its value.
    As for the presumably broken micro, I just can't tell if they are really broken. There are many factors to be evaluated before we can understand if the micro is fallacious. In certain situations they do not meet the requirements, which then put to work for another type of project do not give problems.


    Indeed, I don't throw it away, I keep it for other tests. Just out of curiosity, we are talking about a few euro cents……
    It happened to me a few years ago with a pair of 16F819s that didn't work anymore, then I found a writing that said how to verify them and in fact they go perfectly: In the Pickit2 programmer or 3, setting up “Use Vpp first program entry” . For the logic analyzer, I study on it, up to now I have used the oscilloscope, I haven't had any needs yet “superior”.

    • This reply was modified 2 years ago by piero55.
    • This reply was modified 2 years ago by piero55.

    To analyze logic signals, depends on the type of oscilloscope. A digital one also requires some memory capacity to store the signal. Maybe there are those who also do the decoding of the signals, but they are already of a certain price.


    My oscilloscope is an old analog 5″ double track 15MHz of 40 years…. I use it for what it is. Certainly if I had to analyze several pins of a chip at the same time I would be in trouble. I will probably think about the logic analyzer.

Viewing 8 posts - 1 through 8 (of 17 total)
  • You must be logged in to reply to this topic.