ModalAI Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Unresponsive polling from FPV Racing 4-in-1 ESC

    Ask your questions right here!
    2
    4
    17
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      shawn_ricardo
      last edited by shawn_ricardo

      Hello,

      I'm calibrating the FPV Racing 4-in-1 ESC on the VOXL2 itself (not connected directly to the ESC via FTDI). When performing either the calibration (./voxl-esc-calibrate.py --id 2 --pwm-min 10 --pwm-max 95) or the power ramp test (./voxl-esc-spin.py --id 2 --power 100 --ramp-time 3.0 --timeout 5.0 --enable-plot 1 --cmd-rate 250), there are several instances were the y-values do not change for seconds

      The behavior is more readily seen in the power ramp test, since commanded values are continuous, whereas in the calibration test, a specific value is commanded for a given time period. Still, you can see in the calibration results that y value doesn't change any for far longer than the default step duration of 0.5 seconds

      Looking at the calibrate script, seems that the returned values from:

      • esc.get_current()
      • esc.get_power()
      • esc.get_rpm()
      • esc.get_voltage()
      • esc.get_temperature()

      are directly print to terminal, and not some other variable hanging around that maybe doesn't update.

      @Alex-Kushleyev has this behavior been seen? Any recommendations? It is difficult to tune commutation when values are not updated. The interesting pattern showing itself through repeated runs of the script is that the "duration unresponsiveness" increases as commanded power increases

      The following is output from voxl-esc scan:

      voxl2:/usr/share/modalai/voxl-esc-tools$ voxl-esc scan
      enabling bridge
      bridge enabled
      Detected Python version : 3.6.9 (default, Mar 10 2023, 16:46:00)
      [GCC 8.4.0]
      Found voxl-esc tools bin version: 1.9
      VOXL Platform: M0054
      Detected RB5 Flight, VOXL2 M0054 or M0104!
      INFO: Scanning for ESC firmware: /dev/slpi-uart-2, baud: 2000000
      Sending library name request: libslpi_qrb5165_io.so
      Sending initialization request
      INFO: ESC(s) detected on port: /dev/slpi-uart-2, baud rate: 2000000, protocol: firmware
      
      
      INFO: ESC Information:
      INFO: ---------------------
              ID         : 0
              Board      : version 42: ModalAi 4-in-1 ESC (M0138-1)
              UID        : 0x20373835464757130049002F
              Firmware   : version  39.20, hash 9c6233d6
              Bootloader : version    184, hash e1c038de
      
              ID         : 1
              Board      : version 42: ModalAi 4-in-1 ESC (M0138-1)
              UID        : 0x203738354647571300420025
              Firmware   : version  39.20, hash 9c6233d6
              Bootloader : version    184, hash e1c038de
      
              ID         : 2
              Board      : version 42: ModalAi 4-in-1 ESC (M0138-1)
              UID        : 0x20373835464757130049002A
              Firmware   : version  39.20, hash 9c6233d6
              Bootloader : version    184, hash e1c038de
      
              ID         : 3
              Board      : version 42: ModalAi 4-in-1 ESC (M0138-1)
              UID        : 0x20373835464757130042002A
              Firmware   : version  39.20, hash 9c6233d6
              Bootloader : version    184, hash e1c038de
      
      ---------------------
      successfully pinged ESCs
      disabling bridge
      Sending kill slpi command!
      bridge disabled
      

      I've also included the xml, calibration_results.html, and spin_results.html

      The motor is a Hobbyking CM X6 SE 280KV, a low KV motor.

      I am following the steps outlined in:

      • calibration.md
      • low_kv_motor_tuning.md
      • and guidance from this thread

      calibration_results.png
      spin_test.png

      Here is my XML

      <?xml version="1.0" encoding="UTF-8"?>
      
      <!-- Copyright (c) 2025 ModalAI Inc.
      
      Redistribution and use in source and binary forms, with or without
      modification, are permitted provided that the following conditions are met:
      
      1. Redistributions of source code must retain the above copyright notice,
         this list of conditions and the following disclaimer.
      
      2. Redistributions in binary form must reproduce the above copyright notice,
         this list of conditions and the following disclaimer in the documentation
         and/or other materials provided with the distribution.
      
      3. Neither the name of the copyright holder nor the names of its contributors
         may be used to endorse or promote products derived from this software
         without specific prior written permission.
      
      4. The Software is used solely in conjunction with devices provided by
         ModalAI Inc.
      
      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
      LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      POSSIBILITY OF SUCH DAMAGE.
      
      For a license to use on non-ModalAI hardware, please contact license@modalai.com -->
      
      <EscParameters>
      
        <IdParams>
          <param name="id"        value="127"/> <!-- ID assignment is fixed. Do not change -->
          <param name="dir"       value="2"/>   <!-- 0=fwd, 1=rev, 2=fwd id-based, 3=rev id-based -->
        </IdParams>
      
        <UartParams>
          <param name="protocol_version" value="2"/>          <!-- reserved for future use -->
          <param name="input_mode"       value="0"/>          <!-- reserved for future use -->
          <param name="baud_rate"        value="2000000"/>    <!-- communication bit rate -->
          <param name="char_timeout_ns"  value="0"/>          <!-- not used -->
          <param name="cmd_timeout_ns"   value="100000000"/>  <!-- timeout for incoming commands before ESC will stop the motor -->
        </UartParams>
      
        <TuneParams>
          <param name="pwm_frequency"       value="48000"/>  <!-- 24Khz is the only option for Tmotor board to reduce Mosfet switching losses -->
          <param name="vbat_nominal_mv"     value="22200"/>  <!-- used for sanity checking and limiting of voltage-dependent funcions -->
          <param name="num_cycles_per_rev"  value="14"/>     <!-- number of pole pairs in the motor. used for converting electrical frequency to mechanical rpm -->
          <param name="min_rpm"             value="577"/>    <!-- minimum RPM that will be attempted, otherwise capped -->
          <param name="max_rpm"             value="4626"/>   <!-- maximum RPM that will be attempted, otherwise capped -->
          <param name="min_pwm"             value="100"/>    <!-- cap for minimum power to be ever applied. max is 999 -->
          <param name="max_pwm"             value="999"/>    <!-- cap for maximum power to be ever applied. max is 999 -->
          <param name="pwm_vs_rpm_curve_a0" value="784.739381143"/>  <!-- this is actually motor_voltage vs rpm curve.. using legacy naming -->
          <param name="pwm_vs_rpm_curve_a1" value="2.77418758498"/> <!--  -->
          <param name="pwm_vs_rpm_curve_a2" value="0.000345512059078"/>
          <param name="kp"                  value="50"/>    <!-- 100... RPM controller proportional gain -->
          <param name="ki"                  value="10"/>    <!-- 10.. RPM controller proportional gain -->
          <param name="max_kpe"             value="100"/>    <!-- maximum proportional erorr term (max is 999) -->
          <param name="max_kie"             value="50"/>    <!-- maximum integral error term (max is 999) -->
          <param name="max_rpm_delta"       value="5000"/>    <!-- cap for maximum rpm error used in RPM controller -->
      
          <param name="spinup_type"         value="1"/>      <!-- 0: traditional, 1: sinusoidal . Sinusoidal is not yet implemented on this board-->
          <param name="spinup_power"        value="150"/>    <!-- power used to during spin-up procedure (out of 999)-->
          <param name="latch_power"         value="120"/>    <!-- power used during latching stage of spin-up (out of 999)-->
          <param name="spinup_power_ramp"   value="8"/>      <!-- it will take ( 4096 / (spinup_power_ramp*10000) ) seconds to ramp sinusoidal start-up power from 0 to spinup_power. Not yet implemented. -->
          <param name="spinup_rpm_target"   value="800"/>    <!-- Desired RPM at the end of the sinusoidal spin-up procedure. Not yet implemented. -->
          <param name="spinup_time_ms"      value="1000"/>   <!-- Duration of the sinusoidal spin-up procedure. Not yet implemented. -->
          <param name="spinup_bemf_comp"    value="1"/>      <!-- 0: disable, 1:enable back-emf compensation in sinusoidal spin-up procedure. -->
          <param name="motor_kv"            value="280"/>    <!-- kV value of the motor. used in back-emf compensation during spin-up. -->
      
          <param name="min_num_cross_for_closed_loop" value="50"/>  <!-- exit latching mode of fixed power after this number of zero crossings -->
          <param name="protection_stall_check_rpm" value="500"/>    <!-- if motor spins below this RPM, stall check will trigger and stop / restart the motor -->
      
          <param name="protection_current_soft_limit_a" value="0"/> <!-- over-current soft limit (will limit power to try to stay under the current limit). Only applicable to ESCs with individual current sensing -->
          <param name="protection_trip_current_a" value="0"/>       <!-- over-current hard limit (will stop the motor) after 100ms. Only applicable to ESCs with individual current sensing -->
      
          <param name="brake_to_stop"       value="0"/>             <!-- apply brake when stopping motor (or not) -->
          <param name="stall_timeout_ns"    value="20000000"/>      <!-- after spin-up, if no zero crossing is not detected for this amount of time, motor is considered stalled -->
          <param name="require_reset_if_stalled"      value="0"/>   <!-- require sending an array of zero commands to reset before next spin-up, if motor stalled -->
      
          <!--one beep-->
          <param name="tone_freqs"          value="[200, 200,240, 200, 0,0,0,0, 0,0,0,0]"/> <!-- 200 is 2000Hz, max 255 -->
          <param name="tone_durations"      value="[20,  0,  20,  0, 0,0,0,0, 0,0,0,0]"/> <!-- duration of each tone in units of 10 milli-seconds. Poor naming!!! -->
          <param name="tone_powers"         value="[50,  0,  50,  0, 0,0,0,0, 0,0,0,0]"/> <!-- max is 255 -->
      
      
          <param name="dt_threshold_ns"       value="150000"/>      <!-- during start up, ignore inter-commutation times less than this val, probably noise -->
          <param name="max_dt_ns"             value="2500000"/>     <!-- min and max values for time between two commutations. these are used as caps -->
          <param name="min_dt_ns"             value="50000"/>
          <param name="dt_bootstrap_ns"       value="2000000"/>     <!-- filter bootstrap value for commutation dt during start up -->
      
          <param name="spinup_stall_dt_ns"    value="6000000"/>     <!-- during spin-up, if no zero crossing is not detected for this amount of time, motor is considered stalled -->
          <param name="spinup_stall_check_ns" value="30000000"/>    <!-- time after beginning of spinup to start checking for spinup stall -->
      
          <param name="alignment_time_ns"     value="0"/>           <!-- alignment time before spin-up. not really needed -->
          <param name="timing_advance"        value="60"/>          <!-- positive value -> earlier commutation. helps avoid de-syncs if demag time is long. default: 60. absolute maximum is 90 -->
          <param name="sense_advance"         value="10"/>          <!-- positive value -> delayed zero crossing sensing. default: 20. absolute maximum is 45 (not recommended above 20)-->
      
          <param name="demag_timing"          value="1"/>           <!-- zero crossing timing tweak. default: 0. set to 1 for low kV (< 500kV) motors to reduce chance of de-sync. do not set to 1 if RPM can exceed 100K eRPM -->
        </TuneParams>
      </EscParameters>
      
      Alex KushleyevA 1 Reply Last reply Reply Quote 0
      • Alex KushleyevA
        Alex Kushleyev ModalAI Team @shawn_ricardo
        last edited by

        @shawn_ricardo , your issue looks identical to this one : https://forum.modalai.com/topic/4476/esc-calibration-help

        When the values seem to be "stuck" and don't change for seconds, does the actual motor behavior also reflect that? in other words, does the motor RPM also get stuck? You would definitely hear the uneven transitions during the calibration procedure.

        I have not had a chance to look at it, but there must be something up when running this script on VOXL2.

        Can you please try the same calibration script after setting the voxl2 cpu to perf mode? voxl-set-cpu-mode perf. I will also try it.

        Do you have a chance to try the calibration procedure while connecting the ESC to a Linux PC?

        Alex

        S 1 Reply Last reply Reply Quote 0
        • S
          shawn_ricardo @Alex Kushleyev
          last edited by

          Hi @Alex-Kushleyev

          For the ramp test, the motor doesn't get stuck. I hear a smooth transition up to 95% power and the motor maintains that power for the timeout duration. Same for the calibration script. I hear the motor change speeds at the default duration of 0.5 seconds.

          Regarding the post's comment:
          "We calibrate from 10% - 95% per the instructions, but no matter the ESC/motor, the calibration process maxes out at around 60 - 70% power (11k - 13k RPM)."

          This happens because the loop in the script is tracking a variable that is set / updated only from within the script itself, rather than from esc.get_power(). When I updated the script to set the current power variable to the value returned by esc.get_power(), the loop actually goes to the max power specified. The downside here is that, given my current setup, although the command power seems to be accepted and implemented by the ESC, the returned value from esc.get_power() is not correctly reflected -- so the physical motor is spinning faster than the ESC is reporting and the loop continues to command the user defined MAX_POWER for a long time until the ESC catches up. I suppose one could update the loop to only increase commanded values once the returned value is verified, but for debugging purposes, the above is sufficient.

          I believe I did have the voxl in perf mode, but will try setting testing it again. As well as on a linux PC (i'll be using the same WSL as in the linked post, so maybe i could just try a container on the voxl with updated python)

          Alex KushleyevA 1 Reply Last reply Reply Quote 0
          • Alex KushleyevA
            Alex Kushleyev ModalAI Team @shawn_ricardo
            last edited by Alex Kushleyev

            @shawn_ricardo , thank you for the details. i will investigate shortly.

            Also, just wanted to mention, your motor kV is very low, i don't think we have tested anything below ~400. So you should definitely put the ESC through sufficient testing to ensure that there are no de-syncs. For the tests, i definitely recommend running them from your desktop / laptop, as you get more instant feedback (plots) and can iterate much more quickly. If you need more details for the testing, let me know, but obviously the first step is to get a good calibration done. The step tests, etc, are listed in the low kv tuning guide.

            Alex

            1 Reply Last reply Reply Quote 0
            • First post
              Last post
            Powered by NodeBB | Contributors