Sari la conținut
ELFORUM - Forumul electronistilor

Timer cu PIC12F675


Postări Recomandate

  • 4 luni mai târziu...
Vizitator marinizo

salu, postez si eu aici problema mea daca nu se supara nimeni.

am nevoie sa ma ajute si pe mine cineva cu un fisier hex pentru un pic12f675 care sa comande 2 reley in felul urmator: cand pic-ul primeste comanda pe una din intrari de preferat minus sa cupleze primul releu pe una din iesiri iar la interval de 3-5 secunde sa cupleze al doilea releu pe o a doua iesire si sa le mentina cuplate pe ambele, la o alta comanda pe aceasi intrare sa decupleze prima data al doilea releu si la interval de maxim 3 minute sa decupleze si primul releu si sa ramana asa.

comanda de pornit/oprit vreau sa fie cu impuls dar sa nu depinda de un impuls la un timp anume , adica ca fac un impuls lung sau unul scurt el sa execute comanda

la ce vreau sa il folosesc? am un webasto airtronic de camion montat pe autoturism , fiind de camion lucreaza la 24V pe autoturism am o adoua baterie inseriata cu bateria masini ca sa imi functioneze , la luna trebuie sa pun pe redresor a doua baterie pentru ca nu are cine sa o incarce iar montajul care vreau sa-l fac il folosesc sa incarc a doua baterie mai exact cand comand picul sa cupleze imi va inseria bateriile si va porni webasto cand comand sa opreasca imi va opri webasto care are nevoie de 2 minute dupa oprire sa se ventileze si apoi imi va pune bateriile in paralel, in felul asta a doua baterie se va incarca atunci cand merg si nu folosesc webasto.

Link spre comentariu

As apela si eu la cunostintele voastre in vederea rezolvarii unei probleme cu care ma confrunt de vreo 3 zile. Doresc sa realizez cu PIC12F675 un intrerupator cu push buton. Montajul doresc sa-l fac cu citirea tensiunii pe pe pinul 3 (AN3). In cazul in care se apasa push butonul si valoarea ADC-Read(3) este mai mic ca valoarea setata, pe iesirea GP1 sa palpaie. Daca se apasa push butonul din nou GP1 sa fie ON pana cad se apasa din nou push butonul si daca in continuare ADC_Read este sub valaorea setata sa palpaie. Daca ADC_Read este peste valoarea setata atunci sa faca invertare de port, adica cand este oprit am GPIO=2 iar pornit GPIO=33

 

Explicatie mai simpla:

 

Pornim montajul GPIO=2 Cazul1. se apasa push => ADC_Read <x => GP1 flash (GP5, GP0 OFF) =>se apasa push => GPIO = 2 se apasa push => ADC_Read <x => GP1 flash (GP5, GP0 OFF)

 

Cazul2. se apasa push => ADC_Read >x => GPIO=33 =>se apasa push => GPIO=2 => GPIO=33 => GPIO=2

 

Acesta este programelul pe care l-am scris numai ca nu am reusit in nici un fel sa-l fac sa iasa din palpait atata timp cat voltage este < 400. Adica sa faca ciclul din cazul1. Am rugamintea daca ma poate ajuta cineva cu o solutie.

 

bit oldstate; // Old state flag
bit sstatus;
bit x;
bit undervoltage;
unsigned int voltage;
unsigned cnt; // This is the counter variable which will extend desired period
void InitTimer0(){
// OPTION_REG = 0x87; // Prescaler 256
TMR0 = 61;
INTCON = 0xA0;
}
void Interrupt(){ // Occurs every 2.5ms
if (TMR0IF_bit){
cnt++; // Increment counter, this is the tweak we added in original Timer Calculator code
TMR0IF_bit = 0; // Clear TMR0IF
TMR0 = 61; // Prepare for next interrupt
}
}
void main() {
osccal = 252;
CMCON = 7;
TRISIO = 28;
GPIO = 2; //14
EECON1 = 7;
ADCON0 = 15;
ANSEL = 24;
//INTCON = 160;
InitTimer0();
OPTION_REG = 0x87; // Prescaler 256
cnt = 0; // Initialize cnt
oldstate = 0;
sstatus = 0;
//voltage = 0;
do {
if (Button(&GPIO, 2, 20, 1)) // Detect logical one
{
oldstate = 1; // Update flag
}
if (oldstate && Button(&GPIO, 2, 20, 0)) // Detect one-to-zero transition
{
voltage = ADC_Read(3);
sstatus = 1;
oldstate = 0;
if (x == 1) { GPIO = 2;
x = 0;
// undervoltage = 1;
}
}
if( sstatus == 1)
{ GPIO = ~GPIO; // Invert PORTC
sstatus = 0;
}
if(voltage < 400)
{ x = 1;
voltage = 0;
GP5_bit = 0;
GP0_bit = 0;
if (cnt >= 30) // after x interrupts LEDs will be toggled
{GP1_bit = ~GP1_bit; // Toggle PORTB LEDs
cnt = 0; } // Reset cnt
}
} while(1); // Endless loop
}
Multumesc
Cu respect
Robert
Link spre comentariu
  • 5 săptămâni mai târziu...

Cand nimeni nu raspunde este un semnal pentru tine ca ceva nu este in regula cu enuntul problemei cu care te confrunti.

 

Iti recomand sa faci o noua prezentare a problemei tale in care sa acoperi toate starile posibile: stari de inceput, stari intermediare, stari finale si fluxul in care evolueaza din una in alta.

Clar, punctual, altfel de ex eu nici nu imi bat capul sa citesc.

Succes!

 

LE: Si inca un lucru: daca vrei ca sa ti se citeasca codul ... posteaza-l folosind butonul "CODE" corespunzator din bara de postare. Arata asa: "<>". Ca sa nu mai spun ca trebuia sa iti creezi propriul topic.

Editat de mars01
Link spre comentariu

Multumesc mars01 pentru raspuns, si totodata imi cer scuze pentru modul meu de prezentare anterioara.

 

Doresc sa construiesc o sursa standby care printr-un tranzistor sa alimenteze restul electronicii, cu functie de monitorizare tensiune de intrare. Acel tranzistor va fi comandat de un PIC12F675, respectiv pornirea/ oprirea se va face dintr-un push button.

 

Configurare PIC12F675: GP5 iesire pentru ON/OFF tranzistor

GP4 citire tensiune de alimentare

GP2 intrare push button

GP1 iesire LED rosu pentru vizualizare stare sursa oprit (in aceasta situatie GP5 = 0)

GP0 iesire LED verde pentru vizualizare stare sursa pornit (in aceasta situatie GP5 =1)

 

Moduri de lucru: PORNIT = ( GP5 = 1 ( tranzistor de comanda activat), GP1 = 0 (led stare rosu off), GP0 = 1 (led stare verde on)

OPRIT = ( GP5 = 0 ( tranzistor de comanda dezactivat), GP1 = 1 (led stare rosu on), GP0 = 0 (led stare verde off)

BLINK = ( GP5 = 0, GP1 schimba starea 1 - 0 - 1 - 0 - 1 - 0 - 1 - 0 la fiecare 500 milisecunde (palpaie ledul rosu) GP0 = 0)

 

Pasul 1: La alimentare sursa porneste in stare OPRIT ( ulterior doresc o implementare cu scriere / citire in memorie a starii, adica in cazul in care utilizatorul a lasat montajul in stare PORNIT si are loc o cadere de tensiune, pana curent , la revenirea alimentarii sa porneasca din starea lasata de catre utilizator)

Pasul 2: Se apasa push button pentru pornire.

 

In acel moment pe GP4 are loc un ADC-Read a valorii tensiunii de intrare si pot aparea 2 cazuri :

 

Cazul1:

 

Tensiunea citita pe GP4 ARE valoarea corespunzatoare si apare tranzitia din OPRIT in PORNIT

 

La fiecare actionare a push buton sa aiba loc o tranzitie de stare: PORNIT - OPRIT - PORNIT - OPRIT .......

 

Cazul2:

 

Tensiunea citita pe GP4 nu are valoarea corespunzatoare (ex. tensiune retea < 200V sa nu porneasca montajul) tranzitia sa fie din OPRIT in stare BLINK

 

La fiecare actionare a push buton sa aiba loc o tranzitie de stare: OPRIT - BLINK - OPRIT - BLINK .......

 

 

Eu din cele prezentate mai sus NU am reusit sa pot face comutarea din BLINK in OPRIT, aici as avea nevoie de ajutorul vostru.

 

Codul pe care l-am scris este urmatoarea:

bit oldstate;                                    // Old state flag
bit sstatus;
bit x;
bit undervoltage;
unsigned int voltage;
unsigned cnt;              // This is the counter variable which will extend desired period
 
void InitTimer0(){
//  OPTION_REG = 0x87;       // Prescaler 256
  TMR0 = 61;
  INTCON = 0xA0;
}
 
void Interrupt(){          // Occurs every 2.5ms
  if (TMR0IF_bit){
        cnt++;                 // Increment counter, this is the tweak we added in original Timer Calculator code
        TMR0IF_bit = 0;        // Clear TMR0IF
        TMR0       = 61;       // Prepare for next interrupt
  }
}
 
void main() {
osccal = 252;
CMCON = 7;
TRISIO = 28;
GPIO = 2;  //14
EECON1 = 7;
ADCON0 = 15;
ANSEL = 24;
//INTCON = 160;
InitTimer0();
OPTION_REG = 0x87;       // Prescaler 256
cnt = 0;                 // Initialize cnt
oldstate = 0;
sstatus = 0;
//voltage = 0;
 
 
do {
      if (Button(&GPIO, 2, 20, 1))    // Detect logical one
      {
       oldstate = 1;                   // Update flag
      }
 
       if (oldstate && Button(&GPIO, 2, 20, 0))    // Detect one-to-zero transition
           {
            voltage = ADC_Read(3);
            sstatus = 1;
            oldstate = 0;
            if (x == 1) { GPIO = 2;
                         x = 0;
                    //     undervoltage = 1;
                          }
           }
       if( sstatus == 1)
       { GPIO = ~GPIO;        // Invert PORTC
         sstatus = 0;
       }
 
       if(voltage < 400)
       {   x = 1;
           voltage = 0;
           GP5_bit = 0;
           GP0_bit = 0;
           if (cnt >= 30)       //  after x interrupts LEDs will be toggled
           {GP1_bit = ~GP1_bit;      // Toggle PORTB LEDs
           cnt = 0; }            // Reset cnt
           }
 
  } while(1);                                    // Endless loop
 } 

Sper ca am am reusit sa fiu mai explicit.

Cu respect

Robert

Link spre comentariu

Salut,

 

Atasat ai proiectul mikroC cat si simularea proteus8.

 

Resurse folosite:

RAM 18bytes (38%)

ROM 372bytes(36%)

#include <stdint.h>

/*
  Author: mars01 on elforum.info
  Date:   18 Feb 2018
*/

/*
  HW setup:
  GP5 iesire pentru ON/OFF tranzistor
  GP4 citire tensiune de alimentare - ADC channel 3
  GP2 intrare push button; ACTIVE LOW
  GP1 iesire LED rosu pentru vizualizare stare sursa oprit (in aceasta situatie GP5 = 0)
  GP0 iesire LED verde pentru vizualizare stare sursa pornit (in aceasta situatie GP5 =1)
*/

#define INPUT         1
#define OUTPUT        0

#define ACTIVE        0
#define INACTIVE      1

#define OUT           GP5_bit
#define OUT_DIR       TRISIO5_bit

#define ADC_CH3_DIR   TRISIO4_bit

#define BUTTON        GP2_bit
#define BUTTON_DIR    TRISIO2_bit

#define LED_R         GP1_bit
#define LED_R_DIR     TRISIO1_bit

#define LED_G         GP0_bit
#define LED_G_DIR     TRISIO0_bit

//function prototypes
void hw_init();
uint8_t read_button();
void idle_handler();
void run_handler();
void error_handler();
void shutdown_handler();
uint16_t read_voltage();

enum {
  OFF = 0,
  ON = 1
};

typedef enum state{
  IDLE,
  RUN,
  ERROR,
  SHUTDOWN
}state_t;

//working variables
state_t FSM_state, previous_state;
volatile uint8_t flag = 0;

void hw_init(){
  
  OSCCAL = 0x80;  //oscilator is set in center frequency
  //init timer0
  T0CS_bit = 0;   //TMR0 clock source is internal osc
  
  //set prescaler to 1:8
  PS2_bit = 0;
  PS1_bit = 1;
  PS0_bit = 0;
  
  PSA_bit = 0;    //prescaler assigned to TMR0
  TMR0 = 131;     //interrupt frequency is 1ms
  
  T0IE_bit = 1;   //enable interrupt on TMR0 overflow
  GIE_bit = 1;    //enable general interrupts
  
  CMCON = 0x07;   //disable comparators
  
  //select channel 3 of ADC, the rest of pins are digital IO
  ANSEL = 0b00001000;
  ADC_CH3_DIR = INPUT;
  
  BUTTON_DIR = INPUT;
    
  OUT_DIR = OUTPUT;
  OUT = OFF;

  LED_R_DIR = OUTPUT;
  LED_R = ON;
  
  LED_G_DIR = OUTPUT;
  LED_G = OFF;
  
  ADC_init();
}

//interrupt function is called each 1ms
void interrupt(){
  static uint16_t cnt = 0;
  if (T0IF_bit && T0IE_bit){
    T0IF_bit = 0;
    TMR0 = 131;
    
    if (flag == ON){
      if (cnt >= 500){
        cnt = 0;
        LED_R = !LED_R;
      }
      else cnt++;
    }
  }
}

uint8_t read_button(){
  static uint8_t old_button = INACTIVE;
  
  if (BUTTON == INACTIVE){
    old_button = INACTIVE;
  }

  if (BUTTON == ACTIVE && old_button == INACTIVE){
    delay_ms(10);
    if (BUTTON == ACTIVE){
      old_button = ACTIVE;
      return 1;
    }
  }
  return 0;
}

uint16_t read_voltage(){
  uint8_t i;
  uint16_t voltage = 0;
  
  ADC_read(3);  //dummy read

  for (i = 0; i < 10; i++){
    voltage += ADC_read(3);
  }
  return (voltage / 10);
}

void idle_handler(){
  if (read_button()){
    FSM_state = RUN;
    previous_state = IDLE;
  }
}

void run_handler(){
  if (previous_state != RUN){
    previous_state = RUN;
    if (read_voltage() >= 400){
      OUT = ON;
      LED_R = OFF;
      LED_G = ON;
    }
    else FSM_state = ERROR;
  }
  if (read_button() && (FSM_state != ERROR)){
    FSM_state = SHUTDOWN;
  }
}

void error_handler(){
  if (previous_state != ERROR){
    previous_state = ERROR;
    OUT = OFF;
    LED_G = OFF;
    flag = ON;
  }
  if (read_button()){
    flag = OFF;
    FSM_state = SHUTDOWN;
  }
}

void shutdown_handler(){
  OUT = OFF;
  LED_R = ON;
  LED_G = OFF;
  FSM_state = IDLE;
}

void main() {
  hw_init();
  
  FSM_state = IDLE;
  
  while(1){
    switch(FSM_state){
      case IDLE:
        idle_handler();
        break;
      case RUN:
        run_handler();
        break;
      case ERROR:
        error_handler();
        break;
      case SHUTDOWN:
        shutdown_handler();
        break;
    }
  }
}

LE: uitasem sa atasez arhiva cu proiectul (nu apasasem butonul "Attach This File" ...).

FRobert.zip

Editat de mars01
Link spre comentariu

Mii de multumiri mars01 pentru ajutor si munca depusa. Deseara cand ajung acasa de la munca am sa-l incarc in montaj, si totodata am de mestecat la cod ca multe lucruri nu inteleg (din pacate stiu foarte putin programare). Scopul final ar fi un amplificator audio cu DSP realizat cu procesor ADAU1701. Inca odata multumesc!

Cu respect

Robert

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări