Pages: 1 2 [3] 4 5   Go Down
Author Topic: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Mega) pins  (Read 20354 times)
0 Members and 1 Guest are viewing this topic.
Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Big change, from 108 instructions to 54 - cut the time in half !

Code:
     358: e5 2e        mov r14, r21
     35a: ff 24        eor r15, r15
     35c: 1c c0        rjmp .+56      ; 0x396 <_ZN9PCintPort5PCintEv+0x78>
     35e: 8b 81        ldd r24, Y+3 ; 0x03
     360: 28 2f        mov r18, r24
     362: 30 e0        ldi r19, 0x00 ; 0
     364: c7 01        movw r24, r14
     366: 82 23        and r24, r18
     368: 93 23        and r25, r19
     36a: 89 2b        or r24, r25
     36c: 89 f0        breq .+34      ; 0x390 <_ZN9PCintPort5PCintEv+0x72>
  #ifndef NO_PIN_STATE
  PCintPort::pinState=PCintPort::curr & p->mask ? HIGH : LOW;
     36e: 80 91 44 01 lds r24, 0x0144
     372: 40 e0        ldi r20, 0x00 ; 0
     374: 90 e0        ldi r25, 0x00 ; 0
     376: 82 23        and r24, r18
     378: 93 23        and r25, r19
     37a: 89 2b        or r24, r25
     37c: 09 f0        breq .+2      ; 0x380 <_ZN9PCintPort5PCintEv+0x62>
     37e: 41 e0        ldi r20, 0x01 ; 1
     380: 40 93 46 01 sts 0x0146, r20
  #endif
  #ifndef NO_PIN_NUMBER
  PCintPort::arduinoPin=p->arduinoPin;
     384: 8c 81        ldd r24, Y+4 ; 0x04
     386: 80 93 45 01 sts 0x0145, r24
  #endif
  #ifdef PINMODE
  PCintPort::pinmode=p->mode;
  #endif
  p->PCintFunc();
     38a: e8 81        ld r30, Y
     38c: f9 81        ldd r31, Y+1 ; 0x01
     38e: 09 95        icall
      }
      p = p->next;

Great work Rob and greynomad

Duane B

rcarduino.blogspot.com
Logged


Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The update in action reading RC Signals -



The red line is before, the green line is after. They both represent the maximum variation between two consecutive RC Pulses in 10 seconds periods. There are three channels, when one channel goes high, the adjacent channel goes low meaning we will often need to service two interrupts in one call to the ISR, the improved efficiency has a visible effect in the graph.

Full explanation of the graph towards the end of this -
http://rcarduino.blogspot.com/2012/11/how-to-read-rc-channels-rcarduinofastlib.html

Duane B

rcarduino.blogspot.com
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13921
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what are the average numbers of blue, red and green? (I do not fully understand the test As I did not dived into it yet smiley
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
   The test is very application specific and not a good way to measure pinchangeint performance, however it does illustrate that there is a improvement.

A quick look at the assembly suggests that the instructions have been reduced from 104 to 52 - a saving of 50%.

My application is reading RC Signals, when one pin toggles, the adjacent pin also toggles, this means that the pin change int library will be servicing two pins each time it is called so the saving is very significant in this particular application.

Duane B

rcarduino.blogspot.com
Logged


nr Bundaberg, Australia
Online Online
Tesla Member
***
Karma: 129
Posts: 8605
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Great work Rob and greynomad
Much as I'd love to take the credit you probably meant GreyGnome smiley

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Fixed, thanks

Duane B
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13921
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
They both represent the maximum variation between two consecutive RC Pulses in 10 seconds periods.
What is the unit of the Y-axis ? 
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

X Axis is sample number where a sample is a period of 10 seconds.

Y Axis is the largest deviation between two consecutive RC Signals in milliseconds encountered in the 10 second sample period - in an ideal world it would all be 0.

The signals are being read using the modified PinChangeInt code.

As I say, its very application specific but between my new servo library and other optimizations (blue line to red line)  and the modified PinChangeInt (red line to green line) the improvement is quite dramatic.

Duane B

rcarduino.blogspot.com
Logged


Belgium
Offline Offline
Edison Member
*
Karma: 68
Posts: 1926
Arduino rocks; but with my plugin it can fly rocking the world ;-)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Duane
I guess this also explains the peeks I have we discussed http://arduino.cc/forum/index.php/topic,129802.msg976347.html#msg976347.
as I still use the blue line and the whole scope is about 1 minute and  have 6 rc channels to read that comes close.
Or am I missing something?
Best regards
Jantje
Logged

Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Jante,
   No idea what was causing the peaks, why don't you try the code here including my new servo library -

http://rcarduino.blogspot.com/2012/11/how-to-read-rc-channels-rcarduinofastlib.html

I could use a friendly tester.

I would suggest testing outputs instead of the measured signal - thats the hard part getting highly consistent output pulses - the new servo library helps with this.

As this is now off topic I will start a new topic on the library in a day or two when I have a chance to document it a little more, but Jante, you should be able to find your way around it and have a go at testing in the meantime - if you can find the time.

Duane B
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 224
Posts: 13921
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@GreyGnome
did you have time to look at my remark in #28 regarding your optimization proposal of the boolean expression.

there is a diff in the formulas when rising = 0, falling = 1 and curr = 0



« Last Edit: November 05, 2012, 12:32:06 pm by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

0
Offline Offline
Jr. Member
**
Karma: 4
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@GreyGnome
did you have time to look at my remark in #28 regarding your optimization proposal of the boolean expression.

there is a diff in the formulas when rising = 0, falling = 1 and curr = 0

Yes- sorry. I have been a busy busy busy little beaver! Geez, what a week!

You're right- my optimization was messed up because I made a mistake in my truth table. I think your expression is about the best that we can do. Second- there are more dragons lying about than I had bargained for! I spent the better part of a week's free time wrestling with a big bug in my posted code; I said:
Code:
PCintPort::curr ^ lastPinView & (portRisingPins...
and I should have said: 
Code:
(PCintPort::curr ^ lastPinView) & (portRisingPins...

...Operator precedence. It's not just a good idea, it's the law! OMG what a debugging session I had.

The extra nice thing is, because of my debugging, I uncovered a significant flaw in my code! This is a big deal if you have fast interrupts, and it is real nasty when you have, for example, switches that bounce (don't they all?).  The end of the PCint() function should look like this:
Code:
   #ifndef DISABLE_PCINT_MULTI_SERVICE
        pcifr = PCIFR & PCICRbit;
        PCIFR = pcifr;  // clear the interrupt if we will process it (no effect if bit is zero)
        PCintPort::curr=portInputReg; // BUG! ...Fixed in 2.11beta. Without this, we get really weird interrupt behavior. Sheesh.
                                      // This fix slows down the code, though. Even with only 1 pin interrupting.
    } while(pcifr);
    #endif

...don't worry about the speed slowdown mentioned in the comment. With your fix, robtillaart, my tests speed up by a couple of micros. Sadly, that PCintPort::curr=portInputReg will be run even if pcifr is 0. But it's either that or an if statement, in any event. If you don't need it, best to define DISABLE_PCINT_MULTI_SERVICE.

I hope to post version 2.11beta soon. Right now I think I've uncovered/fixed/optimised/edited/compiled everything necessary, but the code is in a bit of a shambles right now so give me a day or two to clean up. In the meantime, there is that damn bug that you can fix in v. 2.01beta by copying from my snippet above.
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
There are two current forum topics where pinchangeint is being used to read incoming rc signals. In both topics, the ops would like to detach pin change interrupts and later reattach them to enter and exit autonomous and RC Modes. I have suggested that this is not the best approach due to the memory leak in detach. As an alternative, would you consider adding an enable function that will set or clear the relevant bit for given pin in the pin change port masks allowing the user to disable pin changes for one more pins and reenable them later without memory leaks.

Duane B
Logged


0
Offline Offline
Jr. Member
**
Karma: 4
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
There are two current forum topics where pinchangeint is being used to read incoming rc signals. In both topics, the ops would like to detach pin change interrupts and later reattach them to enter and exit autonomous and RC Modes. I have suggested that this is not the best approach due to the memory leak in detach. As an alternative, would you consider adding an enable function that will set or clear the relevant bit for given pin in the pin change port masks allowing the user to disable pin changes for one more pins and reenable them later without memory leaks.

Duane B
Memory leaks!  Yikes! Could you tell me more about that issue? On the face of it I don't mind such a "pause" function, but moreso I am not comfortable with such a bug. It should be fixed.
Logged

Dubai, UAE
Offline Offline
Edison Member
*
Karma: 22
Posts: 1675
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I assume its a memory leak as my understanding is that delete does not free memory in Arduino and the current implementation of detach seems to assume that delete works.

Duane B
Logged


Pages: 1 2 [3] 4 5   Go Up
Jump to: