Menu
  • HOME
  • TAGS

glitches when using time overflow interrupt

Tag: c,timer,interrupt,avr,attiny

I have some trouble with, I guess, the overflow interrupt (used to increase resolution on 8-bit timer from 16µs/step to 1µs/step) in my CODE. It seems like the overflow interrupt triggers while the program is in the if-statements in my main loop and thereby screws thigns up!

    if(pInt == 1)           //PCNINT-if-statment
    {           
        pulse16 = (tot_overflow << 8) | TCNT1;          //adds tot_overflow and TCNT1 to be able to set if-statements in PCINT-while-loop with µs 

        if(PINB & (1 << PINB3))         //if PB3 is HIGH
        {
            TCNT1 = 0;      //resets Timer/Counter1
            tot_overflow = 0;       //resets tot_overflow variable   
        }

        else        
        { 
            if (pulse16 >1555)          //when stick 1 travels from 1555 µs towards 2006 µs  
            {
                PORTB &= ~(1 << relayPin);        //relay pole switch, + & - on motor 
                PORTB |= (1 << greenLED);        //LED green indicates forward motion
                PORTB &= ~(1 << redLED);        //turn off red LED
            }

                else if (pulse16 <1490)         //when stick 1 travels from 1490 ms towards 920 µs  
                {
                    PORTB |= (1 << relayPin);        //relay pole switch, - & + on motor 
                    PORTB &= ~(1 << greenLED);        //turn off green LED
                    PORTB |= (1 << redLED);         //LED red indicates backward motion
                }   

            else        //if µs is 1490> or <1555 - dead-span to prevent gliteches on relay when stick is in centre position 
            { 

            }   

        }

        pInt = 0;       //resets pInt to exit PCNINT-if-statment   
    }

The pInt is a "flag-variable" that indicates PCINT is triggered. The tot_overflow variable is increment every time the overflow interrupt is triggered.

I use an ATtiny85 as a RC-switch, it should go LOW on PB2-pin when µs from receiver is above 1555 and go HIGH when µs goes below 1490.
What happens is the following: when checking if µs is above 1555 or below 1490 and using overflow interrupt it sometimes turn the PB2-pin HIGH/LOW in the "dead-span" of 1490-1555 when it shouldn't, and sometimes outside the "dead-span"! Here's a VIDEO on the glitch. Notice that the green LED is the redLED, and the yellow LED is greenLED in my code.

I'm quite new at this and I'm not sure why this is happening and I don't understand why the code won't work. I have looked at the CTC function but I can't see that it would help since I still have to use the timer overflow interrupt to get my wanted reolution of 1µs/step.


EDIT

I have tried a couple of variations (of @yann-vernier's suggestions) and still don't get it to work properly, this is what gets closest to a working code:

while(1)        //leave and/or put your own code here
{
    static uint8_t tot_overflow;        //variable to count the number of Timer/Counter1 overflows  

    if (TIFR & (1 << TOV1) )
    {
        TIFR |= (1 << TOV1);        // clear timer-overflow-flag
        tot_overflow ++;
    }

    if(GIFR & (1 << PCIF) )         //PCINT-flag idicates PCINT
    {
        uint16_t pulse;         //variable to make a 16 bit integer from tot_overflow and TCNT1  

//          PORTB |= (1 << debugPin);       //pin is HIGH on when interrupt is intialized

        pulse = (tot_overflow << 8) | TCNT1;            //adds tot_overflow and TCNT1 to be able to set if-statements in PCINT-while-loop with µs 

this part I don't get to work:

        if ( ((TIFR & (1 << TOV1)) && ((pulse & 0xff))) < 0x80)
        {
            pulse += 0x100;   // Overflow had not been counted
        }

Im not sure I get what is happening above, the only thing I know is that I probably do it the wrong way! When I comment the above part it works the same as mu old code!

        else
        {
            if(PINB & (1 << PINB3))         //if PB3 is HIGH
            {
                TCNT1 = 0;      //resets Timer/Counter1
                tot_overflow = 0;       //resets tot_overflow variable   
            }

            else        
            {       
                if (pulse > 1555)           //when stick 1 travels from 1555 µs towards 2006 µs  
                {
                PORTB &= ~(1 << relayPin);        //relay pole switch, + & - on motor 
                    PORTB |= (1 << greenLED);        //LED green indicates forward motion
                    PORTB &= ~(1 << redLED);        //turn off red LED
                }

                    else if (pulse < 1490)          //when stick 1 travels from 1490 ms towards 920 µs  
                    {
                        PORTB |= (1 << relayPin);        //relay pole switch, - & + on motor 
                        PORTB &= ~(1 << greenLED);        //turn off green LED
                        PORTB |= (1 << redLED);         //LED red indicates backward motion
                    }   

                else        //if µs is 1490> or <1555 - dead-span to prevent gliteches on relay when stick is in centre position 
                { 
//                  PORTB |= (1 << greenLED);           //for debug to indicate dead-span   
//                  PORTB |= (1 << redLED);         //for debug to indicate dead-span   
                }   

            }

        }

        GIFR |= (1 << PCIF);    //clear PCINT-flag  
    }

    else
    {

    }

}

}

ISR(TIMER1_OVF_vect)            //when Counter/Timer1 overflows  
{

}

ISR(PCINT0_vect)        //when pin-level changes on PB3
{ 

}

Is it close or am I still out in the blue?

Best How To :

Yes, the overflow interrupt could happen at any time (although it does happen regularly). So could the pin change interrupt. Each of them in this case only touch a single 8-bit volatile variable (tot_overflow and pInt respectively), which in turn are polled by your main loop. This construction doesn't really help you unless the main loop has other work to do which may take longer than one full timer period (256*8=2048 cycles in this case).

So instead of enabling interrupts, you could check GIFR bit PCIF (instead of pInt) and TIFR bit TOV1 in your main loop, which would get you more easily understood behaviour. Resetting them is a special case of writing a 1 to that bit and only that bit. This would save you time for the pin change interrupt, as the main loop check could happen more frequently and would not need the latency of jumping to the interrupt service routine.

It would not, however, fix your problem. You are trying to measure a pulse width, which on slightly larger AVRs is easily done using the timer input capture feature. The timers in the ATtiny85 don't have this feature. On AVRs that do, the input capture and timer overflow interrupts are arranged in such a way that the input capture interrupt can safely read the software driven overflow counter.

When you get a timer overflow, you increment tot_overflow, and when you've detected a pin change, you read TCNT1 to combine the values. These two counters, while one feeds the other, are not read at the same time. Your threshold values are 0x5d2 and 0x613. If the rollover occurs after reading tot_overflow but before reading TCNT1, you may well get a time like 0x501 at a time which should be 0x601. Similarly if you stop tot_overflow from updating. If you read TCNT1 before tot_overflow, you might get 0x6fe when you should have read 0x5fe. Simply put, there is no safe order - but there is a relation. What we need to know is if the overflow count value was up to date or not at the time the counter value was read.

static uint8_t ovf;
if (TIFR & 1<<TOV1) {
   TIFR = 1<<TOV1;   // Clear overflow flag
   ovf++;
}
if (GIFR & 1<<PCIF) {
   GIFR = 1<<PCIF;   // clear pin change flag
   uint16_t timestamp = ovf<<8 | TCNT1;
   if (TIFR&1<<TOV1 && (timestamp&0xff)<0x80)
       timestamp += 0x100;   // Overflow had not been counted
   // Do what we like with the timestamp here
}

The key is that we check for an overflow after we have already loaded the timer value. If the overflow occurred before we read the value, the value read must be low; otherwise we want the old count. This particular sample actually relies on the overflow not being handled in an interrupt, but you can use the same method by enclosing the block in an interrupt masking. We need the two reads of TOV1 and ovf to match, and to read TOV1 after TCNT1. What we don't want is to have an interrupt process and thus clear TOV1 so that we can't infer the order of ovf and TCNT1. Note that using a pin change interrupt to do this logic grants us that automatically, since interrupt handlers run with interrupts disabled.

You won't get higher precision on your pulse widths than the latency variance for responding to the pin change, and in the code you've shown, the timer reset (which should also reset the prescaler, bit PSR1 in GTCCR). This usually means you do want to read the timer in the interrupt handler itself. We can also observe that you could choose a timer pace that makes your thresholds fit in the 8 bit value; for instance with timer1 running at 8MHz/64, your thresholds would be at 186 and 194, with an offset of 16-24µs. One might even do tricks like setting one threshold precisely at an overflow since the timer doesn't have to start at 0.

Is there Predefined-Macros define about byte order in armcc

c,armcc,predefined-macro

Well according to this page: http://www.keil.com/support/man/docs/armccref/armccref_BABJFEFG.htm You have __BIG_ENDIAN which is defined when compiling for a big endian target....

How convert unsigned int to unsigned char array

c++,c

#include <stdio.h> int main() { unsigned int i = 0x557e89f3; unsigned char c[4]; c[0] = i & 0xFF; c[1] = (i>>8) & 0xFF; c[2] = (i>>16) & 0xFF; c[3] = (i>>24) & 0xFF; printf("c[0] = %x \n", c[0]); printf("c[1] = %x \n", c[1]); printf("c[2] = %x \n", c[2]); printf("c[3] =...

CallXXXMethod undefined using JNI in C

java,c,jni

There are few fixes required in the code: CallIntMethod should be (*env)->CallIntMethod class Test should be public Invocation should be jint age = (*env)->CallIntMethod(env, mod_obj, mid, NULL); Note that you need class name to call a static function but an object to call a method. (cls2 -> person) mid =...

execl() works on one of my code, but doesn't work on another

c,execl

My C is a bit rusty but your code made many rookie mistakes. execl will replace the current process if it succeeds. So the last line ("i have no idea why") won't print if the child can launch successfully. Which means... execl failed and you didn't check for it! Hint:...

VS2012 Identifer not found when part of static lib

c,visual-studio-2012,linker,static-libraries

C++ uses something called name mangling when it creates symbol names. It's needed because the symbol names must contain the complete function signature. When you use extern "C" the names will not be mangled, and can be used from other programming languages, like C. You clearly make the shunt library...

Does realloc() invalidate all pointers?

c,pointers,dynamic-memory-allocation,behavior,realloc

Yes, ptr2 is unaffected by realloc(), it has no connection to realloc() call whatsoever(as per the current code). However, FWIW, as per the man page of realloc(), (emphasis mine) The realloc() function returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and...

Multiple definition and file management

c,arrays,compilation,compiler-errors,include

include is a preprocessor directive that includes the contents of the file named at compile time. The code that conditionally includes stuff is executed at run time...not compile time. So both files are being compiled in. ( You're also including each file twice, once in the main function and once...

C++ / C #define macro calculation

c++,c,macros

Are DETUNE1 and DETUNE2 calculated every time it is called? Very unlikely. Because you are calling sqrt with constants, most compilers would optimize the call to the sqrt functions and replace it with a constant value. GCC does that at -O1. So does clang. (See live). In the general...

Passing int using char pointer in C

c,exec,ipc

Programs simply do not take integers as arguments, they take strings. Those strings can be decimal representations of integers, but they are still strings. So you are asking how to do something that simply doesn't make any sense. Twenty is an integer. It's the number of things you have if...

Program to reverse a string in C without declaring a char[]

c,string,pointers,char

Important: scanf(" %s", name); has no bounds checking on the input. If someone enters more than 255 characters into your program, it may give undefined behaviour. Now, you have the char array you have the count (number of char in the array), why do you need to bother doing stuffs...

Is post-increment operator guaranteed to run instantly?

c,c89,post-increment,ansi-c

This code is broken for two reasons: Accessing a variable twice between sequence points, for other purposes than to determine which value to store, is undefined behavior. There are no sequence points between the evaluation of function parameters. Meaning anything could happen, your program might crash & burn (or more...

Set a timer in R to execute a program

r,timer

You can do something like this: print_test<-function(x) { Sys.sleep(x) cat("hello world") } print_test(15) If you want to execute it for a certain amount of iterations use to incorporate a 'for loop' in your function with the number of iterations....

Array breaking in Pebble C

c,arrays,pebble-watch,cloudpebble

The problem is this line static char *die_label = "D"; That points die_label to a region of memory that a) should not be written to, and b) only has space for two characters, the D and the \0 terminator. So the strcat is writing into memory that it shouldn't be....

How does this code print odd and even?

c,if-statement,macros,logic

In binary any numbers LSB (Least Significant Bit) is set or 1 means the number is odd, and LSB 0 means the number is even. Lets take a look: Decimal binary 1 001 (odd) 2 010 (even) 3 011 (odd) 4 100 (even) 5 101 (odd) SO, the following line...

What does `strcpy(x+1, SEQX)` do?

c,strcpy

The pointer + offset notation is used as a convenient means to reference memory locations. In your case, the pointer is provided by malloc() after allocating sufficient heap memory, and represents an array of M + 2 elements of type char, thus the notation as used in your code represents...

C binary tree sort - extending it

c,binary-tree,binary-search-tree

a sample to modify like as void inorder ( struct btreenode *, int ** ) ; int* sort(int *array, int arr_size) { struct btreenode *bt = NULL; int i, *p = array; for ( i = 0 ; i < arr_size ; i++ ) insert ( &bt, array[i] ) ;...

Counting bytes received by posix read()

c,function,serial-port,posix

Yes, temp_uart_count will contain the actual number of bytes read, and obviously that number will be smaller or equal to the number of elements of temp_uart_data. If you get 0, it means that the end of file (or an equivalent condition) has been reached and there is nothing else to...

Is i=i+1 an undefined behaviour?

c,increment,undefined-behavior

There is no undefined behavior in this code. i=i+1; is well-defined behavior, not to be confused with i=i++; which gives undefined behavior. The only thing that could cause different outputs here would be floating point inaccuracy. Try value += 4 * (int)nearbyint(pow(10,i)); and see if it makes any difference....

C programming - Confusion regarding curly braces

c,scope

The only difference between the two is the scope of the else. Without the braces, it spans until the end of the full statement, which is the next ;, i.e the next line: else putchar(ch); /* end of else */ lastch = ch; /* outside of if-else */ With the...

What all local variables goto Data/BSS segment?

c++,c,nm

"local" in this context means file scope. That is: static int local_data = 1; /* initialised local data */ static int local_bss; /* uninitialised local bss */ int global_data = 1; /* initialised global data */ int global_bss; /* uninitialised global bss */ void main (void) { // Some code...

How does ((a++,b)) work? [duplicate]

c,function,recursion,comma

In your first code, Case 1: return reverse(i++); will cause stack overflow as the value of unchanged i will be used as the function argument (as the effect of post increment will be sequenced after the function call), and then i will be increased. So, it is basically calling the...

Segmentation fault with generating an RSA and saving in ASN.1/DER?

c,openssl,cryptography,rsa

pub_l = malloc(sizeof(pub_l)); is simply not needed. Nor is priv_l = malloc(sizeof(priv_l));. Remove them both from your function. You should be populating your out-parameters; instead you're throwing out the caller's provided addresses to populate and (a) populating your own, then (b) leaking the memory you just allocated. The result is...

How can I align stack to the end of SRAM?

c,embedded,stm32,gnu-arm,coocox

I've found the reason: that's because stack size is actually fixed and it is located in heap (if I could call it heap). In file startup_stm32f10x*.c there is a section: /*----------Stack Configuration----------*/ #define STACK_SIZE 0x00000100 /*!< The Stack size suggest using even number */ And at then very next line:...

Set precision dynamically using sprintf

c,printf,format-string

Yes, you can do that. You need to use an asterisk * as the field width and .* as the precision. Then, you need to supply the arguments carrying the values. Something like sprintf(myNumber,"%*.*lf",A,B,a); Note: A and B need to be type int. From the C11 standard, chapter §7.21.6.1, fprintf()...

Text justification C language

c,text,alignment

From printf's manual: The field width An optional decimal digit string (with nonzero first digit) specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given). Instead...

getchar() not working in c

c,while-loop,char,scanf,getchar

That's because scanf() left the trailing newline in input. I suggest replacing this: ch = getchar(); With: scanf(" %c", &ch); Note the leading space in the format string. It is needed to force scanf() to ignore every whitespace character until a non-whitespace is read. This is generally more robust than...

Reverse ^ operator for decryption

c,algorithm,security,math,encryption

This is not a power operator. It is the XOR operator. The thing that you notice for the XOR operator is that x ^ k ^ k == x. That means that your encryption function is already the decryption function when called with the same key and the ciphertext instead...

Infinite loop with fread

c,arrays,loops,malloc,fread

If you're "trying to allocate an array 64 bytes in size", you may consider uint8_t Buffer[64]; instead of uint8_t *Buffer[64]; (the latter is an array of 64 pointers to byte) After doing this, you will have no need in malloc as your structure with a 64 bytes array inside is...

Pass self class parameter python

python,timer

Apparently you want sendLog() to call the worker functions every 10 seconds or so. Here's an easy way to do that: class AccessLog: @staticmethod def sendLog(interval, worker_functions, iterations=1): def call_worker_functions(): for f in worker_functions: f(*worker_functions[f]) for i in range(iterations): threading.Timer(interval * i, call_worker_functions).start() And now use it like this: AccessLog.AccessLog.sendLog(...

How to increment the value of an unsigned char * (C)

c++,c,openssl,byte,sha1

I am assuming your pointer refers to 20 bytes, for the 160 bit value. (An alternative may be text characters representing hex values for the same 160 bit meaning, but occupying more characters) You can declare a class for the data, and implement a method to increment the low order...

Segmentation Fault if I don't say int i=0

c,arrays,segmentation-fault,initialization,int

In your code, int i is an automatic local variable. If not initialized explicitly, the value held by that variable in indeterministic. So, without explicit initialization, using (reading the value of ) i in any form, like array[i] invokes undefined behaviour, the side-effect being a segmentation fault. Isn't it automatically...

Efficient comparison of small integer vectors

c,integer,compare,bit-manipulation,string-comparison

It's possible to do this using bit-manipulation. Space your values out so that each takes up 5 bits, with 4 bits for the value and an empty 0 in the most significant position as a kind of spacing bit. Placing a spacing bit between each value stops borrows/carries from propagating...

How to control C Macro Precedence

c,macros

You can redirect the JOIN operation to another macro, which then does the actual pasting, in order to enforce expansion of its arguments: #define VAL1CHK 20 #define NUM 1 #define JOIN1(A, B, C) A##B##C #define JOIN(A, B, C) JOIN1(A, B, C) int x = JOIN(VAL,NUM,CHK); This technique is often used...

free causing different results from malloc

c,string,malloc,free

Every time you are creating your string, you are not appending a null terminator, which causes the error. So change this: for(j=0; j<rem_len; j++) { if(j != i) { remaining_for_next[index_4_next] = remaining[j]; index_4_next++; } } to this: for(j=0; j<rem_len; j++) { if(j != i) { remaining_for_next[index_4_next] = remaining[j]; index_4_next++; }...

Unexpected result when calculating a percentage - even when factoring in integer division rules

c,percentage,integer-overflow,integer-division

Diagnosis The value you expect is, presumably, 91. The problem appears to be that your compiler is using 16-bit int values. You should identify the platform on which you're working and include information about unusual situations such as 16-bit int types. It is reasonable for us to assume 32-bit or...

scanf get multiple values at once

c,char,segmentation-fault,user-input,scanf

I'm not saying that it cannot be done using scanf(), but IMHO, that's not the best way to do it. Instead, use fgets() to read the whole like, use strtok() to tokenize the input and then, based on the first token value, iterate over the input string as required. A...

How to read string until two consecutive spaces?

c,format,sscanf,c-strings

The scanf family of functions are good for simple parsing, but not for more complicated things like you seem to do. You could probably solve it by using e.g. strstr to find the comment starter "//", terminate the string there, and then remove trailing space....

Disadvantages of calling realloc in a loop

c,memory-management,out-of-memory,realloc

When you allocate/deallocate memory many times, it may create fragmentation in the memory and you may not get big contiguous chunk of the memory. When you do a realloc, some extra memory may be needed for a short period of time to move the data. If your algorithm does...

CGO converting Xlib XEvent struct to byte array?

c,go,xlib,cgo

As mentioned in the cgo documentation: As Go doesn't have support for C's union type in the general case, C's union types are represented as a Go byte array with the same length. Another SO question: Golang CGo: converting union field to Go type or a go-nuts mailing list post...

OpenGL glTexImage2D memory issue

c,opengl

Which man page are you quoting? There are multiple man pages available, not all mapping to the same OpenGL version. Anyways, the idea behind the + 2 (border) is to have 2 multiplied by the value of border, which is in your case 0. So your code is just fine....

C language, vector of struct, miss something?

c,vector,struct

What is happening is that tPeca pecaJogo[tam]; is a local variable, and as such the whole array is allocated in the stack frame of the function, which means that it will be deallocated along with the stack frame where the function it self is loaded. The reason it's working is...

Is there any way of protecting a variable for being modified at runtime in C?

c,variables,constants

You can make the result of the input be const like this: int func() { int op = 0; scanf( "%d", &op ); if( op == 0 ) return 1; else return 2; } int main() { const int v = func(); // ... } NB. Of course, there is...

Galois LFSR - how to specify the output bit number

c,prng,shift-register

If you need bit k (k = 0 ..15), you can do the following: return (lfsr >> k) & 1; This shifts the register kbit positions to the right and masks the least significant bit....

Does strlen() always correctly report the number of char's in a pointer initialized string?

c,strlen

What strlen does is basically count all bytes until it hits a zero-byte, the so-called null-terminator, character '\0'. So as long as the string contains a terminator within the bounds of the memory allocated for the string, strlen will correctly return the number of char in the string. Note that...

Recursive signal call using kill function

c,signals

Historically, lots of details about how signals work have changed. For instance, in the earliest variant, the processing of the signal reverted to default when the handler was called, and the handler had to re-establish itself. In this situation, sending the signal from the handler would kill the process. Currently,...

fread(), solaris to unix portability and use of uninitialised values

c,linux,memory,stack,portability

Q 1. why is ch empty even after fread() assignment? (Most probably) because fread() failed. See the detailed answer below. Q 2.Is this a portability issue between Solaris and Linux? No, there is a possible issue with your code itself, which is correctly reported by valgrind. I cannot quite...

On entry to NIT parameter number 9 had an illegal value

c,mpi,intel-mkl,mpich,scalapack

This answer is courtesy of Ying from Intel, all the credits go to him! The int in C are supposed to be 32bit, you may try lp64 mode. mpicc -o test_lp64 ex1.c -I/opt/intel/mkl/include /opt/intel/mkl/lib/intel64/libmkl_scalapack_lp64.a -L/opt/intel/mkl/lib/intel64 -Wl,--start-group /opt/intel/mkl/lib/intel64/libmkl_intel_lp64.a /opt/intel/mkl/lib/intel64/libmkl_core.a /opt/intel/mkl/lib/intel64/libmkl_sequential.a -Wl,--end-group /opt/intel/mkl/lib/intel64/libmkl_blacs_intelmpi_lp64.a -lpthread -lm -ldl [[email protected] scalapack]$ mpirun -n 4...

Loop through database table and compare user input

mysql,c

If you are only looking for fields that match the input, you'll want to search the database using the input string. In other words, write your query string so that it only gives you results that match the user input. This will be much faster than searching through every returned...

Schedule to run a method at periodic time in java

java,methods,timer,scheduler,runnable

Using the following syntax you can create a lambda expression, which will evaluate to an object of type Runnable. When the run method of that object is called the loadConfig method will get called. scheduler.scheduleAtFixedRate(() -> loadConfig(), 60, 60, TimeUnit.SECONDS); Lambda expressions is a new Java 8 feature. In this...

Is it safe to read and write on an array of 32 bit data byte by byte?

c,memory,memory-alignment

Yes, this is correct. The only danger would be generating a bit pattern that does not correspond to any int, but on modern systems there are no such patterns. Also, if the data type was uint32_t specifically, those are prohibited from having any such patterns anyway. Note that the inverse...