Calculating the time a button is held

Calculating the time a button is held

Postby Ricard.Sebastien » Mon Oct 26, 2015 4:03 pm

Hello again,

I am creating a program that will blink an LED light at the speed of which you hold and release a button. I therefore want a timer to count the time the button is held so that I can pass it as an argument through the __delay_ms function. I am using XC16 compiler and have found the time.h in the 16bit language tools library (XC.h).

Here are my encountered problems:

- The functions that I have found only count in seconds. I would like it to be able to count milliseconds
.
- Both clock_t and time_t don't appear to give me the actual time in seconds. I've read that the time function returns clock cycles by default for the 16 bit compiler and that you must do something within the pic30 libs to customize this. However, I haven't been able to find out how to do this. I found this information on this link: http://ww1.microchip.com/downloads/en/d ... 51456b.pdf (Page 366) (It is explained how to rebuild on this page, but it is for the C30 and also I didn't find the file)

Here is the code I am writing. The code runs, but the Elapsed time is random numbers. Sometimes I get numbers in the tens of thousands, sometimes in the hundreds and sometimes negative numbers. I am new to MPLAB and somewhat new to programming. I am sure there are unoptimized lines of code. Any advice is very welcome.

Thank you very much
Sebastien

Code: Select all
#include "xc.h"
#include <time.h>
#include "LCD.h"
#include <stdio.h> /* for printf */

#define FOSC    (7370000ULL)    // Defining Oscillator Speed
#define FCY     (FOSC/2)        // Defining Clock
#include <libpic30.h>           // Includes delay function

int main(void) {
 
    LCD_Initialize();
    TRISDbits.TRISD6 = 1;   /*  made this pin as input  */
    TRISAbits.TRISA7 = 0;
    TRISAbits.TRISA6 = 0;
    LATAbits.LATA7 = 1;
   
    time_t start, stop;
    int Elapsed;
    int count;
    char Time[33];
   
    stop = NULL;
   
    while(1){
       
        if(!PORTDbits.RD6){
            start = NULL;
            time(&start);
            LATAbits.LATA6 = 1;
            stop = NULL;
            while(!PORTDbits.RD6);
        }
   
        while(PORTDbits.RD6){
       
            if(!LATAbits.LATA6){ // For Startup
                count++;                // Only here so that there is something in the if statement.
            }
           
            else{
                if(stop == NULL)
                    time(&stop);
               
                Elapsed = difftime(stop, start);
                LATAbits.LATA7 = 0;
                LATAbits.LATA6 = 0;
               
                sprintf(Time, "%d", Elapsed);
                LCD_PutString(Time, 10);
                __delay_ms(1000);
               
                LATAbits.LATA7 = 1;           
       
                __delay_ms(1000)
           
                LATAbits.LATA6 = 1;
                LCD_ClearScreen();
            }
         
        }

    }
   
   
    return 0;
}
Ricard.Sebastien
 
Posts: 3
Joined: Mon Oct 19, 2015 9:05 pm

Re: Calculating the time a button is held

Postby jtemples » Mon Oct 26, 2015 8:06 pm

Forget about the functions in time.h; they are not useful for what you want to do. Start a hardware timer when the button is pressed, and stop it when the button is released, then inspect the timer value and do what you want with it. You can easily convert that time to seconds or milliseconds or whatever you want.
jtemples
Verified identity
 
Posts: 195
Joined: Sun May 25, 2014 2:23 am
Location: The 805
PIC experience: Professional 5+ years with MCHP products

Re: Calculating the time a button is held

Postby AussieSusan » Tue Oct 27, 2015 3:13 am

Also don't forget to account for the button debounce. While you might get away with no debouncing when the button is pressed, with your code you will have the time reset by the bouncing as you release the button.
Susan
AussieSusan
Verified identity
 
Posts: 173
Joined: Mon Jun 16, 2014 4:45 am
PIC experience: Experienced Hobbyist

Re: Calculating the time a button is held

Postby Ricard.Sebastien » Tue Oct 27, 2015 9:32 pm

To Jtemples: So I've got it to work with the time.h function. It is not perfectly precise, but it does count milliseconds. I plan on doing a version where I use the hardware peripheral timer. Do you know of any tutorials that explain well and in a simple matter the hardware timer for dsPIC33F? Which timer should I use? Timer1 or Timer0? I've looked but I haven't wrapped my head around the explanations I've read thus far.

I really value your judgment since I see you have more than 5 years experience with micro controllers. I was wondering, how do I determine whether it is more better to use software libraries or peripherals?

To Susan: Thank you for your advice for this post and my last. I have been looking into debouncing. I haven't got the code down yet but I'm working at it. Basically, the logic is I've got to check the value twice in an interval of around 20ms to prevent the pic thinking I've pressed, or unpressed a button more than once. Is that correct?

Thank you both.

For anyone who is interested, here is my working code so far. For it to run, you must add the lcd.h and lcd.c given in the dsPIC33FJ256GP710A LCD sample code for explorer 16. If you have trouble finding it, I can try and explain it more clearly.

Code: Select all
#include "xc.h"
#include <time.h>
#include "LCD.h"
#include <stdio.h> /* for printf */
#include <string.h>



#define FOSC    (7370000ULL)    // Defining Oscillator Speed
#define FCY     (FOSC/2)        // Defining Clock
#include <libpic30.h>           // Includes delay function

int main(void) {
 
    LCD_Initialize();
    TRISDbits.TRISD6 = 1;   //  made this pin as Input
    TRISAbits.TRISA7 = 0;   //  made this pin as Output
    TRISAbits.TRISA6 = 0;
    LATAbits.LATA7 = 1;     //  Turn LED D10 ON
   
    clock_t start, stop;    //  Datatype (Or struct) clock_t, gathers seconds
    int count;              //  Dummy variable to have a loop
    char Time[33];          //  Blink rate displayed on LCD
    start = NULL;           //  Time variable
    stop = NULL;            //  Time variable
   
    while(1){
       
        if(!PORTDbits.RD6){ //  While Button S3 is PRESSED, starts time
            start = NULL;   //  Clears timer for new measurement
            stop = NULL;    //  Clears timer for new measurement
            start = clock();//  Starts timer
            LATAbits.LATA6 = 1; //  Visual aide to determine that timer has effectively started   
            LCD_ClearScreen();
            while(!PORTDbits.RD6);
        }
   
       
       
        if(PORTDbits.RD6)   //  While button S3 is NOT PRESSED, blinks LED
        {
            if(!LATAbits.LATA6){ // For initial startup (when button has never been pressed) IDLE MODE
                count++;
            }
           
            else{                       
                if(stop == NULL){   //  To make sure time is only changed when the button is pressed
                    stop = clock(); //  Takes measurement of time
                   
                }
                float seconds = (float) (stop - start)/3884;    //  Determines interval of time PRESSED. Divided by constant I determined experimentally
                LATAbits.LATA7 = 0; //  Start Blinking process. Turn LED D10 off
                LATAbits.LATA6 = 0; //  Start Blinking process. Turn LED D9 off                                         
               
               
                __delay_ms(seconds);
               
                int secondsDisp = (int) seconds;    //  Convert time measured to integer for Display purposes
                sprintf(Time, "%d", secondsDisp);   //  Convert time into string for LCD purposes
               
                char milli[30] = " ms";
                strncat(Time, milli, 3);            //  Append ms to display
                if(LATE == 0x0002)                  //  Writes on LCD if it has is empty
                    LCD_PutString(Time, 16);   
                LATAbits.LATA7 = 1;                 //  Turn ON LED D10
       
                __delay_ms(seconds)
           
                LATAbits.LATA6 = 1;                 //  Turn ON LED D9                   
            }
         
        }

    }
    return 0;
}
Ricard.Sebastien
 
Posts: 3
Joined: Mon Oct 19, 2015 9:05 pm

Re: Calculating the time a button is held

Postby jtemples » Wed Oct 28, 2015 6:24 am

I don't know of any tutorials, but setting up a timer is straightforward. You can do something like

Code: Select all
T1CONbits.TCKPS = 3;   // 256:1 prescale
TMR1 = 0;
T1CONbits.TON = 1;     // start timer

when the button is pressed, then just clear TON when the button is released, and read TMR1. TMR1 will increment at 1/512th of your clock speed, so you can convert its contents back to real time. If that doesn't provide enough range for your requirements, you can chain timers 2 and 3 together to get a 32-bit timer.
jtemples
Verified identity
 
Posts: 195
Joined: Sun May 25, 2014 2:23 am
Location: The 805
PIC experience: Professional 5+ years with MCHP products


Return to dsPIC33F

Who is online

Users browsing this forum: No registered users and 2 guests