Sari la conținut
ELFORUM - Forumul electronistilor

Timer cutie expunere UV cu PIC16F690 si LCD (0 sec - 99 min)


Postări Recomandate

Salut,

De parca nu ar fi fost destule si aici pe forum sau aiurea pe net, m-am apucat si eu de un soft pt. o cutie de expunere...

Nu sunt specialist, am mai tras cu ochiul pe ici pe colo... si cam asta mi-a iesit.

In linii mari functionarea ar fi astfel:

- Butoanele MIn si Sec modifica timpul de expunere, in sens crescator

- Min si Sec apasate simultan reseteaza timpul setat

- Start si Min apasate simultan seteaza ultimul timp memorat

- La prima apasare a butonului Start perneste timerul, la urmatoarea apasare se opreste

- La deschiderea capacului timerul se opreste, pt. reluare trebuie inchis capacul si apasata tasta Start

- Pe timpul temporizarii apasarea butoanelor Min sau Sec nu are efect

- In timpul pauzei se poate modifica timpul, Set Time creste cu valoarea adaugata

 

Nu am momentan posibilitatea sa-l probez fizic intr-un montaj, in simulator pare ca merge, cu urmatoarele probleme:

- uneori ultima secunda din countdown ramane 1 in loc de 0

- uneori butonul Start trebuie sa-l apas de mai multe ori ca sa ia comanda

Vorbesc de ce se intampla in simulare.

Nu am mai lucrat pana acum cu functia "Button" din Mikroc, posibil sa trebuiasca sa mai ajustez timpii, am sa vad cum se comporta cand am sa-l realizez fizic.

 

Cine are idei de imbunatatire sau sesizeaza greseli este rugat sa posteze.

// Countdown Timer using PIC16F690 microcontroller
#define XTAL_FREQUENCY 6000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)   //    1 clock tick = 1 instr. cycle = crystal frequency / 4
//Lid
#define open 0
#define close 1

// Lcd pinout settings
sbit LCD_RS at RC2_bit;
sbit LCD_EN at RC1_bit;
sbit LCD_D7 at RA0_bit;
sbit LCD_D6 at RA1_bit;
sbit LCD_D5 at RA2_bit;
sbit LCD_D4 at RC0_bit;
// Pin direction
sbit LCD_RS_Direction at TRISC2_bit;
sbit LCD_EN_Direction at TRISC1_bit;
sbit LCD_D7_Direction at TRISA0_bit;
sbit LCD_D6_Direction at TRISA1_bit;
sbit LCD_D5_Direction at TRISA2_bit;
sbit LCD_D4_Direction at TRISC0_bit;
// End LCD module connections

char msg[17]; // declare array set to max size required plus 1 [for terminator] for copying into
// copy const to ram string
char * CopyConst2Ram(char * dest, const char * src)
{
 char * d ;
 d = dest;
 for(;*dest++ = *src++;)
 ;
 return d;
}
// Intro Mesages
const char LCD_txt1[] = "Hello Man!";
const char LCD_txt2[] = "How are you?";
const char LCD_txt3[] = "UV Box Timer";
const char LCD_txt4[] = "00 Sec to 99 Min";
const char LCD_txt5[] = " SET  TIME  LEFT";
const char LCD_txt6[] = "00:00      00:00";
const char LCD_txt7[] = "    The  End    ";
const char LCD_txt8[] = "    Lid Open    ";
const char LCD_txt9[] = "STOP";
const char LCD_txt10[]= "      ";

// define Buzzer, LED's and Relay pins.
sbit LED_YELLOW at RC5_bit;
sbit LED_GREEN at RB7_bit;
sbit LED_RED at RC7_bit;
sbit RELAY at RC3_bit;
sbit LID at RC6_bit;
// Variables
char b;
bit oldstate;                                     // Old state flag
//bit Lid;
long int Ticker = TIMER1_FREQUENCY;
int Seconds=0;
int SetSecond=0, SetMinut=0, LeftSecond=0, LeftMinut=0;
int readsec=0, readmin=0;
int memsec, memmin;
int x=0;

void Tone1()
{Sound_Play(659, 50);}                            // Frequency = 659Hz, duration = 250ms
void Tone2()
{Sound_Play(698, 300);}                            // Frequency = 698Hz, duration = 250ms

void show_intro(void)                             // Initial splash screen
{
 char i;
INTCON.GIE = 0;
Tone1();
 delay_ms (100);
 Lcd_Out(1,4,CopyConst2Ram(msg,LCD_txt1));       // Write text "Hello Dan!" in first row
 delay_ms (500);
Tone1();
 Lcd_Out(2,3,CopyConst2Ram(msg,LCD_txt2));       // Write text "How are you?" in second row
 delay_ms (1500);
 Lcd_Cmd(_LCD_CLEAR);
Tone1();
 Lcd_Out(1,3,CopyConst2Ram(msg,LCD_txt3));         // Write text "UV Box Timer" in first row
 Lcd_Out(2,1,CopyConst2Ram(msg,LCD_txt4));         // Write text "0 Sec. to 99 Min." in second row
 delay_ms(2000);
}

// =Process Zero Drift Real Time Clock Information=-
// Most algorithms configure the timer to generate an interrupt every 100ms, and
// then count the number of interrupts. The problem in that approach is that most
// clock frequencies can't be divided by 256 and you don't get an exact 100ms.
// The small errors will add up to an error of several seconds a day.
// The algorithm presented here is exact in the long run because it doesn't
// count the number of interrupts but counts the number of clock cycles.
//   /*
void Interrupt()
{ if (PIR1.TMR1IF ==1)
 {
  Ticker -= 65536;                       // Decrement ticker by clocks per interrupt
  if (Ticker < 65536 )                   // If second has expired
 {
   Ticker += TIMER1_FREQUENCY;           //   Increment ticker by clocks per second
   seconds++;                            //   Increment number of seconds
   x++;
    if (b == 0)
   {
    if (LeftSecond == 0)
    {
     readsec = 60;
     readmin--;
    }
    readsec=readsec--;
    LeftSecond=readsec;
    LeftMinut=readmin;
   }
  }
 }
 PIR1.TMR1IF = 0x00;    // Timer1 interrupt Flag cleared
}   

 void LCD_2nd_row()
{
 Lcd_Chr(2, 1, SetMinut/10 + '0');
 Lcd_Chr_CP(SetMinut%10 + '0');
 Lcd_Chr(2, 3, ':');
 Lcd_Chr(2, 4, SetSecond/10 + '0');
 Lcd_Chr_CP(SetSecond%10 + '0');
 Lcd_Chr(2, 12, LeftMinut/10 + '0');
 Lcd_Chr_CP(LeftMinut%10 + '0');
 Lcd_Chr(2, 14, ':');
 Lcd_Chr(2, 15, LeftSecond/10 + '0');
 Lcd_Chr_CP(LeftSecond%10 + '0');
}
void LIDOPEN()
{
 RELAY = 0;
 LED_RED = 0;
 LED_GREEN = 1;
 INTCON.GIE = 0;                                                // Disables all interrupts
 Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt8));                      // Write text "    Lid Open    " in first row
 if (b > 0)                                                     // If timer is not running
 Lcd_Out(2,7,CopyConst2Ram(msg,LCD_txt9));                      // Write text "STOP"
 else Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt5));                 // Write text " SET  TIME  LEFT" in first row
 LCD_2nd_row();                                                 // Execute function "void LCD_2nd_row()"
}
void START()
{
 if (LID == open)                                                // Open == 0
 {
  LIDOPEN();                                                    // Execute function "void LIDOPEN()"
 }
 if (LID == close)                                               // Close == 1
 {
  RELAY = 1;                                                    // Switch ON relay
  LED_RED = 1;                                                  // Switch ON RED LED
  LED_GREEN = 0;                                                // Switch OFF GREEN LED
  INTCON.GIE = 1;                                               // Enables all unmasked interrupts
  //b = 1;
  Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt5));                     // Write text "SET TIME LEFT" in first row
  LCD_2nd_row();                                                // Execute function "void LCD_2nd_row()"
  Lcd_Out(2,6,CopyConst2Ram(msg,LCD_txt10));                    // Write text "      " in second row
 }
}
void PAUSE()
{
 RELAY = 0;                                                      // Switch OFF relay
 LED_RED = 0;                                                    // Switch OFF RED LED
 LED_GREEN = 1;                                                  // Switch ON GREEN LED
 INTCON.GIE = 0;                                                 // Disables all interrupts
 if (LID == open)
 {
  LIDOPEN();                                                     // Execute function "void LIDOPEN()"
 }
 else
 Lcd_Out(2,7,CopyConst2Ram(msg,LCD_txt9));                       // Write text "STOP" in second row
 LCD_2nd_row();                                                  // Execute function "void LCD_2nd_row()"
}

void main()
{
 // registers and ports configuration
 OPTION_REG = 0b10000000;                   //Option register
 INTCON = 0b11000000;                       // Interrupt Control Register
 CM1CON0 = 0b00000000;                      // Comparator 1 Control Register
 CM2CON0 = 0b00000000;                      // Comparator 2 Control Register
 ANSEL = 0;                                 // Analog select Register
 ANSELH = 0;                                // Analog select High Register
 PIE1.TMR1IE = 0x01;                        // Timer1 interrupt enabled
 T1CON = 0b00000101;                        // Timer1 Control Register
 TMR1L = 0x00;                              // Reset Timer1 lower 8 bits
 TMR1H = 0x00;                              // Reset Timer1 upper 8 bits
 TRISA = 0b00111000;                        // TRISA Register
 TRISB = 0b01110000;                        // TRISB Register
 TRISC = 0b01000000;                        // TRISC Register
 PORTA = 0;                                 // PORTA Register
 PORTB = 0;                                 // PORTB Register
 PORTC = 0;                                 // PORTC Register

 Sound_Init(&PORTC, 4);                     // Configures the MCU pin RC4 for sound generation
 Lcd_Init();                                // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);                       // Clear LCD
 Lcd_Cmd(_LCD_CURSOR_OFF);                  // Turn cursor off
show_intro();                               // Show splash screen
 Tone1();
 Lcd_Cmd(_LCD_CLEAR);                       // Clear LCD
 Delay_ms(100);                             // 100 milliseconds delay
 Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt5));  // Write text "SET TIME LEFT" in first row
 Lcd_Out(2,1,CopyConst2Ram(msg,LCD_txt6));  // Write text "00:00      00:00" in second row

 b=1;
 LED_RED = 0;                                // LED RED off
 LED_GREEN = 0;                              // LED GREEN off
 RELAY = 0;                                  // RELAY off
 readsec=0;
 readmin=0;
 delay_ms(100);
 EEPROM_Write(0x10, 0);
 delay_ms(100);
 EEPROM_Write(0x20, 0);
 delay_ms(100);

 while(1)
 {
  if (Button(&PORTB, 4, 100, 1))                      // START Button Detect logical one
  {
   switch(b)
   {
    case 0: START();
            break;
    case 1: RELAY = 0;
            LED_RED = 0;
            LED_GREEN = 1;
            break;
    case 2: PAUSE();
            break;
    case 3: INTCON.GIE = 0;
    default: b = 1;                                      // Update flag
   }
   oldstate = 1;
  }

  if (oldstate && Button(&PORTB, 4, 100, 0))             // START Button Detect one-to-zero transition
  {
   b = 0;                                                // At first press counter run
   oldstate = 0;                                         // Update flag
   Tone1();                                              // Beep on if the button is pressed
  }

  if ((oldstate == 0) && (Button(&PORTB, 4, 100, 0)))    // START Button Detect one-to-zero transition
  { 
   b = 2;                                                // At second press counter paused                                               // At second press counter paused
   readsec = EEPROM_Read(0x10);
   readmin = EEPROM_Read(0x20);
   Tone1();                                              // Beep on if the button is pressed
  }

  if (Button(&PORTB, 5, 20, 1))                          // MIN Button Detect logical one
  {
   oldstate = 1;                                         // Update flag
  }
  
  if (oldstate && Button(&PORTB, 5, 20, 0))              // MIN Button Detect one-to-zero transition
  { 
   oldstate = 0;                                         // Update flag
   if (b == 0)
   {
    SetMinut = SetMinut;                                 // Can't increment minutes if timer is running
    LeftMinut = LeftMinut;
   }
   else
   { 
    if ((b != 0) && (Button(&PORTB, 5, 20, 0)) && (Button(&PORTB, 6, 20, 0)))
    {
     SetMinut = 0;                                        // If timer not running and Min+Sec are pressed
     LeftMinut = 0;                                       // then reset the set time
    }
    else
    {
     SetMinut++;                                          // If counter not running, increment Set ans Left minuts
     LeftMinut++;
    }
   }
   if (SetMinut>99) SetMinut=0;
   if (LeftMinut>99) LeftMinut=0;
   Lcd_Chr(2, 1, SetMinut/10 + '0');
   Lcd_Chr_CP(SetMinut%10 + '0');
   Lcd_Chr(2, 12, LeftMinut/10 + '0');
   Lcd_Chr_CP(LeftMinut%10 + '0');
   if (b != 0) Tone1();
  }

  EEPROM_Write(0x20, LeftMinut);

  if (Button(&PORTB, 6, 50, 1))                         // SEC Button Detect logical one
  {
   oldstate = 1;                                        // Update flag
  }
  
  if (oldstate && Button(&PORTB, 6, 20, 0))             // SEC Button Detect one-to-zero transition
  {
   oldstate = 0;                                        // Update flag
   if (b == 0)
   {
    SetSecond = SetSecond;                              // Can't increment seconds if counter is running
    LeftSecond = LeftSecond;
   }
   else
   { 
    if ((b != 0) && (Button(&PORTB, 5, 20, 0)) && (Button(&PORTB, 6, 20, 0)))
    {
     SetSecond = 0;                                      // If counter not running and Min+Sec are pressed
     LeftSecond = 0;                                     // then reset Set ans Left seconds
    }
    else
    {
     SetSecond++;                                        // If counter not running, increment
     LeftSecond++;                                       // Set ans Left seconds
    }
   }
   if (SetSecond>59)
   {
    SetSecond = 0;
    if ((b != 0) && (Button(&PORTB, 5, 20, 0)) && (Button(&PORTB, 6, 20, 0)))    // If counter not running and min+sec button are press
    SetMinut = 0;
    else
    SetMinut++;                                           // Increment SetMinut
    if (SetMinut>99) SetMinut = 0;
   }
   if (LeftSecond>59)
   {
    LeftSecond = 0;
    if ((b != 0) && (Button(&PORTB, 5, 20, 0)) && (Button(&PORTB, 6, 20, 0)))    // If counter not running and min+sec button are press
    LeftMinut = 0;
    else
    LeftMinut++;                                                                 // Increment LeftMinut
    if (LeftMinut>99) LeftMinut = 0;
   }
   LCD_2nd_row();
   if (b != 0)                                                                   // If counter not running play Tone1
   Tone1();
  }

  EEPROM_Write(0x10, LeftSecond);

  if ((b != 0) && (Button(&PORTB, 5, 1000, 0)) && (Button(&PORTB, 6, 1000, 0)))       // MIN + SEC Button
  {
   SetMinut = 0;
   SetSecond = 0;
   LeftSecond = 0;
   LeftMinut = 0;
   LCD_2nd_row();
   oldstate = 0;                                                   // Update flag
  }

  if ((readsec == 0) && (readmin == 0) && (b==0) && ((SetMinut || SetSecond) >= 0))
  b = 2;

  if (LID == close)                                               // LID Switch Detect logical one
  {
   //Lid = close;                                                    // Close == 1
   if (((SetMinut || SetSecond) > 0) &&  (LeftSecond == 0 && LeftMinut == 0))
   Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt7));                       // Write text "    The  End    "
   else
   Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt5));                       // Write text "SET TIME LEFT" in first row
   LED_YELLOW = 1;
  }
  else
  {
   LED_YELLOW = 0;
   LIDOPEN();
   b = 2;                                                           // b=2=PAUSE
  }

   if ((b == 0) && (LeftMinut == 0) && (LeftSecond <=5) && (LeftSecond >=0))
  {
   LED_RED = 0;
   Tone1();                                                         // Beep last 5 seconds
   LED_RED = 1;
   //Tone2();
  }
  
  if (((SetMinut || SetSecond) > 0) &&  (LeftSecond == 0) && (LeftMinut == 0))     // When time elapsed
  {
   b = 1;                                                         // RELAY=0, LED_RED = 0, LED_GREEN=1
   if (LID == close)                                              // If Lid closed
   Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt7));                      // Write text "    The  End    "
   else                                                           // If Lid opened
   LIDOPEN();                                                     // Execute function "void LIDOPEN()"
   //LCD_2nd_row();
   Delay_ms(30);
   EEPROM_Write(0x30, SetMinut);                                  // Write in the memory the last set time
   Delay_ms(30);
   EEPROM_Write(0x40, SetSecond);
  }
  
  if ((b != 0) && (Button(&PORTB, 4, 1000, 0)) && (Button(&PORTB, 5, 1000, 0)))       // START + MIN Button
  {
   LeftMinut = SetMinut = EEPROM_Read(0x30);                      // Read from memory the last time set
   LeftSecond = SetSecond = EEPROM_Read(0x40);
   Lcd_Out(1,1,CopyConst2Ram(msg,LCD_txt5));                      // Write text " SET  TIME  LEFT"
   LCD_2nd_row();
   b = 2;                                                         // Update flag  (b=2=PAUSE)
  }
 }
}

UV box timer PIC16F690.Rev00.rar

Editat de danpin
Link spre comentariu
  • Răspunsuri 4
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Top autori în acest subiect

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