├── README.md
├── WebUpdater.ino
├── data
├── BMS 2306.5 2000KV
│ └── btfl_001.bbl
├── EMAX RS2306 2400KV
│ ├── 11_turn - 6s - 2.csv
│ ├── 11_turn - 6s - 2.csv.plot.png
│ ├── 11_turn - 6s - 3.csv
│ ├── 11_turn - 6s - 3.csv.plot.png
│ ├── 11_turn - 6s - 4.csv
│ ├── 11_turn - 6s - 4.csv.plot.png
│ ├── 11_turn - 6s multistrand.csv
│ ├── 11_turn - 6s multistrand.csv.plot.png
│ ├── 11_turn - 6s.csv
│ ├── 11_turn - 6s.csv.plot.png
│ ├── 11_turn.csv
│ ├── 11_turn.csv.plot.png
│ ├── 11_turn_cyclone_5046 - 6s - 2.csv
│ ├── 11_turn_cyclone_5046 - 6s - 2.csv.plot.png
│ ├── 11_turn_cyclone_5046 - 6s - 3.csv
│ ├── 11_turn_cyclone_5046 - 6s - 3.csv.plot.png
│ ├── 11_turn_cyclone_5046 - 6s - noisy.csv
│ ├── 11_turn_cyclone_5046 - 6s - noisy.csv.plot.png
│ ├── 11_turn_cyclone_5046 - 6s multistrand.csv
│ ├── 11_turn_cyclone_5046 - 6s multistrand.csv.plot.png
│ ├── 11_turn_cyclone_5046 - 6s.csv
│ ├── 11_turn_cyclone_5046 - 6s.csv.plot.png
│ ├── 11_turn_cyclone_5046.csv
│ ├── 11_turn_cyclone_5046.csv.plot.png
│ ├── 11_turn_cyclone_5050 - 6s multistrand.csv
│ ├── 11_turn_cyclone_5050 - 6s multistrand.csv.plot.png
│ ├── 11_turn_cyclone_5050 - 6s.csv
│ ├── 11_turn_cyclone_5050 - 6s.csv.plot.png
│ ├── 11_turn_cyclone_5050.csv
│ ├── 11_turn_cyclone_5050.csv.plot.png
│ ├── 8_turn.csv
│ ├── 8_turn.csv.plot.png
│ ├── 8_turn_cyclone_5046.csv
│ ├── 8_turn_cyclone_5046.csv.plot.png
│ ├── 8_turn_cyclone_5050.csv
│ ├── 8_turn_cyclone_5050.csv.plot.png
│ ├── 9_turn.csv
│ ├── 9_turn.csv.plot.png
│ ├── 9_turn_cyclone_5046.csv
│ ├── 9_turn_cyclone_5046.csv.plot.png
│ ├── 9_turn_cyclone_5050.csv
│ ├── 9_turn_cyclone_5050.csv.plot.png
│ ├── comparison plots 4s zoomed.png
│ ├── comparison plots 4s.png
│ ├── comparison plots 6s three motors zoomed.png
│ ├── comparison plots 6s three motors.png
│ ├── comparison plots 6s zoomed.png
│ ├── comparison plots 6s.png
│ ├── emax_rs2306_plots - 6s - M1,2,3.py
│ ├── emax_rs2306_plots - 6s.py
│ ├── emax_rs2306_plots - rpm thrust.py
│ ├── emax_rs2306_plots.py
│ ├── old excel
│ │ ├── EMAX RS2306 2400KV.xlsx
│ │ └── plots.png
│ ├── original.csv
│ ├── original.csv.plot.png
│ ├── original_cyclone_5046.csv
│ ├── original_cyclone_5046.csv.plot.png
│ ├── original_cyclone_5050.csv
│ └── original_cyclone_5050.csv.plot.png
├── drop csv on here to plot.bat
└── thrustPlot.py
├── dshot-esc-tester.ino
├── dshot-esc-tester.ino.esp32.bin
├── images
├── 8turn.jpg
├── 9turn.jpg
├── bottom.jpg
├── builds
│ ├── AlexM1.jpg
│ ├── AlexM2.jpg
│ ├── AlexM3.jpg
│ └── neohito.jpg
├── thruststand.jpg
├── top loadcell.jpg
└── top.jpg
└── pcb
├── Gerber-dshot-esc-tester.zip
└── pcb.png
/README.md:
--------------------------------------------------------------------------------
1 | Uses the dshot600 protocol to communicate with the a blheli32 ESC and receive telemetry. Telemetry data is used to calculate KV and all info is displayed on the OLED.
2 |
3 | Great for testing hand wound motors KV or new/troublesome motors.
4 |
5 | Optional loadcell can be added to the pin header highlighted with the orange circle below. Data is printed via serial every 2-3ms.
6 |
7 | 20 second demo video https://www.youtube.com/watch?v=VLMNEdSz4wI
8 |
9 | Schematics and PCB https://easyeda.com/jyesmith/kv-meter
10 |
11 |
12 |
13 | Results form a rewound emax 2306 stator. Left is with 8 turns and the right images is with 9 turns.
14 |
15 |
16 |
17 | **WARNING - If `#define MINIQUADTESTBENCH` is uncommented the test sequence used by https://www.miniquadtestbench.com/ will automatically start!!!** Below shows the results of testing an original EMAX RS2306 2400KV motor against the same motor wound with 0.5mm wire 8 & 9 turns per tooth.
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 6s data below also shows a comparison between single and multistrand windings.
26 |
27 |
28 |
29 |
30 |
31 | ## BOM
32 |
33 | - Upload the gerber zip in the pcb folder to jlcpcb.com, select 1.6mm PCB thickness, and your favourite colour.
34 | - ESP32 development board. Get the same one as in the images above to be sure it mounts correctly. I removed the black plastic standoff on the pins so that it sits flat on the PCB and gives enough headroom for the upper PCB and regulator.
35 | - You favourite blheli32 esc. Make sure it has telemetry out and ideally a current sensor.
36 | - OLED 128*64. There are 2 common version but the Vcc and GND pins are swapped. This PCB has been designed to take both and you select which pin receives Vcc/GND by soldering the jumpers.
37 | - A 3V3 or 5V regulator. Either can be used and solder the jumper to which ever voltage you have used. This makes sure the ESP32 is powered correctly.
38 | - Optional loadcell for measuring thrust.
39 |
40 |
41 |
42 | ## If you make one I would love to see it. Please post your pics as an issue or add them to this readme :)
43 |
44 | ## neohito
45 |
46 |
47 |
48 | ## Alex
49 |
50 | 

51 |
--------------------------------------------------------------------------------
/WebUpdater.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #define STASSID "DSHOT ESC TESTER"
8 | #define STAPSK "password123"
9 |
10 | const char *host = "dshot-tester-webupdate";
11 | const char *ssid = STASSID;
12 | const char *password = STAPSK;
13 |
14 | WebServer server(80);
15 | const char* serverIndex = "";
16 |
17 | void BeginWebUpdate(void) {
18 |
19 | // Serial.println("Begin Webupdater");
20 | WiFi.mode(WIFI_AP);
21 | WiFi.softAP(ssid, password);
22 |
23 | MDNS.begin(host);
24 | server.on("/", HTTP_GET, []() {
25 | server.sendHeader("Connection", "close");
26 | server.send(200, "text/html", serverIndex);
27 | });
28 | server.on("/update", HTTP_POST, []() {
29 | server.sendHeader("Connection", "close");
30 | server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
31 | ESP.restart();
32 | }, []() {
33 | HTTPUpload& upload = server.upload();
34 | if (upload.status == UPLOAD_FILE_START) {
35 | Serial.setDebugOutput(true);
36 | Serial.printf("Update: %s\n", upload.filename.c_str());
37 | if (!Update.begin()) { //start with max available size
38 | Update.printError(Serial);
39 | }
40 | } else if (upload.status == UPLOAD_FILE_WRITE) {
41 | if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
42 | Update.printError(Serial);
43 | }
44 | } else if (upload.status == UPLOAD_FILE_END) {
45 | if (Update.end(true)) { //true to set the size to the current progress
46 | Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
47 | } else {
48 | Update.printError(Serial);
49 | }
50 | Serial.setDebugOutput(false);
51 | } else {
52 | Serial.printf("Update Failed Unexpectedly (likely broken connection): status=%d\n", upload.status);
53 | }
54 | });
55 | server.begin();
56 | MDNS.addService("http", "tcp", 80);
57 |
58 | // Serial.printf("Ready! Open http://%s.local in your browser\n", host);
59 | }
60 |
61 | void HandleWebUpdate(void) {
62 | server.handleClient();
63 | yield();
64 | }
65 |
--------------------------------------------------------------------------------
/data/BMS 2306.5 2000KV/btfl_001.bbl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/BMS 2306.5 2000KV/btfl_001.bbl
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn - 6s - 2.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn - 6s - 2.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn - 6s - 3.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn - 6s - 3.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn - 6s - 4.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn - 6s - 4.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn - 6s multistrand.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn - 6s multistrand.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn - 6s.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn - 6s.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s - 2.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s - 2.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s - 3.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s - 3.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s - noisy.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s - noisy.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s multistrand.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s multistrand.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5046 - 6s.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5046.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5046.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5050 - 6s multistrand.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5050 - 6s multistrand.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5050 - 6s.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5050 - 6s.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/11_turn_cyclone_5050.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/11_turn_cyclone_5050.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/8_turn.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/8_turn.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/8_turn_cyclone_5046.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/8_turn_cyclone_5046.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/8_turn_cyclone_5050.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/8_turn_cyclone_5050.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/9_turn.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/9_turn.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/9_turn_cyclone_5046.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/9_turn_cyclone_5046.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/9_turn_cyclone_5050.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/9_turn_cyclone_5050.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/comparison plots 4s zoomed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/comparison plots 4s zoomed.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/comparison plots 4s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/comparison plots 4s.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/comparison plots 6s three motors zoomed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/comparison plots 6s three motors zoomed.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/comparison plots 6s three motors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/comparison plots 6s three motors.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/comparison plots 6s zoomed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/comparison plots 6s zoomed.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/comparison plots 6s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/comparison plots 6s.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/emax_rs2306_plots - 6s - M1,2,3.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon Aug 26 19:53:08 2019
4 |
5 | @author: Jye
6 | """
7 |
8 | import numpy as np
9 | import matplotlib.pyplot as plt
10 |
11 |
12 | eleven_turn_1 = np.genfromtxt('11_turn - 6s.csv', delimiter=',', skip_header=1,
13 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
14 | eleven_turn_2 = np.genfromtxt('11_turn - 6s - 2.csv', delimiter=',', skip_header=1,
15 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
16 | eleven_turn_3 = np.genfromtxt('11_turn - 6s - 3.csv', delimiter=',', skip_header=1,
17 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
18 |
19 | eleven_turn_5046_1 = np.genfromtxt('11_turn_cyclone_5046 - 6s.csv', delimiter=',', skip_header=1,
20 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
21 | eleven_turn_5046_2 = np.genfromtxt('11_turn_cyclone_5046 - 6s - 2.csv', delimiter=',', skip_header=1,
22 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
23 | eleven_turn_5046_3 = np.genfromtxt('11_turn_cyclone_5046 - 6s - 3.csv', delimiter=',', skip_header=1,
24 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
25 |
26 |
27 | ## KV plot
28 | fig = plt.figure()
29 | ax1 = fig.add_subplot(221)
30 | ax1.title.set_text('KV')
31 | #ax2 = ax1.twinx()
32 | ax3 = ax1.twinx()
33 | ax3.spines["right"].set_position(("axes", 1.2))
34 | fig.subplots_adjust(right=0.75)
35 |
36 | ax3.plot(eleven_turn_1['Time_ms'], eleven_turn_1['dshot'], color='y', label='dshot')
37 | ax3.set_ylabel('dshot')
38 | ax3.set_ylim([0, 2100])
39 |
40 | #ax1.plot(original['Time_ms'], original['RPM'] / original['Voltage_V'], color='b', label='original')
41 | #ax1.plot(eight_turn['Time_ms'], eight_turn['RPM'] / eight_turn['Voltage_V'], color='r', label='8 turn')
42 | #ax1.plot(nine_turn['Time_ms'], nine_turn['RPM'] / nine_turn['Voltage_V'], color='g', label='9 turn')
43 | ax1.plot(eleven_turn_1['Time_ms'], eleven_turn_1['RPM'] / eleven_turn_1['Voltage_V'], color='b', label='11 turn - 1')
44 | ax1.plot(eleven_turn_2['Time_ms'], eleven_turn_2['RPM'] / eleven_turn_2['Voltage_V'], color='r', label='11 turn - 2')
45 | ax1.plot(eleven_turn_3['Time_ms'], eleven_turn_3['RPM'] / eleven_turn_3['Voltage_V'], color='g', label='11 turn - 3')
46 | ax1.set_xlabel('Time_ms')
47 | ax1.set_xlim([3500, 25000])
48 | ax1.set_ylabel('KV')
49 | ax1.set_ylim([1500, 2500])
50 | ax1.legend()
51 |
52 |
53 | ## Response plot
54 | ax1 = fig.add_subplot(223)
55 | ax1.title.set_text('Response - Cyclone 5046 Vs 5050')
56 | #ax2 = ax1.twinx()
57 | ax3 = ax1.twinx()
58 | ax3.spines["right"].set_position(("axes", 1.2))
59 | fig.subplots_adjust(right=0.75)
60 |
61 | ax3.plot(eleven_turn_5046_1['Time_ms'], eleven_turn_5046_1['dshot'], color='y', label='dshot')
62 | ax3.set_xlabel('Time_ms')
63 | ax3.set_ylabel('dshot')
64 | ax3.set_ylim([0, 2100])
65 |
66 | #ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
67 | #ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
68 | ax1.plot(eleven_turn_5046_1['Time_ms'], eleven_turn_5046_1['Thrust_g'], color='b', label='11 turn - 5046 - 1')
69 | ax1.plot(eleven_turn_5046_2['Time_ms'], eleven_turn_5046_2['Thrust_g'], color='r', label='11 turn - 5046 - 2')
70 | ax1.plot(eleven_turn_5046_3['Time_ms'], eleven_turn_5046_3['Thrust_g'], color='g', label='11 turn - 5046 - 3')
71 | ax1.set_xlabel('Time_ms')
72 | ax1.set_xlim([3500, 25000])
73 | ax1.set_ylabel('Thrust (g)')
74 | ax1.set_xlim([11900, 12300])
75 | ax1.set_ylim([0, 1500])
76 | ax1.legend()
77 |
78 |
79 | ## Thrust efficiency plot Cyclone 5046
80 | ax1 = fig.add_subplot(222)
81 | ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5046')
82 | ax2 = ax1.twinx()
83 | ax3 = ax1.twinx()
84 | ax3.spines["right"].set_position(("axes", 1.2))
85 |
86 | ax3.plot(eleven_turn_5046_1['Time_ms'], eleven_turn_5046_1['dshot'], color='y', label='dshot')
87 | ax3.set_xlabel('Time_ms')
88 | ax3.set_ylabel('dshot')
89 | ax3.set_ylim([0, 2100])
90 |
91 | #ax2.plot(original_5046['Time_ms'], original_5046['Thrust_g'] / (original_5046['Voltage_V'] * original_5046['Current_A']/10), color='b', label='original')
92 | #ax2.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'] / (eight_turn_5046['Voltage_V'] * eight_turn_5046['Current_A']/10), color='r', label='8 turn')
93 | #ax2.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'] / (nine_turn_5046['Voltage_V'] * nine_turn_5046['Current_A']/10), color='g', label='9 turn')
94 | ax2.plot(eleven_turn_5046_1['Time_ms'], eleven_turn_5046_1['Thrust_g'] / (eleven_turn_5046_1['Voltage_V'] * eleven_turn_5046_1['Current_A']/10), color='b', label='11 turn - 1')
95 | ax2.plot(eleven_turn_5046_2['Time_ms'], eleven_turn_5046_2['Thrust_g'] / (eleven_turn_5046_2['Voltage_V'] * eleven_turn_5046_2['Current_A']/10), color='r', label='11 turn - 2')
96 | ax2.plot(eleven_turn_5046_3['Time_ms'], eleven_turn_5046_3['Thrust_g'] / (eleven_turn_5046_3['Voltage_V'] * eleven_turn_5046_3['Current_A']/10), color='g', label='11 turn - 3')
97 | ax2.set_ylabel('Efficiency (g/W)')
98 | ax2.set_ylim([0, 5])
99 |
100 | #ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
101 | #ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
102 | #ax1.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'], color='g', label='9 turn')
103 | ax1.plot(eleven_turn_5046_1['Time_ms'], eleven_turn_5046_1['Thrust_g'], color='b', label='11 turn - 1')
104 | ax1.plot(eleven_turn_5046_2['Time_ms'], eleven_turn_5046_2['Thrust_g'], color='r', label='11 turn - 2')
105 | ax1.plot(eleven_turn_5046_3['Time_ms'], eleven_turn_5046_3['Thrust_g'], color='g', label='11 turn - 3')
106 | ax1.set_xlabel('Time_ms')
107 | ax1.set_xlim([3500, 25000])
108 | ax1.set_ylabel('Thrust (g)')
109 | ax1.set_ylim([0, 1500])
110 | ax1.legend()
111 |
112 |
113 | ### Thrust efficiency plot Cyclone 5050
114 | #ax1 = fig.add_subplot(224)
115 | #ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5050')
116 | #ax2 = ax1.twinx()
117 | #ax3 = ax1.twinx()
118 | #ax3.spines["right"].set_position(("axes", 1.2))
119 | #
120 | #ax3.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['dshot'], color='y', label='dshot')
121 | #ax3.set_xlabel('Time_ms')
122 | #ax3.set_ylabel('dshot')
123 | #ax3.set_ylim([0, 2100])
124 | #
125 | ##ax2.plot(original_5050['Time_ms'], original_5050['Thrust_g'] / (original_5050['Voltage_V'] * original_5050['Current_A']/10), color='b', label='original')
126 | ##ax2.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'] / (eight_turn_5050['Voltage_V'] * eight_turn_5050['Current_A']/10), color='r', label='8 turn')
127 | ##ax2.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'] / (nine_turn_5050['Voltage_V'] * nine_turn_5050['Current_A']/10), color='g', label='9 turn')
128 | #ax2.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'] / (eleven_turn_5050['Voltage_V'] * eleven_turn_5050['Current_A']/10), color='orange', label='11 turn')
129 | #ax2.plot(eleven_turn_5050_ms['Time_ms'], eleven_turn_5050_ms['Thrust_g'] / (eleven_turn_5050_ms['Voltage_V'] * eleven_turn_5050_ms['Current_A']/10), color='r', label='11 turn multistrand')
130 | #ax2.set_ylabel('Efficiency (g/W)')
131 | #ax2.set_ylim([0, 5])
132 | #
133 | ##ax1.plot(original_5050['Time_ms'], original_5050['Thrust_g'], color='b', label='original')
134 | ##ax1.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'], color='r', label='8 turn')
135 | ##ax1.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'], color='g', label='9 turn')
136 | #ax1.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'], color='orange', label='11 turn')
137 | #ax1.plot(eleven_turn_5050_ms['Time_ms'], eleven_turn_5050_ms['Thrust_g'], color='r', label='11 turn multistrand')
138 | #ax1.set_xlabel('Time_ms')
139 | #ax1.set_xlim([3500, 25000])
140 | #ax1.set_ylabel('Thrust (g)')
141 | #ax1.set_ylim([0, 1500])
142 | #ax1.legend()
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/emax_rs2306_plots - 6s.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon Aug 26 19:53:08 2019
4 |
5 | @author: Jye
6 | """
7 |
8 | import numpy as np
9 | import matplotlib.pyplot as plt
10 |
11 | #original = np.genfromtxt('original.csv', delimiter=',', skip_header=1,
12 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
13 | #eight_turn = np.genfromtxt('8_turn.csv', delimiter=',', skip_header=1,
14 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
15 | #nine_turn = np.genfromtxt('9_turn.csv', delimiter=',', skip_header=1,
16 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
17 | eleven_turn = np.genfromtxt('11_turn - 6s.csv', delimiter=',', skip_header=1,
18 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
19 | eleven_turn_ms = np.genfromtxt('11_turn - 6s multistrand.csv', delimiter=',', skip_header=1,
20 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
21 |
22 | #original_5046 = np.genfromtxt('original_cyclone_5046.csv', delimiter=',', skip_header=1,
23 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
24 | #eight_turn_5046 = np.genfromtxt('8_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
25 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
26 | #nine_turn_5046 = np.genfromtxt('9_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
27 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
28 | eleven_turn_5046 = np.genfromtxt('11_turn_cyclone_5046 - 6s.csv', delimiter=',', skip_header=1,
29 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
30 | eleven_turn_5046_ms = np.genfromtxt('11_turn_cyclone_5046 - 6s multistrand.csv', delimiter=',', skip_header=1,
31 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
32 |
33 | #original_5050 = np.genfromtxt('original_cyclone_5050.csv', delimiter=',', skip_header=1,
34 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
35 | #eight_turn_5050 = np.genfromtxt('8_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
36 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
37 | #nine_turn_5050 = np.genfromtxt('9_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
38 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
39 | eleven_turn_5050 = np.genfromtxt('11_turn_cyclone_5050 - 6s.csv', delimiter=',', skip_header=1,
40 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
41 | eleven_turn_5050_ms = np.genfromtxt('11_turn_cyclone_5050 - 6s multistrand.csv', delimiter=',', skip_header=1,
42 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
43 |
44 | ## KV plot
45 | fig = plt.figure()
46 | ax1 = fig.add_subplot(221)
47 | ax1.title.set_text('KV')
48 | #ax2 = ax1.twinx()
49 | ax3 = ax1.twinx()
50 | ax3.spines["right"].set_position(("axes", 1.2))
51 | fig.subplots_adjust(right=0.75)
52 |
53 | ax3.plot(eleven_turn['Time_ms'], eleven_turn['dshot'], color='y', label='dshot')
54 | ax3.set_ylabel('dshot')
55 | ax3.set_ylim([0, 2100])
56 |
57 | #ax1.plot(original['Time_ms'], original['RPM'] / original['Voltage_V'], color='b', label='original')
58 | #ax1.plot(eight_turn['Time_ms'], eight_turn['RPM'] / eight_turn['Voltage_V'], color='r', label='8 turn')
59 | #ax1.plot(nine_turn['Time_ms'], nine_turn['RPM'] / nine_turn['Voltage_V'], color='g', label='9 turn')
60 | ax1.plot(eleven_turn['Time_ms'], eleven_turn['RPM'] / eleven_turn['Voltage_V'], color='b', label='11 turn')
61 | ax1.plot(eleven_turn_ms['Time_ms'], eleven_turn_ms['RPM'] / eleven_turn_ms['Voltage_V'], color='r', label='11 turn multistrand')
62 | ax1.set_xlabel('Time_ms')
63 | ax1.set_xlim([3500, 25000])
64 | ax1.set_ylabel('KV')
65 | ax1.set_ylim([1500, 2500])
66 | ax1.legend()
67 |
68 |
69 | ## Response plot
70 | ax1 = fig.add_subplot(223)
71 | ax1.title.set_text('Response - Cyclone 5046 Vs 5050')
72 | #ax2 = ax1.twinx()
73 | ax3 = ax1.twinx()
74 | ax3.spines["right"].set_position(("axes", 1.2))
75 | fig.subplots_adjust(right=0.75)
76 |
77 | ax3.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['dshot'], color='y', label='dshot')
78 | ax3.set_xlabel('Time_ms')
79 | ax3.set_ylabel('dshot')
80 | ax3.set_ylim([0, 2100])
81 |
82 | #ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
83 | #ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
84 | ax1.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'], color='g', label='11 turn - 5046')
85 | ax1.plot(eleven_turn_5046_ms['Time_ms'], eleven_turn_5046_ms['Thrust_g'], color='r', label='11 turn - 5046 multistrand')
86 | ax1.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'], color='orange', label='11 turn - 5050')
87 | ax1.plot(eleven_turn_5050_ms['Time_ms'], eleven_turn_5050_ms['Thrust_g'], color='b', label='11 turn - 5050 multistrand')
88 | ax1.set_xlabel('Time_ms')
89 | ax1.set_xlim([3500, 25000])
90 | ax1.set_ylabel('Thrust (g)')
91 | ax1.set_xlim([11900, 12300])
92 | ax1.set_ylim([0, 1500])
93 | ax1.legend()
94 |
95 |
96 | ## Thrust efficiency plot Cyclone 5046
97 | ax1 = fig.add_subplot(222)
98 | ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5046')
99 | ax2 = ax1.twinx()
100 | ax3 = ax1.twinx()
101 | ax3.spines["right"].set_position(("axes", 1.2))
102 |
103 | ax3.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['dshot'], color='y', label='dshot')
104 | ax3.set_xlabel('Time_ms')
105 | ax3.set_ylabel('dshot')
106 | ax3.set_ylim([0, 2100])
107 |
108 | #ax2.plot(original_5046['Time_ms'], original_5046['Thrust_g'] / (original_5046['Voltage_V'] * original_5046['Current_A']/10), color='b', label='original')
109 | #ax2.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'] / (eight_turn_5046['Voltage_V'] * eight_turn_5046['Current_A']/10), color='r', label='8 turn')
110 | #ax2.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'] / (nine_turn_5046['Voltage_V'] * nine_turn_5046['Current_A']/10), color='g', label='9 turn')
111 | ax2.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'] / (eleven_turn_5046['Voltage_V'] * eleven_turn_5046['Current_A']/10), color='g', label='11 turn')
112 | ax2.plot(eleven_turn_5046_ms['Time_ms'], eleven_turn_5046_ms['Thrust_g'] / (eleven_turn_5046_ms['Voltage_V'] * eleven_turn_5046_ms['Current_A']/10), color='r', label='11 turn multistrand')
113 | ax2.set_ylabel('Efficiency (g/W)')
114 | ax2.set_ylim([0, 5])
115 |
116 | #ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
117 | #ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
118 | #ax1.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'], color='g', label='9 turn')
119 | ax1.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'], color='g', label='11 turn')
120 | ax1.plot(eleven_turn_5046_ms['Time_ms'], eleven_turn_5046_ms['Thrust_g'], color='r', label='11 turn multistrand')
121 | ax1.set_xlabel('Time_ms')
122 | ax1.set_xlim([3500, 25000])
123 | ax1.set_ylabel('Thrust (g)')
124 | ax1.set_ylim([0, 1500])
125 | ax1.legend()
126 |
127 |
128 | ## Thrust efficiency plot Cyclone 5050
129 | ax1 = fig.add_subplot(224)
130 | ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5050')
131 | ax2 = ax1.twinx()
132 | ax3 = ax1.twinx()
133 | ax3.spines["right"].set_position(("axes", 1.2))
134 |
135 | ax3.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['dshot'], color='y', label='dshot')
136 | ax3.set_xlabel('Time_ms')
137 | ax3.set_ylabel('dshot')
138 | ax3.set_ylim([0, 2100])
139 |
140 | #ax2.plot(original_5050['Time_ms'], original_5050['Thrust_g'] / (original_5050['Voltage_V'] * original_5050['Current_A']/10), color='b', label='original')
141 | #ax2.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'] / (eight_turn_5050['Voltage_V'] * eight_turn_5050['Current_A']/10), color='r', label='8 turn')
142 | #ax2.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'] / (nine_turn_5050['Voltage_V'] * nine_turn_5050['Current_A']/10), color='g', label='9 turn')
143 | ax2.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'] / (eleven_turn_5050['Voltage_V'] * eleven_turn_5050['Current_A']/10), color='orange', label='11 turn')
144 | ax2.plot(eleven_turn_5050_ms['Time_ms'], eleven_turn_5050_ms['Thrust_g'] / (eleven_turn_5050_ms['Voltage_V'] * eleven_turn_5050_ms['Current_A']/10), color='r', label='11 turn multistrand')
145 | ax2.set_ylabel('Efficiency (g/W)')
146 | ax2.set_ylim([0, 5])
147 |
148 | #ax1.plot(original_5050['Time_ms'], original_5050['Thrust_g'], color='b', label='original')
149 | #ax1.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'], color='r', label='8 turn')
150 | #ax1.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'], color='g', label='9 turn')
151 | ax1.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'], color='orange', label='11 turn')
152 | ax1.plot(eleven_turn_5050_ms['Time_ms'], eleven_turn_5050_ms['Thrust_g'], color='r', label='11 turn multistrand')
153 | ax1.set_xlabel('Time_ms')
154 | ax1.set_xlim([3500, 25000])
155 | ax1.set_ylabel('Thrust (g)')
156 | ax1.set_ylim([0, 1500])
157 | ax1.legend()
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/emax_rs2306_plots - rpm thrust.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon Aug 26 19:53:08 2019
4 |
5 | @author: Jye
6 | """
7 |
8 | import numpy as np
9 | import matplotlib.pyplot as plt
10 |
11 | #original = np.genfromtxt('original.csv', delimiter=',', skip_header=1,
12 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
13 | #eight_turn = np.genfromtxt('8_turn.csv', delimiter=',', skip_header=1,
14 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
15 | #nine_turn = np.genfromtxt('9_turn.csv', delimiter=',', skip_header=1,
16 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
17 | eleven_turn = np.genfromtxt('11_turn - 6s.csv', delimiter=',', skip_header=1,
18 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
19 |
20 | #original_5046 = np.genfromtxt('original_cyclone_5046.csv', delimiter=',', skip_header=1,
21 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
22 | #eight_turn_5046 = np.genfromtxt('8_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
23 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
24 | #nine_turn_5046 = np.genfromtxt('9_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
25 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
26 | eleven_turn_5046 = np.genfromtxt('11_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
27 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
28 | eleven_turn_5046_6s = np.genfromtxt('11_turn_cyclone_5046 - 6s.csv', delimiter=',', skip_header=1,
29 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
30 |
31 | #original_5050 = np.genfromtxt('original_cyclone_5050.csv', delimiter=',', skip_header=1,
32 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
33 | #eight_turn_5050 = np.genfromtxt('8_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
34 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
35 | #nine_turn_5050 = np.genfromtxt('9_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
36 | # names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
37 | eleven_turn_5050 = np.genfromtxt('11_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
38 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
39 | eleven_turn_5050_6s = np.genfromtxt('11_turn_cyclone_5050 - 6s.csv', delimiter=',', skip_header=1,
40 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
41 |
42 | ## KV plot
43 | fig = plt.figure()
44 | ax1 = fig.add_subplot(111)
45 | ax1.title.set_text('6s')
46 | #ax2 = ax1.twinx()
47 | #ax3 = ax1.twinx()
48 | #ax3.spines["right"].set_position(("axes", 1.2))
49 | #fig.subplots_adjust(right=0.75)
50 |
51 | #ax3.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['dshot'], color='y', label='dshot')
52 | #ax3.set_ylabel('dshot')
53 | #ax3.set_ylim([0, 2100])
54 |
55 | #ax1.plot(original['Time_ms'], original['RPM'] / original['Voltage_V'], color='b', label='original')
56 | #ax1.plot(eight_turn['Time_ms'], eight_turn['RPM'] / eight_turn['Voltage_V'], color='r', label='8 turn')
57 | #ax1.plot(nine_turn['Time_ms'], nine_turn['RPM'] / nine_turn['Voltage_V'], color='g', label='9 turn')
58 | ax1.plot(eleven_turn_5046['RPM'], eleven_turn_5046['Thrust_g'] , color='b', label='11 turn 5046 4s')
59 | ax1.plot(eleven_turn_5046_6s['RPM'], eleven_turn_5046_6s['Thrust_g'] , color='g', label='11 turn 5046 6s')
60 | ax1.plot(eleven_turn_5050['RPM'], eleven_turn_5050['Thrust_g'] , color='r', label='11 turn 5050 4s')
61 | ax1.plot(eleven_turn_5050_6s['RPM'], eleven_turn_5050_6s['Thrust_g'] , color='orange', label='11 turn 5050 6s')
62 | ax1.set_xlabel('RPM')
63 | ax1.set_xlim([0, 30000])
64 | ax1.set_ylabel('Thrust_g')
65 | ax1.set_ylim([0, 1500])
66 | ax1.legend()
67 |
68 | #
69 | ### Response plot
70 | #ax1 = fig.add_subplot(223)
71 | #ax1.title.set_text('Response - Cyclone 5046 Vs 5050')
72 | ##ax2 = ax1.twinx()
73 | #ax3 = ax1.twinx()
74 | #ax3.spines["right"].set_position(("axes", 1.2))
75 | #fig.subplots_adjust(right=0.75)
76 | #
77 | #ax3.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['dshot'], color='y', label='dshot')
78 | #ax3.set_xlabel('Time_ms')
79 | #ax3.set_ylabel('dshot')
80 | #ax3.set_ylim([0, 2100])
81 | #
82 | ##ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
83 | ##ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
84 | #ax1.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'], color='g', label='11 turn - 5046')
85 | #ax1.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'], color='orange', label='11 turn - 5050')
86 | #ax1.set_xlabel('Time_ms')
87 | #ax1.set_xlim([3500, 25000])
88 | #ax1.set_ylabel('Thrust (g)')
89 | #ax1.set_xlim([11900, 12300])
90 | #ax1.set_ylim([0, 1500])
91 | #ax1.legend()
92 | #
93 | #
94 | ### Thrust efficiency plot Cyclone 5046
95 | #ax1 = fig.add_subplot(222)
96 | #ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5046')
97 | #ax2 = ax1.twinx()
98 | #ax3 = ax1.twinx()
99 | #ax3.spines["right"].set_position(("axes", 1.2))
100 | #
101 | #ax3.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['dshot'], color='y', label='dshot')
102 | #ax3.set_xlabel('Time_ms')
103 | #ax3.set_ylabel('dshot')
104 | #ax3.set_ylim([0, 2100])
105 | #
106 | ##ax2.plot(original_5046['Time_ms'], original_5046['Thrust_g'] / (original_5046['Voltage_V'] * original_5046['Current_A']/10), color='b', label='original')
107 | ##ax2.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'] / (eight_turn_5046['Voltage_V'] * eight_turn_5046['Current_A']/10), color='r', label='8 turn')
108 | ##ax2.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'] / (nine_turn_5046['Voltage_V'] * nine_turn_5046['Current_A']/10), color='g', label='9 turn')
109 | #ax2.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'] / (eleven_turn_5046['Voltage_V'] * eleven_turn_5046['Current_A']/10), color='g', label='11 turn')
110 | #ax2.set_ylabel('Efficiency (g/W)')
111 | #ax2.set_ylim([0, 5])
112 | #
113 | ##ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
114 | ##ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
115 | ##ax1.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'], color='g', label='9 turn')
116 | #ax1.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'], color='g', label='11 turn')
117 | #ax1.set_xlabel('Time_ms')
118 | #ax1.set_xlim([3500, 25000])
119 | #ax1.set_ylabel('Thrust (g)')
120 | #ax1.set_ylim([0, 1500])
121 | #ax1.legend()
122 | #
123 | #
124 | ### Thrust efficiency plot Cyclone 5050
125 | #ax1 = fig.add_subplot(224)
126 | #ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5050')
127 | #ax2 = ax1.twinx()
128 | #ax3 = ax1.twinx()
129 | #ax3.spines["right"].set_position(("axes", 1.2))
130 | #
131 | #ax3.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['dshot'], color='y', label='dshot')
132 | #ax3.set_xlabel('Time_ms')
133 | #ax3.set_ylabel('dshot')
134 | #ax3.set_ylim([0, 2100])
135 | #
136 | ##ax2.plot(original_5050['Time_ms'], original_5050['Thrust_g'] / (original_5050['Voltage_V'] * original_5050['Current_A']/10), color='b', label='original')
137 | ##ax2.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'] / (eight_turn_5050['Voltage_V'] * eight_turn_5050['Current_A']/10), color='r', label='8 turn')
138 | ##ax2.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'] / (nine_turn_5050['Voltage_V'] * nine_turn_5050['Current_A']/10), color='g', label='9 turn')
139 | #ax2.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'] / (eleven_turn_5050['Voltage_V'] * eleven_turn_5050['Current_A']/10), color='orange', label='11 turn')
140 | #ax2.set_ylabel('Efficiency (g/W)')
141 | #ax2.set_ylim([0, 5])
142 | #
143 | ##ax1.plot(original_5050['Time_ms'], original_5050['Thrust_g'], color='b', label='original')
144 | ##ax1.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'], color='r', label='8 turn')
145 | ##ax1.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'], color='g', label='9 turn')
146 | #ax1.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'], color='orange', label='11 turn')
147 | #ax1.set_xlabel('Time_ms')
148 | #ax1.set_xlim([3500, 25000])
149 | #ax1.set_ylabel('Thrust (g)')
150 | #ax1.set_ylim([0, 1500])
151 | #ax1.legend()
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/emax_rs2306_plots.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon Aug 26 19:53:08 2019
4 |
5 | @author: Jye
6 | """
7 |
8 | import numpy as np
9 | import matplotlib.pyplot as plt
10 |
11 | original = np.genfromtxt('original.csv', delimiter=',', skip_header=1,
12 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
13 | eight_turn = np.genfromtxt('8_turn.csv', delimiter=',', skip_header=1,
14 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
15 | nine_turn = np.genfromtxt('9_turn.csv', delimiter=',', skip_header=1,
16 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
17 | eleven_turn = np.genfromtxt('11_turn.csv', delimiter=',', skip_header=1,
18 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
19 |
20 | original_5046 = np.genfromtxt('original_cyclone_5046.csv', delimiter=',', skip_header=1,
21 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
22 | eight_turn_5046 = np.genfromtxt('8_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
23 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
24 | nine_turn_5046 = np.genfromtxt('9_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
25 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
26 | eleven_turn_5046 = np.genfromtxt('11_turn_cyclone_5046.csv', delimiter=',', skip_header=1,
27 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
28 |
29 | original_5050 = np.genfromtxt('original_cyclone_5050.csv', delimiter=',', skip_header=1,
30 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
31 | eight_turn_5050 = np.genfromtxt('8_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
32 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
33 | nine_turn_5050 = np.genfromtxt('9_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
34 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
35 | eleven_turn_5050 = np.genfromtxt('11_turn_cyclone_5050.csv', delimiter=',', skip_header=1,
36 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
37 |
38 | ## KV plot
39 | fig = plt.figure()
40 | ax1 = fig.add_subplot(221)
41 | ax1.title.set_text('KV')
42 | #ax2 = ax1.twinx()
43 | ax3 = ax1.twinx()
44 | ax3.spines["right"].set_position(("axes", 1.2))
45 | fig.subplots_adjust(right=0.75)
46 |
47 | ax3.plot(original['Time_ms'], original['dshot'], color='y', label='dshot')
48 | ax3.set_ylabel('dshot')
49 | ax3.set_ylim([0, 2100])
50 |
51 | ax1.plot(original['Time_ms'], original['RPM'] / original['Voltage_V'], color='b', label='original')
52 | ax1.plot(eight_turn['Time_ms'], eight_turn['RPM'] / eight_turn['Voltage_V'], color='r', label='8 turn')
53 | ax1.plot(nine_turn['Time_ms'], nine_turn['RPM'] / nine_turn['Voltage_V'], color='g', label='9 turn')
54 | ax1.plot(eleven_turn['Time_ms'], eleven_turn['RPM'] / eleven_turn['Voltage_V'], color='orange', label='11 turn')
55 | ax1.set_xlabel('Time_ms')
56 | ax1.set_xlim([3500, 25000])
57 | ax1.set_ylabel('KV')
58 | ax1.set_ylim([1500, 2500])
59 | ax1.legend()
60 |
61 |
62 | ## Response plot
63 | ax1 = fig.add_subplot(223)
64 | ax1.title.set_text('Response - Cyclone 5046')
65 | #ax2 = ax1.twinx()
66 | ax3 = ax1.twinx()
67 | ax3.spines["right"].set_position(("axes", 1.2))
68 | fig.subplots_adjust(right=0.75)
69 |
70 | ax3.plot(original['Time_ms'], original['dshot'], color='y', label='dshot')
71 | ax3.set_xlabel('Time_ms')
72 | ax3.set_ylabel('dshot')
73 | ax3.set_ylim([0, 2100])
74 |
75 | ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
76 | ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
77 | ax1.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'], color='g', label='9 turn')
78 | ax1.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'], color='orange', label='11 turn')
79 | ax1.set_xlabel('Time_ms')
80 | ax1.set_xlim([3500, 25000])
81 | ax1.set_ylabel('Thrust (g)')
82 | ax1.set_xlim([11900, 12300])
83 | ax1.set_ylim([0, 1500])
84 | ax1.legend()
85 |
86 |
87 | ## Thrust efficiency plot Cyclone 5046
88 | ax1 = fig.add_subplot(222)
89 | ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5046')
90 | ax2 = ax1.twinx()
91 | ax3 = ax1.twinx()
92 | ax3.spines["right"].set_position(("axes", 1.2))
93 |
94 | ax3.plot(original_5046['Time_ms'], original_5046['dshot'], color='y', label='dshot')
95 | ax3.set_xlabel('Time_ms')
96 | ax3.set_ylabel('dshot')
97 | ax3.set_ylim([0, 2100])
98 |
99 | ax2.plot(original_5046['Time_ms'], original_5046['Thrust_g'] / (original_5046['Voltage_V'] * original_5046['Current_A']/10), color='b', label='original')
100 | ax2.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'] / (eight_turn_5046['Voltage_V'] * eight_turn_5046['Current_A']/10), color='r', label='8 turn')
101 | ax2.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'] / (nine_turn_5046['Voltage_V'] * nine_turn_5046['Current_A']/10), color='g', label='9 turn')
102 | ax2.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'] / (eleven_turn_5046['Voltage_V'] * eleven_turn_5046['Current_A']/10), color='orange', label='11 turn')
103 | ax2.set_ylabel('Efficiency (g/W)')
104 | ax2.set_ylim([0, 5])
105 |
106 | ax1.plot(original_5046['Time_ms'], original_5046['Thrust_g'], color='b', label='original')
107 | ax1.plot(eight_turn_5046['Time_ms'], eight_turn_5046['Thrust_g'], color='r', label='8 turn')
108 | ax1.plot(nine_turn_5046['Time_ms'], nine_turn_5046['Thrust_g'], color='g', label='9 turn')
109 | ax1.plot(eleven_turn_5046['Time_ms'], eleven_turn_5046['Thrust_g'], color='orange', label='11 turn')
110 | ax1.set_xlabel('Time_ms')
111 | ax1.set_xlim([3500, 25000])
112 | ax1.set_ylabel('Thrust (g)')
113 | ax1.set_ylim([0, 1500])
114 | ax1.legend()
115 |
116 |
117 | ## Thrust efficiency plot Cyclone 5050
118 | ax1 = fig.add_subplot(224)
119 | ax1.title.set_text('Thrust (g) & Efficiency (g/W) - Cyclone 5050')
120 | ax2 = ax1.twinx()
121 | ax3 = ax1.twinx()
122 | ax3.spines["right"].set_position(("axes", 1.2))
123 |
124 | ax3.plot(original_5050['Time_ms'], original_5050['dshot'], color='y', label='dshot')
125 | ax3.set_xlabel('Time_ms')
126 | ax3.set_ylabel('dshot')
127 | ax3.set_ylim([0, 2100])
128 |
129 | ax2.plot(original_5050['Time_ms'], original_5050['Thrust_g'] / (original_5050['Voltage_V'] * original_5050['Current_A']/10), color='b', label='original')
130 | ax2.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'] / (eight_turn_5050['Voltage_V'] * eight_turn_5050['Current_A']/10), color='r', label='8 turn')
131 | ax2.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'] / (nine_turn_5050['Voltage_V'] * nine_turn_5050['Current_A']/10), color='g', label='9 turn')
132 | ax2.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'] / (eleven_turn_5050['Voltage_V'] * eleven_turn_5050['Current_A']/10), color='orange', label='11 turn')
133 | ax2.set_ylabel('Efficiency (g/W)')
134 | ax2.set_ylim([0, 5])
135 |
136 | ax1.plot(original_5050['Time_ms'], original_5050['Thrust_g'], color='b', label='original')
137 | ax1.plot(eight_turn_5050['Time_ms'], eight_turn_5050['Thrust_g'], color='r', label='8 turn')
138 | ax1.plot(nine_turn_5050['Time_ms'], nine_turn_5050['Thrust_g'], color='g', label='9 turn')
139 | ax1.plot(eleven_turn_5050['Time_ms'], eleven_turn_5050['Thrust_g'], color='orange', label='11 turn')
140 | ax1.set_xlabel('Time_ms')
141 | ax1.set_xlim([3500, 25000])
142 | ax1.set_ylabel('Thrust (g)')
143 | ax1.set_ylim([0, 1500])
144 | ax1.legend()
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/old excel/EMAX RS2306 2400KV.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/old excel/EMAX RS2306 2400KV.xlsx
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/old excel/plots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/old excel/plots.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/original.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/original.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/original_cyclone_5046.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/original_cyclone_5046.csv.plot.png
--------------------------------------------------------------------------------
/data/EMAX RS2306 2400KV/original_cyclone_5050.csv.plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JyeSmith/dshot-esc-tester/8695f27fb705892a0906acddc60b4a4e8dfb21a3/data/EMAX RS2306 2400KV/original_cyclone_5050.csv.plot.png
--------------------------------------------------------------------------------
/data/drop csv on here to plot.bat:
--------------------------------------------------------------------------------
1 | python "C:\Users\Jye\Documents\GitHub\dshot-esc-tester\data\thrustPlot.py" %*
--------------------------------------------------------------------------------
/data/thrustPlot.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | import matplotlib.pyplot as plt
4 | import sys
5 |
6 | print(sys.argv[1])
7 |
8 | thrustFile = sys.argv[1]
9 |
10 | data = np.genfromtxt(thrustFile, delimiter=',', skip_header=1,
11 | names=['Time_ms', 'dshot', 'Voltage_V', 'Current_A', 'RPM', 'Thrust_g'])
12 | fig = plt.figure()
13 |
14 | ax1 = fig.add_subplot(311)
15 | fig.subplots_adjust(right=0.75)
16 | ax2 = ax1.twinx()
17 | ax3 = ax1.twinx()
18 | ax3.spines["right"].set_position(("axes", 1.2))
19 |
20 | ax3.plot(data['Time_ms'], data['dshot'], color='y', label='dshot')
21 | ax3.set_xlabel('Time_ms')
22 | ax3.set_ylabel('dshot')
23 | ax3.set_ylim([0, 2100])
24 |
25 | ax2.plot(data['Time_ms'], data['Thrust_g']/(data['Voltage_V']*data['Current_A']/10), color='r', label='g/W')
26 | ax2.set_ylabel('g/W')
27 | ax2.set_ylim([0, 5])
28 | ax2.legend()
29 |
30 | ax1.plot(data['Time_ms'], data['Thrust_g'], color='b', label='Thrust (g)')
31 | ax1.set_ylabel('Thrust (g)')
32 | ax1.set_ylim([0, 1500])
33 | ax1.legend()
34 |
35 |
36 | ax1 = fig.add_subplot(312)
37 | fig.subplots_adjust(right=0.75)
38 | ax2 = ax1.twinx()
39 | ax3 = ax1.twinx()
40 | ax3.spines["right"].set_position(("axes", 1.2))
41 |
42 | ax3.plot(data['Time_ms'], data['dshot'], color='y', label='dshot')
43 | ax3.set_xlabel('Time_ms')
44 | ax3.set_ylabel('dshot')
45 | ax3.set_ylim([0, 2100])
46 |
47 | ax2.plot(data['Time_ms'], data['Voltage_V'], color='r', label='Voltage (V)')
48 | ax2.set_ylabel('Voltage (V)')
49 | ax2.set_ylim([15.5, 26])
50 | ax2.legend()
51 |
52 | ax1.plot(data['Time_ms'], data['Current_A']/10, color='b', label='Current (A)')
53 | ax1.set_ylabel('Current (A)')
54 | ax1.set_ylim([0, 50])
55 | ax1.legend()
56 |
57 |
58 | ax1 = fig.add_subplot(313)
59 | fig.subplots_adjust(right=0.75)
60 | ax2 = ax1.twinx()
61 | ax3 = ax1.twinx()
62 | ax3.spines["right"].set_position(("axes", 1.2))
63 |
64 | ax3.plot(data['Time_ms'], data['dshot'], color='y', label='dshot')
65 | ax3.set_xlabel('Time_ms')
66 | ax3.set_ylabel('dshot')
67 | ax3.set_ylim([0, 2100])
68 |
69 | ax1.plot(data['Time_ms'], data['RPM'], color='r', label='RPM')
70 | ax1.set_ylabel('RPM')
71 | ax1.set_ylim([0, 30000])
72 | ax1.legend()
73 |
74 | ax2.plot(data['Time_ms'], data['RPM']/data['Voltage_V'], color='b', label='KV')
75 | ax2.set_ylabel('KV')
76 | ax2.set_ylim([0, 2600])
77 | ax2.legend()
78 |
79 |
80 | fig.savefig(thrustFile+'.plot.png')
81 | #fig.savefig('plot.pdf')
--------------------------------------------------------------------------------
/dshot-esc-tester.ino:
--------------------------------------------------------------------------------
1 | /*
2 | * ----------------------------------------------------------------------------
3 | * "THE PROP-WARE LICENSE" (Revision 42):
4 | * wrote this file. As long as you retain this notice you
5 | * can do whatever you want with this stuff. If we meet some day, and you think
6 | * this stuff is worth it, you can buy me some props in return. Jye Smith
7 | * ----------------------------------------------------------------------------
8 | */
9 |
10 | /* Some of the below code is taken from examples provided by Felix on RCGroups.com
11 | *
12 | * KISS ESC 24A Serial Example Code for Arduino.
13 | * https://www.rcgroups.com/forums/showthread.php?2555162-KISS-ESC-24A-Race-Edition-Flyduino-32bit-ESC
14 | * https://www.rcgroups.com/forums/showatt.php?attachmentid=8521072&d=1450345654 *
15 | */
16 |
17 | //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
18 | // www.miniquadtestbench.com
19 | // Uncommenting the below define will start the test sequence defined on MQTB
20 | // WARNING - THE MOTOR WILL START TO SPIN AUTOMATICALLY!!!
21 | //#define MINIQUADTESTBENCH
22 | //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
23 |
24 | #include
25 | #include "SSD1306.h"
26 | #include "freertos/FreeRTOS.h"
27 | #include "freertos/task.h"
28 | #include "freertos/event_groups.h"
29 | #include "Arduino.h"
30 | #include "esp32-hal.h"
31 | #include "HX711.h"
32 |
33 | #define MOTOR_POLES 14
34 |
35 | // HX711
36 | #define LOADCELL_DOUT_PIN 25
37 | #define LOADCELL_SCK_PIN 26
38 | #define LOADCELL_CALIBRATION 345.0
39 | HX711 loadcell;
40 | long thrust = 0;
41 |
42 | TaskHandle_t Task1;
43 |
44 | rmt_data_t dshotPacket[16];
45 | rmt_obj_t* rmt_send = NULL;
46 |
47 | hw_timer_t * timer = NULL;
48 |
49 | HardwareSerial MySerial(1);
50 |
51 | SSD1306 display(0x3c, 21, 22); // 21 and 22 are default pins
52 |
53 | uint8_t receivedBytes = 0;
54 | volatile bool requestTelemetry = false;
55 | bool printTelemetry = true;
56 | uint16_t dshotUserInputValue = 0;
57 | uint16_t dshotmin = 48;
58 | uint16_t dshotmax = 2047;
59 | uint16_t dshotidle = dshotmin + round(3.5*(dshotmax-dshotmin)/100); // 3.5%
60 | uint16_t dshot50 = dshotmin + round(50*(dshotmax-dshotmin)/100); // 50%
61 | uint16_t dshot75 = dshotmin + round(75*(dshotmax-dshotmin)/100); // 75%
62 | int16_t ESC_telemetrie[5]; // Temperature, Voltage, Current, used mAh, eRpM
63 | bool runMQTBSequence = false;
64 |
65 | uint32_t currentTime;
66 | uint8_t temperature = 0;
67 | uint8_t temperatureMax = 0;
68 | float voltage = 0;
69 | float voltageMin = 99;
70 | uint32_t current = 0;
71 | uint32_t currentMax = 0;
72 | uint32_t erpm = 0;
73 | uint32_t erpmMax = 0;
74 | uint32_t rpm = 0;
75 | uint32_t rpmMAX = 0;
76 | uint32_t kv = 0;
77 | uint32_t kvMax = 0;
78 |
79 | void gotTouch8(){
80 | dshotUserInputValue = 0;
81 | runMQTBSequence = false;
82 | printTelemetry = true;
83 | } // DIGITAL_CMD_MOTOR_STOP
84 | void gotTouch9(){
85 | dshotUserInputValue = 247;
86 | resetMaxMinValues();
87 | runMQTBSequence = false;
88 | printTelemetry = true;
89 | } // 10%
90 | void gotTouch7(){
91 | dshotUserInputValue = 447;
92 | resetMaxMinValues();
93 | runMQTBSequence = false;
94 | printTelemetry = true;
95 | } // 20%
96 | void gotTouch6(){
97 | dshotUserInputValue = 1047;
98 | resetMaxMinValues();
99 | runMQTBSequence = false;
100 | printTelemetry = true;
101 | } // 50%
102 | void gotTouch5(){
103 | dshotUserInputValue = 2047;
104 | resetMaxMinValues();
105 | runMQTBSequence = false;
106 | printTelemetry = true;
107 | } // 100%
108 | void gotTouch4(){
109 | temperatureMax = 0;
110 | voltageMin = 99;
111 | currentMax = 0;
112 | erpmMax = 0;
113 | rpmMAX = 0;
114 | kvMax = 0;
115 | runMQTBSequence = false;
116 | printTelemetry = true;
117 | }
118 | void resetMaxMinValues() {
119 | gotTouch4();
120 | }
121 |
122 | void IRAM_ATTR getTelemetry(){
123 | requestTelemetry = true;
124 | }
125 |
126 | void startTelemetryTimer() {
127 | timer = timerBegin(0, 80, true); // timer_id = 0; divider=80; countUp = true;
128 | timerAttachInterrupt(timer, &getTelemetry, true); // edge = true
129 | timerAlarmWrite(timer, 20000, true); //1000 = 1 ms
130 | timerAlarmEnable(timer);
131 | }
132 |
133 | // Second core used to handle dshot packets
134 | void secondCoreTask( void * pvParameters ){
135 | while(1){
136 |
137 | dshotOutput(dshotUserInputValue, requestTelemetry);
138 |
139 | if (requestTelemetry) {
140 | requestTelemetry = false;
141 | receivedBytes = 0;
142 | }
143 |
144 | delay(1);
145 |
146 | }
147 | }
148 |
149 | void setup() {
150 |
151 | Serial.begin(115200);
152 | MySerial.begin(115200, SERIAL_8N1, 16, 17);
153 |
154 | loadcell.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
155 | loadcell.set_scale(LOADCELL_CALIBRATION);
156 | loadcell.tare();
157 |
158 | if ((rmt_send = rmtInit(5, true, RMT_MEM_64)) == NULL) {
159 | Serial.println("init sender failed\n");
160 | }
161 |
162 | float realTick = rmtSetTick(rmt_send, 12.5); // 12.5ns sample rate
163 | Serial.printf("rmt_send tick set to: %fns\n", realTick);
164 |
165 | display.init();
166 | display.flipScreenVertically();
167 | display.setFont(ArialMT_Plain_10);
168 |
169 | // Output disarm signal while esc initialises and do some display stuff.
170 | uint8_t xbeep = random(15, 100);
171 | uint8_t ybeep = random(15, 50);
172 | uint8_t ibeep = 0;
173 | while (millis() < 3500) {
174 | dshotOutput(0, false);
175 | delay(1);
176 |
177 | display.clear();
178 | ibeep++;
179 | if (ibeep == 100) {
180 | ibeep = 0;
181 | xbeep = random(15, 50);
182 | ybeep = random(15, 50);
183 | }
184 | display.drawString(xbeep, ybeep, "beep");
185 | if (millis() < 500) {
186 | display.drawString(0, 0, "Initialising ESC... 4s");
187 | } else if (millis() < 1500) {
188 | display.drawString(0, 0, "Initialising ESC... 3s");
189 | } else if (millis() < 2500) {
190 | display.drawString(0, 0, "Initialising ESC... 2s");
191 | } else {
192 | display.drawString(0, 0, "Initialising ESC... 1s");
193 | }
194 | display.display();
195 | }
196 |
197 | touchAttachInterrupt(T4, gotTouch4, 40);
198 | touchAttachInterrupt(T5, gotTouch5, 40);
199 | touchAttachInterrupt(T6, gotTouch6, 40);
200 | touchAttachInterrupt(T7, gotTouch7, 40);
201 | touchAttachInterrupt(T8, gotTouch8, 40);
202 | touchAttachInterrupt(T9, gotTouch9, 40);
203 |
204 | // Empty Rx Serial of garbage telemtry
205 | while(MySerial.available())
206 | MySerial.read();
207 |
208 | requestTelemetry = true;
209 |
210 | BeginWebUpdate();
211 |
212 | startTelemetryTimer(); // Timer used to request tlm continually in case ESC rcv bad packet
213 |
214 | xTaskCreatePinnedToCore(secondCoreTask, "Task1", 10000, NULL, 1, &Task1, 0);
215 |
216 | Serial.print("Time (ms)");
217 | Serial.print(",");
218 | Serial.print("dshot");
219 | Serial.print(",");
220 | Serial.print("Voltage (V)");
221 | Serial.print(",");
222 | Serial.print("Current (A)");
223 | Serial.print(",");
224 | Serial.print("RPM");
225 | Serial.print(",");
226 | Serial.println("Thrust (g)");
227 |
228 | #ifdef MINIQUADTESTBENCH
229 | dshotUserInputValue = dshotidle;
230 | runMQTBSequence = true;
231 | display.clear();
232 | display.setTextAlignment(TEXT_ALIGN_LEFT);
233 | display.drawString(0, 0, "Running MQTB Sequence...");
234 | display.display();
235 | #endif
236 |
237 | }
238 |
239 | void loop() {
240 |
241 | HandleWebUpdate();
242 |
243 | if(loadcell.is_ready()) {
244 | thrust = loadcell.get_units(1);
245 | }
246 |
247 | if(!requestTelemetry) {
248 | receiveTelemtrie();
249 | }
250 |
251 | #ifdef MINIQUADTESTBENCH
252 | if(runMQTBSequence) {
253 | currentTime = millis();
254 | if(currentTime >= 4000 && currentTime < 6000) {
255 | dshotUserInputValue = dshot50;
256 | } else if(currentTime >= 6000 && currentTime < 8000) {
257 | dshotUserInputValue = dshotidle;
258 | } else if(currentTime >= 8000 && currentTime < 10000) {
259 | dshotUserInputValue = dshot75;
260 | } else if(currentTime >= 10000 && currentTime < 12000) {
261 | dshotUserInputValue = dshotidle;
262 | } else if(currentTime >= 12000 && currentTime < 14000) {
263 | dshotUserInputValue = dshotmax;
264 | } else if(currentTime >= 14000 && currentTime < 16000) {
265 | dshotUserInputValue = dshotmin;
266 | } else if(currentTime >= 16000 && currentTime < 22000) {
267 | dshotUserInputValue = dshotmin + (currentTime-16000)*(dshotmax-dshotmin)/6000.0;
268 | } else if(currentTime >= 24000 && currentTime < 26000) {
269 | dshotUserInputValue = dshotidle;
270 | } else if(currentTime >= 26000 && currentTime < 28000) {
271 | printTelemetry = false;
272 | dshotUserInputValue = 0;
273 | }
274 | }
275 | #endif
276 |
277 | }
278 |
279 | void receiveTelemtrie(){
280 | static uint8_t SerialBuf[10];
281 |
282 | if(MySerial.available()){
283 | SerialBuf[receivedBytes] = MySerial.read();
284 | receivedBytes++;
285 | }
286 |
287 | if(receivedBytes > 9){ // transmission complete
288 |
289 | uint8_t crc8 = get_crc8(SerialBuf, 9); // get the 8 bit CRC
290 |
291 | if(crc8 != SerialBuf[9]) {
292 | // Serial.println("CRC transmission failure");
293 |
294 | // Empty Rx Serial of garbage telemtry
295 | while(MySerial.available())
296 | MySerial.read();
297 |
298 | requestTelemetry = true;
299 |
300 | return; // transmission failure
301 | }
302 |
303 | // compute the received values
304 | ESC_telemetrie[0] = SerialBuf[0]; // temperature
305 | ESC_telemetrie[1] = (SerialBuf[1]<<8)|SerialBuf[2]; // voltage
306 | ESC_telemetrie[2] = (SerialBuf[3]<<8)|SerialBuf[4]; // Current
307 | ESC_telemetrie[3] = (SerialBuf[5]<<8)|SerialBuf[6]; // used mA/h
308 | ESC_telemetrie[4] = (SerialBuf[7]<<8)|SerialBuf[8]; // eRpM *100
309 |
310 | requestTelemetry = true;
311 |
312 | if(!runMQTBSequence) { // Do not update during MQTB sequence. Slows serial output.
313 | updateDisplay();
314 | }
315 |
316 | // Serial.println("Requested Telemetrie");
317 | // Serial.print("Temperature (C): ");
318 | // Serial.println(ESC_telemetrie[0]);
319 | // Serial.print("Voltage (V): ");
320 | // Serial.println(ESC_telemetrie[1] / 100.0);
321 | // Serial.print("Current (mA): ");
322 | // Serial.println(ESC_telemetrie[2] * 100);
323 | // Serial.print("mA/h: ");
324 | // Serial.println(ESC_telemetrie[3] * 10);
325 | // Serial.print("eRPM : ");
326 | // Serial.println(ESC_telemetrie[4] * 100);
327 | // Serial.print("RPM : ");
328 | // Serial.println(ESC_telemetrie[4] * 100 / 7.0); // 7 = 14 magnet count / 2
329 | // Serial.print("KV : ");
330 | // Serial.println( (ESC_telemetrie[4] * 100 / 7.0) / (ESC_telemetrie[1] / 100.0) ); // 7 = 14 magnet count / 2
331 | // Serial.println(" ");
332 | // Serial.println(" ");
333 |
334 | if(printTelemetry) {
335 | Serial.print(millis());
336 | Serial.print(",");
337 | Serial.print(dshotUserInputValue);
338 | Serial.print(",");
339 | // Serial.print("Voltage (V): ");
340 | Serial.print(ESC_telemetrie[1] / 100.0);
341 | Serial.print(",");
342 | // Serial.print("Current (A): ");
343 | Serial.print(ESC_telemetrie[2] / 10.0);
344 | Serial.print(",");
345 | // Serial.print("RPM : ");
346 | Serial.print(ESC_telemetrie[4] * 100 / (MOTOR_POLES / 2));
347 | Serial.print(",");
348 | // Thrust
349 | Serial.println(thrust);
350 | }
351 |
352 | temperature = 0.9*temperature + 0.1*ESC_telemetrie[0];
353 | if (temperature > temperatureMax) {
354 | temperatureMax = temperature;
355 | }
356 |
357 | voltage = 0.9*voltage + 0.1*(ESC_telemetrie[1] / 100.0);
358 | if (voltage < voltageMin) {
359 | voltageMin = voltage;
360 | }
361 |
362 | current = 0.9*current + 0.1*(ESC_telemetrie[2] * 100);
363 | if (current > currentMax) {
364 | currentMax = current;
365 | }
366 |
367 | erpm = 0.9*erpm + 0.1*(ESC_telemetrie[4] * 100);
368 | if (erpm > erpmMax) {
369 | erpmMax = erpm;
370 | }
371 |
372 | rpm = erpm / (MOTOR_POLES / 2);
373 | if (rpm > rpmMAX) {
374 | rpmMAX = rpm;
375 | }
376 |
377 | if (rpm) { // Stops weird numbers :|
378 | kv = rpm / voltage / ( (float(dshotUserInputValue) - dshotmin) / (dshotmax - dshotmin) );
379 | } else {
380 | kv = 0;
381 | }
382 | if (kv > kvMax) {
383 | kvMax = kv;
384 | }
385 |
386 | }
387 |
388 | return;
389 |
390 | }
391 |
392 | void dshotOutput(uint16_t value, bool telemetry) {
393 |
394 | uint16_t packet;
395 |
396 | // telemetry bit
397 | if (telemetry) {
398 | packet = (value << 1) | 1;
399 | } else {
400 | packet = (value << 1) | 0;
401 | }
402 |
403 | // https://github.com/betaflight/betaflight/blob/09b52975fbd8f6fcccb22228745d1548b8c3daab/src/main/drivers/pwm_output.c#L523
404 | int csum = 0;
405 | int csum_data = packet;
406 | for (int i = 0; i < 3; i++) {
407 | csum ^= csum_data;
408 | csum_data >>= 4;
409 | }
410 | csum &= 0xf;
411 | packet = (packet << 4) | csum;
412 |
413 | // durations are for dshot600
414 | // https://blck.mn/2016/11/dshot-the-new-kid-on-the-block/
415 | // Bit length (total timing period) is 1.67 microseconds (T0H + T0L or T1H + T1L).
416 | // For a bit to be 1, the pulse width is 1250 nanoseconds (T1H – time the pulse is high for a bit value of ONE)
417 | // For a bit to be 0, the pulse width is 625 nanoseconds (T0H – time the pulse is high for a bit value of ZERO)
418 | for (int i = 0; i < 16; i++) {
419 | if (packet & 0x8000) {
420 | dshotPacket[i].level0 = 1;
421 | dshotPacket[i].duration0 = 100;
422 | dshotPacket[i].level1 = 0;
423 | dshotPacket[i].duration1 = 34;
424 | } else {
425 | dshotPacket[i].level0 = 1;
426 | dshotPacket[i].duration0 = 50;
427 | dshotPacket[i].level1 = 0;
428 | dshotPacket[i].duration1 = 84;
429 | }
430 | packet <<= 1;
431 | }
432 |
433 | rmtWrite(rmt_send, dshotPacket, 16);
434 |
435 | return;
436 |
437 | }
438 |
439 | uint8_t update_crc8(uint8_t crc, uint8_t crc_seed){
440 | uint8_t crc_u, i;
441 | crc_u = crc;
442 | crc_u ^= crc_seed;
443 | for ( i=0; i<8; i++) crc_u = ( crc_u & 0x80 ) ? 0x7 ^ ( crc_u << 1 ) : ( crc_u << 1 );
444 | return (crc_u);
445 | }
446 |
447 | uint8_t get_crc8(uint8_t *Buf, uint8_t BufLen){
448 | uint8_t crc = 0, i;
449 | for( i=0; i