5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
标题:
做了个无刷电调(附原理图和程序)
[打印本页]
作者:
zhxzsh
时间:
2008-12-22 19:43
标题:
做了个无刷电调(附原理图和程序)
(, 下载次数: 1110)
上传
点击文件名下载附件
控制用一片Amega8l控制,电流输出用IRF640和IRF9640,用电位器控制转速,图为控制硬盘电机.
纯属好玩.
(, 下载次数: 185)
上传
点击文件名下载附件
(, 下载次数: 153)
上传
点击文件名下载附件
(, 下载次数: 134)
上传
点击文件名下载附件
[
本帖最后由 zhxzsh 于 2008-12-23 20:32 编辑
]
作者:
wangfine1975
时间:
2008-12-22 19:47
还你厉害
作者:
baohjopg
时间:
2008-12-22 20:32
可否上电路来让后辈学习学习。
作者:
fujianshu
时间:
2008-12-22 21:28
可否上电路学习学习。
作者:
zjzd
时间:
2008-12-22 21:55
可否上电路学习学习 支持楼主
作者:
billylei
时间:
2008-12-22 22:11
关注学习贴!~ 支持LZ上电路图 家里的废弃硬盘很多
作者:
gamegang
时间:
2008-12-23 00:38
强人 羡慕啊 给我电路图我也搞不定
作者:
驼铃
时间:
2008-12-24 19:43
不错,支持!楼主勤俭持家啊,电阻的脚留的挺长,剪下来还可以用。:loveliness:
你用什么软件啊,有几个文件打不开?
[
本帖最后由 驼铃 于 2008-12-24 19:46 编辑
]
作者:
lpqingq86
时间:
2008-12-25 12:34
牛 ....
作者:
icefire
时间:
2008-12-25 14:04
改自德国人的设计,由PPM 控制转速改为电位器控制。
作者:
icefire
时间:
2008-12-25 14:06
原电路图
作者:
icefire
时间:
2008-12-25 14:11
标题:
原始代码 -第1部分
;**** **** **** **** ****
;
;Die Benutzung der Software ist mit folgenden Bedin×gen verbunden:
;
;1. Da ich alles kostenlos zur Verfü×g stelle, gebe ich keinerlei Garantie
; und übernehme auch keinerlei Haftung für die Folgen der Benutzung.
;
;2. Die Software ist ausschließlich zur privaten Nutzung bestimmt. Ich
; habe nicht geprüft, ob bei gewerblicher Nutzung irgendwelche Patentrechte
; verletzt werden oder sonstige rechtliche Einschränkungen vorliegen.
;
;3. Jeder darf Änderungen vornehmen, z.B. um die Funktion seinen Bedürfnissen
; anzupassen oder zu erweitern. Ich würde mich freuen, wenn ich weiterhin als
; Co-Autor in den Unterlagen erscheine und mir ein Link zur entprechenden Seite
; (falls vorhanden) mitgeteilt wird.
;
;4. Auch nach den Änderungen sollen die Software weiterhin frei sein, d.h. kostenlos bleiben.
;
;!! Wer mit den Nutzungbedin×gen nicht einverstanden ist, darf die Software nicht nutzen !!
;
; October 2004
; autor: Bernhard Konze
; email: bernhard.konze(at)versanet.de
;
;**** **** **** **** ****
; Device
;
;**** **** **** **** ****
.include "m8def.inc"
;
;**** **** **** **** ****
;**** **** **** **** ****
; fuses must be set to internal calibrated oscillator = 8 mhz
;**** **** **** **** ****
;**** **** **** **** ****
.equ UART_CONTROL = 1
.equ UART_FULL = 1
.equ RC_PULS = 0
.include "flea.inc"
.equ CHANGE_TIMEOUT = 0x32
.equ CHANGE_TOT_LOW = 0x28
.equ POWER_RANGE = 100 ; full range of tcnt0 setting
.equ MIN_DUTY = 10 ; no power
.equ NO_POWER = 256-MIN_DUTY ; (POWER_OFF)
.equ MAX_POWER = 256-POWER_RANGE ; (FULL_POWER)
.equ defaultTIMEOUT = 32000
.equ compScanTIMEOUT = 48000
.equ T1STOP = 0x00
.equ T1CK8 = 0x02
.equ EXT0_DIS = 0x00 ; disable ext0int
.if RC_PULS == 1
.equ EXT0_EN = 0x40 ; enable ext0int
.else
.equ EXT0_EN = 0x00 ; disable ext0int
.endif
.equ MIN_RC_PULS = 1100 ; µs (or lower) = NO_POWER
;**** **** **** **** ****
; Register Definitions
.def i_sreg = r1 ; status register save in interrupts
.def tcnt0_power_on = r2 ; timer0 counts nFETs are switched on
.def tcnt0_change_tot = r3 ; when zero, tcnt0_power_on is changed by one (inc or dec)
.def TCNT1X = r4 ; upper 8bit timer1 (software-) register
.def uart_cnt = r5
.def tcnt0_pwron_next = r6
.def start_rcpuls_l = r7
.def start_rcpuls_h = r8
.def new_rcpuls_l = r9
.def new_rcpuls_h = r10
.def rcpuls_timeout = r11
.equ RCP_TOT = 100
.def current_err = r12 ; counts consecutive current errors
.equ CURRENT_ERR_MAX = 3 ; performs a reset after MAX errors
.def sys_control = r13
.def temp1 = r16 ; main temporary
.def temp2 = r17 ; main temporary
.def temp3 = r18 ; main temporary
.def temp4 = r19 ; main temporary
.def i_temp1 = r20 ; interrupt temporary
.def i_temp2 = r21 ; interrupt temporary
.def i_temp3 = r22 ; interrupt temporary
.def state0 = r23 ; state flags
.equ OCT1_PENDING = 0 ; if set, output compare interrunpt is pending
.equ UB_LOW = 1 ; set if accu voltage low
.equ I_pFET_HIGH = 2 ; set if over-current detect
.equ GET_STATE = 3 ; set if state is to be send
.equ C_FET = 4 ; if set, C-FET state is to be changed
.equ A_FET = 5 ; if set, A-FET state is to be changed
; if neither 1 nor 2 is set, B-FET state is to be changed
.equ I_OFF_CYCLE = 6 ; if set, current off cycle is active
.equ EVAL_UB = 7 ; if set, next PWM on should look for power
.def state1 = r24 ; state flags
.equ POWER_OFF = 0 ; switch fets on disabled
.equ FULL_POWER = 1 ; 100% on - don't switch off, but do OFF_CYCLE working
.equ CALC_NEXT_OCT1 = 2 ; calculate OCT1 offset, when wait_OCT1_before_switch is called
.equ RC_PULS_UPDATED = 3 ; new rc-puls value available
.equ EVAL_RC_PULS = 4 ; if set, new rc puls is evaluated, while waiting for OCT1
.equ EVAL_SYS_STATE = 5 ; if set, overcurrent and undervoltage are checked
.equ EVAL_I_pFET = 6 ; if set, next PWM on should look for current
.equ T1OVFL_FLAG = 7 ; each timer1 overflow sets this flag - used for voltage + current watch
;rfu .def yyy r25
; here the XYZ registers are placed ( r26-r31)
; ZH = new_duty ; PWM destination
;**** **** **** **** ****
; RAM Definitions
.equ tcnt1_sav_l = 0x0060 ; actual 24-bit timer1 value
.equ tcnt1_sav_h = 0x0061
.equ tcnt1_sav_x = 0x0062
.equ last_tcnt1_l = 0x0063 ; last 24-bit timer1 value
.equ last_tcnt1_h = 0x0064
.equ last_tcnt1_x = 0x0065
.equ wt_comp_scan_l = 0x0066 ; time from switch to comparator scan
.equ wt_comp_scan_h = 0x0067
.equ wt_FET_switch_l = 0x0068 ; time from zero-crossing to switch of the appropriate FET
.equ wt_FET_switch_h = 0x0069
.equ OCT1_high = 0x006a
.equ uart_data = 0x0070 ; only for debug requirements
;**** **** **** **** ****
; ATmega8 interrupts
;.equ INT0addr=$001 ; External Interrupt0 Vector Address
;.equ INT1addr=$002 ; External Interrupt1 Vector Address
;.equ OC2addr =$003 ; Output Compare2 Interrupt Vector Address
;.equ OVF2addr=$004 ; Overflow2 Interrupt Vector Address
;.equ ICP1addr=$005 ; Input Capture1 Interrupt Vector Address
;.equ OC1Aaddr=$006 ; Output Compare1A Interrupt Vector Address
;.equ OC1Baddr=$007 ; Output Compare1B Interrupt Vector Address
;.equ OVF1addr=$008 ; Overflow1 Interrupt Vector Address
;.equ OVF0addr=$009 ; Overflow0 Interrupt Vector Address
;.equ SPIaddr =$00a ; SPI Interrupt Vector Address
;.equ URXCaddr=$00b ; USART Receive Complete Interrupt Vector Address
;.equ UDREaddr=$00c ; USART Data Register Empty Interrupt Vector Address
;.equ UTXCaddr=$00d ; USART Transmit Complete Interrupt Vector Address
;.equ ADCCaddr=$00e ; ADC Interrupt Vector Address
;.equ ERDYaddr=$00f ; EEPROM Interrupt Vector Address
;.equ ACIaddr =$010 ; Analog Comparator Interrupt Vector Address
;.equ TWIaddr =$011 ; Irq. vector address for Two-Wire Interface
;.equ SPMaddr =$012 ; SPM complete Interrupt Vector Address
;.equ SPMRaddr =$012 ; SPM complete Interrupt Vector Address
;-----bko-----------------------------------------------------------------
;**** **** **** **** ****
.cseg
.org 0
;**** **** **** **** ****
;-----bko-----------------------------------------------------------------
; reset and interrupt jump table
rjmp reset
.if RC_PULS == 1
rjmp ext_int0
.else
nop ; int0
.endif
nop ; ext_int1
nop ; t2oc_int
nop ; t2ovfl_int
nop ; icp1
rjmp t1oca_int
nop ; t1ocb_int
rjmp t1ovfl_int
rjmp t0ovfl_int
nop ; spi_int
nop ; urxc
nop ; udre
.if UART_CONTROL == 1
.if UART_FULL == 1
rjmp utxc
.else
nop ; utxc
.endif
.else
nop ; utxc
.endif
; not used nop ; adc_int
; not used nop ; eep_int
; not used nop ; aci_int
; not used nop ; wire2_int
; not used nop ; spmc_int
version: .db "bkf101"
;-----bko-----------------------------------------------------------------
; init after reset
reset: ldi temp1, high(RAMEND) ; stack = RAMEND
out SPH, temp1
ldi temp1, low(RAMEND)
out SPL, temp1
; portB - all FETs off
ldi temp1, INIT_PB ; PORTB initially holds 0x00
out PORTB, temp1
ldi temp1, DIR_PB
out DDRB, temp1
; portC reads comparator inputs
ldi temp1, INIT_PC
out PORTD, temp1
ldi temp1, DIR_PC
out DDRD, temp1
; portD reads rc-puls + AIN0 ( + RxD, TxD for debug )
ldi temp1, INIT_PD
out PORTD, temp1
ldi temp1, DIR_PD
out DDRD, temp1
; timer0: PWM + beep control = 0x02 ; start timer0 with CK/8 (1µs/count)
ldi temp1, 0x02
out TCCR0, temp1
; timer1: commutation control = 0x02 ; start timer1 with CK/8 (1µs/count)
ldi temp1, T1CK8
out TCCR1B, temp1
; reset state flags
clr state0
clr state1
; power off
rcall switch_power_off
; reset rc puls timeout
ldi temp1, RCP_TOT
mov rcpuls_timeout, temp1
.if UART_CONTROL == 1
ldi ZH,high(version*2)
ldi ZL,low(version*2)
;**** UART Initialization ****
ldi temp1, 0 ; set to 38400baud (8MHz)
out UBRRH, temp1
ldi temp1, 12
out UBRRL, temp1
ldi temp1, 0x18
out UCSRB, temp1 ; enable rx+tx - no interrupts !
in temp1, UDR ; clear possibly pending rxc
lpm
adiw ZL,1 ;increment Z-pointer
mov temp1, r0 ; b
rcall send_byte
.endif
rcall wait260ms ; wait a while
rcall wait260ms
.if UART_CONTROL == 1
lpm
adiw ZL,1 ;increment Z-pointer
mov temp1, r0 ; k
rcall send_byte
.endif
复制代码
作者:
icefire
时间:
2008-12-25 14:12
标题:
第2部分
rcall beep328ms ; signal ready
.if UART_CONTROL == 1
lpm
adiw ZL,1 ;increment Z-pointer
mov temp1, r0 ; o
rcall send_byte
lpm
adiw ZL,1 ;increment Z-pointer
mov temp1, r0 ; (1st number)
rcall send_byte
.endif
control_start: ; init variables
ldi temp1, CHANGE_TIMEOUT
mov tcnt0_change_tot, temp1
ldi temp1, NO_POWER
mov tcnt0_power_on, temp1
ldi temp1, 0 ; reset error counters
mov current_err,temp1
mov sys_control, temp1
; init registers and interrupts
ldi temp1, (1<<<
out TIFR, temp1 ; clear TOIE1,OCIE1A & TOIE0
out TIMSK, temp1 ; enable TOIE1,OCIE1A & TOIE0 interrupts
.if UART_CONTROL == 1
lpm
adiw ZL,1 ;increment Z-pointer
mov temp1, r0 ; (2nd number)
rcall send_byte
.endif
sei ; enable all interrupts
.if RC_PULS == 1
; init rc-puls
ldi temp1, (1<<
out MCUCR, temp1 ; set next int0 to rising edge
ldi temp1, EXT0_EN ; enable ext0int
out GIMSK, temp1
i_rc_puls1: ldi temp3, 10 ; wait for this count of receiving power off
i_rc_puls2: sbrs state1, RC_PULS_UPDATED
rjmp i_rc_puls2
mov temp1, new_rcpuls_l
mov temp2, new_rcpuls_h
cbr state1, (1<
subi temp1, low (MIN_RC_PULS) ; power off received ?
sbci temp2, high (MIN_RC_PULS)
brcc i_rc_puls1 ; no - reset counter
dec temp3 ; yes - decrement counter
brne i_rc_puls2 ; repeat until zero
cli ; disable all interrupts
rcall beep328ms ; signal: rcpuls ready
rcall beep328ms
sei ; enable all interrupts
.endif
.if UART_CONTROL == 1
lpm
adiw ZL,1 ;increment Z-pointer
mov temp1, r0 ; (3rd number)
rcall send_byte
.endif
ldi ZH, MIN_DUTY-1 ; ZH is new_duty from now
cbr state0, (1<
sbr state0, (1<
rcall calculate_next_timing_values
rcall set_default_timeout
rcall wait_OCT1_tot ; init first timeout
ldi temp1, mux_a ; set comparator multiplexer to phase A
out ADMUX, temp1
rjmp state1
.if RC_PULS == 1
;-------------------------------------------------------------------------
; external interrupt0 = rc pulse input
ext_int0: in i_sreg, SREG
clr i_temp1 ; disable extint edge may be changed
out GIMSK, i_temp1
; evaluate edge of this interrupt
in i_temp1, MCUCR
sbrs i_temp1, ISC00
rjmp falling_edge ; bit is clear = falling edge
; should be rising edge - test rc impuls level state for possible jitter
sbis PIND, rcp_in
rjmp extint1_exit ; jump, if low state
; rc impuls is at high state
ldi i_temp1, (1<
out MCUCR, i_temp1 ; set next int0 to falling edge
; get timer1 values
in i_temp1, TCNT1L
in i_temp2, TCNT1H
mov start_rcpuls_l, i_temp1
mov start_rcpuls_h, i_temp2
rjmp extint1_exit
; rc impuls is at low state
falling_edge: sbic PIND, rcp_in ; test level of rc impuls
rjmp extint1_exit ; seems to be a spike
ldi i_temp1, (1<<
out MCUCR, i_temp1 ; set next int0 to rising edge
sbrc state1, RC_PULS_UPDATED
rjmp extint1_exit
; get timer1 values
in i_temp1, TCNT1L
in i_temp2, TCNT1H
sub i_temp1, start_rcpuls_l
sbc i_temp2, start_rcpuls_h
; save impuls length
mov new_rcpuls_l, i_temp1
mov new_rcpuls_h, i_temp2
cpi i_temp1, low (2200)
ldi i_temp3, high(2200) ; test range high
cpc i_temp2, i_temp3
brsh extint1_exit ; through away
cpi i_temp1, low (800)
ldi i_temp3, high(800) ; test range low
cpc i_temp2, i_temp3
brlo extint1_exit ; through away
sbr state1, (1<
ldi i_temp1, RCP_TOT
mov rcpuls_timeout, i_temp1
; enable int1 again - also entry for spike detect
extint1_exit: ldi i_temp2, EXT0_EN
out GIMSK, i_temp2
out SREG, i_sreg
reti
.endif
;-----bko-----------------------------------------------------------------
; output compare timer1 interrupt
t1oca_int: in i_sreg, SREG
cbr state0, (1<
out SREG, i_sreg
reti
;-----bko-----------------------------------------------------------------
; overflow timer1 / happens all 65536µs
t1ovfl_int: in i_sreg, SREG
inc TCNT1X ; make a 24-bit counter
sbr state1, (1<
.if RC_PULS == 1
tst rcpuls_timeout
breq t1ovfl_99
dec rcpuls_timeout
.endif
t1ovfl_99: out SREG, i_sreg
reti
;-----bko-----------------------------------------------------------------
; timer0 overflow interrupt
t0ovfl_int: in i_sreg, SREG
.if RC_PULS == 0
sbis ACSR, ACO ; mirror ACO to rc_puls, if not used
cbi PORTD, rcp_in
sbic ACSR, ACO
sbi PORTD, rcp_in
.endif
sbrc state0, I_OFF_CYCLE
rjmp t0_on_cycle
t0_off_cycle:
; changes in PWM ?
mov i_temp1, tcnt0_power_on
mov i_temp2, tcnt0_pwron_next
cp i_temp2, i_temp1
brsh lower_pwm ; next power-on-time is lower or same
higher_pwm: dec tcnt0_change_tot ; change-timeout passed ?
brne nFET_off ; .. no
ldi i_temp2, CHANGE_TIMEOUT ; .. yes - change-timeout for more power
mov tcnt0_change_tot, i_temp2 ; reset change-timeout and decrement
dec i_temp1 ; increases power-on-time
rjmp set_next_pwm
lower_pwm: breq nFET_off ; pwm is unchanged
dec tcnt0_change_tot ; change-timeout passed ?
brne nFET_off ; .. no
ldi i_temp2, CHANGE_TOT_LOW ; .. yes - change-timeout for lower power
mov tcnt0_change_tot, i_temp2 ; reset change-timeout and increment
inc i_temp1 ; decreases power-on-time
set_next_pwm: mov tcnt0_power_on, i_temp1
nFET_off: sbr state0, (1<
; switch appropriate nFET off
sbrs state0, C_FET
rjmp test_AnFET
; C_FET is active
sbrs state1, FULL_POWER
cbi PORTB, CnFET ; Cn off
rjmp reload_t0_off_cycle
test_AnFET: sbrs state0, A_FET
rjmp switch_BnFET
; A_FET is active
switch_AnFET: sbrs state1, FULL_POWER
cbi PORTB, AnFET ; An off
rjmp reload_t0_off_cycle
; B_FET is active
switch_BnFET: sbrs state1, FULL_POWER
cbi PORTB, BnFET ; Bn off
; reload timer0 with the appropriate value
reload_t0_off_cycle:
mov i_temp1, tcnt0_power_on
subi i_temp1, -POWER_RANGE ; adi i_temp1, POWER_RANGE
com i_temp1 ; timer0 increments
out TCNT0, i_temp1
rjmp t0_int_exit
; reload timer90 + switch appropriate nFET on
t0_on_cycle: mov i_temp1, tcnt0_power_on
out TCNT0, i_temp1 ; reload t0
cbr state0, (1<
; switch appropriate nFET on
nFET_on: sbrs state0, C_FET ; is Cn choppered ?
rjmp test_AnFET_on ; .. no - test An
sbrs state1, POWER_OFF
sbi PORTB, CnFET ; Cn on
rjmp eval_power_state
test_AnFET_on: sbrs state0, A_FET ; is An choppered ?
rjmp sw_BnFET_on ; .. no - Bn has to be choppered
sbrs state1, POWER_OFF
sbi PORTB, AnFET ; An on
rjmp eval_power_state
sw_BnFET_on: sbrs state1, POWER_OFF
sbi PORTB, BnFET ; Bn on
; evaluate power state
eval_power_state:
cpi i_temp1, MAX_POWER+1
brsh not_full_power
; FULL POWER
sbr state1, (1<
cbr state1, (1<
rjmp t0_int_exit
not_full_power: cpi i_temp1, NO_POWER
brlo neither_full_nor_off
; POWER OFF
cbr state1, (1<
sbr state1, (1<
rjmp t0_int_exit
neither_full_nor_off:
cbr state1, (1<
cbr state1, (1<
t0_int_exit: out SREG, i_sreg
reti
;-----bko-----------------------------------------------------------------
; beeper: timer0 is set to 8µs/count - 2072µs period (about 500hz beep)
beep328ms: ; 128 pulses = 265ms beep
ldi temp2, 128
beep_ApBn: clr temp1
out TCNT0, temp1
cbi PORTB, ApFET ; ApFET on
sbi PORTB, BnFET ; BnFET on
beep_ApBn10: in temp1, TCNT0
cpi temp1, 32 ; 32µs on
brne beep_ApBn10
sbi PORTB, ApFET ; ApFET off
cbi PORTB, BnFET ; BnFET off
ldi temp3, 8 ; 2040µs off
beep_ApBn12: clr temp1
out TCNT0, temp1
beep_ApBn13: in temp1, TCNT0
cpi temp1, 255
brne beep_ApBn13
dec temp3
brne beep_ApBn12
dec temp2
brne beep_ApBn
; 128 periods = 261ms silence
wait260ms: ldi temp2, 128
beep_ApBn20: ldi temp3, 8
beep_ApBn21: clr temp1
out TCNT0, temp1
beep_ApBn22: in temp1, TCNT0
cpi temp1, 255
brne beep_ApBn22
dec temp3
brne beep_ApBn21
dec temp2
brne beep_ApBn20
ret
;-----bko-----------------------------------------------------------------
tcnt1_to_temp: ldi temp4, EXT0_DIS ; disable ext0int
out GIMSK, temp4
ldi temp4, T1STOP ; stop timer1
out TCCR1B, temp4
ldi temp4, T1CK8 ; preload temp with restart timer1
in temp1, TCNT1L ; - the preload cycle is needed to complete stop operation
in temp2, TCNT1H
mov temp3, TCNT1X
out TCCR1B, temp4
ret ; !!! ext0int stays disabled - must be enabled again by caller
; there seems to be only one TEMP register in the AVR
; if the ext0int interrupt falls between readad LOW value while HIGH value is captured in TEMP and
; read HIGH value, TEMP register is changed in ext0int routine
;-----bko-----------------------------------------------------------------
calculate_next_timing_values:
rcall tcnt1_to_temp
ldi temp4, EXT0_EN ; ext0int enable
out GIMSK, temp4 ; enable ext0int
sts tcnt1_sav_l, temp1
sts tcnt1_sav_h, temp2
sts tcnt1_sav_x, temp3
lds YL, last_tcnt1_l
lds YH, last_tcnt1_h
lds ZL, last_tcnt1_x
sub temp1, YL
sbc temp2, YH
sbc temp3, ZL
复制代码
作者:
icefire
时间:
2008-12-25 14:13
标题:
第3部分
; now temp-registers hold the time of 360° - means: 6 commutations
; each commutation is divided in two stages:
; a) wait for expected zero-crossing
; b) wait less than 30° and commutate
; divide by 12 would result in 0° timing ( 30° )
; *** earlier zero-crossing as it is expected, cannot be detected
; *** switch to next commutation not less than 30° - means: stall
; divide by 16 would result in 7.5 degree timing ( 30.0°-22.5° ), works !
; *** start to look for zero-crossing 7.5° earlier than it is expected
; *** switch to next commutation 7.5° earlier than 30°
; 7.5° value can be changed when setting
ldi temp4, 4 ; divide by 16
calc_OCT1_d16: lsr temp3
ror temp2
ror temp1
dec temp4
brne calc_OCT1_d16
mov YL, temp1
mov YH, temp2
mov ZL, temp3
; ZL should be zero - if not, use max value
tst temp3
brne calc_OCT1_res
sts OCT1_high, temp2
tst temp2
breq calc_OCT1_of10
subi temp1, low (defaultTIMEOUT)
sbci temp2, high(defaultTIMEOUT)
brcc calc_OCT1_res
rjmp calc_OCT1_of80
calc_OCT1_of10: mov temp2, tcnt0_power_on
asr temp2
asr temp2 ; (e7-ff)
subi temp2, 0xca ; 9c->1b and ff->33
; the maximum of allowed RPM is dependent from PWM
; therefore 134000 RPM (refered to 6 commutations each) is reached now
;temp2 rpm (6 Kom.) rpm Achse
;0x1b 138888 23148 ; full power
;0x33 73529 12254 ; lowest power
cp temp1, temp2
brcc calc_OCT1_of80
calc_OCT1_res: rcall set_default_timeout
rjmp calc_OCT1_of90
calc_OCT1_of80:
sts wt_comp_scan_l, YL ; capture compare offset for time from switch to comparator scanning
sts wt_comp_scan_h, YH
; if an other timing than 7.5° is wanted, change YL,YH here
; example (13.1°):
; lsr YH
; ror YL
; mov temp1,YL ; 1/32 + 1/64 = 1/21.33 (30°-16.9°=13.1°)
; mov temp2,YH
; lsr temp2
; ror temp1
; add YL, temp1
; adc YH, temp2
; example (10.3°):
; lsr YH
; ror YL
; mov temp1,YL ; 1/32 + 1/64 + 1/128 = 1/18.3 (30°-19.7°=10.3°)
; mov temp2,YH
; lsr temp2
; ror temp1
; add YL, temp1
; adc YH, temp2
; lsr temp2
; ror temp1
; add YL, temp1
; adc YH, temp2
; example (8.9°):
; lsr YH
; ror YL
; mov temp1,YL ; 1/32 + 1/64 + 1/128 + 1/256 = 1/17.1 (30°-21.1°=8.9°)
; mov temp2,YH
; lsr temp2
; ror temp1
; add YL, temp1
; adc YH, temp2
; lsr temp2
; ror temp1
; add YL, temp1
; adc YH, temp2
; lsr temp2
; ror temp1
; add YL, temp1
; adc YH, temp2
; example (7.5°):
; do nothing
; example (6.1°):
; mov temp1,YL ; 1/16 + 1/256 = 1/15.06 (30°-23.9°=6.1°)
; mov temp2,YH
; ldi temp4, 4 ; divide by 16
;calc_OCT1_dt: lsr temp2
; ror temp1
; dec temp4
; brne calc_OCT1_dt
; add YL, temp1
; adc YH, temp2
; example (4.7°):
; mov temp1,YL ; 1/16 + 1/128 = 1/14.22 (30°-25.3°=4.7°)
; mov temp2,YH
; ldi temp4, 3 ; divide by 8
;calc_OCT1_dt: lsr temp2
; ror temp1
; dec temp4
; brne calc_OCT1_dt
; add YL, temp1
; adc YH, temp2
sts wt_FET_switch_l, YL ; capture compare offset for time from zero-crossing to switch
sts wt_FET_switch_h, YH
calc_OCT1_of90: lds temp1, tcnt1_sav_l
lds temp2, tcnt1_sav_h
lds temp3, tcnt1_sav_x
sts last_tcnt1_l, temp1
sts last_tcnt1_h, temp2
sts last_tcnt1_x, temp3
ret
;-----bko-----------------------------------------------------------------
.if RC_PULS == 1
evaluate_rc_puls:
sbrs state1, RC_PULS_UPDATED
rjmp eval_rc_p90
mov temp1, new_rcpuls_l
mov temp2, new_rcpuls_h
cbr state1, (1<
subi temp1, low (MIN_RC_PULS)
sbci temp2, high (MIN_RC_PULS)
brcc eval_rc_p00
clr temp1
clr temp2
eval_rc_p00: lsr temp2
ror temp1
lsr temp2
ror temp1
lsr temp2
ror temp1
mov temp3, temp1
subi temp1, low (POWER_RANGE)
sbci temp2, high (POWER_RANGE)
brcs eval_rc_p10
ldi temp3, low (POWER_RANGE)
eval_rc_p10: mov ZH, temp3
eval_rc_p90: ret
.endif
;-----bko-----------------------------------------------------------------
evaluate_sys_state:
sbrs state1, T1OVFL_FLAG
rjmp eval_sys_s99
; do it not more often as every 65µs
cbr state1, (1<
; control current
eval_sys_i: sbrs state0, I_pFET_HIGH
rjmp eval_sys_i_ok
cbr state0, (1<
mov i_temp1, current_err
cpi i_temp1, CURRENT_ERR_MAX
brcc panic_exit
inc current_err
rjmp eval_sys_ub
eval_sys_i_ok: tst current_err
breq eval_sys_ub
dec current_err
; control voltage
eval_sys_ub: sbrs state0, UB_LOW
rjmp eval_sys_ub_ok
cbr state0, (1<
mov i_temp1, sys_control
cpi i_temp1, POWER_RANGE
brcc eval_sys_s99
inc sys_control
rjmp eval_sys_s99
eval_sys_ub_ok: tst sys_control
breq eval_sys_s99
dec sys_control
eval_sys_s99: rcall set_new_duty
ret
panic_exit: ; !!!!!! OVERCURRENT !!!!!!!!
cli
rjmp reset
;-----bko-----------------------------------------------------------------
wait_OCT1_before_comp_scan:
sbr state0, (1<
lds YL, wt_comp_scan_l
lds YH, wt_comp_scan_h
rcall tcnt1_to_temp
add YL, temp1
adc YH, temp2
ldi temp1, (1<<
out TIMSK, temp1
out OCR1AH, YH
out OCR1AL, YL
ldi temp1, (1<<<
out TIMSK, temp1
ldi temp4, EXT0_EN ; ext0int enable
out GIMSK, temp4 ; enable ext0int
wait_OCT1_next: sbrc state0, OCT1_PENDING
rjmp wait_OCT1_next
wait_OCT1_tot: cbi ADCSRA, ADEN ; switch to comparator multiplexed
in temp1, SFIOR
ori temp1, (1<
out SFIOR, temp1
sbr state0, (1<
rcall tcnt1_to_temp
ldi YL, low (compScanTIMEOUT)
ldi YH, high(compScanTIMEOUT)
add temp1, YL
adc temp2, YH
ldi temp3, (1<<
out TIMSK, temp3
out OCR1AH, temp2
out OCR1AL, temp1
ldi temp3, (1<<<
out TIMSK, temp3
ldi temp4, EXT0_EN ; ext0int enable
out GIMSK, temp4 ; enable ext0int
ret
;-----bko-----------------------------------------------------------------
wait_OCT1_before_switch:
sbr state0, (1<
rcall tcnt1_to_temp
lds YL, wt_FET_switch_l
lds YH, wt_FET_switch_h
add temp1, YL
adc temp2, YH
ldi temp3, (1<<
out TIMSK, temp3
out OCR1AH, temp2
out OCR1AL, temp1
ldi temp3, (1<<<
out TIMSK, temp3
ldi temp4, EXT0_EN ; ext0int enable
out GIMSK, temp4 ; enable ext0int
; don't waste time while waiting - do some controls, if indicated
OCT1_ready: sbrc state1, CALC_NEXT_OCT1
rcall calculate_next_timing_values ; calculate values while compare timer is active
.if RC_PULS == 1
sbrc state1, EVAL_RC_PULS
rcall evaluate_rc_puls
.endif
sbrc state1, EVAL_SYS_STATE
rcall evaluate_sys_state
OCT1_wait: sbrc state0, OCT1_PENDING
rjmp OCT1_wait
ret
;-----bko-----------------------------------------------------------------
set_new_duty: mov temp1, ZH
sub temp1, sys_control
brcc set_new_duty10
ldi temp1, MIN_DUTY-1
set_new_duty10: lds temp2, OCT1_high ; get actual RPM reference high
cpi temp2, 8 ; lower than 8xx? ( 1831 RPM )
brcs set_new_duty20 ; on carry - test next range
ldi temp2, POWER_RANGE ; higher than 1/4 power max ?
lsr temp2
lsr temp2
cp temp1, temp2
brcs set_new_duty30 ; on carry - not higher, no restriction
mov temp1, temp2 ; low (range1) RPM - set to 1/4 max
rjmp set_new_duty30
set_new_duty20: cpi temp2, 4 ; lower than 4xx? ( 3662 RPM )
brcs set_new_duty30 ; on carry - not lower, no restriction
ldi temp2, POWER_RANGE ; higher than 1/2 power max ?
lsr temp2
cp temp1, temp2
brcs set_new_duty30 ; on carry - not higher, no restriction
mov temp1, temp2 ; low (range2) RPM - set to 1/2 max
set_new_duty30: com temp1 ; down-count to up-count (T0)
mov tcnt0_pwron_next, temp1 ; save in next
; tcnt0_power_on is updated to tcnt0_pwron_next in acceptable steps
ret
;-----bko-----------------------------------------------------------------
set_default_timeout:
ldi temp1, NO_POWER
mov tcnt0_power_on, temp1
ldi temp1, 8
sts OCT1_high, temp1
ldi YL, low (defaultTIMEOUT)
ldi YH, high(defaultTIMEOUT)
sts wt_comp_scan_l, YL ; write default timing value
sts wt_comp_scan_h, YH
ret
;-----bko-----------------------------------------------------------------
.if UART_CONTROL == 1
read_uart: in temp1,UDR ; read data - clear rxc-flag
cpi temp1,'+'
brne read_uart_10
; do (+) job
cpi ZH, POWER_RANGE
brsh read_uart_90
rcall send_byte
inc ZH
rcall set_new_duty
rjmp read_uart_90
read_uart_10: cpi temp1,'-'
brne read_uart_20
; do (-) job
cpi ZH, MIN_DUTY-1
breq read_uart_90
rcall send_byte
dec ZH
rcall set_new_duty
rjmp read_uart_90
read_uart_20:
.if UART_FULL == 1
cpi temp1,'#'
brne read_uart_30
; do (#) job
clr XH
ldi XL, uart_data
sbr state0, (1<
ldi temp1,0x0d
rcall send_byte
ldi temp1,'#'
st X+,temp1
mov temp1,state0
rcall hex2buf
mov temp1,state1
rcall hex2buf
mov temp1,tcnt0_power_on
rcall hex2buf
lds temp1,wt_comp_scan_h
rcall hex2buf
lds temp1,wt_comp_scan_l
rcall hex2buf
ldi temp1,'-'
st X+,temp1
rjmp read_uart_90
.endif
read_uart_30: cpi temp1,'1'
brne read_uart_40
; do (1) job
ldi ZH, MIN_DUTY+0x30
rcall send_byte
rcall set_new_duty
rjmp read_uart_90
read_uart_40: cpi temp1,'2'
brne read_uart_89
; do (2) job
ldi ZH, MIN_DUTY-1
rcall send_byte
rcall set_new_duty
rjmp read_uart_90
read_uart_89: ldi temp1,'?'
rcall send_byte
read_uart_90: ret
复制代码
作者:
icefire
时间:
2008-12-25 14:14
标题:
第4部分
;-----bko-----------------------------------------------------------------
hex_out: mov temp2,temp1
swap temp1
rcall nibble_out
mov temp1,temp2
rcall nibble_out
ret
nibble_out: andi temp1,0x0f
ori temp1,0x30
cpi temp1,0x3a
brlo nibble_out_10
subi temp1,-7
nibble_out_10:
send_byte: sbi UCSRA,TXC ; clear flag
out UDR,temp1
nibble_out_20: sbis UCSRA,TXC
rjmp nibble_out_20
ret
;-----bko-----------------------------------------------------------------
.if UART_FULL == 1
hex2buf: mov temp2,temp1
swap temp1
rcall nibble2buf
mov temp1,temp2
rcall nibble2buf
ret
nibble2buf: andi temp1,0x0f
ori temp1,0x30
cpi temp1,0x3a
brlo nibble2buf_10
subi temp1,-7
nibble2buf_10: st X+,temp1
ret
;-----bko-----------------------------------------------------------------
save_state: mov temp1,state0
rcall hex2buf
mov temp1, current_err
rcall hex2buf
mov temp1, sys_control
rcall hex2buf
ldi temp1,'-'
st X+,temp1
ret
;-----bko-----------------------------------------------------------------
send_state: ldi temp1,0x0d
st X+,temp1
ldi temp1,0x0a
st X+,temp1
subi XL,uart_data
mov uart_cnt,XL
ldi XL,uart_data
sbi UCSRA, TXC ; clear flag
sbi UCSRB, TXCIE ; enable irq
ldi temp1,0x0a ; start transmission
out UDR,temp1
cbr state0, (1<
ret
;-----bko-----------------------------------------------------------------
utxc: ld i_temp1,X+
out UDR, i_temp1
dec uart_cnt
brne utxc_90
cbi UCSRB, TXCIE ; disable irq
utxc_90: reti
.endif ; UART_FULL == 1
.endif ; UART_CONTROL == 1
;-----bko-----------------------------------------------------------------
switch_power_off:
ldi temp1, NO_POWER ; lowest tcnt0_power_on value
mov tcnt0_pwron_next, temp1 ; set lowest
ldi temp1, INIT_PB ; all off
out PORTB, temp1
ldi temp1, CHANGE_TIMEOUT ; reset change-timeout
mov tcnt0_change_tot, temp1
sbr state1, (1<
ret ; motor is off
;-----bko-----------------------------------------------------------------
wait_if_spike: ldi temp1, 4
wait_if_spike2: dec temp1
brne wait_if_spike2
ret
;-----bko-----------------------------------------------------------------
; **** start closed control loop ****
; state 1 = B(p-on) + C(n-choppered) - comparator A evaluated
; out_cA changes from low to high
state1: sbrc state0, OCT1_PENDING
rjmp state1_2
; rjmp state1
rjmp s1_close
state1_2: sbic ACSR, ACO ; high ?
rjmp state1 ; .. no - loop, while low
rcall wait_if_spike ; .. yes - look for a spike
sbic ACSR, ACO ; test again
rjmp state1 ; .. is low again, was a spike
rcall wait_OCT1_before_switch
s1_close:
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall save_state
.endif
.endif
sbi PORTB, BpFET ; Bp off
sbrs state1, POWER_OFF
cbi PORTB, ApFET ; Ap on
ldi temp1, mux_b ; set comparator multiplexer to phase B
out ADMUX, temp1
rcall wait_OCT1_before_comp_scan
; state 2 = A(p-on) + C(n-choppered) - comparator B evaluated
; out_cB changes from high to low
state2: sbrc state0, OCT1_PENDING
rjmp state2_2
; rjmp state2
.if RC_PULS == 1
rcall evaluate_rc_puls
.endif
rjmp s2_close
state2_2: sbis ACSR, ACO ; low ?
rjmp state2 ; .. no
rcall wait_if_spike
sbis ACSR, ACO
rjmp state2 ; high again
sbr state1, (1<
rcall wait_OCT1_before_switch
cbr state1, (1<
cbr state0, (1<
s2_close:
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall save_state
.endif
.endif
ldi temp1, (1<<
out TIMSK, temp1 ; .. only ONE should change these values at the time
nop
cbr state0, (1< cbr state0, (1<
cbi PORTB, CnFET ; Cn off
sbrc state1, FULL_POWER
rjmp s2_switch
sbrc state0, I_OFF_CYCLE ; was power off ?
rjmp s2_done ; .. yes - futhermore work is done in timer0 interrupt
s2_switch: sbrs state1, POWER_OFF
sbi PORTB, BnFET ; Bn on
s2_done: ldi temp1, (1<<<
out TIMSK, temp1
ldi temp1, mux_c ; set comparator multiplexer to phase C
out ADMUX, temp1
rcall wait_OCT1_before_comp_scan
; state 3 = A(p-on) + B(n-choppered) - comparator C evaluated
; out_cC changes from low to high
state3: sbrc state0, OCT1_PENDING
rjmp state3_2
; rjmp state3
rjmp s3_close
state3_2: sbic ACSR, ACO
rjmp state3
rcall wait_if_spike
sbic ACSR, ACO
rjmp state3
; no job for wait_OCT1 here, calc_rc_puls is probably executed
rcall wait_OCT1_before_switch
s3_close:
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall save_state
.endif
.endif
sbi PORTB, ApFET ; Ap off
sbrs state1, POWER_OFF
cbi PORTB, CpFET ; Cp on
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall send_state
.endif
; not very much to do - look for UART input
sbic UCSRA,RXC
rcall read_uart
.endif
ldi temp1, mux_a ; set comparator multiplexer to phase A
out ADMUX, temp1
rcall wait_OCT1_before_comp_scan
; state 4 = C(p-on) + B(n-choppered) - comparator A evaluated
; out_cA changes from high to low
state4: sbrc state0, OCT1_PENDING
rjmp state4_2
; rjmp state4
rjmp s4_close
state4_2: sbis ACSR, ACO
rjmp state4
rcall wait_if_spike
sbis ACSR, ACO
rjmp state4
; this job is yet free
rcall wait_OCT1_before_switch
cbr state1, (1<
s4_close:
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall save_state
.endif
.endif
ldi temp1, (1<<
out TIMSK, temp1 ; .. only ONE should change these values at the time
nop
sbr state0, (1< cbr state0, (1<
cbi PORTB, BnFET ; Bn off
sbrc state1, FULL_POWER
rjmp s4_switch
sbrc state0, I_OFF_CYCLE ; was power off ?
rjmp s4_done ; .. yes - futhermore work is done in timer0 interrupt
s4_switch: sbrs state1, POWER_OFF
sbi PORTB, AnFET ; An on
s4_done: ldi temp1, (1<<<
out TIMSK, temp1
ldi temp1, mux_b ; set comparator multiplexer to phase B
out ADMUX, temp1
rcall wait_OCT1_before_comp_scan
; state 5 = C(p-on) + A(n-choppered) - comparator B evaluated
; out_cB changes from low to high
state5: sbrc state0, OCT1_PENDING
rjmp state5_2
; rjmp state5
rcall evaluate_sys_state
rjmp s5_close
state5_2: sbic ACSR, ACO
rjmp state5
rcall wait_if_spike
sbic ACSR, ACO
rjmp state5
sbr state1, (1<
rcall wait_OCT1_before_switch
cbr state1, (1<
s5_close:
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall save_state
.endif
.endif
sbi PORTB, CpFET ; Cp off
sbrs state1, POWER_OFF
cbi PORTB, BpFET ; Bp on
ldi temp1, mux_c ; set comparator multiplexer to phase C
out ADMUX, temp1
rcall wait_OCT1_before_comp_scan
; state 6 = B(p-on) + A(n-choppered) - comparator C evaluated
; out_cC changes from high to low
state6: sbrc state0, OCT1_PENDING
rjmp state6_2
; rjmp state6
rcall calculate_next_timing_values
rjmp s6_close
state6_2: sbis ACSR, ACO
rjmp state6
rcall wait_if_spike
sbis ACSR, ACO
rjmp state6
sbr state1, (1<
rcall wait_OCT1_before_switch
cbr state1, (1<
s6_close:
.if UART_CONTROL == 1
.if UART_FULL == 1
sbrc state0, GET_STATE
rcall save_state
.endif
.endif
ldi temp1, (1<<
out TIMSK, temp1 ; .. only ONE should change these values at the time
nop
cbr state0, (1< sbr state0, (1<
cbi PORTB, AnFET ; An off
sbrc state1, FULL_POWER
rjmp s6_switch
sbrc state0, I_OFF_CYCLE ; was power off ?
rjmp s6_done ; .. yes - futhermore work is done in timer0 interrupt
s6_switch: sbrs state1, POWER_OFF
sbi PORTB, CnFET ; Cn on
s6_done: ldi temp1, (1<<<
out TIMSK, temp1
ldi temp1, mux_a ; set comparator multiplexer to phase A
out ADMUX, temp1
rcall wait_OCT1_before_comp_scan ; use newly calculated values
tst rcpuls_timeout
breq restart_control
rjmp state1 ; go back to state 1
restart_control:
cli ; disable all interrupts
rjmp reset
.exit
复制代码
作者:
sdca945
时间:
2008-12-25 14:39
汗~~~~~~~~代码看不懂:em15:
作者:
ghg123456
时间:
2008-12-25 20:52
研究研究他,给个配件表格把
作者:
mm.dd138
时间:
2008-12-26 09:31
调个速,就就这么《间单》鸟文学4年。我倒。
作者:
mm.dd138
时间:
2008-12-26 09:32
调个速,就就这么《间单》鸟文学4年。我倒。
作者:
cyclone1983
时间:
2008-12-27 22:50
搂主可不可以讲一讲电机从静止启动的方法
作者:
zht9961020
时间:
2009-1-5 14:17
这个程序我也用过,感觉还可以,后来看汇编太麻烦改成c的,但有些地方不太懂,改完就用不了了
作者:
the5moon
时间:
2009-1-13 22:37
我也想知道楼主的启动!~~
顶
作者:
winster
时间:
2009-2-8 15:17
原帖由
cyclone1983
于 2008-12-27 22:50 发表
搂主可不可以讲一讲电机从静止启动的方法
无感BLDC的MCU启动程序由三个阶段组成:
1、转子预定位;利用软件编程将转子设定在一个确定的位置上,使起动动能以正确的转向顺利进行,不会产生转子震荡、甚至反向的情况,接通一个高侧IGBT开关和另两组的低侧IGBT开关。为把电动机转子从它的起始位置转到预定位置,将在一个充分长的时间内施加一个逐步上升的斜坡电流,可运用25步斜坡电流的方法,25步电流斜坡,每步30毫秒。
2、然后是启动斜坡阶段;一个启动斜坡表被运用,使电动机启动、加速,而且检测切换到自动换相阶段需要的信息。可运用38步启动斜坡
3、自动换相阶段;检测到反电动势过零,经过根据2阶段计算出的换相延迟时间后,进行自动换相。这个阶段就叫同步
作者:
zhaogub
时间:
2009-2-10 20:10
看了,不懂
作者:
BrushlessMoto
时间:
2009-2-14 21:19
LZ,能告诉我你用的,什么版本的,AVR STUDIO? flea.inc找不到,老是报错. 能指点一下吗?
作者:
誰伴我闖蕩
时间:
2009-2-18 14:55
东西是好,要是楼主把所用原件型号也列个表,那就堪称完美了。期待
作者:
小拖鞋
时间:
2009-2-18 20:47
留个记号学习下
欢迎光临 5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年) (http://5imx.com./)
Powered by Discuz! X3.3