Concept code which launches two threads, one of which implements a Modbus Tunnel protocol to talk with an ISEM, the other which launches a Modbus RTU protocol to talk to a CPUM (most of the Modbus code has been removed prior to publishing.) A canned AC and DC spectra is provided to display wave forms on start-up however the project normally polls for spectra from the ISEM and then plots is (that functionality has been removed prior to publishing.)

Dependencies:   LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI

/media/uploads/Damotclese/img_20190530_100915.jpg

Plot of the initial start-up canned AC and DC spectra.

Revision:
1:01394e5db95b
Parent:
0:387684ec9d92
Child:
2:346119b3db6c
--- a/NextGen-Exerciser-Main.cpp	Thu May 30 05:16:27 2019 +0000
+++ b/NextGen-Exerciser-Main.cpp	Thu May 30 18:24:08 2019 +0000
@@ -112,10 +112,83 @@
         -191.656234000,-180.377243000,-169.183487000,-158.009185000,-146.788055440,-135.456863440,-123.959488000,-112.251495330,
         -100.304824000,-88.112571711,-75.693458500,-63.095802300,-50.400745400,-37.724391933,-25.218734744,-13.071174622
     } ;
+
+    static float f_decimatedDCSpectrum[] =
+    {
+        164622.859, 156185.187, 130679.648, 94457.766, 60629.086, 35816.664, 20260.646, 12169.420,
+        9521.371, 9680.042, 10389.553, 14924.355, 29797.771, 54048.340, 79677.930, 100584.007,
+        114916.859, 123130.789, 126640.937, 127108.539, 125978.539, 124264.656, 122565.765, 121160.593,
+        120120.234, 119405.492, 118934.531, 118622.812, 118402.031, 118224.390, 118060.507, 117896.296,
+        117727.086, 117552.828, 117375.304, 117196.453, 117017.570, 116837.726, 116656.039, 116473.492,
+        116289.906, 116104.265, 115915.937, 115723.570, 115526.664, 115325.656, 115120.421, 114911.429,
+        114697.828, 114476.804, 114247.992, 114013.179, 113771.867, 113522.140, 113264.578, 113002.109,
+        112735.640, 112462.671, 112182.187, 111892.171, 111590.554, 111280.000, 110962.125, 110639.429,
+        110312.679, 109975.781, 109623.398, 109255.132, 108878.789, 108498.742, 108109.039, 107706.664,
+        107291.461, 106863.039, 106420.086, 105960.101, 105483.578, 104994.242, 104495.437, 103984.203,
+        103457.976, 102917.992, 102363.515, 101794.343, 101214.031, 100629.211, 100040.492, 99439.859,
+        98819.461, 98173.063, 97503.469, 96825.117, 96144.188, 95452.000, 94738.039, 93996.977,
+        93228.984, 92435.734, 91625.875, 90815.219, 90004.086, 89177.555, 88331.219, 87471.523,
+        86607.555, 85742.336, 84864.008, 83967.336, 83058.867, 82140.016, 81212.930, 80285.523,
+        79358.758, 78424.992, 77494.000, 76579.289, 75662.469, 74731.563, 73808.039, 72908.133,
+        72025.875, 71144.391, 70256.500, 69372.094, 68501.109, 67648.109, 66813.898, 65996.867,
+        65195.641, 64414.758, 63665.418, 62947.723, 62251.930, 61577.820, 60930.938, 60310.703,
+        59717.070, 59153.746, 58622.043, 58124.535, 57664.281, 57239.590, 56849.543, 56495.852,
+        56177.289, 55892.000, 55643.016, 55431.777, 55257.840, 55124.254, 55029.434, 54971.840,
+        54955.445, 54979.289, 55040.957, 55139.879, 55278.230, 55457.840, 55673.457, 55925.805,
+        56220.500, 56554.961, 56925.184, 57330.996, 57773.441, 58253.074, 58770.402, 59326.258,
+        59917.891, 60538.234, 61187.504, 61875.184, 62605.102, 63370.285, 64161.137, 64974.477,
+        65816.297, 66691.320, 67592.148, 68503.984, 69422.414, 70364.266, 71343.883, 72351.906,
+        73372.016, 74390.320, 75401.859, 76421.227, 77464.242, 78523.742, 79582.586, 80642.227,
+        81714.758, 82804.367, 83906.422, 85006.211, 86092.281, 87169.992, 88245.125, 89310.359,
+        90360.758, 91407.516, 92457.242, 93497.219, 94524.414, 95552.211, 96577.430, 97588.609,
+        98588.539, 99575.063, 100543.234, 101498.179, 102434.992, 103344.476, 104234.867, 105114.281,
+        105982.656, 106839.539, 107682.593, 108518.468, 109349.765, 110166.625, 110967.500, 111753.843,
+        112524.437, 113279.453, 114016.820, 114732.929, 115433.171, 116129.640, 116820.101, 117493.351,
+        118144.578, 118774.367, 119390.500, 119997.554, 120589.562, 121168.031, 121741.507, 122308.328,
+        122861.468, 123400.164, 123925.187, 124437.125, 124944.039, 125448.539, 125940.484, 126416.187,
+        126881.367, 127340.125, 127790.164, 128227.226, 128651.578, 129064.890, 129469.812, 129867.937,
+        130259.703, 130648.023, 131031.523, 131406.046, 131770.140, 132124.406, 132471.937, 132814.875,
+        133153.359, 133487.703, 133816.296, 134134.171, 134439.421, 134738.953, 135040.187, 135338.218,
+        135628.468, 135915.687, 136198.750, 136474.656, 136746.062, 137011.234, 137270.937, 137531.343,
+        137787.781, 138033.875, 138274.046, 138511.078, 138741.453, 138967.078, 139194.343, 139418.796,
+        139635.859, 139849.718, 140059.359, 140263.546, 140464.187, 140661.343, 140856.937, 141051.328,
+        141241.859, 141427.875, 141610.156, 141789.250, 141965.359, 142139.234, 142310.125, 142476.343,
+        142639.187, 142799.046, 142954.359, 143106.234, 143255.687, 143402.343, 143547.250, 143690.609,
+        143830.875, 143967.234, 144099.421, 144228.046, 144353.625, 144475.734, 144594.656, 144710.671,
+        144823.093, 144931.390, 145036.046, 145138.921, 145240.593, 145339.421, 145434.562, 145525.906,
+        145612.765, 145694.562, 145771.609, 145845.453, 145916.843, 145984.953, 146049.296, 146109.531,
+        146165.484, 146216.843, 146262.718, 146304.031, 146341.515, 146373.906, 146400.953, 146423.250,
+        146440.265, 146451.703, 146457.453, 146456.968, 146450.687, 146439.015, 146420.750, 146395.453,
+        146364.703, 146329.000, 146286.328, 146235.890, 146179.187, 146116.390, 146046.562, 145970.250,
+        145888.875, 145802.343, 145709.578, 145611.015, 145507.875, 145400.656, 145289.718, 145175.437,
+        145058.906, 144941.578, 144823.593, 144704.640, 144585.046, 144464.984, 144345.546, 144229.687,
+        144119.281, 144013.609, 143912.671, 143818.609, 143732.531, 143654.062, 143584.265, 143524.062,
+        143472.843, 143430.656, 143398.421, 143376.796, 143365.031, 143361.171, 143364.421, 143375.312,
+        143393.546, 143417.750, 143448.921, 143488.828, 143537.078, 143593.468, 143657.265, 143727.843,
+        143806.734, 143893.125, 143984.609, 144081.359, 144184.625, 144293.546, 144406.218, 144524.500,
+        144650.468, 144782.187, 144918.953, 145061.843, 145211.578, 145369.562, 145536.781, 145712.218,
+        145895.156, 146085.937, 146284.156, 146491.125, 146708.437, 146934.328, 147168.796, 147413.734,
+        147668.906, 147933.296, 148206.078, 148487.953, 148777.734, 149071.968, 149373.265, 149686.093,
+        150007.109, 150328.703, 150648.953, 150969.625, 151287.671, 151603.171, 151921.078, 152239.421,
+        152552.781, 152860.218, 153163.453, 153463.234, 153758.718, 154050.921, 154341.515, 154628.250,
+        154907.796, 155179.656, 155444.531, 155703.500, 155957.656, 156205.265, 156446.359, 156685.718,
+        156922.781, 157152.437, 157374.281, 157590.484, 157802.796, 158010.562, 158211.375, 158407.156,
+        158600.015, 158787.093, 158967.703, 159144.312, 159317.187, 159486.218, 159652.437, 159816.218,
+        159976.906, 160135.031, 160291.250, 160443.359, 160590.359, 160733.843, 160875.171, 161015.390,
+        161154.515, 161291.843, 161427.000, 161559.953, 161689.953, 161815.781, 161939.203, 162063.375,
+        162187.312, 162307.875, 162424.328, 162538.328, 162651.750, 162765.296, 162878.078, 162987.562,
+        163093.531, 163199.171, 163305.312, 163410.593, 163514.609, 163617.453, 163720.437, 163824.093,
+        163926.906, 164028.125, 164126.515, 164224.531, 164334.281, 164304.281, 163889.750, 164209.968
+    } ;
    
     // We will be using the LCD so instantiate an object locally
     static LCD_DISCO_F429ZI st_lcd;
     
+    // When searching for the intersection of AC and DC curves, we store the values here
+    static uint16_t u16_firstIntersectionHeight;
+    static uint16_t u16_secondIntersectionHeight;
+
+    
 // ----------------------------------------------------------------------
 // MainProcessDecimatedSpectrum()
 //
@@ -140,45 +213,74 @@
 // ----------------------------------------------------------------------
 static void MainProcessDecimatedSpectrum(void)
 {
-    uint16_t u16_searchLoop  = 0;
-    uint32_t u32_sampleRatio = 0;
-    uint16_t u16_resultIndex = 0;
-    float    f_smallNumber   = 10000000.0f;
-    float    f_largeNumber   = 0.0f;
+    uint16_t u16_searchLoop    = 0;
+    uint32_t u32_sampleACRatio = 0;
+    uint32_t u32_sampleDCRatio = 0;
+    uint16_t u16_resultIndex   = 0;
+    float    f_smallACNumber   = 10000000.0f;
+    float    f_largeACNumber   = 0.0f;
+    float    f_smallDCNumber   = 10000000.0f;
+    float    f_largeDCNumber   = 0.0f;
     
     // Search through the AC spectrum for the smallest and the largest values
     for (u16_searchLoop = 0; u16_searchLoop < 512; u16_searchLoop++)
     {
-        if (f_decimatedACSpectrum[u16_searchLoop] < f_smallNumber)
+        // First do the AC SPectrum
+        if (f_decimatedACSpectrum[u16_searchLoop] < f_smallACNumber)
         {
             // This value is the new lowest number
-            f_smallNumber = f_decimatedACSpectrum[u16_searchLoop];
+            f_smallACNumber = f_decimatedACSpectrum[u16_searchLoop];
+        }
+        
+        if (f_decimatedACSpectrum[u16_searchLoop] > f_largeACNumber)
+        {
+            // This value is the new highest number
+            f_largeACNumber = f_decimatedACSpectrum[u16_searchLoop];
         }
         
-        if (f_decimatedACSpectrum[u16_searchLoop] > f_largeNumber)
+        // Now do the DC spectrum
+        if (f_decimatedDCSpectrum[u16_searchLoop] < f_smallDCNumber)
+        {
+            // This value is the new lowest number
+            f_smallDCNumber = f_decimatedDCSpectrum[u16_searchLoop];
+        }
+        
+        if (f_decimatedDCSpectrum[u16_searchLoop] > f_largeDCNumber)
         {
             // This value is the new highest number
-            f_largeNumber = f_decimatedACSpectrum[u16_searchLoop];
+            f_largeDCNumber = f_decimatedDCSpectrum[u16_searchLoop];
         }        
     }
     
-    // Is the smallest number negative? We know that it is but we check
-    if (f_smallNumber < 0.0f)
+    // Is the smallest AC number negative? We know that it is but we check
+    if (f_smallACNumber < 0.0f)
     {
         // Make the value absolute so that it is positive
-        f_smallNumber = abs(f_smallNumber);
+        f_smallACNumber = abs(f_smallACNumber);
     }
     
+    // Is the smallest DC number negative?
+    if (f_smallDCNumber < 0.0f)
+    {
+        // Make the value absolute so that it is positive
+        f_smallDCNumber = abs(f_smallDCNumber);
+    }
+     
     // To make all values positive, add the newly-derived positive value.
     // This makes all numbers positive and ensures that the smallest
     // value in the spectra is zero.
     for (u16_searchLoop = 0; u16_searchLoop < 512; u16_searchLoop++)
     {
-        f_decimatedACSpectrum[u16_searchLoop] += f_smallNumber;
+        // Do the AC spectrum 
+        f_decimatedACSpectrum[u16_searchLoop] += f_smallACNumber;
+
+        // Do the DC spectrum 
+        f_decimatedDCSpectrum[u16_searchLoop] += f_smallDCNumber;
     }
     
     // Also add the newly-positive number to our largest known value
-    f_largeNumber += f_smallNumber;
+    f_largeACNumber += f_smallACNumber;
+    f_largeDCNumber += f_smallDCNumber;
     
     // Determine the ratio to use, the LCD screen is 240 by 320 so we 
     // take the highest number value in the spectra and divide by 240
@@ -186,19 +288,28 @@
     // plotted across the 320 by averaging every 2 samples to yield
     // 256 horizontal positions. We plot with the screen laying on
     // its side
-    u32_sampleRatio = (f_largeNumber / LCD_WIDTH);
+    u32_sampleACRatio = (f_largeACNumber / LCD_WIDTH);
+    u32_sampleDCRatio = (f_largeDCNumber / LCD_WIDTH);
     
     // Go through each pairs of samples and average them and then
     // divide the result by the ratio. Step through in twos
     for (u16_searchLoop = 0; u16_searchLoop < 512; u16_searchLoop += 2, u16_resultIndex++)
     {
-        // Take the next two samples and average them, putting the result
+        // Take the next two AC samples and average them, putting the result
         // in to the next result index of the same buffer we're processing
         f_decimatedACSpectrum[u16_resultIndex] =
             (f_decimatedACSpectrum[u16_searchLoop] + f_decimatedACSpectrum[u16_searchLoop]) / 2;
     
         // Divide the sample value by the ratio
-        f_decimatedACSpectrum[u16_resultIndex] /= u32_sampleRatio;
+        f_decimatedACSpectrum[u16_resultIndex] /= u32_sampleACRatio;
+        
+        // Take the next two DC samples and average them, putting the result
+        // in to the next result index of the same buffer we're processing
+        f_decimatedDCSpectrum[u16_resultIndex] =
+            (f_decimatedDCSpectrum[u16_searchLoop] + f_decimatedDCSpectrum[u16_searchLoop]) / 2;
+    
+        // Divide the sample value by the ratio
+        f_decimatedDCSpectrum[u16_resultIndex] /= u32_sampleDCRatio;
     }
 }
 
@@ -217,7 +328,7 @@
     // Plot the spectrum values, plotting a line from point to point
     for (u16_searchLoop = 0; u16_searchLoop < ((512 / 2) - 1); u16_searchLoop++)
     {
-        // Ensure that we actually fit. The sample should
+        // Ensure that we actually fit. The AC sample should
         if (f_decimatedACSpectrum[u16_searchLoop] <= LCD_WIDTH)
         {
             st_lcd.DrawLine(f_decimatedACSpectrum[u16_searchLoop], u16_searchLoop, 
@@ -228,6 +339,105 @@
             // Mathematically we topped-out past the maximum some how
             st_lcd.DrawPixel(0, u16_searchLoop, LCD_COLOR_WHITE);
         }
+
+        // Ensure that we actually fit. The DC sample should
+        if (f_decimatedDCSpectrum[u16_searchLoop] <= LCD_WIDTH)
+        {
+            st_lcd.DrawLine(f_decimatedDCSpectrum[u16_searchLoop], u16_searchLoop, 
+                f_decimatedDCSpectrum[u16_searchLoop + 1], u16_searchLoop + 1);
+        }
+        else
+        {
+            // Mathematically we topped-out past the maximum some how
+            st_lcd.DrawPixel(0, u16_searchLoop, LCD_COLOR_WHITE);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------
+// MainFindACandDCintersections()
+//
+// This function attempts to locate the intersections where the AC and
+// DC spectra curve meets. It locates the last intersection point 
+// encountered sweeping from left to right across the spectra, and for
+// the second intersection point it locates the first intersection
+// point.
+//
+// In this way we find the two locations at LCT_HEIGHT which indicates
+// the surface area volume arena of the water peak, bounded by the AC
+// curve to the top of the peak, and the DC curve at the bottom of 
+// the curve.
+//
+// ----------------------------------------------------------------------
+static void MainFindACandDCintersections(void)
+{
+    uint16_t u16_searchLoop        = 0;
+    bool     b_atFirstIntersection = false;
+    uint16_t u16_possibleFirst     = 0;
+    uint16_t u16_areaACMin         = 0;
+    uint16_t u16_areaACMax         = 0;
+#if 0    
+    uint16_t u16_areaDCMin         = 0;
+    uint16_t u16_areaDCMax         = 0;
+#endif
+
+    // Go through the 256 sample within both the AC and the DC
+    // spectra and first locate the first insersection point and
+    // then the second intersection point
+    for (u16_searchLoop = 0; u16_searchLoop < 256; u16_searchLoop++)
+    {
+        // Make sure that what we're looking at can be generally examined
+        if ((int)f_decimatedACSpectrum[u16_searchLoop] > 10 && 
+            (int)f_decimatedDCSpectrum[u16_searchLoop] > 10)
+        {
+            // Each point on the plot is examined to see if the point is
+            // plus or minus 5 pixels to determine if they intersect.
+            u16_areaACMin = (int)f_decimatedACSpectrum[u16_searchLoop] - 5;
+            u16_areaACMax = (int)f_decimatedACSpectrum[u16_searchLoop] + 5;
+#if 0
+            u16_areaDCMin = (int)f_decimatedDCSpectrum[u16_searchLoop] - 5;
+            u16_areaDCMax = (int)f_decimatedDCSpectrum[u16_searchLoop] + 5;
+#endif
+             
+            // Do these two points intersect?
+            if ((int)f_decimatedDCSpectrum[u16_searchLoop] >= u16_areaACMin &&
+                (int)f_decimatedDCSpectrum[u16_searchLoop] <= u16_areaACMax)
+            {
+                // Do we have the first intersection already?
+                if (0 != u16_firstIntersectionHeight)
+                {
+                    // We have the first intersection so this is the second
+                    u16_secondIntersectionHeight = u16_searchLoop;
+                
+                    // We have found both intersections so we are done
+                    break;
+                }
+                else
+                {
+                    // We are still searching for the first intersection
+                    // so because we intersect here, note that we found it
+                    b_atFirstIntersection = true;
+
+                    // Record the point at which the first intersected
+                    u16_possibleFirst = u16_searchLoop;
+                }
+            }
+            else
+            {
+                // These two points do not intersect.
+                // Did we already find the first intersection point?
+                if (true == b_atFirstIntersection)
+                {
+                    // We found the intersection point and then left the area where
+                    // it intersected, so the last possible intersection point is
+                    // the first area of intersection
+                    u16_firstIntersectionHeight = u16_possibleFirst;
+                
+                    // Since we have the first intersectiopn point located
+                    b_atFirstIntersection = false;
+                }
+            }
+        }
     }
 }
 
@@ -242,6 +452,12 @@
 // ----------------------------------------------------------------------
 static void MainInit(void)
 {
+    uint8_t ach_intersectionString[31] = { 0 };
+    
+    // Initialize the module's locall-held data
+    u16_firstIntersectionHeight  = 0;
+    u16_secondIntersectionHeight = 0;
+    
     // Bring the LCD up and set its various colors
     st_lcd.Clear(LCD_COLOR_BLACK);
     st_lcd.SetBackColor(LCD_COLOR_BLACK);
@@ -250,6 +466,16 @@
     // Process the decimated spectrum and then plot it
     MainProcessDecimatedSpectrum();
     MainPlotFinalSpectrum();
+    
+    // Search the AC and DC plots for where they intersect
+    MainFindACandDCintersections();
+    
+    (void)sprintf((char *)ach_intersectionString, 
+        "Intersections %d and %d", 
+        u16_firstIntersectionHeight,
+        u16_secondIntersectionHeight);
+        
+    st_lcd.DisplayStringAt(0, LINE(1), (uint8_t *)ach_intersectionString, LEFT_MODE);
 }
 
 // ----------------------------------------------------------------------