From fde5429cc8555ec5762996fa65c59c5e797c9a4c Mon Sep 17 00:00:00 2001
From: "remi.clement@inrae.fr" <remi.clement@inrae.fr>
Date: Tue, 25 Oct 2022 17:44:41 +0200
Subject: [PATCH] inj time

---
 ohmpi.py | 75 ++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 48 insertions(+), 27 deletions(-)

diff --git a/ohmpi.py b/ohmpi.py
index 038d1372..49c6ab35 100644
--- a/ohmpi.py
+++ b/ohmpi.py
@@ -539,8 +539,6 @@ class OhmPi(object):
         if injection_duration is None:
             injection_duration = self.pardict['injection_duration']
 
-        start_time = time.time()
-
         # inner variable initialization
         sum_i = 0
         sum_vmn = 0
@@ -556,9 +554,9 @@ class OhmPi(object):
         else:
             polarity = 1
         
-        # first reset the gain to 2/3 before trying to find best gain
-        self.ads_current = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=128, address=0x49)
-        self.ads_voltage = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=128, address=0x48)
+        # first reset the gain to 2/3 before trying to find best gain (mode 0 is continuous)
+        self.ads_current = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=128, address=0x49, mode=0)
+        self.ads_voltage = ads.ADS1115(self.i2c, gain=2 / 3, data_rate=128, address=0x48, mode=0)
         
         # turn on the power supply
         oor = False
@@ -584,12 +582,24 @@ class OhmPi(object):
                 self.pin0.value = False
                 self.pin1.value = False
                 print('gain current: {:.3f}, gain voltage: {:.3f}'.format(gain_current, gain_voltage))
-                self.ads_current = ads.ADS1115(self.i2c, gain=gain_current, data_rate=128, address=0x49)
-                self.ads_voltage = ads.ADS1115(self.i2c, gain=gain_voltage, data_rate=128, address=0x48)
+                self.ads_current = ads.ADS1115(self.i2c, gain=gain_current, data_rate=860, address=0x49, mode=0)
+                self.ads_voltage = ads.ADS1115(self.i2c, gain=gain_voltage, data_rate=860, address=0x48, mode=0)
 
             # one stack = 2 half-cycles (one positive, one negative)
             pinMN = 0 if polarity > 0 else 2
+            
+            # start counter
+            #  we sample every 10 ms (as using AnalogIn for both current
+            # and voltage takes about 7 ms). When we go over the injection
+            # duration, we break the loop and truncate the meas arrays
+            # only the last values in meas will be taken into account
+            start_time = time.time()
             for n in range(0, nb_stack * 2):  # for each half-cycles
+                # sampling for each stack at the end of the injection
+                sampling_interval = 10  # ms
+                self.nb_samples = int(injection_duration * 1000 // sampling_interval) + 1
+                meas = np.zeros((self.nb_samples, 2))
+                
                 # current injection
                 if (n % 2) == 0:
                     self.pin0.value = True
@@ -599,19 +609,30 @@ class OhmPi(object):
                     self.pin1.value = True  # current injection nr2
                     
                 start_delay = time.time()  # stating measurement time
-                time.sleep(injection_duration)  # delay depending on current injection duration
+                #time.sleep(injection_duration)  # delay depending on current injection duration
 
                 # measurement of current i and voltage u
-                # sampling for each stack at the end of the injection
-                meas = np.zeros((self.nb_samples, 2))
+                dt = 0
                 for k in range(0, self.nb_samples):
-                    # reading current value on ADS channel A0
+                    # reading current value on ADS channels
                     meas[k, 0] = (AnalogIn(self.ads_current, ads.P0).voltage * 1000) / (50 * self.r_shunt)
                     if pinMN == 0:
                         meas[k, 1] = AnalogIn(self.ads_voltage, ads.P0).voltage * 1000
                     else:
                         meas[k, 1] = AnalogIn(self.ads_voltage, ads.P2).voltage * 1000 *-1
-                print(meas)
+                    time.sleep(sampling_interval / 1000)
+                    dt = time.time() - start_delay  # real injection time (s)
+                    if dt > (injection_duration - 0 * sampling_interval /1000):
+                        break
+                
+                # stop current injection
+                self.pin0.value = False
+                self.pin1.value = False
+                
+                end_delay = time.time()
+                
+                # truncate the meas array if we didn't fill the last samples
+                meas = meas[:k+1:]
                 
                 # we alternate on which ADS1115 pin we measure because of sign of voltage
                 if pinMN == 0:
@@ -619,15 +640,11 @@ class OhmPi(object):
                 else:
                     pinMN = 0
                 
-                # stop current injection
-                self.pin0.value = False
-                self.pin1.value = False
-                end_delay = time.time()
-
                 # take average from the samples per stack, then sum them all
-                # average for all stack is done outside the loop
-                sum_i = sum_i + (np.mean(meas[:, 0]))
-                vmn1 = np.mean(meas[:, 1])
+                # average for the last third of the stacked values
+                #  is done outside the loop
+                sum_i = sum_i + (np.mean(meas[-int(meas.shape[0]//3):, 0]))
+                vmn1 = np.mean(meas[-int(meas.shape[0]//3), 1])
                 if (n % 2) == 0:
                     sum_vmn = sum_vmn - vmn1
                     sum_ps = sum_ps + vmn1
@@ -637,12 +654,14 @@ class OhmPi(object):
 
                 # TODO get battery voltage and warn if battery is running low
                 # TODO send a message on SOH stating the battery level
-                end_calc = time.time()
-
-                # TODO I am not sure I understand the computation below
-                # wait twice the actual injection time between two injection
-                # so it's a 50% duty cycle right?
-                time.sleep(2 * (end_delay - start_delay) - (end_calc - start_delay))
+                
+                # wait once the actual injection time between two injection
+                # so it's a 50% duty cycle
+                print('crenaux (s)', (end_delay - start_delay))
+                print('sleep for (s)', injection_duration - (end_delay - start_delay))
+                time.sleep(dt)
+                #time.sleep(injection_duration)  # off time between half-cycles
+#                time.sleep(2*(end_delay - start_delay) - (end_calc - start_delay))
                 
             if self.idps:
                 self.DPS.write_register(0x0000, 0, 2)  # reset to 0 volt
@@ -666,7 +685,7 @@ class OhmPi(object):
             "Ps [mV]": sum_ps / (2 * nb_stack),
             "nbStack": nb_stack,
             "CPU temp [degC]": CPUTemperature().temperature,
-            "Time [s]": (-start_time + time.time()),
+            "Time [s]": (time.time() - start_time),
             "Nb samples [-]": self.nb_samples
         }
         print(d)
@@ -791,6 +810,7 @@ class OhmPi(object):
     #         # TODO if interrupted, we would need to restore the values
     #         # TODO or we offer the possiblity in 'run_measurement' to have rs_check each time?
 
+
     @staticmethod
     def append_and_save(filename, last_measurement):
         """Append and save last measurement dataframe.
@@ -817,6 +837,7 @@ class OhmPi(object):
                 w.writerow(last_measurement)
                 # last_measurement.to_csv(f, header=True)
 
+
     def measure(self):
         """Run the sequence in a separate thread. Can be stopped by 'OhmPi.stop()'.
         """
-- 
GitLab