CapableRobot / CapableRobot_USBHub_Firmware

https://www.crowdsupply.com/capable-robot-components/programmable-usb-hub
MIT License
9 stars 4 forks source link

Power LED "flicker" due to fluctuations in current measurement noise floor #3

Closed jynik closed 2 years ago

jynik commented 4 years ago

Just wanted to follow up our Twitter conversation with some more data.

Per what we discussed, the LED flicker I'm seeing is the result of the LEDs being illuminated by fluctuations in low-order bits of the per-port current measurements, shown below. It appears to be significantly more noticeable when no upstream host is connected (i.e. powered down).

current_noise_plot

Before diving into the firmware to attempt add a bit of filtering, I just wanted to get some test data to evaluate things offline.

Below is my logging code and sample output (note the error reported in #4). Attached is a sample current_log.csv.zip.

➤ ./log_current.py 
Power samples: 7252 samples [01:21, 89.96 samples/s] Operation terminated due to USB Error: [Errno 32] Pipe error
Noise floor:                                        
  Port 1: 10.493931 mA
  Port 2: 9.895376 mA
  Port 3: 10.603757 mA
  Port 4: 11.032081 mA
Max value:
  Port 1: 53.200000 mA
  Port 2: 53.200000 mA
  Port 3: 53.200000 mA
  Port 4: 53.200000 mA
#!/usr/bin/env python3
import matplotlib.pyplot as plt
import os
import usb

from capablerobot_usbhub import USBHub
from tqdm import tqdm

def print_stats(log):
    noise_floor = [sum(sample) / len(log) for sample in zip(*log)]
    print('Noise floor:')
    for ch in range(0, 4):
        print('  Port {:d}: {:f} mA'.format(ch+1, noise_floor[ch]))

    max_val = [max(sample) for sample in zip(*log)]
    print('Max value:')
    for ch in range(0, 4):
        print('  Port {:d}: {:f} mA'.format(ch+1, max_val[ch]))

def plot_log(log):
    sample_no = list(range(0, len(log)))
    portno = 1
    for port in zip(*log):
        plt.plot(sample_no, port, '.', label='Port {:d}'.format(portno))
        portno += 1

    plt.xlabel('sample')
    plt.ylabel('mA')
    plt.show_grid=True
    plt.legend()
    plt.show()

if __name__ == '__main__':

    hub = USBHub()
    log = []

    with tqdm(desc='Power samples', unit=' samples', leave=False) as progress:
        try:
            while True:
                log.append(hub.power.measurements())
                progress.update()
        except KeyboardInterrupt:
            pass
        except usb.core.USBError as err:
            print('Operation terminated due to USB Error: ' + str(err))

    with tqdm(desc='Saving log', unit=' entries', leave=False) as progress:
        with open('current_log.csv', 'w') as outfile:
            for entry in log:
                line = '{:f}, {:f}, {:f}, {:f}{:s}'.format(*entry, os.linesep)
                outfile.write(line)
                progress.update()

    print_stats(log)
    plot_log(log)
osterwood commented 4 years ago

Thanks for looking into this!

Below are two of long runs of the script for me. Sometimes it would exit with a Pipe error have a few hundred samples, most of the time after a few thousand, and a few times got runs this long.

This is on a Mac Mini (10.14), with the Hub directly connected to a USB C port via a USB C to micro B cable.

› python3 ../port_power_log.py
Power samples: 7066 samples [00:55, 150.50 samples/s]Operation terminated due to USB Error: [Errno 32] Pipe error
Noise floor:                                         
  Port 1: 8.282623 mA
  Port 2: 7.955158 mA
  Port 3: 10.945635 mA
  Port 4: 10.238008 mA
Max value:
  Port 1: 53.200000 mA
  Port 2: 53.200000 mA
  Port 3: 53.200000 mA
  Port 4: 53.200000 mA
› python3 ../port_power_log.py
Power samples: 8170 samples [00:52, 183.73 samples/s]Operation terminated due to USB Error: [Errno 32] Pipe error
Noise floor:                                         
  Port 1: 8.314328 mA
  Port 2: 7.911445 mA
  Port 3: 10.609784 mA
  Port 4: 10.413216 mA
Max value:
  Port 1: 53.200000 mA
  Port 2: 53.200000 mA
  Port 3: 53.200000 mA
  Port 4: 53.200000 mA

So, reading fluctuations on my setup look very similar to yours.