Browse Source

Bugfixes for staggered PWM

Kevin Lee 3 years ago
parent
commit
6ac5916d41
2 changed files with 51 additions and 35 deletions
  1. 43 25
      Nixie_Firmware_Mbed/main.cpp
  2. 8 10
      Nixie_Firmware_Mbed/pca9685.cpp

+ 43 - 25
Nixie_Firmware_Mbed/main.cpp

@@ -87,7 +87,7 @@ TUBE_CALLBACK(3)
 
 // In the event that there are multiple PWM outputs at less than 100% duty cycle,
 // stagger the start time of each PWM to reduce the switch on surge current.
-void StaggerPwmOutput() {
+void ComputePwmOffsets() {
     int validOutputs = 0;
     int totalOnTime = 0;
     int lastPwmEnd = 0;
@@ -115,9 +115,15 @@ void StaggerPwmOutput() {
 
         for (int i = 0; i < NUM_TUBES; i++) {
             for (int j = 0; j < NUM_DIGITS; j++) {
-                if (Tubes[i].Digits[j].Value != PCA9685_Min_Brightness && 
-                    Tubes[i].Digits[j].Value != PCA9685_Max_Brightness) {
-
+                if (Tubes[i].Digits[j].Value == PCA9685_Min_Brightness) {
+                    Tubes[i].Digits[j].PwmStart = 0;
+                    Tubes[i].Digits[j].PwmEnd = 0;
+                }
+                else if (Tubes[i].Digits[j].Value == PCA9685_Max_Brightness) {
+                    Tubes[i].Digits[j].PwmStart = 0;
+                    Tubes[i].Digits[j].PwmEnd = PCA9685_Max_Brightness;
+                }
+                else {
                     Tubes[i].Digits[j].PwmStart = lastPwmEnd;
                     Tubes[i].Digits[j].PwmEnd = lastPwmEnd + Tubes[i].Digits[j].Value;
                     lastPwmEnd = Tubes[i].Digits[j].PwmEnd;
@@ -125,7 +131,15 @@ void StaggerPwmOutput() {
                 }
             }
         }
-        if (Dot.Value != PCA9685_Min_Brightness && Dot.Value != PCA9685_Max_Brightness) {
+        if (Dot.Value == PCA9685_Min_Brightness) {
+            Dot.PwmStart = 0;
+            Dot.PwmEnd = 0;
+        }
+        else if (Dot.Value == PCA9685_Max_Brightness) {
+            Dot.PwmStart = 0;
+            Dot.PwmEnd = PCA9685_Max_Brightness;
+        }
+        else {
             Dot.PwmStart = lastPwmEnd;
             Dot.PwmEnd = lastPwmEnd + Dot.Value;
             lastPwmEnd = Dot.PwmEnd;
@@ -134,23 +148,37 @@ void StaggerPwmOutput() {
     }
     else {
         // Compute the amount of overlap between all outputs
-        int overlap = totalOnTime / (validOutputs - 1);
+        int overlap = (totalOnTime - PCA9685_Max_Brightness) / (validOutputs - 1);
 
         // Compute the staggered output period for each output
         for (int i = 0; i < NUM_TUBES; i++) {
             for (int j = 0; j < NUM_DIGITS; j++) {
-                if (Tubes[i].Digits[j].Value != PCA9685_Min_Brightness && 
-                    Tubes[i].Digits[j].Value != PCA9685_Max_Brightness) {
-
-                    Tubes[i].Digits[j].PwmStart = (lastPwmEnd == 0) ? 0 : lastPwmEnd - overlap;
+                if (Tubes[i].Digits[j].Value == PCA9685_Min_Brightness) {
+                    Tubes[i].Digits[j].PwmStart = 0;
+                    Tubes[i].Digits[j].PwmEnd = 0;
+                }
+                else if (Tubes[i].Digits[j].Value == PCA9685_Max_Brightness) {
+                    Tubes[i].Digits[j].PwmStart = 0;
+                    Tubes[i].Digits[j].PwmEnd = PCA9685_Max_Brightness;
+                }
+                else {
+                    Tubes[i].Digits[j].PwmStart = (lastPwmEnd - overlap < 0) ? 0 : lastPwmEnd - overlap;
                     Tubes[i].Digits[j].PwmEnd = Tubes[i].Digits[j].PwmStart + Tubes[i].Digits[j].Value;
                     lastPwmEnd = Tubes[i].Digits[j].PwmEnd;
                     Tubes[i].Digits[j].Updated = true;
                 }
             }
         }
-        if (Dot.Value != PCA9685_Min_Brightness && Dot.Value != PCA9685_Max_Brightness) {
-            Dot.PwmStart = (lastPwmEnd == 0) ? 0 : lastPwmEnd - overlap;
+        if (Dot.Value == PCA9685_Min_Brightness) {
+            Dot.PwmStart = 0;
+            Dot.PwmEnd = 0;
+        }
+        else if (Dot.Value == PCA9685_Max_Brightness) {
+            Dot.PwmStart = 0;
+            Dot.PwmEnd = PCA9685_Max_Brightness;
+        }
+        else {
+            Dot.PwmStart = (lastPwmEnd - overlap < 0) ? 0 : lastPwmEnd - overlap;
             Dot.PwmEnd = Dot.PwmStart + Dot.Value;
             lastPwmEnd = Dot.PwmEnd;
             Dot.Updated = true;
@@ -329,28 +357,18 @@ int main() {
         if (RefreshTick) {
             RefreshTick = false;
 
-            StaggerPwmOutput();
+            ComputePwmOffsets();
             for (int i = 0; i < NUM_TUBES; i++) {
                 for (int j = 0; j < NUM_DIGITS; j++) {
                     if (Tubes[i].Digits[j].Updated) {
-                        if (Tubes[i].Digits[j].Value == PCA9685_Min_Brightness ||
-                            Tubes[i].Digits[j].Value == PCA9685_Max_Brightness) {
-
-                            PCA9685_SetDigit(i, j, Tubes[i].Digits[j].Value);
-                        } else {
-                            PCA9685_SetDigitPwm(i, j, Tubes[i].Digits[j].PwmStart, Tubes[i].Digits[j].PwmEnd);
-                        }
+                        PCA9685_SetDigitPwm(i, j, Tubes[i].Digits[j].PwmStart, Tubes[i].Digits[j].PwmEnd);
                         Tubes[i].Digits[j].Updated = false;
                     }
                 }
             }
 
             if (Dot.Updated) {
-                if (Dot.Value == PCA9685_Min_Brightness || Dot.Value == PCA9685_Max_Brightness) {
-                    PCA9685_SetDot(Dot.Value);
-                } else {
-                    PCA9685_SetDotPwm(Dot.PwmStart, Dot.PwmEnd);
-                }
+                PCA9685_SetDotPwm(Dot.PwmStart, Dot.PwmEnd);
                 Dot.Updated = false;
             }
         }

+ 8 - 10
Nixie_Firmware_Mbed/pca9685.cpp

@@ -71,13 +71,12 @@ void PCA9685_SetDigit(int Tube, int Digit, int Brightness) {
 void PCA9685_SetDigitPwm(int Tube, int Digit, int StartPwm, int EndPwm) {
     LED_CTRL reg = {0};
 
-    if (StartPwm == PCA9685_Min_Brightness && EndPwm == PCA9685_Max_Brightness) {
+    reg.ON = StartPwm;
+    reg.OFF = EndPwm;
+    if (EndPwm - StartPwm >= PCA9685_Max_Brightness) {
         reg.ON_FULL = 1;
-    } else if (StartPwm == EndPwm) {
+    } else if (EndPwm == 0) {
         reg.OFF_FULL = 1;
-    } else {
-        reg.ON = StartPwm;
-        reg.OFF = EndPwm;
     }
 
     I2C_Write(Tube_Mapping[Tube][Digit][MAP_ADDR],
@@ -102,13 +101,12 @@ void PCA9685_SetDot(int Brightness) {
 void PCA9685_SetDotPwm(int StartPwm, int EndPwm) {
     LED_CTRL reg = {0};
 
-    if (StartPwm == PCA9685_Min_Brightness && EndPwm == PCA9685_Max_Brightness) {
+    reg.ON = StartPwm;
+    reg.OFF = EndPwm;
+    if (EndPwm - StartPwm >= PCA9685_Max_Brightness) {
         reg.ON_FULL = 1;
-    } else if (StartPwm == EndPwm) {
+    } else if (EndPwm == 0) {
         reg.OFF_FULL = 1;
-    } else {
-        reg.ON = StartPwm;
-        reg.OFF = EndPwm;
     }
 
     I2C_Write(TUBE_DOT_ADDR, FIELD_OFFSET(PCA9685_REGS, TUBE_DOT_PIN), reg.AS_BYTE, sizeof(LED_CTRL));