bitdump / BLHeli

BLHeli for brushless ESC firmware
GNU General Public License v3.0
1.94k stars 1.09k forks source link

500Hz PWM Input and start point #135

Open Jimqjp opened 8 years ago

Jimqjp commented 8 years ago

I am working on a project of brushless update of Walkera Master CP.

The receiver of Master CP outputs 500 Hz PWM for both main and tail motors.

The first step is to upgrade the main motor. I am using a SuperSimple 30A ESC with V14.2.

Though the manual states that the lowest PWM frequency supported is 1 kHz, it seems working with the ESC. However, instead of 0 to 100% PWM working range, the ESC accepts PWM from about 55% to 100%. Is this supposed to be, or because of the half of the PWM frequency?

The main motor can work with this, but it will not work with tail motor. The tail locking loop assumes 0 to %100 for 0 to 100% rpm.

Is there a way to fully utilize the PWM duty?

Thanks in advance.

sskaug commented 8 years ago

It sounds like the ESC detects your input signal as 1-2ms regular RC signal. Which is the intended way of detecting a 500Hz input signal. You will need to change the code if you are to use a 500Hz input signal

Jimqjp commented 8 years ago

Thank you for your reply.

For the latest version 14.4, based on 6 searched "RCP_PWM_FREQ_1KHZ" I will do the following modifications.

Do you mind to point out where I need to modify other than these?

I appreciate your help very much.


1. Line 1111: Add a 500Hz PWM .EQU before 1Khz, and shift rest numbers by one

.EQU    RCP_PWM_FREQ_0_5KHZ     =   0       ; RC pulse pwm frequency is 0.5kHz
.EQU    RCP_PWM_FREQ_1KHZ       =   1       ; RC pulse pwm frequency is 1kHz
.EQU    RCP_PWM_FREQ_2KHZ       =   2       ; RC pulse pwm frequency is 2kHz
.EQU    RCP_PWM_FREQ_4KHZ       =   3       ; RC pulse pwm frequency is 4kHz
.EQU    RCP_PWM_FREQ_8KHZ       =   4       ; RC pulse pwm frequency is 8kHz
.EQU    RCP_PWM_FREQ_12KHZ      =   5       ; RC pulse pwm frequency is 12kHz
.EQU    PGM_DIR_REV         =   6           ; Programmed direction. 0=normal, 1=reversed
.EQU    PGM_RCP_PWM_POL     =   7           ; Programmed RC pulse pwm polarity. 0=positive, 1=negative
.EQU    FULL_THROTTLE_RANGE     =   8       ; When set full throttle range is used (1000-2000us) and stored calibration values are ignored

2. Line 2279:

rcp_int_check_1kHz:
    ; Check if pwm frequency is 1kHz
    cpi I_Temp1, low(2200)          ; If below 1100us, 1kHz pwm is assumed
    ldi XL, high(2200)
    cpc I_Temp2, XL
    brcc    rcp_int_check_0_5kHz

    ldi XL, (1<<RCP_PWM_FREQ_1KHZ)
    mov I_Temp4, XL
    ldi XL, 120                 ; Set period tolerance requirement (LSB)
    mov I_Temp3, XL
    rjmp    rcp_int_restore_edge

rcp_int_check_0_5kHz:
    ; Check if pwm frequency is 0.5kHz
    cpi I_Temp1, low(4400)          ; If below 2200us, 0.5kHz pwm is assumed
    ldi XL, high(4400)
    cpc I_Temp2, XL
    brcc    rcp_int_restore_edge

    ldi XL, (1<<RCP_PWM_FREQ_0_5KHZ)
    mov I_Temp4, XL
    ldi XL, 240                 ; Set period tolerance requirement (LSB)
    mov I_Temp3, XL

rcp_int_restore_edge:

3. Line 2363

sbrc    Flags3, RCP_PWM_FREQ_1KHZ       ; Is RC input pwm frequency 1kHz?
rjmp    rcp_int_pwm_divide              ; Yes - branch forward

lsr I_Temp2                             ; No - 1kHz. Divide by 2 again
ror I_Temp1

sbrc    Flags3, RCP_PWM_FREQ_0_5KHZ     ; Is RC input pwm frequency 0.5kHz?

4. Line 2652:

ldi XL, ((1<<RCP_PWM_FREQ_0_5KHZ)+(1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))

5. Line 5639:

addi XL, ((1<<RCP_PWM_FREQ_0_5KHZ)+(1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))        

6. Line 5661:

andi XH, !((1<<RCP_PWM_FREQ_0_5KHZ)+(1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ)+(1<<RCP_PWM_FREQ_12KHZ))
Jimqjp commented 8 years ago

I successfully modified the code and my ESC accepts 500Hz PWM signal now!

The table size is limited by 8 extra value can cause compile failure. So in stead of adding another value, the table is shifted, the 12KHz is removed from the bottom and 500Hz is added to the top (0).

May be because the 500Hz pulse width is close to the pulse width of PPM (about 1ms to 2ms), once PWM is turned one, PPM signal cannot recognized. I do not expect to use both with the same setup anyway.

kiwi-craig commented 8 years ago

Hi, I 'm converting my master, any chance I could get a copy of your file ? Many Thanks

crainic@ihug.co.nz

Jimqjp commented 8 years ago

I was using Atmel Stduio 7 to build the code. I do not know how to attache file here. SO list the modified parts:

1. Line 1111: Original file (BLHeli.asm rev14.4) line number, modified file contents

.DEF    Flags3              =   R25     ; State flags. NOT reset upon init_start
.EQU    RCP_PWM_FREQ_0_5KHZ     =   0       ; RC pulse pwm frequency is 0.5kHz
.EQU    RCP_PWM_FREQ_1KHZ       =   1       ; RC pulse pwm frequency is 1kHz
.EQU    RCP_PWM_FREQ_2KHZ       =   2       ; RC pulse pwm frequency is 2kHz
.EQU    RCP_PWM_FREQ_4KHZ       =   3       ; RC pulse pwm frequency is 4kHz
.EQU    RCP_PWM_FREQ_8KHZ       =   4       ; RC pulse pwm frequency is 8kHz
.EQU    PGM_DIR_REV             =   5       ; Programmed direction. 0=normal, 1=reversed
.EQU    PGM_RCP_PWM_POL         =   6       ; Programmed RC pulse pwm polarity. 0=positive, 1=negative
.EQU    FULL_THROTTLE_RANGE     =   7       ; When set full throttle range is used (1000-2000us) and stored calibration values are ignored

2. Line 2196:

rcp_int_second_meas_pwm_freq:
    ; Prepare for next interrupt
    Rcp_Int_First XL                ; Set first edge trig
    cbr Flags2, (1<<RCP_EDGE_NO)        ; Set first edge flag
    ; Check if pwm frequency shall be measured
    sbrs    Flags0, RCP_MEAS_PWM_FREQ   ; Is measure RCP pwm frequency flag set?
    rjmp    rcp_int_fall                ; No - skip measurements

    ; Set second edge trig only during pwm frequency measurement
    Rcp_Int_Second XL               ; Set second edge trig
    Rcp_Clear_Int_Flag XL           ; Clear interrupt flag
    sbr Flags2, (1<<RCP_EDGE_NO)        ; Set second edge flag
    ; Store edge data to RAM
    sts Rcp_Edge_L, I_Temp1
    sts Rcp_Edge_H, I_Temp2
    ; Calculate pwm frequency
    lds I_Temp3, Rcp_PrePrev_Edge_L
    sub I_Temp1, I_Temp3
    lds I_Temp4, Rcp_PrePrev_Edge_H
    sbc I_Temp2, I_Temp4
    clr I_Temp4
    mov I_Temp3, Zero               ; (LSB)
    ; Check if pulse is too short
    cpi I_Temp1, low(200)           ; If pulse below 100us, not accepted
    cpc I_Temp2, Zero
    brcc    rcp_int_check_8kHz
    sts Rcp_Period_Diff_Accepted, Zero  ; Set not accepted 
    rjmp    rcp_int_store_data

rcp_int_check_8kHz:

3. Line 2283:

rcp_int_check_1kHz:
    ; Check if pwm frequency is 1kHz
    cpi I_Temp1, low(2200)          ; If below 1100us, 1kHz pwm is assumed
    ldi XL, high(2200)
    cpc I_Temp2, XL
    brcc    rcp_int_check_0_5kHz

    ldi XL, (1<<RCP_PWM_FREQ_1KHZ)
    mov I_Temp4, XL
    ldi XL, 120                 ; Set period tolerance requirement (LSB)
    mov I_Temp3, XL
    rjmp    rcp_int_restore_edge

rcp_int_check_0_5kHz:
    ; Check if pwm frequency is 0.5kHz
    cpi I_Temp1, low(4400)          ; If below 2200us, 0.5kHz pwm is assumed
    ldi XL, high(4400)
    cpc I_Temp2, XL
    brcc    rcp_int_restore_edge

    ldi XL, (1<<RCP_PWM_FREQ_0_5KHZ)
    mov I_Temp4, XL
    ldi XL, 240                 ; Set period tolerance requirement (LSB)
    mov I_Temp3, XL

rcp_int_restore_edge:

4. Line 2353:

rcp_int_fall:
    ; RC pulse edge was second, calculate new pulse length
    lds XL, Rcp_Prev_Edge_L
    sub I_Temp1, XL
    lds XL, Rcp_Prev_Edge_H
    sbc I_Temp2, XL
    sbrc    Flags3, RCP_PWM_FREQ_8KHZ       ; Is RC input pwm frequency 8kHz?
    rjmp    rcp_int_pwm_divide_done         ; Yes - branch forward

    sbrc    Flags3, RCP_PWM_FREQ_4KHZ       ; Is RC input pwm frequency 4kHz?
    rjmp    rcp_int_pwm_divide              ; Yes - branch forward

    sbrs    Flags2, RCP_PPM_ONESHOT125
    rjmp    rcp_int_fall_not_oneshot

    mov I_Temp6, I_Temp2                ; Oneshot125 - move to I_Temp5/6
    mov I_Temp5, I_Temp1
    rjmp    rcp_int_fall_check_range

rcp_int_fall_not_oneshot:
    lsr I_Temp2                     ; No - 2kHz. Divide by 2
    ror I_Temp1

    sbrc    Flags3, RCP_PWM_FREQ_2KHZ       ; Is RC input pwm frequency 2kHz?
    rjmp    rcp_int_pwm_divide              ; Yes - branch forward

    lsr I_Temp2                     ; No - 1kHz. Divide by 2 again
    ror I_Temp1

    sbrc    Flags3, RCP_PWM_FREQ_1KHZ       ; Is RC input pwm frequency 1kHz?
    rjmp    rcp_int_pwm_divide              ; Yes - branch forward

    lsr I_Temp2                     ; No - 0.5kHz. Divide by 2 again
    ror I_Temp1

    sbrc    Flags3, RCP_PWM_FREQ_0_5KHZ     ; Is RC input pwm frequency 0.5kHz?
    rjmp    rcp_int_pwm_divide              ; Yes - branch forward

    mov I_Temp6, I_Temp2                ; No - PPM. Divide by 2 (to bring range to 256) and move to I_Temp5/6
    mov I_Temp5, I_Temp1
    lsr I_Temp6
    ror I_Temp5
rcp_int_fall_check_range:

5. Line 2575:

rcp_int_limited:
    ; RC pulse value accepted
    sts New_Rcp, I_Temp1            ; Store new pulse length
    sbr Flags2, (1<<RCP_UPDATED)        ; Set updated flag
    sbrs    Flags0, RCP_MEAS_PWM_FREQ   ; Is measure RCP pwm frequency flag set?
    rjmp    rcp_int_set_timeout         ; No - skip measurements

    ldi XL, ((1<<RCP_PWM_FREQ_0_5KHZ)+(1<<RCP_PWM_FREQ_1KHZ)+(1<<RCP_PWM_FREQ_2KHZ)+(1<<RCP_PWM_FREQ_4KHZ)+(1<<RCP_PWM_FREQ_8KHZ))
    com XL
    and XL, Flags3              ; Clear all pwm frequency flags
    or  XL, I_Temp4             ; Store pwm frequency value in flags
    mov Flags3, XL
    cbr Flags2, (1<<RCP_PPM)        ; Default, flag is not set (PWM)    
    tst I_Temp4                 ; Check if all flags are cleared
    brne    rcp_int_set_timeout

    sbr Flags2, (1<<RCP_PPM)        ; Flag is set (PPM) 

rcp_int_set_timeout:
kiwi-craig commented 8 years ago

thanks, unfortunately coding is beyond capabilities with my setup at home (imac) but I can flash BLheli files from an old laptop (XP).

if you could send me your revised file to my home email I'd be grateful, there are allot of guys on RC Groups - Master CP thread who would appreciate this

crainic@ihug.co.nz

Many Thanks

Jimqjp commented 8 years ago

I am using SuperSimple 30A ESC. The complied .hex file is only good for that type. Need to build separately for each compatible ESC. This site actually pre-built all compatible .hex versions for download.

What ESC are you going to use? Maybe I can help to build the type for your ESC.

kiwi-craig commented 8 years ago

Jimgjp

okay, right.

I'm running with the DYS BL30A, same file used as the DYS BL20A

http://www.banggood.com/DYS-BL30A-Mini-30A-BLHeli-ESC-OPTO-2-6s-for-RC-Multicopter-p-975799.html?cur_warehouse=CN

The DYS 20 / 30 units seem decent, and compact as well.

Many Thanks

Craig

On 13/06/2016 14:56, Jimqjp wrote:

I am using SuperSimple 30A ESC. The complied .hex file is only good for that type. Need to build separately for each compatible ESC.

What ESC are you going to use? Maybe I can help to build the type for your ESC.

You are receiving this because you commented. Reply to this email directly, view it on GitHub [1], or mute the thread [2].

Links:

[1] https://github.com/bitdump/BLHeli/issues/135#issuecomment-225480022 [2] https://github.com/notifications/unsubscribe/AS94QKADb0hxe4LJmvtP0mGjVWCQooj-ks5qLMbdgaJpZM4IAfen

kiwi-craig commented 8 years ago

sorry for the confusion above DYS BL and or Afro esc seem to be the pick.

thanks

Craig

Jimqjp commented 8 years ago

DYS uses SiLabs chip, which is 8051 family. The mod is for Atmel Atmega family only.

otrofox commented 7 years ago

Hi,

Thanks so much for your work. It has inspired me to try a similar mod for my Syma X8HC, which works at 6Khz PWM.

I'm using SiLabs, but I think the code to change is the same as for Atmel chips.

I'll try to change 8Khzs code for 6Khz parameters, instead lf adding a new frequency mode. Can you please give me any advice? As far as I know, the only change to do should be:

pca_int_check_8kHz: ; Check if pwm frequency is 8kHz clr C mov A, Temp1 subb A, #low(480) ; If below 240us, 6kHz pwm is assumed mov A, Temp2 subb A, #high(480) jnc pca_int_check_4kHz clr A setb ACC.RCP_PWM_FREQ_8KHZ mov Temp4, A mov Temp3, #20 ; Set period tolerance requirement (LSB) ajmp pca_int_restore_edge_set_msb

Thanks for your help!!!