• AVR Freaks

AnsweredHot!Need help for input capture for dsPIC33

Page: 12 > Showing page 1 of 2
Author
mgs166
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/09/08 16:16:38
  • Location: 0
  • Status: offline
2019/09/09 12:19:38 (permalink)
0

Need help for input capture for dsPIC33

Hello everyone,
 
I am relatively new to dsPIC programming and this is my first post on the Microchip forum.  My question involves a project that I am working on which utilizes a dsPIC33EP64MC502 that will be used to measure the walking speed of an elderly person during a 4 meter walk and will display the speed in m/s on an LCD.  I am using an ultrasonic sensor that outputs an analog voltage which is directly proportional to distance.  The theory of operation is as follows:  The person stands in front of the sensor facing away from the sensor.  The person starts walking.  When the person is 2 meters from the sensor a timer is started.  Once the person is 6 meters away from the sensor the timer is stopped.  By dividing the distance by the elapsed time the person's walking speed can be calculated.  My question concerns the elapsed time acquisition.  I have a good deal of the code completed already, I just don't know how to obtain the elapsed time.  After looking through all of the data sheets and manuals that I could find, it seems that I could use either input capture or a timer of some sort with interrupt. With input capture and having the pin (IC1R) go high when the person passes the 2 meter mark and keeping it high until they pass the 6 meter mark when it would then be set low.  The project boils down to measuring the width of a single pulse whose width could be 30 seconds or more.  I'm just not sure how to write the input capture code or the interrupt service routine code or where to put them in the main code.  Please see the attached code that I have completed so far.  Thank you very much in advance for your help.
 
 
 
 
********************************************MAIN CODE*********************************8*****
/* define FCY before including libpic30.h */
#define FCY 3685000UL

#include <p33EP64MC502.h>
#include <libpic30.h>
#include <stdio.h>
 
 
#include <math.h>
#include <xc.h>
#include "EE200_LCD.h"

/* set Configuration Bits */
#pragma config ICS = PGD2    // communicate on PGED2 (pin 14) and PGEC2 (pin 15)
#pragma config JTAGEN = OFF  // disable JTAG inorder to use RB8 through RB11


/* declare functions */
void Init_ADC(void);
double Read_ADC(int channel);


void Init_ADC (void) {
    ANSELAbits.ANSA0 = 1;  // set pin 2 (ANO) for analog input
    TRISAbits.TRISA0 = 1;  // configure for input (disable DO)

    AD1CON1bits.ADON = 1;  // turn ADC module on
  }

double Read_ADC(int channel) {
    double Vmeas;
    
    AD1CHS0 = channel;         // choose CH-0 positive input
    AD1CON1bits.SAMP = 1;      // start sample; place input signal across cap
    __delay_us(10);            // wait for cap voltage to track analog input
    AD1CON1bits.SAMP = 0;      // start SA converter
    while (!AD1CON1bits.DONE); // wait for SA conversion to complete
    Vmeas = 3.3 * (double) ADC1BUF0 / 1023.0; // convert to units of volts
    
    return Vmeas;  
}


int main(void) {
    char Line_char_Array[16];
    unsigned int TS;
    double Volt, Time_elapsed;

    /* Set Parameters */
    TS = 50;                // sample period in ms
    Time_elapsed = 0;
    
    Init_LCD_Module();
    Init_ADC();
        
    while (1) {
       __delay_ms(TS);      // set sample rate to 50 ms

       /* Acquire analog input signal */
       Volt = Read_ADC(0); // read voltage (distance) on pin 2 (ANO)
        //  If Volt >= 2 meters
           // LATBbits.LATB15 = 1; //write a logic high to pin 26 and get timer value from input capture
        //  Else If Volt > 6 meters
          //  LATBbits.LATB15 = 0;  //write a logic low to pin 26 and get timer value from input capture
            
                 
       
            
            /* Update LCD */
     // Position_LCD_Cursor(0x00); // place cursor at cell 0x00
     //  sprintf(Line_char_Array,"Distance: 4m", "Speed: ", "distance/(Time_2 - Time_1");
     //  Write_LCD_String(Line_char_Array);

       ClrWdt(); // restart the watchdog timer
    }
    return 0;
}
 
 
 
 
******************************************INPUT CAPTURE CODE*******************************
#define FCY 3685000UL

#include <p33EP64MC502.h>
#include <libpic30.h>
#include <xc.h>
#include <incap.h>


void Init_Capture (void);
void __attribute__((__interrupt__,no_auto_psv)) _IC1Interrupt (void);
double Count;

void Init_Capture (void)
{
    IFS0bits.IC1IF = 0;            //clear the IC1 interrupt status flag
    IEC0bits.IC1IE = 1;            //enable IC1 interrupts
    IPC0bits.IC1IP = 1;            //set module interrupt priority as 1
    
    IC1CON1bits.ICTSEL = 0b11;     //use peripheral clock source
    IC1CON1bits.ICI = 1;           //interrupt on every capture event
    
    IC1CON1bits.ICBNE = 0;         //input capture is empty
    IC1CON1bits.ICM = 1;           //capture on every rising and falling edge
    
    IC1CON2bits.IC32 = 0;          //disable cascade operation
    IC1CON2bits.ICTRIG = 0;        //input source used to synchronize the input
                                              //capture of another module (synchronization mode)
    IC1CON2bits.TRIGSTAT = 0;      //IC1TMR has not been triggered and is being held clear
    IC1CON2bits.SYNCSEL = 0;       //no synch or trigger source for the IC1 module
    
    TRISBbits.TRISB15 = 1;         //configure pin RPI47 for input
    RPINR7bits.IC1R = 0x2F;        //use pin RPI47 (pin 26) for capture trigger
    
unsigned int Time_1, Time_2;   
void __attribute__((__interrupt__,no_auto_psv)) _IC1Interrupt (void)
    {
       IFS0bits.IC1IF = 0;         //reset the interrupt flag
       Time_1 = IC1BUF;            //read and save first capture entry
       Time_2 = IC1BUF;            //read and save second capture entry
    }
   
}


 
********************************LCD CODE*************************************************
 
/* define FCY before including libpic30.h */
#define FCY 3685000UL

#include <p33EP64MC502.h>
#include <libpic30.h>
#include <string.h>

/* define constants for programming the LCD module */
#define pgm_delay_ms 2
#define INSTRUCTION 0
#define DATA 1

/* declare local functions */
void Init_LCD_DIO_Port(void);
void Toggle_Enable_line(void);
void Write_LCD_Nibble(int data, int cmd);
void Write_LCD_Byte(int data, int cmd);

/* declare global functions */
void Init_LCD_Module(void);
void Position_Cursor(int cell_num);
void Write_LCD_String(char char_Array[16]);

void Init_LCD_DIO_Port (void) {
    ANSELB = 0;     // use peripheral pins associated with PORTB for digital I/O
    TRISB = 0xC0FF; // set RB8 to RB13 for output, the rest for input
    PORTB =  0;     // set all LCD inputs low
  }

void Toggle_Enable_line (void) {
    __delay_ms(pgm_delay_ms);   // delay
    PORTBbits.RB13 = 1;         // set E high
    __delay_ms(pgm_delay_ms);   // delay
    PORTBbits.RB13 = 0;         // set E low
    __delay_ms(pgm_delay_ms);   // delay
}

void Write_LCD_Nibble(int data, int cmd) {
 PORTB =  data << 8;     // place nibble at LCD inputs DB4 through DB7
 PORTBbits.RB12 = cmd;   // set RS; cmd = 0 for instruction, 1 for data
 Toggle_Enable_line ();  // strobe data into LCD module
 PORTB =  0;             // set all LCD inputs low
}

void Write_LCD_Byte(int data, int cmd) {
    Write_LCD_Nibble((data & 0x00F0) >> 4, cmd); // write upper nibble
    Write_LCD_Nibble( data & 0x000F, cmd);       // write lower nibble
}

void Init_LCD_Module(void) {
    Init_LCD_DIO_Port(); // Configure RB8 through RB13 for digital output
    Write_LCD_Nibble(0b0011, INSTRUCTION);  // Initialize the LCD Module
    Write_LCD_Nibble(0b0011, INSTRUCTION);
    Write_LCD_Nibble(0b0011, INSTRUCTION);
    Write_LCD_Nibble(0b0010, INSTRUCTION);  // invoke 4-bit mode
    Write_LCD_Byte(0b00101000, INSTRUCTION);// 4-bit mode, two-line,5X7 dot
    Write_LCD_Byte(0b00000001, INSTRUCTION);// clear display, cursor at 0x00
    Write_LCD_Byte(0b00001100, INSTRUCTION);// display on,cursor off
}

void Position_LCD_Cursor(int cell_num) {
    Write_LCD_Byte(0x80 + cell_num, INSTRUCTION);
}

void Write_LCD_String(char char_Array[16]) {
    int idx;

    for(idx = 0; idx < strlen(char_Array); idx++)
        Write_LCD_Byte(char_Array[idx], DATA);  
}
#1
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3292
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/09 14:27:29 (permalink) ☄ Helpfulby mgs166 2019/09/09 18:09:54
5 (1)
This 2 Metre distance, is that when maximum volocity is obtained from the Elderly Person?
 
Are you calculating the speed of the Elderly Person ?
(I hope He/She are not part of your wicked Frankenstein experiments)
 
Why not set up some Matrix style cameras?
 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#2
Gort2015
Klaatu Barada Nikto
  • Total Posts : 3292
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/09 14:35:19 (permalink) ☄ Helpfulby mgs166 2019/09/09 18:09:52
5 (1)
That was short for use code tags.
 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#3
du00000001
Just Some Member
  • Total Posts : 3066
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/09 14:47:35 (permalink) ☼ Best Answerby mgs166 2019/09/09 18:13:12
5 (1)
Provided the ultrasonic sensor's analog output is connected to the dsPIC, there's nothing söuseful to do with input capture. A sensible solution would be the following:
  • Set up some timer (interrupt).
  • Once the 2 m mark is passed, have the timer increment some variable that had been set to 0 before.
  • Once the 4 m mark is passed, stop the timer incrementing.
Now you have the ms for the 2 m distance. A simple division will give you the speed.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#4
ric
Super Member
  • Total Posts : 23860
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Need help for input capture for dsPIC33 2019/09/09 15:50:01 (permalink) ☄ Helpfulby mgs166 2019/09/09 18:09:43
4 (1)
n.b. Just expanding on the above.
Set the timer interrupt for a 1ms interval (i.e. 1000 Hz). Then your count will give the time in milliseconds.

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#5
mgs166
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/09/08 16:16:38
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/09 19:01:04 (permalink)
0
Thank you all very much for your suggestions.  I will first try creating an up counter.  It will begin incrementing the moment that the person is 2 meters away from the sensor and will stop incrementing once the person passes the 6 meter mark.  Also, yes the analog output from the sensor is connected to an analog input on the device (pin 2, analog input AN0).  I'm reading the voltage on this pin in order to determine the distance since they are directlly proportional.  If I can't get the counter to work, I will try an interrupt with a timer.  Since the time interval could be lengthy, will I have problems with the timer rolling over and, thus, give me an inaccurate time interval?  Thanks again everyone.
#6
ric
Super Member
  • Total Posts : 23860
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Need help for input capture for dsPIC33 2019/09/09 19:14:06 (permalink)
0
I would recommend doing the ADC reading in the timer interrupt.
I haven't worked with PIC33 devices, but in most you can start a conversion at the end of one timer interrupt service, and read the result in the next one. That means you're sampling at precisely 1 kHz, and it has 1ms to do the conversion.

Since the time interval could be lengthy, will I have problems with the timer rolling over and, thus, give me an inaccurate time interval?  Thanks again everyone.

The "timer" is rolling over every 1 millisecond. It's your counter variable that you have to worry about rolling over.
A 16 bit unsigned variable can count to 65535, so that's over 65 seconds if you're counting in milliseconds.
Hopefully your target can cover the 2 meter distance in less than 65 seconds!
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#7
du00000001
Just Some Member
  • Total Posts : 3066
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/10 00:32:34 (permalink)
0
When counting ms, a 16-Bit counter (as already stated) will give you a max 8nterval of about 65 s - a good minute.
Longer intervals can be realized by lowering the"tick rate" - 2 ms or 5 ms instead of 1 ms (we're not exactly on the race track). Or by using a larger counter - e.g. 32 Bits: > 65 k minutes would certainly be more than enough.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#8
mgs166
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/09/08 16:16:38
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/11 11:41:30 (permalink)
0
Good afternoon Microchip community.  Thank you all again for your previous replies to my question. 
 
Since the time intervals are lengthy for my project, I decided to just go with a simple counter that will start incrementing when the person is 2 meters away from the ultrasonic transducer and will stop incrementing when they are 6 meters away from the sensor.  Please see my code below.  The LCD display does show the counter incrementing in 0.01 steps. My question is:  How can I get the counter to count accurately?  For example, it takes my counter roughly 55 seconds to count to 10 when it should take only 10 seconds.  I have created counters before, but I never needed them to be counting accurately in real-time. 
 
Also, how can I save the initial Distance value (the distance the person is away from the sensor when the system is turned on) and the final Time_elapsed value (time taken for person to walk 4 meters) for future use?  For example, if the person has finished their 4 meter walk and they turn around and walk back towards the sensor, the counter will start incrementing again since the person is back within the range in which the counter is active.
 
while (1)
    {
      Distance = Read_ADC(0);                           // read voltage (Distance) on pin 2 (ANO)
        
      if (Distance >=1 && Distance <=3)              // person within measurement region
           Time_elapsed = Time_elapsed + 0.01;    // count in 10ms increments
       else if (Distance <1 || Distance >3)            // person not within measurement region
           Time_elapsed = Time_elapsed;              // don't increment counter
    }
 
Again, I would like to thank everyone in advance for any help / guidance.
#9
du00000001
Just Some Member
  • Total Posts : 3066
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/11 12:11:53 (permalink)
0
  • How can I get the timer count accurately? - - - Time to find out how to implement a timer (interrupt)!
  • How to save the initial Distance value? - - - Should be "speed value" or "timer period".  There are several possible concepts - e.g. only starting the measurement once the distance increases from e.g. 1.5 m to beyond 2 m.
You're a student? Get accustomed to concepts like timer interrupts, finite state machines etc.
And (re-)search on your own instead of posing questions in forums and waiting for "pre-digested" solutions! Or take appropriate courses and pay attention! This is what's expected from a student.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#10
mgs166
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/09/08 16:16:38
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/11 13:06:22 (permalink)
0
I've never dealt with microcontrollers before and have never programmed one before.  I have never had a class on the subject.  So far, I spent roughly 30 hours on this project and I don't really have that much time to begin with as I go to college full-time and also work full-time.  I was assigned this project to see if I could do it.  Most of the code I was able to get to work, it is just the timer/counter aspect that confuses me.  I'm not here just looking for answers, but I need detailed help on this particular aspect of the project.  It appears that I could set up a timer to create an interrupt every 1ms and read the ADC voltage and then increment the counter by 0.001 each time.  When I do this, however, my LCD display just flickers and while the Distance value is updated, the counter is not so it is obvious that I'm not coding correctly.  As I said, I am completely lost and confused on this part and I'm seeking some assistance from people who have MUCH MORE experience than I do regarding the dsPIC33EP64MC502 microcontroller.  I value your  constructive criticism, but I just need a little help.
 
Again, thank you very much in advance for your help.
#11
ric
Super Member
  • Total Posts : 23860
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Need help for input capture for dsPIC33 2019/09/11 13:25:57 (permalink)
0
mgs166
It appears that I could set up a timer to create an interrupt every 1ms and read the ADC voltage and then increment the counter by 0.001 each time.

This was sounding good until you got to "increment the counter by 0.001"
Do NOT use floating point in things that have to happen rapidly.
Use integers, then do the calculations for floating point at the end.
So, change that to "increment the counter by 1", or thinking another way, count milliseconds, not fractions of seconds.
 

  When I do this, however, my LCD display just flickers and while the Distance value is updated, the counter is not so it is obvious that I'm not coding correctly.

Can only guess without seeing your code, but using floating point calculations inside an interrupt service, and not being careful about variable shared between the interrupt code and the non-interrupt coide can cause all sorts of unusual effects.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#12
dan1138
Super Member
  • Total Posts : 3229
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/11 14:37:25 (permalink)
0
mgs166
I've never dealt with microcontrollers before and have never programmed one before.  I have never had a class on the subject.  So far, I spent roughly 30 hours on this project and I don't really have that much time to begin with as I go to college full-time and also work full-time.  I was assigned this project to see if I could do it.  Most of the code I was able to get to work, it is just the timer/counter aspect that confuses me.  I'm not here just looking for answers, but I need detailed help on this particular aspect of the project.  It appears that I could set up a timer to create an interrupt every 1ms and read the ADC voltage and then increment the counter by 0.001 each time.  When I do this, however, my LCD display just flickers and while the Distance value is updated, the counter is not so it is obvious that I'm not coding correctly.  As I said, I am completely lost and confused on this part and I'm seeking some assistance from people who have MUCH MORE experience than I do regarding the dsPIC33EP64MC502 microcontroller.  I value your  constructive criticism, but I just need a little help.

Again, thank you very much in advance for your help.


So you have spent 4 working days on this assignment.

Can you share the status of the items on this list that you have started or completed:
  1. Project planning (what is it? how's it suppose to work?) document
  2. Description of usage (user guide) document
  3. Description of implementation method (flow chart) document
  4. Circuit diagram (schematic)
  5. Bill Of Materials (often a spreadsheet)
  6. Code implementation (project source code)
  7. Analysis of operation (debugging and correction) document
Are any of these items something you are willing to share with us here?
 
Do you want detailed help in creating any of these items?
#13
du00000001
Just Some Member
  • Total Posts : 3066
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/11 14:50:20 (permalink)
0
Let's cut things somewhat shorter:
  • Currently you're incrementing the timer variable in some sw loop. That's not stable.
  • Set up a timer such that you have an interrupt every 1 or 10 ms and move your counting code to the ISR. I'd suggest to use integer math, but float might do as well if you're not familiar with integer math.
  • Your counter value doesn't seem to increment? Add the magic word "volatile" to the variable declaration! That should solve this issue.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#14
dan1138
Super Member
  • Total Posts : 3229
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/11 15:31:54 (permalink)
0
mgs166 post #9
Good afternoon Microchip community.

Thank you all again for your previous replies to my question.

Since the time intervals are lengthy for my project, I decided to just go with a simple counter that will start incrementing when the person is 2 meters away from the ultrasonic transducer and will stop incrementing when they are 6 meters away from the sensor.

Please see my code below.

The LCD display does show the counter incrementing in 0.01 steps.

My question is:  How can I get the counter to count accurately?  For example, it takes my counter roughly 55 seconds to count to 10 when it should take only 10 seconds.

I have created counters before, but I never needed them to be counting accurately in real-time.

Also, how can I save the initial Distance value (the distance the person is away from the sensor when the system is turned on) and the final Time_elapsed value (time taken for person to walk 4 meters) for future use?

For example, if the person has finished their 4 meter walk and they turn around and walk back towards the sensor, the counter will start incrementing again since the person is back within the range in which the counter is active.

    while (1)
    {
    Distance = Read_ADC(0);                 // read voltage (Distance) on pin 2 (ANO)

    if (Distance >= 1 && Distance <= 3)     // person within measurement region
        Time_elapsed = Time_elapsed + 0.01; // count in 10ms increments
    else
    if (Distance < 1 || Distance > 3)       // person not within measurement region
        Time_elapsed = Time_elapsed;        // don't increment counter
    }


Again, I would like to thank everyone in advance for any help / guidance.

Seems to me that you need to consider alternate methods of how to perform this task.

Lets collect the same kind of information but in a different setting using different tools.

Consider the scene of a city street in a shopping district. The street lined by shops and cafes. You are seated at a sidewalk cafe table. Across the street is a shop front with a display window that just happens to be 4 meters wide. In the shop window is a large analog clock with hour, minute and second hands. The task is to measure how long is takes a person to walk along the display window using only what you can see and remember.

This is what I would do: Note the time on the clock (hour:minute:second) when a person begins to walk in front of the display window, then note the time clock when the same person has completed crossing in front of the display window. Later calculate 4 meters divided by the difference of those two times in seconds to find the rate the person walked at in meters per seconds.
#15
mgs166
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/09/08 16:16:38
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/12 19:29:11 (permalink)
0
Good evening Microchip forum,
I set up Timer1 to create an interrupt every 1ms.  I then put the counter inside the ISR routine where it is reading the ADC every 1ms and incrementing the counter when appropriate.  The LCD display shows the correct voltage and it indicates changes to the voltage in real-time.  The counter does count, but it counts slower that what would be expected.  It also skips a number here and there.  This may have something to do with the fact that in my LCD code, I have inserted 2ms delays in toggling the enable bit between high and low.  Could the counter be actually incrementing accurately but I am not able to see it due to the way I've written the LCD code?  I have also attached an image (I apologize for the low resolution) of my applicable code if anyone would like to see how I have modified the code based on the feedback that I have received thus far from this forum.  I can also attach an image of my LCD code if anyone thinks that would be helpful.  There are more than likely errors still within my code as I am just not sure where to put certain items.  If I can get this timer/counter sorted out, I will be well on my way to completing this project.  I do not believe I mentioned it before, but this is a project that I am working on for college in conjunction with the school's college of medicine.  They are looking for a more reliable and repeatable method for measuring the walking speed of persons who have musculoskeletal disorders, degenerative neurological conditions or someone who has suffered a stroke.  Apparently, a person's walking speed is an excellent indicator of their overall health and is considered to be the "sixth vital sign."  When the counter is functioning correctly, I will just need to obtain the final counter value to use in order to calculate the walking speed.  I've seen examples of counters using the dsPIC33, but I have never read about or have seen where a counter value was retrieved and used elsewhere within the program.  Again, thank you very much for your help and feedback.

Attached Image(s)

#16
ric
Super Member
  • Total Posts : 23860
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Need help for input capture for dsPIC33 2019/09/12 19:47:28 (permalink)
0
You ignored this recommendation.
ric
...
I haven't worked with PIC33 devices, but in most you can start a conversion at the end of one timer interrupt service, and read the result in the next one.

Your code is starting the conversion inside the ISR, and then waiting for that conversion to complete. The exact opposite of what I recommended.
You then compound this by doing a floating point calculation inside the ISR. Don't!
 
Do what I said. Start the conversion at the END of the interrupt service, and read the result in the NEXT service.
You never ever want to be sitting in a loop inside an ISR waiting for something to happen.
Then, ONLY do integer calculations inside the ISR. Leave any floating point calculations to your non-ISR code.
 
 
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#17
dan1138
Super Member
  • Total Posts : 3229
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/12 21:04:26 (permalink)
0
I did not wish to be this blunt.
 
You have closed your mind to thinking about other methods to make the measurements you want.
 
You have been told in nicer ways by smarter members than me that what you have have done, so far, is wrong and why it is wrong.
 
Until you start listening to them and learning from them your project is doomed to failure.
 
This is proof of concept code that shows how to initialize two 16-bit timers to make a 32-bit counter then use it measure elapse time from one read to the next read of the timer:
/*
 * File     : main.c
 * Author   : dan1138
 * target   : dsPIC33EP64MC502
 * compiler : XC16 v1.36
 * IDE      : MPLABX v5.25
 *
 * Created on September 11, 2019, 3:37 PM
 *
 *                           dsPIC33EP64MC502
 *              +------------------:_:------------------+
 *   ICD_VPP -> :  1 MCLR                       AVDD 28 : <- 3v3
 *           <> :  2 RA0/AN0                    AVSS 27 : <- GND
 *           <> :  3 RA1/AN1              RPI47/RB15 26 : <>
 *   IDC_PGD <> :  4 RB0/PGED3/AN2        RPI46/RB14 25 : <>
 *   ICD_PGC <> :  5 RB1/PGEC3/AN3        RPI45/RB13 24 : <>
 *           <> :  6 RB2/RPI34/AN4        RPI44/RB12 23 : <>
 *           <> :  7 RB3/RP35/AN5          RP43/RB11 22 : <>
 *       GND <> :  8 VSS                   RP42/RB10 21 : <>
 *           <> :  9 RA2/OSCI                   VCAP 20 : <- 10uF capacitor
 *           <> : 10 RA3/OSCO                    VSS 19 : <- GND
 *           <> : 11 RB4/RP36               RP41/RB9 18 : <>
 *           <> : 12 RA4/RP20               RP40/RB8 17 : <>
 *       3v3 <> : 13 VDD                    RP39/RB7 16 : <>
 *           <> : 14 RB5/RP37               RP38/RB6 15 : <>
 *              +---------------------------------------+
 *                               DIP-28
 *
 * Description:
 *  This is proof of concept code to initialize timers for
 *  a 32-bit count clocked at the instruction cycle rate
 *  divided by a 1:256 prescaler with a 32-bit read function.
 */

// FICD
#pragma config ICS = PGD3               // ICD Communication Channel Select bits (Communicate on PGEC3 and PGED3)
#pragma config JTAGEN = OFF             // JTAG Enable bit (JTAG is disabled)

// FPOR
#pragma config ALTI2C1 = OFF            // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF            // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25           // Watchdog Window Select bits (WDT Window is 25% of WDT period)

// FWDT
#pragma config WDTPOST = PS32768        // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128           // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON              // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)

// FOSC
#pragma config POSCMD = NONE            // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = ON            // OSC2 Pin Function bit (OSC2 is general purpose digital I/O pin)
#pragma config IOL1WAY = OFF            // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD           // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)

// FOSCSEL
#pragma config FNOSC = FRC              // Oscillator Source Selection (Internal Fast RC (FRC))
#pragma config PWMLOCK = OFF            // PWM Lock Enable bit (PWM registers may be written without key sequence)
#pragma config IESO = OFF               // Two-speed Oscillator Start-up Enable bit (Start up with user-selected oscillator source)

// FGS
#pragma config GWRP = OFF               // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF                // General Segment Code-Protect bit (General Segment Code protect is Disabled)

#include "xc.h"
/* Setup the clock to run at about 60 MIPS (59.904 actual)*/
#define FCLK  (7372800L)    /* nominal fast RC frequency */
#define PLL_N1 (2L)         /* PLLPRE  CLKDIV<4:0> range 2 to 33 */
#define PLL_M  (65L)        /* PLLDIV  PLLFBD<8:0> range 2 to 513 */
#define PLL_N2 (2L)         /* PLLPOST CLKDIV<7:6> range 2, 4 or 8 */
#define FSYS (FCLK*PLL_M/(PLL_N1*PLL_N2))
#define FCYC (FSYS/2L)

/*
 * Initialize this PIC
 */
void PIC_Init(void)
{
    unsigned short ClockSwitchTimeout;

    /*
     * Disable all interrupt sources
     */
    __builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */
    IEC0 = 0;
    IEC1 = 0;
    IEC2 = 0;
    IEC3 = 0;
    IEC4 = 0;
    IEC5 = 0;
    IEC6 = 0;
    IEC8 = 0;
    IEC9 = 0;
    __builtin_disi(0x0000); /* enable interrupts */

    /*
     * At Power On Reset the configuration words set the system clock
     * to use the FRC oscillator. At this point we need to enable the
     * PLL to get the system clock running at 120MHz.
     *
     * Clock switching on the dsPIC33E family with the PLL can be a bit tricky.
     *
     * First we need to check if the configuration words enabled clock
     * switching at all, then turn off the PLL, then setup the PLL and
     * finally enable it. Sounds simple, I know. Make sure you verify this
     * clock setup on the real hardware.
     */

    if(!OSCCONbits.CLKLOCK) /* if primary oscillator switching is unlocked */
    {
        /* Select primary oscillator as FRC */
        __builtin_write_OSCCONH(0b000);

        /* Request switch primary to new selection */
        __builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_OSWEN_POSITION));

        /* wait, with timeout, for clock switch to complete */
        for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && OSCCONbits.OSWEN;);

        /* configure PLL register */
        CLKDIVbits.DOZE = 0;
        CLKDIVbits.DOZEN = 0;
        CLKDIVbits.PLLPRE = PLL_N1-2;
      #if   PLL_N2==2
        CLKDIVbits.PLLPOST=0; /* N2=2 */
      #elif PLL_N2==4
        CLKDIVbits.PLLPOST=1; /* N2=4 */
      #elif PLL_N2==8
        CLKDIVbits.PLLPOST=3; /* N2=8 */
      #else
      #error invalid PLL_N2 paramenter
      #endif
        PLLFBDbits.PLLDIV = PLL_M-2; /* set PLL to multiply by 32 */

        /* Select primary oscillator as FRCPLL */
        __builtin_write_OSCCONH(0b001);
        /* Request switch primary to new selection */
        __builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_OSWEN_POSITION));
        
        /* wait, with timeout, for clock switch to complete */
        for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && OSCCONbits.OSWEN;);

        /* wait, with timeout, for the PLL to lock */
        for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && !OSCCONbits.LOCK;);
        
        /* at this point the system oscillator should be 120MHz */
    }
}
/*
 * Initialize Timer to be used to measure elapse time.
 *
 * Notes:
 *  This is a 32-bit timer that has a rollover
 *  interval of 4294967296 / (FCYC / 256) seconds,
 *  or at 70 MIPS about 4.36 hours.
 */
 
#define TIMER_COUNTS_PER_SECOND (FCYC/256ul) /* document how fast the timer counts with this setup */
 
void TIMER_Init(void)
{
    T2CON = 0;
    T3CON = 0;
    TMR2 = 0;
    TMR3 = 0;
    PR2  = 0xFFFF;
    PR3  = 0xFFFF;
    T2CONbits.T32 = 1;
    T2CONbits.TCKPS = 0b11;     /* select prescale 1:256 */
    T2CONbits.TON = 1;
}
/*
 * Return the number of 32-bit timer counts since last read.
 */
unsigned long TIMER_ReadElapseCounts(void)
{
    static unsigned long LastTime = 0;
    union {
        struct {
            unsigned short W0;
            unsigned short W1;
        };
        unsigned long DW;
    } RetVal;
    
    /* 32-bit timer count registers must be read in this order */
    RetVal.W0 = TMR2;
    RetVal.W1 = TMR3HLD;
    
    /* compute change since last read */
    RetVal.DW -= LastTime;
    
    /* update last read time */
    LastTime += RetVal.DW;
    
    return RetVal.DW;
}
/*
 * Main Application
 */
volatile unsigned long DeltaTime;
int main(void)
{
    unsigned long i;
    PIC_Init();
    TIMER_Init();
    /*
     * Application loop
     */
    for(;;)
    {
        DeltaTime = TIMER_ReadElapseCounts();

        for(i=1000000;i;i--);
    }
    return 0;
}

#18
du00000001
Just Some Member
  • Total Posts : 3066
  • Reward points : 0
  • Joined: 2016/05/03 13:52:42
  • Location: Germany
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/13 01:48:50 (permalink)
0
A 1 ms ticker is incrementing way faster than you can read!
And I somewhat doubt the LCD update can follow the ticker given usual LCD interface speeds.
Even a 10 ms ticker would be too fast to read every update (not sure about the LCD then).
 
ric is right about starting the next conversion at the end of the ISR, reading the result at the start. This is how I do such things all the time - not wasting any time.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
#19
mgs166
New Member
  • Total Posts : 6
  • Reward points : 0
  • Joined: 2019/09/08 16:16:38
  • Location: 0
  • Status: offline
Re: Need help for input capture for dsPIC33 2019/09/13 12:14:13 (permalink)
4 (1)
Hello ric,
 
It works!  After making the changes you suggested, the counter performs as intended.  Thank you very much for your help and guidance.  I just have one last question.  Right before the test, the person whose speed is to be measured will be standing at some distance "x" from the sensor.  The distance "x" will vary depending on where the person decides to stand.  I don't want the counter to start until the person is distance (x+2) meters away from the sensor.  This is to be done because the person's "starting speed" is less than their natural walking speed.  What would be the best method to go about this?  Again, thanks ric!
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5