baldengineer

Arduino Software PWM with mills Example

Oct 6th, 2015
2,175
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //pwm-with-millis.ino
  2.  
  3. // macros for LED state
  4. #define ON true
  5. #define OFF false
  6.  
  7. // variables for pattern timing
  8. unsigned long currentMillis = millis();
  9. unsigned long previousMillis = 0;
  10. unsigned long millisInterval = 100;
  11.  
  12. // variables for software PWM
  13. unsigned long currentMicros = micros();
  14. unsigned long previousMicros = 0;
  15. // this is the frequency of the sw PWM
  16. // frequency = 1/(2 * microInterval)
  17. unsigned long microInterval = 250;
  18.  
  19. const byte pwmMax = 100;
  20.  
  21. // fading (for the timing)
  22. int fadeIncrement = 1;
  23.  
  24. // typedef for properties of each sw pwm pin
  25. typedef struct pwmPins {
  26.   int pin;
  27.   int pwmValue;
  28.   bool pinState;
  29.   int pwmTickCount;
  30. } pwmPin;
  31.  
  32. // create the sw pwm pins
  33. // these can be any I/O pin
  34. // that can be set to output!
  35. const int pinCount = 8;
  36. const byte pins[pinCount] = {2,3,5,6,9,10,11,12};
  37.  
  38. pwmPin myPWMpins[pinCount];
  39.  
  40. // function to "setup" the sw pwm pin states
  41. // modify to suit your needs
  42. // this creates an alternating fade pattern
  43. void setupPWMpins() {
  44.   for (int index=0; index < pinCount; index++) {
  45.     myPWMpins[index].pin = pins[index];
  46.  
  47.     // mix it up a little bit
  48.     // changes the starting pwmValue for odd and even
  49.     if (index % 2)
  50.       myPWMpins[index].pwmValue = 25;
  51.     else
  52.       myPWMpins[index].pwmValue = 75;
  53.  
  54.     myPWMpins[index].pinState = ON;
  55.     myPWMpins[index].pwmTickCount = 0;
  56.  
  57.     // unlike analogWrite(), this is necessary
  58.     pinMode(pins[index], OUTPUT);
  59.   }
  60. }
  61.  
  62. void pwmFadePattern() {
  63.   // go through each sw pwm pin, and increase
  64.   // the pwm value. this would be like
  65.   // calling analogWrite() on each hw pwm pin
  66.   for (int index=0; index < pinCount; index++) {
  67.     myPWMpins[index].pwmValue += fadeIncrement;
  68.     if (myPWMpins[index].pwmValue > 100)
  69.       myPWMpins[index].pwmValue = 0;
  70.   }
  71. }
  72.  
  73. void handlePWM() {
  74.   currentMicros = micros();
  75.   // check to see if we need to increment our PWM counters yet
  76.     if (currentMicros - previousMicros >= microInterval) {
  77.     // Increment each pin's counter
  78.     for (int index=0; index < pinCount; index++) {
  79.     // each pin has its own tickCounter
  80.       myPWMpins[index].pwmTickCount++;
  81.  
  82.     // determine if we're counting on or off time
  83.       if (myPWMpins[index].pinState == ON) {
  84.         // see if we hit the desired on percentage
  85.         // not as precise as 255 or 1024, but easier to do math
  86.         if (myPWMpins[index].pwmTickCount >= myPWMpins[index].pwmValue) {
  87.           myPWMpins[index].pinState = OFF;
  88.         }
  89.       } else {
  90.         // if it isn't on, it is off
  91.         if (myPWMpins[index].pwmTickCount >= pwmMax) {
  92.           myPWMpins[index].pinState = ON;
  93.           myPWMpins[index].pwmTickCount = 0;
  94.         }
  95.       }
  96.       // could probably use some bitwise optimization here, digitalWrite()
  97.       // really slows things down after 10 pins.
  98.       digitalWrite(myPWMpins[index].pin, myPWMpins[index].pinState);
  99.     }
  100.     // reset the micros() tick counter.
  101.     digitalWrite(13, !digitalRead(13));
  102.     previousMicros = currentMicros;
  103.   }
  104. }
  105.  
  106. void setup() {
  107.   setupPWMpins();
  108.   pinMode(13, OUTPUT);
  109. }
  110.  
  111. void loop() {
  112.   // this is the magic for sw pwm
  113.   // need to call this anytime you
  114.   // have a long operation
  115.   handlePWM();
  116.  
  117.   // check timer for fading pattern
  118.   // this would be the same
  119.   // if we used analogWrite()
  120.   currentMillis = millis();
  121.   if (currentMillis - previousMillis >= millisInterval) {
  122.     // moved to own funciton for clarity
  123.     pwmFadePattern();
  124.  
  125.     // setup clock for next tick
  126.     previousMillis = currentMillis;
  127.   }
  128. }
  129.  
  130. // Code from james@baldengineer.com
  131. // email | twitter | www
  132. // See more at: https://www.baldengineer.com/software-pwm-with-millis.html
RAW Paste Data