Provide data from .c file to .py file VS Code - matplotlib.pyplot

Hello,

I got saadc example on my nrf5340 dk running and now I would like to plot the incoming serial data.

saadc code example: saadc.zip

changed the way I got adviced in nrfx_saadc - buildconf. error PPI_CHEN / DPPIC_CHEN  / nrfx_saadc---buildconf-error-ppi_chen-dppic_chen

My approach is using matplotlib from python and already got code running and some plot in real time.

#https://code.visualstudio.com/docs/python/python-tutorial
#https://learn.sparkfun.com/tutorials/graph-sensor-data-with-python-and-matplotlib/update-a-graph-in-real-time

import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

# Create figure for plotting
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
xs = []
ys = []

# This function is called periodically from FuncAnimation
def animate(i, xs, ys):

    # Add x and y to lists
    xs.append(dt.datetime.now().strftime('%H:%M:%S.%f'))
    ys.append(20)       #straightforward plotting value 20

    # Limit x and y lists to 20 items
    xs = xs[-20:]
    ys = ys[-20:]

    # Draw x and y lists
    ax.clear()
    ax.plot(xs, ys)

    # Format plot
    plt.xticks(rotation=45, ha='right')
    plt.subplots_adjust(bottom=0.30)
    plt.title('Graph in real time')
    plt.ylabel('int')

# Set up plot to call animate() function periodically
ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys), interval=100)
plt.show()

Now I am plotting value 20 all the time and would appreciate any help how to get the ADC value from main.c to python file for plotting task. Is it even possible or any workaround?

Many many thanks in advance,

Christoph

Parents
  • Dear Christoph,

    Thank you for contacting DevZone at NordicSemi.

    As per your query, you are using SAADC example for nRF5340-DK and want to plot the incoming serial data using Python.

    The code you have provided is not building and is causing so many errors. Nonetheless, I worked on to solve your basic problem, that is plotting incoming data.

    So, I configured my DK to send (x,y) data over UART to the computer. In this case, I am sending square of a number (y = x^2) after every second.

    Using online resources, I generated python code which would read from the serial port and then plot in real-time. Please note that the code might not be accurate, and also may not suffice your needs. However, you can use it as guideline and built your own code from it. Other solutions, using commercial data loggers, might also be possible.

    So basically,

    • I am configuring the COM port (in my case its COM5) and the baudrate (as per DK baudrate)
    • Then, within the animate() function, I am reading a line from the serial port
    • Then splitting the line data and making a list of items from it
    • As I know that I am sending (x,y) data, I am expecting 2 items. If there are two items in the list then I extract integer values and put them in x and y list
    • Then we print the (x,y) data on the plot

    Example run of code is shown in the attached image. Python code is also attached. Hope it will be helpful.

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import serial
    
    # initialize serial port
    ser = serial.Serial()
    ser.port = 'COM5'
    ser.baudrate = 115200
    ser.timeout = 1     # specify timeout when using readline()
    ser.open()
    if ser.is_open == True:
        print("\nSerial port open. Configuration:\n", ser, "\n")
    
    # Create figure for plotting
    fig = plt.figure()
    #ax = fig.add_subplot(1, 1, 1)
    xs = []
    ys = []
    
    # This function is called periodically from FuncAnimation
    def animate(i, xs, ys):
        line = ser.readline()       # ascii
        print("line=",line)
        line_as_list = line.split()
        print("line as list=",line_as_list)
        if len(line_as_list) == 2:  # only (x,y) data present
            xval = int(line_as_list[0])
            yval = int(line_as_list[1])
            print("xval = ",xval, "  yval = ", yval)
            i = int(line_as_list[0])
            xs.append(xval)
            ys.append(yval)
        elif len(line_as_list) >2:
            xs = []     # re-booting device
            ys = []
            plt.clf()
    
        #  Plotting x and y data
        plt.cla() #.clear()
        plt.plot(xs, ys, label="From Serial Data")
        plt.title('2-D Serial Data from COM5')
        plt.ylabel('values / voltages')
        plt.legend()
    
    
    # Set up plot to call animate() function periodically
    ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys), interval=1)
    plt.show()
    

    With regards,
    Naeem

Reply
  • Dear Christoph,

    Thank you for contacting DevZone at NordicSemi.

    As per your query, you are using SAADC example for nRF5340-DK and want to plot the incoming serial data using Python.

    The code you have provided is not building and is causing so many errors. Nonetheless, I worked on to solve your basic problem, that is plotting incoming data.

    So, I configured my DK to send (x,y) data over UART to the computer. In this case, I am sending square of a number (y = x^2) after every second.

    Using online resources, I generated python code which would read from the serial port and then plot in real-time. Please note that the code might not be accurate, and also may not suffice your needs. However, you can use it as guideline and built your own code from it. Other solutions, using commercial data loggers, might also be possible.

    So basically,

    • I am configuring the COM port (in my case its COM5) and the baudrate (as per DK baudrate)
    • Then, within the animate() function, I am reading a line from the serial port
    • Then splitting the line data and making a list of items from it
    • As I know that I am sending (x,y) data, I am expecting 2 items. If there are two items in the list then I extract integer values and put them in x and y list
    • Then we print the (x,y) data on the plot

    Example run of code is shown in the attached image. Python code is also attached. Hope it will be helpful.

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import serial
    
    # initialize serial port
    ser = serial.Serial()
    ser.port = 'COM5'
    ser.baudrate = 115200
    ser.timeout = 1     # specify timeout when using readline()
    ser.open()
    if ser.is_open == True:
        print("\nSerial port open. Configuration:\n", ser, "\n")
    
    # Create figure for plotting
    fig = plt.figure()
    #ax = fig.add_subplot(1, 1, 1)
    xs = []
    ys = []
    
    # This function is called periodically from FuncAnimation
    def animate(i, xs, ys):
        line = ser.readline()       # ascii
        print("line=",line)
        line_as_list = line.split()
        print("line as list=",line_as_list)
        if len(line_as_list) == 2:  # only (x,y) data present
            xval = int(line_as_list[0])
            yval = int(line_as_list[1])
            print("xval = ",xval, "  yval = ", yval)
            i = int(line_as_list[0])
            xs.append(xval)
            ys.append(yval)
        elif len(line_as_list) >2:
            xs = []     # re-booting device
            ys = []
            plt.clf()
    
        #  Plotting x and y data
        plt.cla() #.clear()
        plt.plot(xs, ys, label="From Serial Data")
        plt.title('2-D Serial Data from COM5')
        plt.ylabel('values / voltages')
        plt.legend()
    
    
    # Set up plot to call animate() function periodically
    ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys), interval=1)
    plt.show()
    

    With regards,
    Naeem

Children
Related