eFlexPWM with DMA working fine on some pins but does not work at all on some other

gplante

Member
Hi,

To make a long story short, I borrowed some code from a project ( https://github.com/jacqu/teensyshot ) to generate a DSHOT signal. I'm currently adapting this code for my own project using a Teensy 4.1 board. Note that DSHOT protocol is used to control a motor via an ESC (Electronic Speed Controller), but this is not really important for my question here.

So, using eFlexPWM / DMA to generate the signal on an output pin, it works fine with some pins however it does not work at all with some other pins. So, I'm not able to figure out why it is not working with some pins.

So, I created the simplest as possible program below to demonstrate the problem. If you run the program below as is, you will see that the signal is correctly generated on pin 4. If you comment out the line #define TEST_PIN_4 then uncomment line #define TEST_PIN_22, you will see that the program works fine as well but that time generating signal on pin 22.

Now, if you comment out back line #define TEST_PIN_22 and you uncomment line #define TEST_PIN_2 , #define TEST_PIN_3 or #define TEST_PIN_9 (uncomment only one line pin at a time) you will see that signal is not generated on those pins.

So, is somebody could help me to understand what I missed? It should work fine on those pins too.


Code:
// Minimal test program to create a dshot 600 protocol signal. (for a support request purpose)
// Some code borrowed from https://github.com/jacqu/teensyshot

#include <Arduino.h>
#include "DMAChannel.h"

#define F_TMR F_BUS_ACTUAL // teensy 4

#define DSHOT_DMA_LENGTH          18            // Number of steps of one DMA sequence (the two last values are zero)
#define DSHOT_DMA_MARGIN          2             // Number of additional bit duration to wait until checking if DMA is over
#define DSHOT_DSHOT_LENGTH        16            // Number of bits in a DSHOT sequence
#define DSHOT_BT_DURATION         1670          // Duration of 1 DSHOT600 bit in ns
#define DSHOT_LP_DURATION         1250          // Duration of a DSHOT600 long pulse in ns
#define DSHOT_SP_DURATION         625           // Duration of a DSHOT600 short pulse in ns
#define DSHOT_MAX_VALUE           2047          // Maximum DSHOT value

const uint16_t DSHOT_short_pulse  = uint64_t(F_TMR) * DSHOT_SP_DURATION / 1000000000;     // DSHOT short pulse duration (nb of F_BUS periods)
const uint16_t DSHOT_long_pulse   = uint64_t(F_TMR) * DSHOT_LP_DURATION / 1000000000;     // DSHOT long pulse duration (nb of F_BUS periods)
const uint16_t DSHOT_bit_length   = uint64_t(F_TMR) * DSHOT_BT_DURATION / 1000000000;     // DSHOT bit duration (nb of F_BUS periods)

// **************************************
// Begin define test pins
//
// Uncomment only one TEST_PIN_? at a time below to do a test with that specific pin.
#define TEST_PIN_4   //Works fine
//#define TEST_PIN_22  //Works fine
//#define TEST_PIN_2   //Does not work ??? Help needed with that pin
//#define TEST_PIN_3   //Does not work ??? Help needed with that pin
//#define TEST_PIN_9   //Does not work ??? Help needed with that pin
//
// End define test pins
// **************************************

#ifdef TEST_PIN_4   
 volatile uint8_t  	       my_eFlexPWM_pin               = 4; // Output pin: 4 = EMC_06 = FLEXPWM2_PWM0_A ALT1 //See Table 10-1. Muxing Options at page 297
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM2; // FLEXPWM2_PWM0_A -> FLEXPWM2
 volatile uint8_t          my_eFlexPWM_submodule         = 0;               // FLEXPWM2_PWM0_A -> _PWM0 = submodule 0
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 0;               // FLEXPWM2_PWM0_A -> _A    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 1;               // ALT1 -> 1
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = DMAMUX_SOURCE_FLEXPWM2_WRITE0; //Table 4-3. DMA MUX Mapping, page 52
#endif

#ifdef TEST_PIN_22 
 volatile uint8_t  	       my_eFlexPWM_pin               = 22; // Output pin: 22 = AD_B1_08 = FLEXPWM4_PWM0_A ALT1 //See Table 10-1. Muxing Options at page 298
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM4; // FLEXPWM4_PWM0_A -> FLEXPWM4
 volatile uint8_t          my_eFlexPWM_submodule         = 0;               // FLEXPWM4_PWM0_A -> _PWM0 = submodule 0
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 0;               // FLEXPWM2_PWM0_A -> _A    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 1;               // ALT1 -> 1
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = DMAMUX_SOURCE_FLEXPWM4_WRITE0; //Table 4-3. DMA MUX Mapping, page 52
#endif

#ifdef TEST_PIN_2 
 volatile uint8_t  	       my_eFlexPWM_pin               = 2; // Output pin: 2 = EMC_04 = FLEXPWM4_PWM2_A ALT1 //See Table 10-1. Muxing Options at page 298
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM4; // FLEXPWM4_PWM2_A -> FLEXPWM4
 volatile uint8_t          my_eFlexPWM_submodule         = 2;               // FLEXPWM4_PWM2_A -> _PWM2 = submodule 2
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 0;               // FLEXPWM4_PWM2_A -> _A    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 1;               // ALT1 -> 1
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = DMAMUX_SOURCE_FLEXPWM4_WRITE0; //Table 4-3. DMA MUX Mapping, page 52
#endif

#ifdef TEST_PIN_3 
 volatile uint8_t  	       my_eFlexPWM_pin               = 3; // Output pin: 3 = EMC_05 = FLEXPWM4_PWM2_B ALT1 //See Table 10-1. Muxing Options at page 298
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM4; // FLEXPWM4_PWM2_B -> FLEXPWM4
 volatile uint8_t          my_eFlexPWM_submodule         = 2;               // FLEXPWM4_PWM2_B -> _PWM2 = submodule 2
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 1;               // FLEXPWM4_PWM2_B -> _B    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 1;               // ALT1 -> 1
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = DMAMUX_SOURCE_FLEXPWM4_WRITE0; //Table 4-3. DMA MUX Mapping, page 52
#endif

#ifdef TEST_PIN_9
 volatile uint8_t  	       my_eFlexPWM_pin               = 9; // Output pin: 9 = B0_11 = FLEXPWM2_PWM2_B ALT2 //See Table 10-1. Muxing Options at page 298
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM2; // FLEXPWM2_PWM2_B -> FLEXPWM2
 volatile uint8_t          my_eFlexPWM_submodule         = 2;               // FLEXPWM2_PWM2_B -> _PWM2 = submodule 2
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 1;               // FLEXPWM2_PWM2_B -> _B    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 2;               // ALT2 -> 2
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = DMAMUX_SOURCE_FLEXPWM2_WRITE0; //Table 4-3. DMA MUX Mapping, page 52
#endif

// DMA objects
DMAChannel          myDMAChannel;

// DMA data
volatile uint16_t   DSHOT_dma_data[DSHOT_DMA_LENGTH] = { 0 };

elapsedMillis sinceChange;
uint16_t      lastDshotCommandSent = 0;

//  Send the DSHOT signal to the configured channel
int DSHOT_send( uint16_t dshotCommand) {
  int       j;
  int       requestTelemetry = 0;
  uint16_t  data;

  // Initialize DMA buffer  
  // Compute the packet to send
  // 11 first MSB = command
  // 12th MSB = telemetry request
  // 4 LSB = CRC
  data = ( dshotCommand << 5 ) | ( requestTelemetry << 4 ); 
  data |= ( ( data >> 4 ) ^ ( data >> 8 ) ^ ( data >> 12 ) ) & 0x0f;
  
  // Generate DSHOT timings corresponding to the packet
  for ( j = 0; j < DSHOT_DSHOT_LENGTH; j++ )  {
    if ( data & ( 1 << ( DSHOT_DSHOT_LENGTH - 1 - j ) ) ) {
      DSHOT_dma_data[j] = DSHOT_long_pulse;
    } else {
      DSHOT_dma_data[j] = DSHOT_short_pulse;
    }
  }
  
  // Clear error flag on  DMA channel  
  myDMAChannel.clearError( );
  
  return 0;
}


void setup() {
  // Configure pin on the board as DSHOT output
  // This pin is configured as eFlexPWM (FLEXPWMn) PWM output  
  *(portConfigRegister( my_eFlexPWM_pin ))  = my_eFlexPWM_mux_alt;

  // Configure eFlexPWM module and submodule for PWM generation
  // --- submodule specific registers ---
  // INIT: initial counter value
  // VAL0: PWM_X compare value
  // VAL1: counter max value
  // VAL2: must be 0 for edge-aligned PWM
  // VAL3: PWM_A compare value
  // VAL4: must be 0 for edge-aligned PWM
  // VAL5: PWM_B compare value
  // OCTRL: invert polarity of PWMq FLEXPWM_SMOCTRL_POLq
  // DMAEN: FLEXPWM_SMDMAEN_VALDE to enable DMA
  // --- module specific registers ---
  // OUTEN: output enable for submodule n and PWM q FLEXPWM_OUTEN_PWMq_EN( 1 << n )
  
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].INIT = 0;
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL0 = 0;
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL1 = DSHOT_bit_length;
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL2 = 0;
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL3 = 0;
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL4 = 0;
  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL5 = 0;

  if ( my_eFlexPWM_submodule_channel == 2 ) { //A=0, B=1, X=2 
    (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].OCTRL = FLEXPWM_SMOCTRL_POLX;
    (*my_eFlexPWM_module).OUTEN |= FLEXPWM_OUTEN_PWMX_EN(1 << my_eFlexPWM_submodule);
  } else if ( my_eFlexPWM_submodule_channel == 1 ) { //A=0, B=1, X=2 
    (*my_eFlexPWM_module).OUTEN |= FLEXPWM_OUTEN_PWMB_EN(1 << my_eFlexPWM_submodule);
  } else { //A=0, B=1, X=2 
    (*my_eFlexPWM_module).OUTEN |= FLEXPWM_OUTEN_PWMA_EN(1 << my_eFlexPWM_submodule);      
  }

  (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].DMAEN = FLEXPWM_SMDMAEN_VALDE;
  
  // DMA channel is linked to a unique eFlexPWM submodule
  // DMA channel is triggered by independant hardware events
  
  myDMAChannel.sourceBuffer( DSHOT_dma_data, DSHOT_DMA_LENGTH * sizeof( uint16_t ) );
  if ( my_eFlexPWM_submodule_channel  == 2 ) {
    myDMAChannel.destination( (uint16_t&) (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL0 );
  } else if ( my_eFlexPWM_submodule_channel  == 1 ) {
    myDMAChannel.destination( (uint16_t&) (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL5 );
  } else {
    myDMAChannel.destination( (uint16_t&) (*my_eFlexPWM_module).SM[my_eFlexPWM_submodule].VAL3 );      
  }
  myDMAChannel.triggerAtHardwareEvent( my_eFlexPWM_mux_dma_source );
  myDMAChannel.enable( );  

  DSHOT_send(lastDshotCommandSent);
  
}

void loop() {
  if (sinceChange > 1000) { //Just change the dshot signal each second to see the signal changing on my scope.
   if (lastDshotCommandSent == 0) {
     lastDshotCommandSent = 2047; //Command 2047 = Motor 100% Throttle
   } else {
     lastDshotCommandSent = 0; //Command 0 = Motor stop
   }

   DSHOT_send(lastDshotCommandSent); 
   sinceChange = 0;
  }
}

Thank you.
 
Wrong DMA Source
Code:
#ifdef TEST_PIN_2 
 volatile uint8_t  	       my_eFlexPWM_pin               = 2; // Output pin: 2 = EMC_04 = FLEXPWM4_PWM2_A ALT1 //See Table 10-1. Muxing Options at page 298
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM4; // FLEXPWM4_PWM2_A -> FLEXPWM4
 volatile uint8_t          my_eFlexPWM_submodule         = 2;               // FLEXPWM4_PWM2_A -> _PWM2 = submodule 2
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 0;               // FLEXPWM4_PWM2_A -> _A    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 1;               // ALT1 -> 1
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = [COLOR="#FF0000"]DMAMUX_SOURCE_FLEXPWM4_WRITE2[/COLOR]; //Table 4-3. DMA MUX Mapping, page 52
#endif

#ifdef TEST_PIN_3 
 volatile uint8_t  	       my_eFlexPWM_pin               = 3; // Output pin: 3 = EMC_05 = FLEXPWM4_PWM2_B ALT1 //See Table 10-1. Muxing Options at page 298
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM4; // FLEXPWM4_PWM2_B -> FLEXPWM4
 volatile uint8_t          my_eFlexPWM_submodule         = 2;               // FLEXPWM4_PWM2_B -> _PWM2 = submodule 2
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 1;               // FLEXPWM4_PWM2_B -> _B    = A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 1;               // ALT1 -> 1
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = [COLOR="#FF0000"]DMAMUX_SOURCE_FLEXPWM4_WRITE2[/COLOR]; //Table 4-3. DMA MUX Mapping, page 52
#endif

I only tried 2 and 3 (and 4)
 
Hi,

Thank you for your quick reply! It worked :)

Is there a reason why I cannot use DMAMUX_SOURCE_FLEXPWM4_WRITE0 ?

I thought that I could use DMAMUX_SOURCE_FLEXPWM4_WRITE0, DMAMUX_SOURCE_FLEXPWM4_WRITE1, DMAMUX_SOURCE_FLEXPWM4_WRITE2 or DMAMUX_SOURCE_FLEXPWM4_WRITE3.

Best regards,
 
It is my understanding that:
DMAMUX_SOURCE_FLEXPWM4_WRITE0 is for FlexPWM4 Write to Sub-module 0
...
DMAMUX_SOURCE_FLEXPWM4_WRITE2 is for FlexPWM4 Write to Sub-module 2
...
DMAMUX_SOURCE_FLEXPWM4_WRITE4 is for FlexPWM4 Write to Sub-module 4

And from the table in pwm.c file
Code:
	{1, M(4, [COLOR="#FF0000"]2[/COLOR]), 1, 1},  // FlexPWM4_2_A   2  // EMC_04
	{1, M(4, [COLOR="#FF0000"]2[/COLOR]), 2, 1},  // FlexPWM4_2_B   3  // EMC_05
And your own settings, it looked like both of these were sub-module 2
 
Did you manage to use the code for an ESC? I can't get it to be used with BLHELI_S. Previously I was using an arduino with dshot which worked fine so I assume it must be an implementation detail.
 
Yes I finally was able to output 4 dshot signal for my 4 motors (drone) using Teensy 4.1 and eFlexPWM and DMA.
The ESC is a 4-in-1 with BLHELI_32.

Teensy, eFlexPWM and DMA and all this stuff is new for me so I hard hard time to figure out how it works despite the fact that I had a very good DSHOT/Teensy starting point here (Thanks to these guys):
https://github.com/jacqu/teensyshot

I had to read the Teensy 4.1 documentation (DMA/eFlexPWM part) several times and I do not understand it at 100% yet however my code seams to work fine now. You can have a look at my code if you want however it is not over yet. I'm just working on it at part time. I'm currently developing my own flight controller software (just for fun) for a drone using a Teensy 4.1 board. Look at files gpf_dshot.h and gpf_dshot.cpp for the DSHOT part. My code is located here:
https://github.com/gplante/gpflight

Hope it will help you.

P.S.: Almost all my comments are in French in my code however you do not need to look at my comments to understand how it works.
 
Ha, funnily enough I was googling your username hoping to find a GitHub repo with working code, found yours but noticed it hasn't been updated in a while. Glad it's there now!
Is there anything significantly different in the dshot part as compared to what's been posted here? My esc doesn't arm with that code. I am running a BLHeli_S esc with a Teensy 4.1. Did you step up the output voltage of the pins of the teensy?
 
Small update: managed to get it work by increasing the DMA length and consequently increasing the margin. Any idea why that is? Also; I am trying to use Pin 7 (gpio_b1_01). According to the NXP doc, this is to be used with FLEXPWM1_PWM3_B and ALT6. However, the corresponding motor does not arm or move. Any idea why?
 
Small update: managed to get it work by increasing the DMA length and consequently increasing the margin. Any idea why that is? Also; I am trying to use Pin 7 (gpio_b1_01). According to the NXP doc, this is to be used with FLEXPWM1_PWM3_B and ALT6. However, the corresponding motor does not arm or move. Any idea why?

Might help to know what your settings are? That if we go off of the same stuff like was mentioned on the first posting, it might be something like:
Code:
#ifdef TEST_PIN_7
 volatile uint8_t  	       my_eFlexPWM_pin               = 7; // Output pin: 7 = B1_1 = FLEXPWM1_PWMB03
 volatile IMXRT_FLEXPWM_t *my_eFlexPWM_module            = &IMXRT_FLEXPWM1; 
 volatile uint8_t          my_eFlexPWM_submodule         = 3;
 volatile uint8_t  	       my_eFlexPWM_submodule_channel = 1;               //  A=0, B=1, X=2 
 volatile uint8_t  	       my_eFlexPWM_mux_alt           = 6;
 volatile uint8_t  	       my_eFlexPWM_mux_dma_source    = DMAMUX_SOURCE_FLEXPWM1_WRITE3;
#endif
 
Last edited:
That is exactly what I have. For some reason, it arms and responds to throttle commands now. But, when I send 0, it periodically rotates for a split second only to stop again. As if it would receive impulses. Sending 48 (minimum throttle, as opposed to motor stop) works fine, the motor does not rotate.
 
Last edited:
Small update: managed to get it work by increasing the DMA length and consequently increasing the margin. Any idea why that is? Also; I am trying to use Pin 7 (gpio_b1_01). According to the NXP doc, this is to be used with FLEXPWM1_PWM3_B and ALT6. However, the corresponding motor does not arm or move. Any idea why?

Hi again, do not increase DSHOT_DMA_LENGTH, it is not the way to do. Probably that your ESC does not support DSHOT600 and the example above was made for DSHOT600. Try with DSHOT 150 instead. This is the exact same code except the width of the pulse is longer. So, just change this code:

Code:
#define DSHOT_BT_DURATION         1670          // Duration of 1 DSHOT600 bit in ns
#define DSHOT_LP_DURATION         1250          // Duration of a DSHOT600 long pulse in ns
#define DSHOT_SP_DURATION         625           // Duration of a DSHOT600 short pulse in ns

For This code:

Code:
#define DSHOT_DURATION_MULTIPLIER_600 1 //DSHOT 600
#define DSHOT_DURATION_MULTIPLIER_300 2 //DSHOT 300
#define DSHOT_DURATION_MULTIPLIER_150 4 //DSHOT 150

#define DSHOT_DURATION_MULTIPLIER     DSHOT_DURATION_MULTIPLIER_150 //DSHOT 150 is enough for this project

#define DSHOT_BT_DURATION         (1670 * DSHOT_DURATION_MULTIPLIER)  // Duration of 1 DSHOT bit in ns
#define DSHOT_LP_DURATION         (1250 * DSHOT_DURATION_MULTIPLIER)  // Duration of a DSHOT long pulse in ns
#define DSHOT_SP_DURATION         (625 * DSHOT_DURATION_MULTIPLIER)   // Duration of a DSHOT short pulse in ns

About pin 7, I did not test it since there is plenty other pins to use. Try with a different pin to see if your code work. If you want to stick with pin 7, I think that DMAMUX_SOURCE_FLEXPWM1_WRITE3 can also be shared by some other pins. Maybe this is the problem you are facing. Be sure to not use pins that are using the same DMA source.
 
I've tried all three DSHOT protocols. Furthermore, I used to run DSHOT300 or DSHOT600 with an arduino with this very ESC. I have tried DSHOT150, 300 and 600 without success unless I change the DMA_LENGTH. EDIT: Just went back to test with the Pins you used and DSHOT150 with the original DMA_LENGTH of 18. No success
 
Sorry I am only seeing bits and pieces here, like the simple test program, but not the whole thing.
So for example I don't know what all you do with setting up the PWM. Nor which other pins you might be using.

Specifically Pin 7 and Pin 8 use the same module/sub-module. So they are using the same timer. So anything you change in the underlying timing for one of them will effect the other.
 
I haven't provided much code because I copied the code provided here, there's nothing else going on. No other pins are used.
 
That is exactly what I have. For some reason, it arms and responds to throttle commands now. But, when I send 0, it periodically rotates for a split second only to stop again. As if it would receive impulses. Sending 47 (minimum throttle, as opposed to motor stop) works fine, the motor does not rotate.

47 is not minimum throttle.
48 is minimum throttle.
2047 is maximum throttle.
You can have a look here for more information: https://brushlesswhoop.com/dshot-and-bidirectional-dshot/
 
Sorry, typo. I meant to say 48. But still, it is confusing that the motor jerks a bit when on 0, right? Anyways, considering that you suggested that changing the DMA_LENGTH is not the way to go, I think I should address that problem first. However, I can't think of anything else to try and fix it. I've tried different pins all three DSHOT protocols
 
I only tried my code with my 4-in-1 ESC that I have here. This ESC is flashed with BLHELI_32. So, I cannot guarantee that my code will work with BLHELI_S since I neved tested it :-(
 
Out of curiosity, which ESC do you use? I also have a 4-in-1 ESC. Also, could you help me understand what the DMA_LENGTH is set for? Why does it not equal the DSHOT_LENGTH? How is the extra 2 bits determined? Thank you for all the help!
 
This is a 4-in-1 SkyStars KO60:
https://skystars-rc.com/product/ko60-blheli32-60a-3-6s-esc-support-128k-dshot1200-4-in-1-esc/

Each frame of the DSHOT protocol has 16 bits. However, the DSHOT prococol requires a pause between each frame. So the pause in this case here is 2 bits long. This is why the DMA_LENGTH is 18 bits. Since the last 2 bits as 0, the signal will be LOW for 2 bits long between each frame. For testing purpose, maybe you could increase the DMA_LENGTH from 18 to 19 or 20 or even higher if you want. However do not decrease it since a minimum pause is required between each frame.

Good luck!
 
I've tried all three DSHOT protocols. Furthermore, I used to run DSHOT300 or DSHOT600 with an arduino with this very ESC. I have tried DSHOT150, 300 and 600 without success unless I change the DMA_LENGTH. EDIT: Just went back to test with the Pins you used and DSHOT150 with the original DMA_LENGTH of 18. No success

I also experienced the same problem. I tried a lot, and unfortunately, my Teensy Dshot did not work with BLHELI_S ESC. However, it worked perfectly with Arduino UNO for DSHOT150, 300, and 600, without success with the same ESC. Earlier, I thought my code might be wrong, but since you used the code that worked with BLHELI 32 and not with BLHELI_S, it suggests that there is a problem with BLHELI_S. After reading your discussions with others, I think there may be an issue with the voltage level that BLHELI_S can accept. Since Arduino UNO provides 5 V and Teensy provides a 3.3-volt output for the same.
 
Back
Top