diff --git a/src/dataprovider/pumpcalibprovider.py b/src/dataprovider/pumpcalibprovider.py
index f60a5f95bfd15f216b2373fe00c9fed5772216e3..4ebeb1f3547624e8dc74ed7a6e0ae4d5bed6b5c1 100644
--- a/src/dataprovider/pumpcalibprovider.py
+++ b/src/dataprovider/pumpcalibprovider.py
@@ -44,3 +44,69 @@ class PumpCalibProvider:
         df["calib_id_str"] = df["first_run_datetime"].dt.strftime("%Y%m%d-%H%M")
         df["calib_id_int"] = df.index
         return df
+
+    def get_turning_df(self) -> pd.DataFrame:
+        # Keep only state-change-related files (like: 20190911_COMPUMP_state_changes.csv)
+        regex = re.compile(r'^[0-9]{8}_' + self.pump_id + '_state_changes.csv$')
+        state_files = list(filter(regex.search, self.all_files))
+        state_files.sort()
+
+        turning_df = pd.DataFrame()
+        for filename in state_files:
+            df = pd.read_csv(filepath_or_buffer=self.data_dir + filename,
+                             sep=",",
+                             parse_dates=["datetime"])
+            df["datetime"] = df["datetime"].dt.tz_localize('UTC')
+            turning_df = turning_df.append(df)
+
+        turning_df = turning_df[turning_df["name"] != "direction"]
+        turning_df["value"] = pd.to_numeric(turning_df["value"])
+
+        # raw_rpm_df contains only the "change rpm" command values, at the time they were originally sent,
+        # not the moment they were applied.
+        raw_rpm_df = turning_df[turning_df["name"] == "rpm"]
+        raw_rpm_df = raw_rpm_df.drop(columns=["name"])
+        raw_rpm_df.rename(columns={"value": 'rpm'}, inplace=True)
+
+        # rpm_df contains the rpm value, timestamped at the moment they were applied, i.e. when the pump was actually
+        # turning.
+        rpm_df = pd.DataFrame()
+        last_start = None
+        for index, row in turning_df[turning_df["name"] == "turning"].iterrows():
+            if row["value"] == 1:
+                last_start = row["datetime"]
+                try:
+                    previous_rpm = turning_df.loc[(turning_df["name"] == "rpm")
+                                              & (turning_df["datetime"] < row["datetime"])].iloc[-1]["value"]
+                except IndexError:
+                    # Happens when the first line is turning=True, so RPM at that time is not known.
+                    previous_rpm = 0.0
+                rpm_df = rpm_df.append({"datetime": row["datetime"],
+                                        "rpm": previous_rpm},
+                                       ignore_index=True)
+            else:
+                rpm_df = rpm_df.append(raw_rpm_df.loc[(raw_rpm_df["datetime"] >= last_start)
+                                                      & (raw_rpm_df["datetime"] <= row["datetime"])])
+                rpm_df = rpm_df.append({"datetime": row["datetime"],
+                                        "rpm": 0},
+                                       ignore_index=True)
+
+        # Integrate to get the number of turns
+        rpm_df["turns"] = rpm_df["rpm"].shift(1) * rpm_df["datetime"].diff().dt.total_seconds() / 60
+        rpm_df["total_turns"] = rpm_df["turns"].cumsum()
+
+        return rpm_df
+
+    def get_mlmin_to_rpm_evol_df(self):
+        turning_df = self.get_turning_df()
+
+        runs_df = self.get_runs_df()
+        runs_df = runs_df[["start_time", "rpm", "flow"]]
+        runs_df["total_turns"] = 0
+        runs_df = runs_df.reset_index(drop=True)
+
+        for index, row in runs_df.iterrows():
+            last_known_total_turns = turning_df.loc[turning_df["datetime"] < row["start_time"]].iloc[-1]["total_turns"]
+            runs_df.at[index, 'total_turns'] = last_known_total_turns
+
+        return runs_df
\ No newline at end of file
diff --git a/src/uim/pumpcalibuim.py b/src/uim/pumpcalibuim.py
index c0be36a7315eaf4217d603cbd3cf97a55720040d..719dbd9355f6e406f06ae85c32f7c7bdcaa8c781 100644
--- a/src/uim/pumpcalibuim.py
+++ b/src/uim/pumpcalibuim.py
@@ -53,6 +53,7 @@ class PumpCalibUim:
         self.runs_df = self.pump_prvd.get_runs_df()
         self.coef_df = self.pump_prvd.get_coef_df()
         self.__update_runs_plot__(self.runs_df, self.coef_df)
+        self.__update_evol_plot__(self.pump_prvd.get_mlmin_to_rpm_evol_df())
 
     ####################################################################
     # Plot
@@ -89,3 +90,27 @@ class PumpCalibUim:
                                             name=run_df["calib_id_str"].unique()[0])
             legend.addItem(run_points, run_df["calib_id_str"].unique()[0])
             plot_item.addItem(run_points)
+
+    def __update_evol_plot__(self, evol_df: pd.DataFrame) -> None:
+        # Create plot item
+        plot_item = pg.PlotItem(labels={"left": "ml/min", "bottom": "Total rounds"})
+        self.main_ui.pump_graphicsview_repro.setCentralItem(plot_item)
+
+        # Create legend
+        legend = pg.LegendItem(offset=(57, 5))
+        legend.setParentItem(plot_item.graphicsItem())
+
+        # Create the color scale
+        color_map = pg.ColorMap(pos=[evol_df["rpm"].min(),
+                                     evol_df["rpm"].max()],
+                                color=[[255, 0, 255], [255, 0, 0]])
+
+        for rpm in evol_df["rpm"].unique():
+            rpm_df = evol_df[evol_df["rpm"] == rpm]
+            rpm_points = pg.ScatterPlotItem(rpm_df["total_turns"],
+                                            rpm_df["flow"],
+                                            size=6,
+                                            brush=color_map.mapToQColor(rpm),
+                                            name=rpm)
+            legend.addItem(rpm_points, rpm)
+            plot_item.addItem(rpm_points)
\ No newline at end of file