CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Help with PIC16F818
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Namams



Joined: 01 Feb 2019
Posts: 9

View user's profile Send private message

Help with PIC16F818
PostPosted: Fri Feb 01, 2019 3:56 pm     Reply with quote

I'm a newbie to this site, so please excuse me if I'm posting in the wrong forum section, or if my question is too elementary. I've just recently started using MPLab with a CCS complier to program a PIC16F819 I'm trying to write a code in which a single LED is switched on if 2 certain switches are pressed within 2 seconds of each other. I've started a basic code in which I have 4 inputs (switches) and four outputs (LED's) at the moment each switch corresponds to a single LED so if I was to press switch1 then LED1 lights up.

I want to program the PIC so that LED1 would light up if I was to press switch1 and then switch2 (within 2 seconds of each other).

I was thinking of having a timer running in the background so when the first button is pressed, it makes a copy of the current time and when the second button is pressed, it takes another copy of the current time. I could then subtract the first time from the second time to see the difference between them. If the difference is 2 seconds or less, then the LED would light up.

However, I have no idea how to program the above can someone please help me with the coding required.
Thanks in advance.

Current code:
Code:

#include <16F819.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,MCLR,NOBROWNOUT
#use delay(clock=4000000)

#define SW2 PIN_B7
#define SW2 PIN_B6
#define SW3 PIN_B5
#define SW4 PIN_B4
#define LED1 PIN_B3
#define LED2 PIN_B2
#define LED3 PIN_B1
#define LED4 PIN_B0

void main()
{
port_b_pullups(TRUE);

while(1)
  {
   if(!input(SW1)) output_high(LED1);
   if(!input(SW2)) output_high(LED2);
   if(!input(SW3)) output_high(LED3);
   if(!input(SW4)) output_high(LED4);
  }
}
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 5:51 am     Reply with quote

Hi,

the code is completely untested, but this is how I would do it. I'm sure there are easier ways :-)

Code:

#include <main.h>


#define SW1 PIN_B7
#define SW2 PIN_B6
#define SW3 PIN_B5
#define SW4 PIN_B4
#define LED1 PIN_B3
#define LED2 PIN_B2
#define LED3 PIN_B1
#define LED4 PIN_B0

int1 GO = 0;
int1 SW1_PRESSED = 0;
int1 SW2_PRESSED = 0;
int1 SW3_PRESSED = 0;
int1 SW4_PRESSED = 0;       
int8 LIGHT_LED1 = 0;    // LED1 state machine
#define LED1_SW1 0      // states for LED1                         
#define LED1_SW2 1
#define LED1_ON 2
int8 Counter1 = 0;      // counter between two switches

#INT_RB
void  RB_isr(void) {             // something changed

   if(!input_state(SW1)){           // SW1 level = 0V. I presume that you close the switch to 0   
      SW1_PRESSED = 1;
   }
   else{
      SW1_PRESSED = 0;
   }
   if(!input_state(SW2)){            // SW2 level = 0V. I presume that you close the switch to 0   
      SW2_PRESSED = 1;
   }
   else{
      SW2_PRESSED = 0;
   }
   if(!input_state(SW3)){            // SW3 level = 0V. I presume that you close the switch to 0   
      SW3_PRESSED = 1;
   }
   else{                                         
      SW3_PRESSED = 0;
   }                                         
   if(!input_state(SW4)){            // SW4 level = 0V. I presume that you close the switch to 0   
      SW4_PRESSED = 1;
   }
   else{                                       
      SW4_PRESSED = 0;
   }                                     
}


#INT_TIMER1                   // 131ms overflow                   
void  TIMER1_isr(void) {

}

#INT_TIMER0                   // 65,5ms overflow
void  TIMER0_isr(void) {
   GO = 1;
}

void main() {
   port_b_pullups(0xFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);       //65,5 ms overflow
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);                     //131 ms overflow
   setup_timer_2(T2_DIV_BY_16,77,16);                          //1,2 ms overflow, 19,9 ms interrupt


   enable_interrupts(INT_RB);
   enable_interrupts(INT_TIMER1);                   
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   while(TRUE){
      if(GO){
         GO = 0;                                // execute this loop every 65,5ms
         
// ******************** check LED1 condition **********************************         
         switch (LIGHT_LED1){                  // nothing is pressed, we are waiting for SW1 to be pressed
            case LED1_SW1:{
               if(SW1_pressed){                 // we have SW1 press, go check SW2                         
               Counter1 = 0;
               LIGHT_LED1 = LED1_SW2;           // proceed to SW2 wait
               break;
               }                                                           
            }                                       
            case LED1_SW2:{
               Counter1++;
               if(Counter1 > 31){
                  LIGHT_LED1 = LED1_SW1;        // go back waiting for SW1, we waited for more than 2s 65,5ms * 32
                  break;
               }
               if(SW2_pressed){                     
                  LIGHT_LED1 = LED1_ON;         //  proceed to turn on LED1                                                 
                  break;
               }
             
            }                                         
               
            case LED1_ON:{                             
               output_low(LED1);               
               break;
            }                                                             
         }              // switch LIGHT_LED1 brace
// ************************ END LED1 check ************************************         
     
      }                 // if GO brace


   }                    // while brace

}                     


Please note, you have no debouncing and no code to turn the LED1 off.

Regards
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 5:52 am     Reply with quote

and main.h
Code:

#include <16F819.h>
#device ADC=10
#use delay(internal=4000000)
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 6:03 am     Reply with quote

First error, the code never exits case 2. It should be:


if(SW2_pressed){
LIGHT_LED1 = LED1_ON; // proceed to turn on LED1
break;
}
else{
break;
}

And I chose the wrong pic, 819 instead of 818
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 8:08 am     Reply with quote

Spotted another mistake, break in case. This is the corrected version:
Code:

#include <main.h>


#define SW1 PIN_B7
#define SW2 PIN_B6
#define SW3 PIN_B5
#define SW4 PIN_B4
#define LED1 PIN_B3
#define LED2 PIN_B2
#define LED3 PIN_B1
#define LED4 PIN_B0

int1 GO = 0;                           
int1 SW1_PRESSED = 0;
int1 SW2_PRESSED = 0;
int1 SW3_PRESSED = 0;
int1 SW4_PRESSED = 0;       
int8 LIGHT_LED1 = 0;    // LED1 state machine
#define LED1_SW1 0      // states for LED1                         
#define LED1_SW2 1
#define LED1_ON 2
int8 Counter1 = 0;      // counter between two switches

#INT_RB
void  RB_isr(void) {             // something changed

   if(!input_state(SW1)){           // SW1 level = 0V. I presume that you close the switch to 0   
      SW1_PRESSED = 1;
   }
   else{
      SW1_PRESSED = 0;
   }
   if(!input_state(SW2)){            // SW2 level = 0V. I presume that you close the switch to 0   
      SW2_PRESSED = 1;
   }
   else{
      SW2_PRESSED = 0;
   }
   if(!input_state(SW3)){            // SW3 level = 0V. I presume that you close the switch to 0   
      SW3_PRESSED = 1;
   }
   else{                                         
      SW3_PRESSED = 0;
   }                                         
   if(!input_state(SW4)){            // SW4 level = 0V. I presume that you close the switch to 0   
      SW4_PRESSED = 1;
   }
   else{                                       
      SW4_PRESSED = 0;
   }                                     
}


#INT_TIMER1                   // 131ms overflow                   
void  TIMER1_isr(void) {

}

#INT_TIMER0                   // 65,5ms overflow
void  TIMER0_isr(void) {
   GO = 1;
}

void main() {
   port_b_pullups(0xFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);       //65,5 ms overflow
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);                     //131 ms overflow
   setup_timer_2(T2_DIV_BY_16,77,16);                          //1,2 ms overflow, 19,9 ms interrupt


   enable_interrupts(INT_RB);
   enable_interrupts(INT_TIMER1);                   
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   while(TRUE){
      if(GO){
         GO = 0;                                // execute this loop every 65,5ms
         
// ******************** check LED1 condition **********************************         
         switch (LIGHT_LED1){                  // nothing is pressed, we are waiting for SW1 to be pressed
            case LED1_SW1:{
               if(SW1_pressed){                 // we have SW1 press, go check SW2                         
                  Counter1 = 0;
                  LIGHT_LED1 = LED1_SW2;           // proceed to SW2 wait               
                  }
               break;
            }                                       
            case LED1_SW2:{                               
               Counter1++;
               if(Counter1 > 31){
                  LIGHT_LED1 = LED1_SW1;        // go back waiting for SW1, we waited for more than 2s 65,5ms * 32
                  break;
               }
               if(SW2_pressed){                     
                  LIGHT_LED1 = LED1_ON;         //  proceed to turn on LED1                                                                   
               }
               break;                     
            }                                         
               
            case LED1_ON:{                             
               output_low(LED1);               
               break;
            }                                                             
         }              // switch LIGHT_LED1 brace
// ************************ END LED1 check ************************************         
     
      }                 // if GO brace

                                               
   }                    // while brace

}
Namams



Joined: 01 Feb 2019
Posts: 9

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 8:30 am     Reply with quote

Thank you that's really helpful I think I understand most of it I just wanted to ask if the code would keep the LED on after both buttons are pressed( or if it switches off after a while) . Also if I want to do the same thing multipule times using different switch combinations would I copy the same body of test but just change the switches and LED's accordingly. Thank you again for your reply
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 8:50 am     Reply with quote

Right now the diode stays lit, but you could easily add some code to turn it off after a while or when you press some key. Please test first if this part works as intended.

Regards,
Samo
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 02, 2019 9:56 am     Reply with quote

I just tested it, it works. I changed SW1 and SW2 to B4 and B5 so to be able to use the debugger and added some code that switches the diode off after a while.
Code:

   while(TRUE){
      if(GO){
         GO = 0;                                   // execute this loop every 65,5ms
         
// ******************** check LED1 condition **********************************         
         switch (LIGHT_LED1){                      // nothing is pressed, we are waiting for SW1 to be pressed
            case LED1_SW1:{
               output_high(LED1);                  // turn off the led
               if(SW1_pressed){                    // we have SW1 press, go check SW2                         
                  Counter1 = 0;
                  LIGHT_LED1 = LED1_SW2;           // proceed to SW2 wait               
                  }
               break;
            }                                       
            case LED1_SW2:{                               
               Counter1++;
               if(Counter1 > 31){
                  LIGHT_LED1 = LED1_SW1;           // go back waiting for SW1, we waited for more than 2s 65,5ms * 32
                  break;
               }
               if(SW2_pressed){                     
                  LIGHT_LED1 = LED1_ON;            //  proceed to turn on LED1
                  Counter1 = 0;
               }
               break;                     
            }                                         
               
            case LED1_ON:{             
               Counter1++;                         // Counter1 is zero when we come here
               if(Counter1 < 50){
                  output_low(LED1);                // turn on the led                                                                           
               }
               else{
                  Counter1 = 0;
                  LIGHT_LED1 =  LED1_SW1;          // leave the led on for a while, then go to beggining
               }
                break;                                   
            }                                                             
         }              // switch LIGHT_LED1 brace
// ************************ END LED1 check ************************************         
     
      }                 // if GO brace                                       

   }                     // while(TRUE) brace
Namams



Joined: 01 Feb 2019
Posts: 9

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 4:36 am     Reply with quote

Hi I've just tried the code but it doesn't see to be doing anything, the LED stays off regardless of if the switches are pressed or not.

Also can you please explain the setup_timer lines of the code.For example I understand that the DIV_BY is used to set the prescaler but why does timer 2 say DIV_BY_16,77,16 and why does it not have the _INTERNAL part like the other 2 timers.Finally can you also explain the switch case loop briefly.

If it's possible can you please upload a image of your circuit setup so I can compare it to mine to see if I have made an error setting it up.

Thank you again for taking time to help me.


Last edited by Namams on Mon Feb 04, 2019 4:53 am; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 4:46 am     Reply with quote

You do have pull up resistors on the switches?.

The code all assumes that the pins have resistors on them (perhaps 10KR)
pulling the pins 'up' to the supply. Then the switches pull the pins down.
So when the switch is 'on', the input is 0v, and when the switch is 'off' the
input goes up to the supply voltage.
Namams



Joined: 01 Feb 2019
Posts: 9

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 4:48 am     Reply with quote

Yep the switches are connected to pull up resistors
temtronic



Joined: 01 Jul 2010
Posts: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 5:53 am     Reply with quote

also, you should have a small value cap, say .1mfd across the switch (parallel). This will help minimize or reduce contact bounce'. Without it, the switch will give several '1-0-1-0' levels for every press. This is a hardware solution. You can and should also add a software delay(10-50 ms) when reading pushbuttons.

you can use the light blue search button ,enter 'bounce' and you'' get a lot of hits.
Jay
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 7:19 am     Reply with quote

Hi,

the code was tested on 18f252. The setup is very simple, PIC, two push button switches and 4 wires. I didn't even use external resistors. Can you confirm that your PIC is working? Maybe by turning a LED on at the start? And if it is, then turn a LED on when the PIC enters the interrupt routine, to see if it ever comes there at all. Please check if the push of the button actually changes the voltage from 5V to 0V on those two pins.

As for the timers, the built-in wizard in CCS created the code :-). I did an excel spreadsheet once to see how it works and what the numbers mean, but I must admit that I'm too lazy to do it by hand. Anyway, the code doesn't use Timer2.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 8:02 am     Reply with quote

and, of 'why it doesn't have INTERNAL', this is a read the data sheet and look
at the header question.
Basically Timer2 on most of the standard PIC's, has 'no choice' about where
it is fed from. No external input pin, only capable of being fed from the
internal oscillator, so no selection has to be made.
If you look at the block diagram in the data sheet, the only clock input
to timer2, is Fosc/4. Nothing else.
PrinceNai



Joined: 31 Oct 2016
Posts: 481
Location: Montenegro

View user's profile Send private message

PostPosted: Mon Feb 04, 2019 8:19 am     Reply with quote

Please also check how the LED is oriented. It should go from 5V to the PIC pin. 0V on that pin turns the diode on.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group