IRNAS / ppk2-api-python

Power Profiling Kit 2 unofficial python api.
http://irnas.eu
GNU General Public License v2.0
145 stars 37 forks source link

Current values obtained are incorrect #3

Closed Codeencoder closed 2 years ago

Codeencoder commented 3 years ago

The current plot looks right on nRF Connect app. When the same function run with this code using Python gives totally different values. Tried adjusting the baud rate. The timing between samples, but nothing worked so far, Capture Screen Shot 2021-01-20 at 2 27 54 PM I tried verifying api with the original source code and it all looks clean. Is there any possible reason/solution to this? Any parameters I can play around with! Any help would be appreciated.

NejcKle commented 3 years ago

Hi @Codeencoder,

could you please paste your Python code and describe the setup a bit more. Which device mode are you using? What is the delay between sampling periods?

Code-Decoder-m commented 3 years ago

I am trying this code on a BGM13P22GA. The device mode is source meter mode. while True: while True:
ppk2_test = PPK2_API("COM#") ppk2_test.get_modifiers() ppk2_test.use_source_meter() ppk2_test.set_source_voltage(3300)# set ampere meter mode ppk2_test.toggle_DUT_power("ON") time.sleep(1)

disable DUT power

ppk2_test.start_measuring()  # start measuring
# measurements are a constant stream of bytes
# the number of measurements in one sampling period depends on the wait between serial reads
# it appears the maximum number of bytes received is 1024
# the sampling rate of the PPK2 is 100 samples per millisecond
for i in range(0, 1000):
    read_data = ppk2_test.get_data()
    if read_data != b'':
        samples = ppk2_test.get_samples(read_data)
        print(f"Average of {len(samples)} samples is: {sum(samples)/len(samples)}uA" )
    time.sleep(0.001)
ppk2_test.__del__()
time.sleep (1)

I had to force the device to recognize the com port as it is not listing PPK2 device. Vout of PPK2 connected to my Device Vdd and GND-->GND

NejcKle commented 3 years ago

@Code-Decoder-m The connections and mode setting seem fine.

I am curious as to why you are closing the serial port each iteration. Maybe try something like this:

ppk2_test = PPK2_API("/dev/ttyACM3")
ppk2_test.get_modifiers()
ppk2_test.use_source_meter()
ppk2_test.set_source_voltage(3300)# set ampere meter mode
ppk2_test.toggle_DUT_power("ON")
time.sleep(1)
ppk2_test.start_measuring() # start measuring

while True:
    period_avg = 0
    num_periods = 0
    for i in range(0, 100):
        read_data = ppk2_test.get_data()
        if read_data != b'':
            samples = ppk2_test.get_samples(read_data)
            #print(f"Average of {len(samples)} samples is: {sum(samples)/len(samples)}uA" )
            period_avg += (sum(samples)/len(samples))
            num_periods += 1
        time.sleep(0.001)

    print(f"Average of period is: {period_avg/num_periods}uA" )
Code-Decoder-m commented 3 years ago

@NejcKle Thanks for the response. I am writing the data to a file with a timestamp so I use a destructor to restart the function after every few samples.

The issue still remains that the current average doe not match with the value on nRF connect. It works with a Resistance box but when I connect the board the values are completely incorrect.

while True:

ppk2_test = PPK2_API("COM4")
ppk2_test.get_modifiers()
ppk2_test.use_source_meter()
ppk2_test.set_source_voltage(3300)# set ampere meter mode
ppk2_test.toggle_DUT_power("ON")
time.sleep(1)
# disable DUT power
ppk2_test.start_measuring()  # start measuring
# measurements are a constant stream of bytes
# the number of measurements in one sampling period depends on the wait between serial reads
# it appears the maximum number of bytes received is 1024
# the sampling rate of the PPK2 is 100 samples per millisecond
val = []
Ts = time.time()
for i in range(0, 100):
    read_data = ppk2_test.get_data()
    if read_data != b'':
        samples = ppk2_test.get_samples(read_data)
        filez = open(str(Ts) + ".csv","a+")
        t = str(time.time())      
        print(t + ": " + f"Average of {len(samples)} samples is: {sum(samples)/len(samples)}uA", file = filez)
    time.sleep(0.001)
ppk2_test.__del__()
time.sleep (1)

The average current values are supposed to be 40mA but I seem to get 4mA and after about 10 samples it falls down to 0.04mA, which does not seem right. Thanks.

NejcKle commented 3 years ago

@Code-Decoder-m Looking at the provided picture it seems average current is calculated in a window of 60 seconds in the nRF Connect app. Those measurements you are getting are averaged over a very short time window (in case of 1024 samples thats ~10ms). Try averaging your values over a longer time window, for example:

ppk2_test = PPK2_API("/dev/ttyACM3")
ppk2_test.get_modifiers()
ppk2_test.use_source_meter()
ppk2_test.set_source_voltage(3300)# set ampere meter mode
ppk2_test.toggle_DUT_power("ON")
time.sleep(1)
ppk2_test.start_measuring() # start measuring

start_time = time.time()
duration = 5  # duration in seconds
period_avg = 0
num_periods = 0
while time.time() - start_time < duration:
    read_data = ppk2_test.get_data()
    if read_data != b'':
        samples = ppk2_test.get_samples(read_data)
        #print(f"Average of {len(samples)} samples is: {sum(samples)/len(samples)}uA" )
        period_avg += (sum(samples)/len(samples))
        num_periods += 1
    time.sleep(0.001)

print(f"Average of {duration}s is: {period_avg/num_periods}uA")
Code-Decoder-m commented 3 years ago

Thanks @NejcKle. When I run the code mentioned above I read Average of 60s is: 294uA Capture2 which is definitely incorrect. When I run it on nRF Connect app. The average consumption is 56.1uA. Capture

Similarly in the picture below. I can see the three peaks but they are supposed to occur at 40,000uA while the value is aprrox 8,000uA. As you may notice. the values drop down to near zero and all I notice is just the irregularities once in a while. Capture3 But this is not the case on the app. Thanks once again.

NejcKle commented 3 years ago

@Code-Decoder-m thanks for the detailed report. We have noticed something similiar on one of our devices, the device reports higher average values than the application. In the next few days we plan on testing a few devices to establish a baseline reading. There could be some calibration values we are not accounting for in the API. I'm sorry I can't help you right now! I'll get back to you as soon as we figure something out!

Code-Decoder-m commented 3 years ago

Thanks @NejcKle for looking into this. Appreciate that. I tried playing around with handle raw data functions it give the data correct for the first few minutes then its back to normal again. The major difference I found was this function from source code. handleRawDataSet(adcValue) { try { const currentMeasurementRange = Math.min( getMaskedValue(adcValue, MEAS_RANGE), this.modifiers.r.length

the length of modifier["R"]. I will keep tracking the code for any further changes. Thanks!

NejcKle commented 3 years ago

@Code-Decoder-m Does the chip you are measuring continue to work after measurements become wrong? Thank you for using this API! Feel free to create pull requests for any potential bug fixes!

Code-Decoder-m commented 3 years ago

@NejcKle. Yes it works. Its a Bluetooth module and I can see it advertising, I think the function handle_raw_data seems incorrect. current_measurement_range is "0" after 6s. I think it is due to the min function. The adc_val is correct. so obviously this function needs refining. I will create a pull request. Thanks.

NejcKle commented 3 years ago

Hello @Code-Decoder-m, we managed to pinpoint the bug, there was a typo in the adc result calculation.

Issue was fixed here: https://github.com/IRNAS/ppk2-api-python/commit/9c280e5e106a947af2cc70391ee220352b708e25 We have also added a power profiler class which should make profiling much easier.

Please try it out and report!

SloMusti commented 2 years ago

This issue is assumed resolved as there is no further activity.