energia / msp432r-core

MSP432 EMT core for the production silicon (RED LaunchPad only)
2 stars 5 forks source link

Conflict when using PWM and Servo at the same time #27

Open fcooper opened 5 years ago

fcooper commented 5 years ago

OS: Windows 10 64bit IDE Version: Energia 1.8.7E21 Board: MSP_EXP432E401Y Core: MSP432 EMT Red v5.25.0

Currently I'm having an issue when using both analogWrite and the Servo library. It appears that the Servo library isn't aware of what timers analogWrite is using. Therefore, the two can conflict which causes weird behavior on both the pwm and servo pins.

Pins I'm using for PWM P2.7, P2.6, P2.4 and P5.7

Pins I'm using for Servo P3.7 and P3.6

Base example I used for testing is below

// Sweep
// by BARRAGAN <http://barraganstudio.com> 
// Modified for Energia/Stellaris Launchpad by Kevin Balke <fughilli@gmail.com>
// This example code is in the public domain.

#include <Servo.h> 

#define P2_4  38
#define P2_6  39
#define P2_7  40
#define P5_7  17

#define P3_6  11
#define P3_7  31

Servo myservo1;  // create servo object to control a servo 
Servo myservo2;             // a maximum of eight servo objects can be created 

int pos = 0;    // variable to store the servo position 

void setup() 
{ 

  myservo1.attach(P3_6);  // attaches the servo on Port F, pin 1 (Red LED pin) to the servo object
  myservo2.attach(P3_7);  // attaches the servo on Port F, pin 1 (Red LED pin) to the servo object

  analogWrite(P2_4,50);
  analogWrite(P2_6,100);
  analogWrite(P2_7,150);
  analogWrite(P5_7,200);      
} 

void loop() 
{ 
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo1.write(pos);              // tell servo to go to position in variable 'pos' 
    myservo2.write(pos);   
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo1.write(pos);   
    myservo2.write(pos);       // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
} 

Based on the above example image

Based on the above example but I made P5_7 a servo pin and P3_7 a pwm pin. image

Based on the above example but I made P5_7 a servo pin and P3_6 a pwm pin. image

As you can see at times depending on the order that pwm and servo pins are first used the output can vary. All six pins should have some kind of output but that isn't the case with the above.

fcooper commented 5 years ago

Based on conversations with Robert and looking at the code this issue is due to the way the PWM code is written. PWM uses port mapping to allow almost an pin to be used for PWM. This port mapped pwm uses Timer A. However, the PWM code does not "claim" the timer it is using. Therefore, when other code attempts to request a free timer it may grab the same timer A instance that PWM may already be using. The proper fix is to have the PWM to properly claim the timer it is using so no other code will accidentally grab it. Also PWM code needs to check to see if the timer a instance is claimed by someone else before port mapping.

fcooper commented 5 years ago

Tested this again on the official 5.25.0 release. I'm still seeing this issue.

ndroid commented 1 year ago

I believe v5.29 correctly claims (and checks for availability) of timer for analogWrite, though there is still a potential limitation produced by the conflict for the Timer_A resources. I have updated the MSP432 core to work on Arduino and have modified the Servo library so that it uses Timer32 instead, thereby having no conflict with PWM outputs. It is thus theoretically possible to have 12 PWM and 8 servo outputs concurrently.

You can find the package index file, board package and source at msp432-core.

This core is also included with the broader Energia core maintenance effort provided by TI_Platform_Cores_For_Arduino.