Pages: [1]   Go Down
Author Topic: Multiple PWM signal reading on Arduino Mega 2560  (Read 1511 times)
0 Members and 1 Guest are viewing this topic.
Paris
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dear Sirs,


I’m new in the Arduino world, and I would need, for data acquisition, to read PWM data coming from a R/C receiver (very classical problem) on my Arduino MEGA 2560.

After few hours on Google, the best code I found to do it is:
http://scottrharris.blogspot.fr/2010/01/reading-servo-pwm-with-arduino.html
I tried it, and it run perfectly…!!

However, I would need to read 4 different channels, so I tried to modify the code (see just bellow) to be able to read another channel in the same time.
The code read PIN2 at its origin, and I tried to read PIN3 in the same time.

But this code is still able to read PWM signals on PIN2, but not in PIN3.

Would someone have any idea of the problem??

Thanks in advance for your help,

Best Regards,

Stéphane


 // Reading servos with interrupts 
 // For an Arduino Mega 
 // Scott Harris January 2010 
 // 
 // This work is licensed under the Creative Commons Attribution-Share Alike 3.0 United States License.   
 // To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/us/   

 volatile long servo0; // servo value 
 volatile long count0; // temporary variable for servo1 

 volatile long servo1; // servo value 
 volatile long count1; // temporary variable for servo1
 
 // PIN 2
 // #define int0 (PINE & 0b00010000) // Faster than digitalRead   
 #define int0 (PINE & 0x10)

 // PIN 3
 // #define int0 (PINE & 0b00100000)
 #define int1 (PINE & 0x20)

 void handleInterrupt() 
 { 
  if(int0) 
    count0=micros(); // we got a positive edge 
  else 
   servo0=micros()-count0; // Negative edge: get pulsewidth 
   
  if(int1) 
    count1=micros(); // we got a positive edge 
  else 
   servo1=micros()-count1; // Negative edge: get pulsewidth 
 } 

 void setup() 
 { 
  Serial.begin(9600); 
 
  pinMode(2,INPUT); 
  pinMode(3,INPUT);   
 
  attachInterrupt(0,handleInterrupt,CHANGE); // Catch up and down   
 } 

 void loop() 
 { 
  delay(10); 
  Serial.println(servo0,DEC); // Pulsewidth in microseconds
  Serial.println(servo1,DEC); // Pulsewidth in microseconds 
 } 
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

For pin D3 you need to attachInterrupt (1, blah blah) not zero.
eg.

Code:
attachInterrupt(0, handleInterrupt_D2, CHANGE); // Catch up and down   
attachInterrupt(1, handleInterrupt_D3, CHANGE); // Catch up and down   
Logged

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

Hi,
   Your missing several important points most of which are covered here  -

http://rcarduino.blogspot.com/2012/04/how-to-read-multiple-rc-channels-draft.html

As your using a Mega, you do not need to use the pinchangeint library as you have enough external interrupts already, but you still need to pay attention to shared variable access, could benefit from using bit flags to signal new values are available rather than outputting data whether it has changed or not etc etc.

I am planning a new post showing finished code and standalone hardware that runs in my RC Car based on this code with some additionals to any errors that might occur.

Duane B

rcarduino.blogspot.com
Logged


Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@DuaneB:

attachInterrupt is for external interrupts, not pin change interrupts.
Logged

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

Hi,
  Yes, I know, I was referring to the post I linked where I am using an UNO which has only two external interrupts and so I am using the pinchangeint library to get acccess to additional interrupts.

Also from my blog - http://rcarduino.blogspot.com/2012/03/need-more-interrupts-to-read-more.html

Rakma74,
   Your Mega has more external interrupts than my UNO so you can use attachInterrupt and do not need to use the pcintchange library which provides those of use using UNO's with access to upto 20 additional interrupts. The principles and code are the same for both boards so I suggest you do read the post I linked originally and again below, you can imply drop the PCintChange:: before attachInterrupt, everything else remains the same.

Duane B.

rcarduino.blogspot.com
Logged


Paris
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dear Sirs,


Thank you so much for your answers, you saved my life (smiley-kitty)!
Now, I can read 2 R/C channels in the same time (I just have to extend to 4 r/C channels, and I’ll be happy!).

In fact, I implemented the solution of Nick Gammon (see code bellow).
Also, thank you DuaneB, I’ll try your approach to improve my beginning knowledge of the board!!

Best Regards,

Stéphane


 // Reading servos with interrupts 
 // For an Arduino Mega 
 // Scott Harris January 2010 
 // 
 // This work is licensed under the Creative Commons Attribution-Share Alike 3.0 United States License.   
 // To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/us/   

 volatile long servo0; // servo value 
 volatile long count0; // temporary variable for servo1 

 volatile long servo1; // servo value 
 volatile long count1; // temporary variable for servo1
 
 // PIN 2
 // #define int0 (PINE & 0b00010000) // Faster than digitalRead   
 #define int0 (PINE & 0x10)

 // PIN 3
 // #define int0 (PINE & 0b00100000)
 #define int1 (PINE & 0x20)

 void handleInterrupt_P2() 
 { 
  if(int0) 
    count0=micros(); // we got a positive edge 
  else 
   servo0=micros()-count0; // Negative edge: get pulsewidth 
 }
 
 void handleInterrupt_P3() 
 { 
  if(int1) 
    count1=micros(); // we got a positive edge 
  else 
   servo1=micros()-count1; // Negative edge: get pulsewidth 
 } 

 void setup() 
 { 
  Serial.begin(9600); 
 
  pinMode(2,INPUT); 
  pinMode(3,INPUT);   
 
  attachInterrupt(0,handleInterrupt_P2,CHANGE); // Catch up and down   
  attachInterrupt(1,handleInterrupt_P3,CHANGE); // Catch up and down   
 } 

 void loop() 
 { 
  delay(10); 
  // Serial.println(servo0,DEC); // Pulsewidth in microseconds
  Serial.println(servo1,DEC); // Pulsewidth in microseconds 
 } 
Logged

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

Hi,

Do please read the link, this code below is a car crash waiting to happen as is the code you copied from the post you linked -

Code:
void loop()
 {
  delay(10);
  Serial.println(servo0,DEC); // Pulsewidth in microseconds
  Serial.println(servo1,DEC); // Pulsewidth in microseconds
 } 

When you use servo0 and servo1 in a real world application they will be all over the place.

I use my code in 40km/h RC Race car which is why I protect my shared variable access.

Duane B

rcarduino.blogspot.com
Logged


Paris
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello !!

This is me again, a little bit sad...
I tried to extend to 4 PWM channels, but it does not work for the third and forth channel...
Would you have any idea ?

Thanks in advance and Best Regards,

Stéphane

Code:

 // Reading servos with interrupts 
 // For an Arduino Mega 
 // Scott Harris January 2010 
 // 
 // This work is licensed under the Creative Commons Attribution-Share Alike 3.0 United States License.   
 // To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/us/   

 volatile long servo0; // servo value 
 volatile long count0; // temporary variable for servo0 

 volatile long servo1; // servo value 
 volatile long count1; // temporary variable for servo1

 volatile long servo2; // servo value 
 volatile long count2; // temporary variable for servo2 

 volatile long servo3; // servo value 
 volatile long count3; // temporary variable for servo3
 
 // PIN 2   
 #define int0 (PINE & 0x10)

 // PIN 3
 #define int1 (PINE & 0x20)

 // PIN 18   
 #define int2 (PIND & 0b00001000)

 // PIN 19
 #define int3 (PIND & 0b00000100)

 void handleInterrupt_P2() 
 { 
  if(int0) 
    count0=micros(); // we got a positive edge 
  else 
   servo0=micros()-count0; // Negative edge: get pulsewidth 
 }
 
 void handleInterrupt_P3() 
 { 
  if(int1) 
    count1=micros(); // we got a positive edge 
  else 
   servo1=micros()-count1; // Negative edge: get pulsewidth 
 } 

 void handleInterrupt_P18() 
 { 
  if(int2) 
    count2=micros(); // we got a positive edge 
  else 
   servo2=micros()-count2; // Negative edge: get pulsewidth 
 }
 
  void handleInterrupt_P19() 
 { 
  if(int3) 
    count3=micros(); // we got a positive edge 
  else 
   servo3=micros()-count3; // Negative edge: get pulsewidth 
 }
 
 void setup() 
 { 
  Serial.begin(9600); 
 
  pinMode(2,INPUT); 
  pinMode(3,INPUT);   
  pinMode(18,INPUT);
  pinMode(19,INPUT);
 
  attachInterrupt(0,handleInterrupt_P2,CHANGE); // Catch up and down   
  attachInterrupt(1,handleInterrupt_P3,CHANGE); // Catch up and down   
  attachInterrupt(2,handleInterrupt_P18,CHANGE); // Catch up and down   
  attachInterrupt(3,handleInterrupt_P19,CHANGE); // Catch up and down   

 } 

 void loop() 
 { 
  delay(10); 
  // Serial.println(servo0,DEC); // Pulsewidth in microseconds
  // Serial.println(servo1,DEC); // Pulsewidth in microseconds 
  Serial.println(servo2,DEC); // Pulsewidth in microseconds 
  // Serial.println(servo3,DEC); // Pulsewidth in microseconds 
 } 
Logged

Paris
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ DuaneB

Surely, I read you link !!
Just that the code seems a little bit more complicate, and since I only got my Arduino board yesterday, I'm really a newcomer !!
I tried to compile it, where can I get the library which is missing ?

Best Regards,

Stéphane
Logged

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

Hi,

It's the pinchangeint library, you don't need it on a mega, so remove the include statement and change PCintPort:: before each of the attachInterrupts

You will also need to change the pin numbers, look for the comments 'assign your channel pins' and 'assign your out pins' the channel pins should be updated to whatever pins your channels are connected to from your receiver, the out pins are you channel output pins if you want to drive servos or electronic speed controllers, again update these to whatever pins you have your devices connected to.

Duane B
Logged


Paris
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Dear DuaneB,

I "Finally" succeeded in running both codes (Yours and the other one), thank you !!!

The problems come from the 'attachInterrupt' numbers assignment...
The following worked with my board, I don't really know why, but anyway, this is the only funtion I needed from this board, so, I'm happy (smiley-kitty)

Code:
  // PIN 2
  attachInterrupt(0,handleInterrupt_P2,CHANGE); // Catch up and down   
 
  // PIN 3
  attachInterrupt(1,handleInterrupt_P3,CHANGE); // Catch up and down   
 
  // PIN 18
  attachInterrupt(5,handleInterrupt_P18,CHANGE); // Catch up and down   
 
  // PIN 19
  attachInterrupt(4,handleInterrupt_P19,CHANGE); // Catch up and down

Thanks for all !!

Best Regards,

Stéphane
Logged

Pages: [1]   Go Up
Jump to: