Search code examples
pythonpandasfilematplotlibcan-bus

Reading a CAN .asc file and plot specific data from it


I am quite new to this datascience and python stuff i have a code that looks fine at first sight and also runs without problems but it doesnt give me the outcome i expect. the data i want in my tables arent inside at all so it doesnt plot in the end.

import pandas as pd
import matplotlib.pyplot as plt

# Step 1: Read the .asc file, ignoring the header and using varying spaces as separators
file_path = 'StartupElektroMode.asc'
data = []
try:
    with open(file_path, 'r') as file:
        lines = file.readlines()
except FileNotFoundError:
    print(f"Error: The file'{file_path}' was not found")
timestamps = []
voltage_data = []
current_data = []

for line in lines[6:]:
    parts = line.split()
    if len(parts) >= 3:
        timestamp = parts[0]
        can_id = parts[2]
        voltage_hex = None
        current_hex = None

    if can_id == '1E3' and len(parts) > 12:
        voltage_hex = parts[13]
     elif can_id == '4E3' and len(parts) > 13:
        current_hex = parts[12]

# Step 2: Convert the hex values to decimal
for item in data:
    if voltage_hex is not None:
        first_digit = int(voltage_hex[0], 16)
        second_digit = int(voltage_hex[1], 16)
        voltage = (first_digit * 256 + second_digit) * 0.25
        voltage_data.append(voltage)

    if current_hex is not None:
        first_digit = int(current_hex[0], 16)
        second_digit = int(current_hex[1], 16)
        current = (first_digit * 256 + second_digit) * 0.25
        current_data.append(current)

data = {'Time': timestamps, 'Voltage': voltage_data, 'Current': current_data}
# Step 3: Create Pandas DataFrame
df = pd.DataFrame(data)

# Step 4: Plot Voltage and Current over time
plt.figure(figsize=(12, 6))
plt.plot(timestamps, voltage_data, label='Voltage (1E3)')
plt.title('Voltage Over Time')
plt.xlabel('Time')
plt.ylabel('Voltage (V)')
plt.legend()
plt.grid()


plt.plot(timestamps, current_data, label='Current (4E3)')
plt.title('Current Over Time')
plt.xlabel('Time')
plt.ylabel('Current (A)')
plt.legend()
plt.grid()

plt.tight_layout()
plt.show()

file.close()

here a part of the file i try to read

   0.028121 1  CFF4912x        Rx   d 8 00 00 03 00 11 00 00 00  Length = 280152 BitCount = 144 ID = 218056978x
   0.029376 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.029492 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
   0.031802 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.031918 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
   0.034060 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239683 BitCount = 124 ID = 1302
   0.034176 1  206             Rx   d 1 04  Length = 107929 BitCount = 58 ID = 518
   0.036204 1  1E3             Rx   d 8 01 59 00 00 00 00 1A 05  Length = 235910 BitCount = 122 ID = 483
   0.036456 1  100             Rx   d 8 00 00 00 00 00 00 00 08  Length = 243683 BitCount = 126 ID = 256
   0.036703 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.036819 1  206             Rx   d 1 04  Length = 107680 BitCount = 58 ID = 518
   0.037249 1  2E3             Rx   d 8 C4 C3 00 64 19 15 01 01  Length = 221668 BitCount = 115 ID = 739
   0.038204 1  3E3             Rx   d 8 68 01 38 04 03 00 00 00  Length = 235910 BitCount = 122 ID = 995
   0.038885 1  144             Rx   d 8 00 00 00 00 00 00 01 00  Length = 241668 BitCount = 125 ID = 324
   0.039133 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.039249 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
   0.039487 1  4E3             Rx   d 8 1E 00 8C 00 00 F8 FF 00  Length = 229910 BitCount = 119 ID = 1251
   0.041397 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.041513 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
   0.043613 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.043729 1  206             Rx   d 1 04  Length = 107929 BitCount = 58 ID = 518
   0.045825 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
   0.045941 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
   0.046193 1  100             Rx   d 8 00 00 00 00 00 00 00 08  Length = 243668 BitCount = 126 ID = 256
   0.047126 1  CF00400x        Rx   d 8 F8 7D 7D 00 00 00 F0 7D  Length = 280167 BitCount = 144 ID = 217056256x

Any suggestions what I could do or where my problem might be


Solution

  • Your voltage and current data are received in different frames and thus always have different timestamps. A dataframe isn't quite adapted to plot your data since you would end up with a lot of NaN values.

    Build timestamp lists in parallel to voltage and current and plot them both (on one or different graphs). Also it seems that your hex conversion is wrong (or are current/voltage meant to be spread on two bytes?) I slightly modified your example to have more than one datapoint:

    import pandas as pd
    import matplotlib.pyplot as plt
    from io import StringIO
    
    file = StringIO(""""   0.028121 1  CFF4912x        Rx   d 8 00 00 03 00 11 00 00 00  Length = 280152 BitCount = 144 ID = 218056978x
       0.029376 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.029492 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
       0.031802 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.031918 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
       0.034060 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239683 BitCount = 124 ID = 1302
       0.034176 1  206             Rx   d 1 04  Length = 107929 BitCount = 58 ID = 518
       0.036204 1  1E3             Rx   d 8 01 59 00 00 00 00 1A 05  Length = 235910 BitCount = 122 ID = 483
       0.036456 1  100             Rx   d 8 00 00 00 00 00 00 00 08  Length = 243683 BitCount = 126 ID = 256
       0.036703 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.036819 1  206             Rx   d 1 04  Length = 107680 BitCount = 58 ID = 518
       0.037249 1  2E3             Rx   d 8 C4 C3 00 64 19 15 01 01  Length = 221668 BitCount = 115 ID = 739
       0.038204 1  3E3             Rx   d 8 68 01 38 04 03 00 00 00  Length = 235910 BitCount = 122 ID = 995
       0.038885 1  144             Rx   d 8 00 00 00 00 00 00 01 00  Length = 241668 BitCount = 125 ID = 324
       0.039133 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.039249 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
       0.039487 1  4E3             Rx   d 8 1E 00 8C 00 00 F8 FF 00  Length = 229910 BitCount = 119 ID = 1251
       0.041397 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.041513 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
       0.043613 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.043729 1  206             Rx   d 1 04  Length = 107929 BitCount = 58 ID = 518
       0.045825 1  516             Rx   d 8 00 00 00 00 00 00 00 00  Length = 239668 BitCount = 124 ID = 1302
       0.045941 1  206             Rx   d 1 04  Length = 107914 BitCount = 58 ID = 518
       0.046193 1  100             Rx   d 8 00 00 00 00 00 00 00 08  Length = 243668 BitCount = 126 ID = 256
       0.046194 1  1E3             Rx   d 8 01 59 00 00 00 00 1A 0F  Length = 235910 BitCount = 122 ID = 483
       0.046195 1  4E3             Rx   d 8 1E 00 8C 00 00 F8 2F 00  Length = 229910 BitCount = 119 ID = 1251
       0.047126 1  CF00400x        Rx   d 8 F8 7D 7D 00 00 00 F0 7D  Length = 280167 BitCount = 144 ID = 217056256x""")
    
    lines = file.readlines()
    
    t_volt = []
    voltage_data = []
    t_curr = []
    current_data = []
    
    for line in lines:
        parts = line.split()
        if len(parts) >= 3:
            timestamp = parts[0]
            can_id = parts[2]
            voltage_hex = None
            current_hex = None
    
        if can_id == '1E3' and len(parts) > 12:
            voltage_hex = parts[13]
        elif can_id == '4E3' and len(parts) > 13:
            current_hex = parts[12]
    
        # Convert the hex values to decimal
        if voltage_hex is not None:
            voltage = int(voltage_hex, 16) * 0.25
            voltage_data.append(voltage)
            t_volt.append(float(parts[0]))
    
        if current_hex is not None:
            current = int(current_hex, 16) * 0.25
            current_data.append(current)
            t_curr.append(float(parts[0]))
    
    
    # Plot Voltage and Current over time
    fig, ax = plt.subplots(figsize=(12, 6))
    ax.plot(t_volt, voltage_data, label='Voltage (1E3)')
    ax.set_title('Voltage and Current Over Time')
    ax.set_xlabel('Time')
    ax.set_ylabel('Voltage (V)')
    
    ax2 = ax.twinx()
    ax2.plot(t_curr, current_data, color='orange', label='Current (4E3)')
    ax2.set_ylabel('Current (A)')
    
    fig.legend()
    ax.grid()
    
    fig.tight_layout()
    plt.show()
    

    Output:

    enter image description here