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

Wave form edge detection
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
temtronic



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

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 12:35 pm     Reply with quote

couple of things....

1) 4MHz clock is slow for that PIC,depending on what else it has to do....

2) should never,ever have delays in any ISR ! Set flags, do 'stuff' in main() based upon the flags.

3) no apparent 'default' or 'startup' edge detection, maybe that's not a problem but........

4) if 'inputsignal' is the zero cross, 'high' will always be true, L to H edge ....
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 12:35 pm     Reply with quote

matthewmilford wrote:

#fuses HS, XT, NOWDT, NOPROTECT, NOPUT, NOLVP
#use delay(clock = 4MHz)

XT is the correct oscillator fuse for a 4 MHz crystal. Get rid of the
HS fuse. Also, when using a crystal, the PUT fuse is normally good
to use.

matthewmilford wrote:

#INT_EXT // external interrupt ISR
void EXT_ISR()
{
int1 high;

if(input(inputsignal) == 1)
{
high=TRUE;
delay_cycles(1);
ext_int_edge(L_TO_H);
}

else
{
high=FALSE;
delay_cycles(1);
ext_int_edge(H_TO_L);
}

delay_ms(2);
output_high(gate2);
delay_us(50);
output_low(gate2);

}

You have swapped the edges from the way that Ttelmah showed you. It's not going to work.


Quote:
void main()
{
output_drive(gate2);
output_low(gate2);

clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);

while(TRUE)
{
delay_cycles(1);

}
}


In the above code, you don't set the initial edge that you want to
have it interrupt on.
matthewmilford



Joined: 09 Feb 2021
Posts: 23

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 1:33 pm     Reply with quote

temtronic

1. its primary job is really to do this interrupt. Everything else is secondary and not all that time sensitive (it only needs to go as fast as a human for display and stuff). So how fast or slow is semi - irrelevant.

2. I know in the end I won't use a delay....that was just a quick and dirty way of getting a pulse rather than setting a timer. I was trying to simplify the code as much as possible.

3. I put one in.... no change. Good thought though.

4. Okay so I swapped around the delay and gating to be in front of edge detection rather than after. Thus it should be checking if its high or low in the middle of the square wave rather than an edge. No change. Yes I am still using a delay to do this, if it would have worked I would write a timer to do it.

PCM
I am not using a crystal I removed the XT to make sure its not trying to use an external clock. I want to do it internal. Is this correct?

I swapped the edges back but either way that I put it, no change.
I added a line to set initial edge to interrupt on.

See new code.

Code:

#include <18f26k42.H>
#device ADC = 10

#include <BMLCD420.c>

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#fuses HS,NOWDT, NOPROTECT, NOPUT, NOLVP
#use delay(clock = 4MHz)

#define inputsignal   PIN_B0
#define gate2 PIN_B2


#INT_EXT            // external interrupt ISR
void EXT_ISR()
{
    int1 high;

    delay_ms(2);
    output_high(gate2);
    delay_us(50);
    output_low(gate2); 
 
    if(input(inputsignal) == 1)
   {
        high=TRUE;
        delay_cycles(1);
        ext_int_edge(H_TO_L);
   }
    else
   {
        high=FALSE;
        delay_cycles(1);       
        ext_int_edge(L_TO_H);
   }

}

void main()
{
    output_drive(gate2);
    output_low(gate2);
   
    clear_interrupt(INT_EXT);   
    enable_interrupts(INT_EXT);       
    enable_interrupts(GLOBAL);
   
    ext_int_edge(L_TO_H);
   
    while(TRUE)
    {
        delay_cycles(1);

    }
}


P.S.
Thanks for all the help, I really appreciate the feedback.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 2:09 pm     Reply with quote

matthewmilford wrote:

#fuses HS,NOWDT, NOPROTECT, NOPUT, NOLVP
#use delay(clock = 4MHz)

This code above is for an external crystal.

The quick way to setup for the internal 4 MHz oscillator is to use this:
Code:
#fuses NOWDT, NOPROTECT, NOPUT, NOLVP
#use delay(internal = 4MHz)
matthewmilford



Joined: 09 Feb 2021
Posts: 23

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 2:25 pm     Reply with quote

Okay fixed that. Still no change but certainly good to get it right.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 3:27 pm     Reply with quote

Have you run an LED blinker program to make sure your PIC is
really running at 4 MHz ? Example:
Code:
#include <18F26K42.h>
#fuses NOWDT 
#use delay(internal=4M)

#define LED_PIN  PIN_B1  // Put in a suitable pin

//=================================
void main()
{

while(TRUE)
  {
   output_toggle(LED_PIN);
   delay_ms(500);
  }

}


The LED circuit should be like this:
Code:

pin      470 ohms      LED       
B1  -----/\/\/\/------->|----
                            |
                            |
                          -----  Ground 
                           ---
                            -
 
PrinceNai



Joined: 31 Oct 2016
Posts: 478
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Jun 16, 2021 4:13 pm     Reply with quote

It looks like a very simple thing to do, changing the firing edge of the interrupt. Those other guys answering you are doing it while they sleep, and then some. Have you tried changing PIC? Maybe your debugger doesn't work (not that I believe that). Have you checked if the appropriate SFR changes when you reverse the edge? I'd hook two LED's and toggle them inside ISR, one for L-H and the other for the H-L part of if statement. Just to see "live" what happens, which one glows. Maybe try EXT1, if your stuff is on a breadboard.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Jun 17, 2021 8:13 am     Reply with quote

Lets make a comment.
The edge changing code has worked many times for people here in the past.
However this chip is more complex, since it has three EXT interrupts. I'd
suspect you probably have to specify which interrupt is involved in the
change code to make it work.

However 'why use this'?. This PIC also supports IOC on this pin. Much
simpler. So:
Code:

#include <18f26k42.H>
#device ADC = 10

#include <BMLCD420.c>

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#fuses NOWDT, NOPROTECT, NOPUT, NOLVP
#use delay(internal = 4MHz)

#define inputsignal   PIN_B0
#define gate2 PIN_B2

//#PIN_SELECT INT0=PIN_B0
#byte IOCBF=getenv("SFR:IOCBF")

#INT_IOC          // external interrupt ISR
void EXT_ISR()
{
   int1 high;

   if(input(inputsignal) == 1)
   {
        high=TRUE;
        delay_cycles(1);
   }
   
   else
   {
        high=FALSE;
        delay_cycles(1);       
   }
   IOCBF=FALSE;
}

void main()
{
    output_drive(gate2);
    output_low(gate2);
    IOCBF=FALSE;
    clear_interrupt(INT_IOC);
    enable_interrupts(INT_IOC_B0);  //enable IOC in both directions on B0 
    enable_interrupts(GLOBAL);
   
    while(TRUE)
    {
        delay_cycles(1);
    }
}


This enables IOC on pin B0 for both directions. Much easier. The only
complexity for this is you have to manually clear the IOCBF.0 bit
before the interrupt can be cleared. I've done this by just defining the
register and clearing this.
matthewmilford



Joined: 09 Feb 2021
Posts: 23

View user's profile Send private message

PostPosted: Thu Jun 17, 2021 9:00 am     Reply with quote

Everyone,

I finally got a working code. A bit strange as, so far as I can tell the ext_int_edge command is not working properly on this chip. So, I decided to change the bits manually and with a bit of twiddling here is a small working code for doing both edges.


Code:

#include <18f26k42.H>
#device ADC = 10

#include <BMLCD420.c>

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#fuses NOWDT, NOPROTECT, NOPUT, NOLVP
#use delay(internal = 4MHz)

#define inputsignal   PIN_B0
#define gate2 PIN_B2

#byte OPTION_REG = GETENV("SFR:INTCON0")    // get OPTION_REG register address
#bit  INTEDG = OPTION_REG.0


#INT_EXT            // external interrupt ISR
void EXT_ISR()
{
   
    delay_ms(2);
    output_high(gate2);
    delay_us(50);
    output_low(gate2); 
 
    if(input(inputsignal) == 1)
   {

        delay_cycles(1);
        //ext_int_edge(H_TO_L);
        INTEDG = 0;
   }
    else
   {

        delay_cycles(1);       
        //ext_int_edge(L_TO_H);
        INTEDG = 1;
   }

}

void main()
{
    output_drive(gate2);
    output_low(gate2);
   
    clear_interrupt(INT_EXT);   
    enable_interrupts(INT_EXT);       
    enable_interrupts(GLOBAL);
   
    ext_int_edge(L_TO_H);
   
    while(TRUE)
    {
        delay_cycles(1);

    }
}
PrinceNai



Joined: 31 Oct 2016
Posts: 478
Location: Montenegro

View user's profile Send private message

PostPosted: Thu Jun 17, 2021 10:15 am     Reply with quote

It's nice you have a working code and also that Mr. Ttelmah posted an alternative. And I do like his "only complexity" thing. One line, once :-). I'd like all the things to be that complex. BTW, what chip are you using for ZCD, to buy some?

Regards,
Samo
PrinceNai



Joined: 31 Oct 2016
Posts: 478
Location: Montenegro

View user's profile Send private message

PostPosted: Thu Jun 17, 2021 11:17 am     Reply with quote

It would be interesting to see the .lst code for this part of program with int_ext and manual change of the SFR. Maybe your version of CCS is the culprit for this behavior.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Jun 17, 2021 11:23 am     Reply with quote

Yes. The interesting thing for me, is I haven't kept 5.102. I don't keep
versions where I have found a major issue.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Fri Jun 18, 2021 1:12 am     Reply with quote

As I guessed (and mentioned earlier), the issue is simply that your code is
not telling the compiler 'which' interrupt to set the edge on.

You need:
Code:

#INT_EXT          // external interrupt ISR
void EXT_ISR()
{
    int1 high;

   if(input(inputsignal) == 1)
   {
        high=TRUE;
        delay_cycles(1);
        ext_int_edge(0,H_TO_L);
   }
   
   else
   {
        high=FALSE;
        delay_cycles(1);       
        ext_int_edge(0,L_TO_H);
   }
}


Note the '0'.

Though the manual says these should default to the first interrupt, checking
the assembly on 5.101 (since I don't have 5.102), shows that without this
the second entry is accessing the FSR register, and not the INTCON0
register. Add the zero, and the first clears INT0EDG bit while the second
sets it.
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 Previous  1, 2
Page 2 of 2

 
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