From 70a17af3f2cf5e837e150a8e60b16463963e31c6 Mon Sep 17 00:00:00 2001 From: Fisch Date: Sun, 16 May 2021 18:06:36 +0200 Subject: [PATCH 01/11] fix swapped feedback speed_measured left and right --- controller_teensy/src/main.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/controller_teensy/src/main.cpp b/controller_teensy/src/main.cpp index 0de8403..744650c 100644 --- a/controller_teensy/src/main.cpp +++ b/controller_teensy/src/main.cpp @@ -23,7 +23,7 @@ unsigned long last_log_send=0; #define LOGMININTERVAL 20 //minimum interval (ms) to send logs #define LOGMAXINTERVAL 10000 //maximum time (ms) after which data is send -#define WRITE_HEADER_TIME 1000 +#define WRITE_HEADER_TIME 400 //just before FEEDBACKRECEIVETIMEOUT, so header gets written before error comments bool log_header_written = false; @@ -112,12 +112,12 @@ SerialCommand CommandFront; SerialCommand CommandRear; -typedef struct{ +typedef struct{ //match this struct to hoverboard-firmware SerialFeedback struct in main.c uint16_t start; int16_t cmd1; int16_t cmd2; - int16_t speedL_meas; //left speed is negative when driving forward - int16_t speedR_meas; //right speed is positive when driving forward + int16_t speedR_meas; //right speed is negatie when driving forward + int16_t speedL_meas; //left speed is positive when driving forward int16_t batVoltage; int16_t boardTemp; int16_t curL_DC; //negative values are current consumed. positive values mean generated current @@ -130,8 +130,8 @@ SerialFeedback NewFeedbackFront; SerialFeedback FeedbackRear; SerialFeedback NewFeedbackRear; -#define CURRENT_FILTER_SIZE 20 //latency is about CURRENT_FILTER_SIZE/2*MEASURE_INTERVAL (measure interval is defined by hoverboard controller) -#define CURRENT_MEANVALUECOUNT 4 //0<= meanvaluecount < CURRENT_FILTER_SIZE/2. how many values will be used from sorted weight array from the center region. abour double this values reading are used +#define CURRENT_FILTER_SIZE 40 //latency is about CURRENT_FILTER_SIZE/2*MEASURE_INTERVAL (measure interval is defined by hoverboard controller) +#define CURRENT_MEANVALUECOUNT 10 //0<= meanvaluecount < CURRENT_FILTER_SIZE/2. how many values will be used from sorted weight array from the center region. abour double this values reading are used typedef struct{ int16_t curL_DC[CURRENT_FILTER_SIZE] = {0}; //current will be inverted for this so positive value means consumed current int16_t curR_DC[CURRENT_FILTER_SIZE] = {0}; @@ -359,10 +359,10 @@ void writeLog(HardwareSerial &SerialRef, unsigned long time, MotorParameter &mpf SerialRef.print(mprear.filtered_curL,3); SerialRef.print(","); SerialRef.print(mprear.filtered_curR,3); SerialRef.print(","); - SerialRef.print(-fbfront.speedL_meas); SerialRef.print(","); //invert speed, because left wheels are negated - SerialRef.print(fbfront.speedR_meas); SerialRef.print(","); - SerialRef.print(-fbrear.speedL_meas); SerialRef.print(","); //invert speed, because left wheels are negated - SerialRef.print(fbrear.speedR_meas); SerialRef.print(","); + SerialRef.print(fbfront.speedL_meas); SerialRef.print(","); //invert speed, because left wheels are negated + SerialRef.print(-fbfront.speedR_meas); SerialRef.print(","); + SerialRef.print(fbrear.speedL_meas); SerialRef.print(","); //invert speed, because left wheels are negated + SerialRef.print(-fbrear.speedR_meas); SerialRef.print(","); SerialRef.print(fbfront.boardTemp/10.0); SerialRef.print(","); //in degC SerialRef.print(fbrear.boardTemp/10.0); SerialRef.print(","); //in degC @@ -569,7 +569,7 @@ void readButtons() { if (button_start_state) { //pressed if ( (loopmillis> button_start_lastchange + LONG_PRESS_ARMING_TIME)) { //pressed long - if (throttle_pos<=0 && brake_pos<=0 && !armed) { //brake or thottle not pressed + if (throttle_pos<=0 && brake_pos<=0 && controllers_connected && !armed) { //brake or thottle not pressed, controllers connected armed=true; //arm if button pressed long enough writeLogComment(Serial1,loopmillis, "Armed by button"); } From d5a60cd4999bdceb61765434021fe8d94f8f815d Mon Sep 17 00:00:00 2001 From: Fisch Date: Sun, 16 May 2021 18:55:43 +0200 Subject: [PATCH 02/11] matplotlib scatter plot for cmd vs speed --- logdata_visualization/analyze.py | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 logdata_visualization/analyze.py diff --git a/logdata_visualization/analyze.py b/logdata_visualization/analyze.py new file mode 100644 index 0000000..dfe513c --- /dev/null +++ b/logdata_visualization/analyze.py @@ -0,0 +1,52 @@ +import matplotlib.pyplot as plt +import csv + +x=[] +speed_FrontL=[] +speed_FrontR=[] +speed_RearL=[] +speed_RearR=[] + +fp = open('LOG00193_20210516_fixedSpeedLR_freewheelingTest.TXT') + +rdr = csv.DictReader(filter(lambda row: row[0]!='#', fp)) +for row in rdr: + #print(row) + x.append(float(row['cmd_FrontL'])) + + speed_FrontL.append(float(row['speed_FrontL'])) + speed_FrontR.append(float(row['speed_FrontR'])) + speed_RearL.append(float(row['speed_RearL'])) + speed_RearR.append(float(row['speed_RearR'])) +fp.close() + + +#plt.plot(x,y, label='Loaded from file!') +scattersize=5 +scatteralpha=0.1 +plt.scatter(x,speed_FrontL, s=scattersize, alpha=scatteralpha, label="speed_FrontL") +plt.scatter(x,speed_FrontR, s=scattersize, alpha=scatteralpha, label="speed_FrontR") +plt.scatter(x,speed_RearL, s=scattersize, alpha=scatteralpha, label="speed_RearL") +plt.scatter(x,speed_RearR, s=scattersize, alpha=scatteralpha, label="speed_RearR") +plt.xlabel('cmd') +plt.ylabel('speed') +plt.title('Interesting Graph\nCheck it out') +plt.legend() +plt.show() + + +''' +with open(,'r') as csvfile: + plots = csv.reader(filter(lambda row: row[0]!='#', csvfile), delimiter=',') + for row in plots: + x.append(float(row[0])) + y.append(float(row[1])) + +plt.plot(x,y, label='Loaded from file!') +plt.xlabel('x') +plt.ylabel('y') +plt.title('Interesting Graph\nCheck it out') +plt.legend() +plt.show() +''' + From dfc53c494b5982b77f3ab9d7f346a11f6d193f74 Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 17:52:58 +0200 Subject: [PATCH 03/11] improve csv error check --- .../logdata_visualization.pde | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/logdata_visualization/logdata_visualization.pde b/logdata_visualization/logdata_visualization.pde index 51b722b..d167cef 100644 --- a/logdata_visualization/logdata_visualization.pde +++ b/logdata_visualization/logdata_visualization.pde @@ -8,7 +8,7 @@ TODO int vis_textsize=12; //copy from Visualization class //String logfile_name="LOG00008_rumfahren_neu.TXT"; -String logfile_name="LOG00184_20210515b_Video_Treff_FreewheelCurrentFix.TXT"; +String logfile_name="20210524_Phaseadvance_enabled.TXT"; int columnCount=20; boolean useSerial=false; //false=read from csv log, true=read from serial port @@ -109,12 +109,25 @@ void setup() { serialString = null; }else{ logdata = loadTable(logfile_name, "header, csv"); + float _checkTimeLast=-100; + + for (int i=0; i < logdata.getRowCount();i++) { + float _checkTimeCurrent=logdata.getRow(i).getFloat("time")*1000; + if (logdata.getRow(i).getString(0).charAt(0)=='#') { //check if row starts with # (comment) - print("removed row:"); - for (int is=0;is< logdata.getRow(i).getColumnCount(); is++) + print("removed comment:"); + for (int is=0;is< logdata.getRow(i).getColumnCount() && logdata.getRow(i).getString(is) != null; is++) { - print(logdata.getRow(i).getString(is)+","); + print(", "+logdata.getRow(i).getString(is)); + } + println(); + logdata.removeRow(i); + }else if (Float.isNaN(_checkTimeCurrent) || _checkTimeCurrent <= _checkTimeLast) { //check if time is plausible + print("removed unplausible time:"); + for (int is=0;is< logdata.getRow(i).getColumnCount() && logdata.getRow(i).getString(is) != null; is++) + { + print(", "+logdata.getRow(i).getString(is)); } println(); logdata.removeRow(i); @@ -122,7 +135,7 @@ void setup() { } logdata_start_time=logdata.getRow(0).getFloat("time"); logdata_end_time = logdata.getRow(logdata.getRowCount()-1).getFloat("time"); - println("loaded "+logdata.getRowCount()+" lines. Times: "+logdata_start_time+"s to "+logdata_end_time+"s"); + println("loaded "+logdata.getRowCount()+" lines. Starttime: "+logdata_start_time+"s , Endtime: "+logdata_end_time+"s"); } PVector pos_vis_cmd = new PVector(100,200); @@ -237,9 +250,11 @@ void setup() { if (showTimeline) { + println("Preparing Timeline"); tl = new Timeline(30,height-30, width-30*2, 28); tl.setTimes(logdata_start_time,logdata_end_time); tl.generatePreview(logdata); + println("Timeline prepared"); } } @@ -305,18 +320,18 @@ void draw() { current_FrontL=row.getFloat("current_FrontL"); current_FrontR=row.getFloat("current_FrontR"); current_RearL=row.getFloat("current_RearL"); - current_RearR=row.getFloat("current_RearR"); - speed_FrontL=row.getInt("speed_FrontL"); - speed_FrontR=row.getInt("speed_FrontR"); - speed_RearL=row.getInt("speed_RearL"); - speed_RearR=row.getInt("speed_RearR"); - temp_Front=row.getFloat("temp_Front"); - temp_Rear=row.getFloat("temp_Rear"); - vbat_Front=row.getFloat("vbat_Front"); - vbat_Rear=row.getFloat("vbat_Rear"); - currentAll=row.getFloat("currentAll"); - throttle=row.getInt("throttle"); - brake=row.getInt("brake"); + current_RearR=row.getFloat("current_RearR"); + speed_FrontL=row.getInt("speed_FrontL"); + speed_FrontR=row.getInt("speed_FrontR"); + speed_RearL=row.getInt("speed_RearL"); + speed_RearR=row.getInt("speed_RearR"); + temp_Front=row.getFloat("temp_Front"); + temp_Rear=row.getFloat("temp_Rear"); + vbat_Front=row.getFloat("vbat_Front"); + vbat_Rear=row.getFloat("vbat_Rear"); + currentAll=row.getFloat("currentAll"); + throttle=row.getInt("throttle"); + brake=row.getInt("brake"); if (loopmillis-nextTimeData>1000 && nextTimeData>lastTimeData) {//too much behind long _timestep=nextTimeData-lastTimeData; //approximated time step From e11defbd88c12bcff44997ae8773cce956287f46 Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 18:40:23 +0200 Subject: [PATCH 04/11] add pause button --- .../logdata_visualization.pde | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/logdata_visualization/logdata_visualization.pde b/logdata_visualization/logdata_visualization.pde index d167cef..0e6be05 100644 --- a/logdata_visualization/logdata_visualization.pde +++ b/logdata_visualization/logdata_visualization.pde @@ -59,14 +59,17 @@ int timeoffset=0; //for moving timeslider Table logdata; int nextID=0; //next row number to be displayed long lastTimeData=0; //last time data received -long nextTimeData=0; //time of nextID row -long lastTimeMillis=0; //local time -long nextTimeMillis=0; //local time +int nextTimeData=0; //time of nextID row +int lastTimeMillis=0; //local time +int nextTimeMillis=0; //local time boolean newdataforced=true; int dataErrorCount=0; +boolean running=true; +int timePaused=0; + //Data from log int cmd_FrontL; int cmd_FrontR; @@ -260,7 +263,12 @@ void setup() { } void draw() { - long loopmillis=millis()-timeoffset; + int loopmillis=0; + if (running) { + loopmillis=millis()-timeoffset; + }else{ //paused + loopmillis=timePaused-timeoffset; + } if (useSerial) { if (serial.available() > 0) { @@ -308,7 +316,7 @@ void draw() { TableRow row = logdata.getRow(nextID); lastTimeData=nextTimeData; - nextTimeData=(long)(logdata.getRow(nextID+1).getFloat("time")*1000); //get time and convert from seconds to ms + nextTimeData=(int)(logdata.getRow(nextID+1).getFloat("time")*1000); //get time and convert from seconds to ms lastTimeMillis=nextTimeMillis; nextTimeMillis=loopmillis; @@ -405,8 +413,14 @@ void draw() { if (!useSerial && loopmillis-lastTimeData>(nextTimeData-lastTimeData)*10) { //deviation too high when reading from file text("ff="+(loopmillis-lastTimeData)+"ms", 5+75*2,12); //show warning } - + if (!running) { + fill(color(255,100,100)); + } text("t="+(loopmillis/1000.0)+"s", 5,12); + text("nextID="+nextID, 5,12+12); + fill(color(200,200,200)); + + text(""+(dataErrorCount)+" errors", 5+70*3,12); @@ -421,12 +435,15 @@ void draw() { void keyPressed() { if (key == CODED) { - /*if (keyCode == UP) { - fillVal = 255; - } else if (keyCode == DOWN) { - fillVal = 0; - } - */ + if (!running) { //paused + if (keyCode == LEFT) { + + } else if (keyCode == RIGHT) { + timeoffset=timePaused-nextTimeData; + } + } + + } else { //println("key="+keyCode); if (keyCode==82) { //82=r @@ -435,6 +452,14 @@ void keyPressed() { nextID=0; newdataforced=true; } + if (keyCode == 32) { + if (running) { //switching from running to pause + timePaused=millis(); + }else{ //unpause + timeoffset=+millis()-timePaused+timeoffset; + } + running=!running; + } } } From 0165b0b5df2147194edb7800c0c0146534394373 Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 18:58:49 +0200 Subject: [PATCH 05/11] swap speed measured left and right --- controller_teensy/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller_teensy/src/main.cpp b/controller_teensy/src/main.cpp index 744650c..154791d 100644 --- a/controller_teensy/src/main.cpp +++ b/controller_teensy/src/main.cpp @@ -116,8 +116,8 @@ typedef struct{ //match this struct to hoverboard-firmware SerialFeedback struct uint16_t start; int16_t cmd1; int16_t cmd2; - int16_t speedR_meas; //right speed is negatie when driving forward int16_t speedL_meas; //left speed is positive when driving forward + int16_t speedR_meas; //right speed is negatie when driving forward int16_t batVoltage; int16_t boardTemp; int16_t curL_DC; //negative values are current consumed. positive values mean generated current From ea80d1b381a2b93ed6f0fef5c88f330dc48006aa Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 18:59:18 +0200 Subject: [PATCH 06/11] swap speed measured left and right --- hoverboard-firmware-hack-foc-serial-esc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoverboard-firmware-hack-foc-serial-esc b/hoverboard-firmware-hack-foc-serial-esc index 898898a..ea1a7ae 160000 --- a/hoverboard-firmware-hack-foc-serial-esc +++ b/hoverboard-firmware-hack-foc-serial-esc @@ -1 +1 @@ -Subproject commit 898898a63c6b494e0525df8a8ed2da98fcd5cdb1 +Subproject commit ea1a7ae0575bb4106cf9fa2fc44bfd1d4b0a8ea4 From 2f252f594af9ee77efe78dbf5bf0886426150de0 Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 18:59:47 +0200 Subject: [PATCH 07/11] fix long and int --- logdata_visualization/Timeline.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logdata_visualization/Timeline.pde b/logdata_visualization/Timeline.pde index 06c3a03..f3c53bd 100644 --- a/logdata_visualization/Timeline.pde +++ b/logdata_visualization/Timeline.pde @@ -47,7 +47,7 @@ public class Timeline while ((cID+1 < logdata.getRowCount()) && ( t2 > (logdata.getRow(cID+1).getFloat("time")))) { //while endtime not reached TableRow row = logdata.getRow(cID); - nextTimeData=(long)(logdata.getRow(cID+1).getFloat("time")*1000); //get time and convert from seconds to ms + nextTimeData=(int)(logdata.getRow(cID+1).getFloat("time")*1000); //get time and convert from seconds to ms lastTimeMillis=nextTimeMillis; From cc69ccec65546bccb2358ef3ce8e49682dd66828 Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 19:14:24 +0200 Subject: [PATCH 08/11] fix skipping checking removed rows --- logdata_visualization/logdata_visualization.pde | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logdata_visualization/logdata_visualization.pde b/logdata_visualization/logdata_visualization.pde index 0e6be05..d355ecf 100644 --- a/logdata_visualization/logdata_visualization.pde +++ b/logdata_visualization/logdata_visualization.pde @@ -8,7 +8,7 @@ TODO int vis_textsize=12; //copy from Visualization class //String logfile_name="LOG00008_rumfahren_neu.TXT"; -String logfile_name="20210524_Phaseadvance_enabled.TXT"; +String logfile_name="20210524b_Phaseadvance10_freewheeling.TXT"; int columnCount=20; boolean useSerial=false; //false=read from csv log, true=read from serial port @@ -125,7 +125,7 @@ void setup() { print(", "+logdata.getRow(i).getString(is)); } println(); - logdata.removeRow(i); + logdata.removeRow(i); i--; }else if (Float.isNaN(_checkTimeCurrent) || _checkTimeCurrent <= _checkTimeLast) { //check if time is plausible print("removed unplausible time:"); for (int is=0;is< logdata.getRow(i).getColumnCount() && logdata.getRow(i).getString(is) != null; is++) @@ -133,7 +133,7 @@ void setup() { print(", "+logdata.getRow(i).getString(is)); } println(); - logdata.removeRow(i); + logdata.removeRow(i); i--; } } logdata_start_time=logdata.getRow(0).getFloat("time"); From da09098a14a2337f4ffc2fb84dded32cb457dd0d Mon Sep 17 00:00:00 2001 From: Fisch Date: Mon, 24 May 2021 19:15:13 +0200 Subject: [PATCH 09/11] update repo to current firmware --- hoverboard-firmware-hack-foc-serial-esc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoverboard-firmware-hack-foc-serial-esc b/hoverboard-firmware-hack-foc-serial-esc index ea1a7ae..40eb491 160000 --- a/hoverboard-firmware-hack-foc-serial-esc +++ b/hoverboard-firmware-hack-foc-serial-esc @@ -1 +1 @@ -Subproject commit ea1a7ae0575bb4106cf9fa2fc44bfd1d4b0a8ea4 +Subproject commit 40eb4916f98447f23c28058e31cd867cbc8f0e6c From cc74c5ac636c43f6ce48c183f6aacdde3ff82336 Mon Sep 17 00:00:00 2001 From: Fisch Date: Fri, 28 May 2021 18:24:14 +0200 Subject: [PATCH 10/11] add speed and trip distance log --- controller_teensy/src/main.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/controller_teensy/src/main.cpp b/controller_teensy/src/main.cpp index 154791d..43f24e3 100644 --- a/controller_teensy/src/main.cpp +++ b/controller_teensy/src/main.cpp @@ -57,6 +57,14 @@ unsigned long brake_ok_time=0; bool error_throttle_outofrange=false; bool error_brake_outofrange=false; +unsigned long last_feedback=0; //time millis at last feedback receive + +float meanSpeedms=0; +float trip=0; //trip distance in meters +float wheelcircumference=0.5278; //wheel diameter in m. 8.4cm radius -> 0.084m*2*Pi + + + #define PIN_START A9 #define PIN_LED_START 2 //Enginge start led @@ -285,6 +293,13 @@ void loop() { updateMotorparams(motorparamsRear,FeedbackRear); } + if (newData2 || newData3) { //when new data arrived from one controller + float _meanRPM=FeedbackFront.speedL_meas-FeedbackFront.speedR_meas+FeedbackRear.speedL_meas-FeedbackRear.speedR_meas; + float meanSpeedms=_meanRPM*wheelcircumference/60.0; // Units: 1/min * m / 60s + trip+=abs(meanSpeedms)* (millis()-last_feedback) / 1000.0; + last_feedback=millis(); + } + if (loopmillis - last_adcread > ADCREADPERIOD) { //read teensy adc and filter last_adcread=loopmillis; @@ -341,9 +356,9 @@ float filterMedian(int16_t* values) { void writeLogHeader(HardwareSerial &SerialRef) { SerialRef.print("time,cmd_FrontL,cmd_FrontR,cmd_RearL,cmd_RearR,"); SerialRef.print("current_FrontL,current_FrontR,current_RearL,current_RearR,"); - SerialRef.print("speed_FrontL,speed_FrontR,speed_RearL,speed_RearR,"); + SerialRef.print("rpm_FrontL,rpm_FrontR,rpm_RearL,rpm_RearR,"); SerialRef.print("temp_Front,temp_Rear,vbat_Front,vbat_Rear,"); - SerialRef.println("currentAll,throttle,brake"); + SerialRef.println("currentAll,throttle,brake,speed,trip"); } void writeLog(HardwareSerial &SerialRef, unsigned long time, MotorParameter &mpfront, MotorParameter &mprear, SerialFeedback &fbfront, SerialFeedback &fbrear, float currentAll, int16_t throttle, int16_t brake) @@ -371,7 +386,9 @@ void writeLog(HardwareSerial &SerialRef, unsigned long time, MotorParameter &mpf SerialRef.print(currentAll,3); SerialRef.print(","); //invert. positive current is drive current SerialRef.print(throttle); SerialRef.print(","); - SerialRef.print(brake); SerialRef.println(); + SerialRef.print(brake); SerialRef.print(","); + SerialRef.print(meanSpeedms); SerialRef.print(","); // m/s + SerialRef.print(trip); SerialRef.println(); //in m } void writeLogComment(HardwareSerial &SerialRef, unsigned long time, String msg) From be17a015447819d9615e6cd08a8d1c2b2d6f2c19 Mon Sep 17 00:00:00 2001 From: Fisch Date: Fri, 28 May 2021 18:24:32 +0200 Subject: [PATCH 11/11] reduce proportional braking strength --- controller_teensy/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller_teensy/src/main.cpp b/controller_teensy/src/main.cpp index 43f24e3..1c01163 100644 --- a/controller_teensy/src/main.cpp +++ b/controller_teensy/src/main.cpp @@ -482,7 +482,7 @@ void failChecks() { void sendCMD() { #define MINIMUM_CONSTANT_CMD_REDUCE 1 //reduce cmd every loop by this constant amount when freewheeling/braking - #define BREAK_CMDREDUCE_PROPORTIONAL 500 //cmd gets reduced by an amount proportional to brake position (ignores freewheeling). cmd_new-=BREAK_CMDREDUCE_PROPORTIONAL / second @ full brake. with BREAK_CMDREDUCE_CONSTANT=1000 car would stop with full brake at least after a second (ignoring influence of brake current control/freewheeling) + #define BREAK_CMDREDUCE_PROPORTIONAL 100 //cmd gets reduced by an amount proportional to brake position (ignores freewheeling). cmd_new-=BREAK_CMDREDUCE_PROPORTIONAL / second @ full brake. with BREAK_CMDREDUCE_CONSTANT=1000 car would stop with full brake at least after a second (ignoring influence of brake current control/freewheeling) int16_t cmdreduce_constant=map(brake_pos,0,1000,0,(int16_t)(BREAK_CMDREDUCE_PROPORTIONAL*SENDPERIOD/1000)); //reduce cmd value every cycle #define STARTBREAKCURRENT 5 //Ampere. at what point to start apply brake proportional to brake_pos. for everything above that cmd is reduced by freewheel_break_factor #define STARTBREAKCURRENT_OFFSET 0.1 //offset start point for breaking, because of reading fluctuations around 0A. set this slightly above idle current reading