Make a graph that updates live using select variables from code.
Alternatives:
Output to an SD card using a .csv which can be rendered using excel. This would be fine but, it’s nice to see a reaction on the graph when moving or affect some part of the robot.
Draw the graph yourself. This is great but it requires view of the vex brain at all times and I desire the ability to save the graph.
Some Ideas:
Writing a file on the computer which is being read by some python to draw a graph.
Watching the cout stream using python and drawing a graph.
Using C++ to open Cmd to write to a file, which is then read by python.
Finding some gadget online that acts as a wireless dongle between two sd card ports.
Problems:
All of the methods I have found to write to a file (fprint, ofstream, and other methods) have all wrote to the SD card instead of the computer.
Most of the ways I have found to watch a cout stream in python is to start the .cpp file from the python program.
Using system to open Cmd is how I ended up thing about this so I included it, but it doesn’t work.
Amazon sells WiFi SD cards that allow for wireless transmission of photos and videos, but none that can send .txt, .csv, etc. The SD cards are also not SD micro.
My Limitations:
I use VEXcode V5 Pro. I wouldn’t mind learning Pros, but I’d rather not.
I started C++ last year so, I’m not to good with bash, Cmd, and most of the standard library.
I can code in python to a fairly high proficiency.
Thanks for any and all help.
PS: Please correct any problems in my post. I’ve never really used any kind of code help website or program.
At least in PROS, all we do is write our data to stdout (printf or std::cout), then it will appear in the PROS terminal (pros terminal) command. This requires your brain to be plugged into the computer, or you can plug in the controller if it is paired and send data at a much lower rate. To make graphics, pros terminal is generally piped into a file which is being read by another program. Some people choose to modify/include the PROS CLI source in their own projects to get the output that way.
Since I have never used VEXCode V5 Pro, I’m not sure if it has something similar to the PROS terminal. I would assume that there is some way to get what is being written to the vexcode console without needing to get that SD card.
As for your limitations, a majority of this work is python side so you will be fine.
Somebody correct me if I am wrong, but I have had school projects where serial data has been piped from an Arduino to excel directly. It is probably possible to do the same with a V5 brain and excel too.
In order to transform data from the vex brain , you could use simpley use a function called printf() in VEXCode Pro. This function will actually transform data through the serial port, which means you could write some python code to show the data.
For example:
In the cpp file (Robot Progarm):
int serial_monitor(){
while (true) {
// use print if to transform some data you want
// the name of the data(things before the ":") is very import.
// it should be maintained the same in the same in both cpp file and py file
printf("Time:%f\n", Brain.timer(sec));
printf("DriveTem:%f\n", Drivetrain.temperature(pct));
printf("DriveRpm:%f\n", Drivetrain.velocity(rpm));
printf("LeftRpm:%f\n", LeftDriveSmart.velocity(rpm));
printf("RightRpm:%f\n", RightDriveSmart.velocity(rpm));
printf("LeftEff:%f\n", LeftDriveSmart.efficiency());
printf("RightEff:%f\n", RightDriveSmart.efficiency());
printf("FlyRPM:%f\n", ShootMotor.velocity(rpm));
printf("FlyEma:%f\n", ema_num);
printf("End\n");
wait(0.1, sec);
}
}
int main(){
vex::task serialM(serial_monitor); // run the function in a muti-task
//do something else
}
In the py file (the file runs on your computer to show the graph):
import serial
import matplotlib.pyplot as plt
# funciton to make two lists at the same length and output them into one list
def two_list_len_same(a, b):
len_min = min( len(a), len(b) )
result_a = a[0:len_min]
result_b = b[0:len_min]
return [result_a, result_b]
# funciton to make three lists at the same length and output them into one list
def three_list_len_same(a, b, c):
len_min = min( len(a), len(b) , len(c))
result_a = a[0:len_min]
result_b = b[0:len_min]
result_c = c[0:len_min]
return [result_a, result_b, result_c]
if __name__ == '__main__':
# init some varibles
data_list = [0] # A list to store the date transformed from the brain
cycle_mark = True # To mark whether to maintain the cycle or not
# create bunch of lists to group the data that transformed from the brain
time_list = []
rpm_list = []
tem_list = []
left_eff_list = []
right_eff_list = []
left_rpm_list = []
right_rpm_list = []
fly_temp_list = []
fly_rpm_list = []
fly_ema_list = []
# create a picture
plt.ion()
plt.figure(1)
# declare(create) a serial port
ser = serial.Serial('COM6', 115200)
while True:
while cycle_mark:
data = ser.readline() # read the data until read the line break(/n)
# process the data
data = data.decode("utf-8")[0:-2]
data_list = data.split(":")
# group the data
if data_list[0] == "Time":
time_list.append(float(data_list[1]))
elif data_list[0] == "DriveRpm":
rpm_list.append(float(data_list[1]))
elif data_list[0] == "DriveTem":
tem_list.append(float(data_list[1]))
elif data_list[0] == "LeftEff":
left_eff_list.append(float(data_list[1]))
elif data_list[0] == "RightEff":
right_eff_list.append(float(data_list[1]))
elif data_list[0] == "LeftRpm":
left_rpm_list.append(float(data_list[1]))
elif data_list[0] == "RightRpm":
right_rpm_list.append(float(data_list[1]))
elif data_list[0] == "FlyTemp":
fly_temp_list.append( float(data_list[1]) )
elif data_list[0] == "FlyRPM":
fly_rpm_list.append( float(data_list[1]) )
elif data_list[0] == "FlyEma":
fly_ema_list.append( float(data_list[1]) )
# cycle_mark == true means that this round of data has been read
# then this cycle can stop to read the data from the next round
elif data_list[0] == "End":
cycle_mark = False
cycle_mark = True
tmp_list_a = two_list_len_same(time_list, fly_rpm_list) # you could change the list to draw differnt data
# draw the picture
plt.clf()
plt.title("FlyMotorRPM")
plt.plot(tmp_list_a[0], tmp_list_a[1])
plt.plot(tmp_list_a[0], tmp_list_a[2])
plt.draw()
plt.pause(0.1)
For me all I do is use std::cout in my program then I get the output to the computer if my controller is plugged in and paired to the brain. I can then copy and paste the data into Google sheets and graph it through there. It’s not real time but it’s good enough for me. I use the vex vs code extension which is the exact same syntax and functions as vexcode pro V5 with the advantage of being run inside of vs code. You may want to look into that as it may be easier to connect to the vs code terminal vs. the vex one.
This python program is actually written in a hurry.So the logic is kind of silly.Here are some you could improve:
Use the DataFrame from the pandas library to
store the data instead of bunch of silly lists.
Use tkinter or PYQT to write a simple GUI menu.
By the way, this post is also actually written in a hurry.So some expressions might be unclear. If you have any problems, feel free to ask and I will try my best to help.