-
Hola como andan, quiero ver si me pueden dar una mano, de programación se muy poco , solo hago retoques y nada mas.. digamos que casi nada..
,Quiero invertir la fase del pwm del codigo que adjunto, mi problema es que si uso un mosfet canal n me queda al revés en la consola dmx (cuando el potenciometro esta al maximo el pwm esta en 0, y cuando el potenciometro esta al minimo el pwm esta en valos 255) , lo soluciones agregando un CD4069, pero bueno se que se puede invertir, estoy buscando información pero mayormente es en lenguaje C.... si me pueden ayudar muchas gracias... igual sigo buscando...
Saludos
include "m8515def.inc"
;Register and Pin definitions
.def tempL = r16
.def tempH = r17
.def Flags = r18
.def DMXstate = r19
.def null = r2
.def status = r21
.def ind_count = r3
.def blink = r4
.def PwmCnt = r20
.def SREGbuf = r5
.def ChaseFine = r6
.def ChaseRes = r7
.equ StrobeFreqH = 0x80
.equ StrobeFreqL = 0x81
.equ StrobeBuf = 0x82
.equ OldStepH = 0x83
.equ OldStepL = 0x84
.equ NewStepH = 0x85
.equ NewStepL = 0x86
.equ StepCnt = 0x87
.equ ChaseCnt = 0x88
.equ ChaseSeed = 0x89
.equ LED1= PD7
.equ LED2= PE0
.equ BIT9= PE2
.equ DMX_FIELD= 0x60 ;SRAM-Beginn
.equ DMX_CHANNELS= 5
.equ PWM_FIELD= 0x70
.equ F_OSC= 8000
.equ FLASH_DURATION= 400
.equ IND_OFFSET= 12 ;Offset für indicator-Timer (14Hz)
#define CHS_SPD (0x600)
#define RATE (0x500)
#define PAT0 (0x400)
#define PAT1 (PAT0 +0xA)
#define PAT2 (PAT1 +0xA)
#define PAT3 (PAT2 +0xA)
#define PAT4 (PAT3 +0xA)
#define PAT5 (PAT4 +0xA)
#define PAT6 (PAT5 +0xA)
#define PAT7 (PAT6 +0xA)
;***** special Flags
#define VALID_DMX (0)
#define SIGNAL_COMING (1)
#define doIND (5)
#define BLACK_OUT (6)
#define DATA_REFRESHED (7)
;interrupt vectors
.org 0
rjmp init ;reset vector address
reti ;External Interrupt0 Vector Address
reti ;External Interrupt1 Vector Address
reti ;Input Capture1 Interrupt Vector Address
rjmp strobe ;Output Compare1A Interrupt Vector Address
reti ;Output Compare1B Interrupt Vector Address
reti ;Overflow1 Interrupt Vector Address
rjmp pwm ;Overflow0 Interrupt Vector Address
reti ;SPI Interrupt Vector Address
rjmp get_byte ;UART Receive Complete Interrupt Vector Address
reti ;UART Data Register Empty Interrupt Vector Address
reti ;UART Transmit Complete Interrupt Vector Address
reti ;Analog Comparator Interrupt Vector Address
reti ;External Interrupt2 Vector Address
reti ;Output Compare0 Interrupt Vector Address
reti ; EEPROM Interrupt Vector Address
reti ; SPM complete Interrupt Vector Address
reti ; SPM complete Interrupt Vector Address
; INIT
init:
; Stack
ldi tempH,high(RAMEND)
ldi tempL,low(RAMEND)
out SPH,tempH
out SPL,tempL
; WATCHDOG
wdr
ldi tempL, (1<<WDE)|(1<<WDCE)
out WDTCR, tempL
ldi tempL, (1<<WDE)|(1<<WDCE)|(1<<WDP2)|(1<<WDP1)
out WDTCR, tempL
wdr ;set prescaler @0,5s
; PortA
ser tempL
out DDRA, tempL
clr tempL
out PortA, tempL ;low Outputs
; PortB
ldi tempL, 0b00000011
out DDRB, tempL
ldi tempL, 0b11110100
out PortB, tempL
; PortD
ldi tempL, 0b10000100
out DDRD, tempL
ldi tempL, 0b01111000
out PortD, tempL ;DMX & Spare , LED1 on
; PortE
ldi tempL, 0b00000001
out DDRE, tempL
ser tempL
out PortE, tempL ;LED2 off, BIT9 & OPTION Pullup
; Timers
ldi tempL, (1<<CS01) ;set counter0 @clock/8 frequency
out TCCR0, tempL
clr tempL
out TCCR1A, tempL
ldi tempL, (1<<CS12)|(1<<WGM12) ;set counter1 @clock/256 frequency, CTCmode
out TCCR1B, tempL
ldi tempL, (1<<TOIE0) ;aktivate overflow interrupt
out TIMSK, tempL
rcall init_dmx
; set Register
clr null
clr blink
com blink
mov ChaseFine, blink
ldi tempL, IND_OFFSET
mov ind_count, tempL
ldi PwmCnt, 0xFF
ldi Flags, 0 ;clear Flags
sts StepCnt, null
sts NewStepH, null
sts NewStepL, null
ldi tempL, 1
sts ChaseCnt, tempL
sts ChaseSeed, tempL
mov ChaseRes, tempL
wdr
sei
main: sbrc Flags, doIND
rcall indicate
rcall eval_strobe_freq
;rcall chase
rjmp main
;****************************** LED INDICATOR ***********************************
indicate:
cbr Flags, (1<<doIND) ;clear flag
rcall chase
dec ind_count
breq ind_a
ret
ind_a:
wdr ;reset Watchdog
;working LED
sbrc Flags, DATA_REFRESHED ;should flash?
rjmp data_flash
sbi PortE, LED2 ; LED off
Error_LED:
sbrc blink, 0 ;wenn erstes bit HI
rjmp on
sbi PortD, LED1
rjmp ind_tst
on:
cbi PortD, LED1
ind_tst:
lsr blink
ldi tempL, 1
cp blink, tempL
brne no_ind
;wenn durchrotiert (blink = 0)
ldi tempL, 0b10000000
sbrs Flags, VALID_DMX
ldi tempL, 0b10001010
sbrs Flags, SIGNAL_COMING
ldi tempL, 0b10000010
mov blink, tempL
cbr Flags, (1<<VALID_DMX)|(1<<SIGNAL_COMING)
no_ind:
ldi tempL, IND_OFFSET
mov ind_count, tempL ;plant prescaler
ret
data_flash:
cbr Flags, (1<<DATA_REFRESHED)
sbis PortE,LED2 ;blinken grün
rjmp off
cbi PortE,LED2
rjmp Error_LED
off:
sbi PortE,LED2
rjmp Error_LED
;****************************** strobe frequency ***********************************
eval_strobe_freq:
lds tempL, DMX_FIELD ;get 1st DMX ch
cpi tempL, 246
brlo esf_1
ldi tempL, 245
esf_1:
lds tempH, StrobeBuf
cp tempL, tempH
brne esf_2 ;only eval if changed
ret
esf_2:
sts StrobeBuf, tempL
cpi tempL, 30
brlo esf_no_strobe
cpi tempL, 245
brsh esf_sync
subi tempL, 30 ;0-200 allowed
ldi ZL, low(RATE*2) ;get freq from table
ldi ZH, high(RATE*2)
add ZL, tempL
adc ZH, null
add ZL, tempL
adc ZH, null
lpm tempL, Z+
lpm tempH, Z
cli
sts StrobeFreqL, tempL ;atomic store
sts StrobeFreqH, tempH
in tempL, TIMSK
sbr tempL, (1<<OCIE1A) ;enable irq
out TIMSK, tempL
in tempL, TIFR
sbr tempL, (1<<OCF1A) ;enable irq
out TIFR, tempL
reti
esf_no_strobe:
in tempL, TIMSK
cbr tempL, (1<<OCIE1A) ;disable irq
out TIMSK, tempL
cbr Flags, (1<<BLACK_OUT) ;enable pwm
ret
esf_sync:
in tempL, TIMSK
sbrs tempL, OCIE1A ;only when strobing
ret
cli
sbr Flags, (1<<BLACK_OUT) ;blank!
lds ZH, StrobeFreqH
lds ZL, StrobeFreqL
out OCR1AH, ZH
out OCR1AL, ZL
sbiw ZH:ZL, 20
out TCNT1H, ZH
out TCNT1L, ZL
reti
;****************************** manual chaser mode ***********************************
chase: ;called by indicator
sbis PinE, PE1
rjmp chs_a
sbic UCSRB,RXEN
ret ;enable DMX reception
sbi UCSRB, RXEN
clr DMXstate
ret
chs_exit:
sts ChaseCnt, tempH
ret
chs_a:
cbi UCSRB,RXEN ;disable DMX
sbr Flags, (1<<VALID_DMX)|(1<<SIGNAL_COMING)
lds tempH, ChaseCnt ;load prescaler
dec tempH
brne chs_exit
lds tempL, ChaseSeed ;reseed prescaler
sts ChaseCnt, tempL
add ChaseFine, ChaseRes ;up-fade val
adc tempH, null ;(tempH was 0)
mov tempL, ChaseFine
com tempL ;down-fade val
tst tempH
brne chs_step
chs_step_ret:
ldi XL, low(DMX_FIELD +1)
ldi XH, high(DMX_FIELD)
ldi ZL, 1
chase_fade: ;ch1..8
clr tempH
lds ZH, OldStepL
and ZH, ZL
breq cf_no_old
mov tempH, tempL
cf_no_old:
lds ZH, NewStepL
and ZH, ZL
breq cf_no_new
add tempH, ChaseFine
cf_no_new:
st X+, tempH
lsl ZL
brne chase_fade
clr tempH ;9th ch
lds ZH, OldStepH
sbrc ZH, 0
mov tempH, tempL
lds ZH, NewStepH
sbrc ZH, 0
add tempH, ChaseFine
st X, tempH
ret
chs_step:
sbr Flags, (1<<DATA_REFRESHED)
clr ChaseFine ;reset fader
ser tempL
lds tempH, NewStepL ;change steps
sts OldStepL, tempH
lds tempH, NewStepH
sts OldStepH, tempH
ldi ZH, high(CHS_SPD*2) ;get speed
in ZL, PinC
com ZL
swap ZL
andi ZL, 0b00001111 ;isolate pattern
lpm ZH, Z
ldi tempH, 1
cpi ZL, 5 ;switch between resolution and prescale
brsh chs_decres
mov ChaseRes, tempH
sts ChaseSeed, ZH
rjmp chs_strb
chs_decres:
mov ChaseRes, ZH
sts ChaseSeed, tempH
chs_strb:
clr ZH ;add strobe
sbis PinE, PE2
ldi ZH, 220
sts DMX_FIELD, ZH
ldi ZH, high(PAT0*2) ;get next step
lds tempH, StepCnt
mov ZL, tempH
lsl ZL
inc tempH
sts StepCnt, tempH
lpm tempH, Z+
sts NewStepL, tempH
lpm tempH, Z
sts NewStepH, tempH
sbrs tempH, 1 ;reset pattern?
rjmp chs_step_ret
in ZL, PinC
com ZL
andi ZL, 0b00000111 ;isolate pattern
ldi tempH, 10
mul ZL, tempH
sts StepCnt, r0 ;save pattern
rjmp chs_step_ret
; ***************************9ch 8bitpwm-Ausgabe ****************************************
pwm:
in SREGbuf, SREG
push tempL
sbrc Flags, BLACK_OUT ;blanked by strobe?
rjmp pwm_bo_exit
lds tempL, PWM_FIELD
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+1)
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+2)
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+3)
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+4)
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+5)
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+6)
cp tempL, PwmCnt
ror status
lds tempL, (PWM_FIELD+7)
cp tempL, PwmCnt
ror status
;9th bit
sbis PinD, PD4 ;invert option
rjmp pwm9_pos ; no invert
lds tempL, (PWM_FIELD+8)
sbi PortB, 0
cp tempL, PwmCnt
brlo pwm_exit
cbi PortB, 0
rjmp pwm_exit
pwm9_pos:
com status
lds tempL, (PWM_FIELD+8)
cbi PortB, 0
cp tempL, PwmCnt
brlo pwm_exit
sbi PortB, 0
rjmp pwm_exit
pwm_bo_exit:
sbis PinD, PD4 ;invert option
rjmp pwm_bo_pos ; no invert
ser status ;all ch off (inverted)
sbi PortB, 0
rjmp pwm_exit
pwm_bo_pos:
clr status ;all ch off
cbi PortB, 0
pwm_exit:
out PortA, status ;output
mov tempL, PwmCnt ;set next compare time
lsr tempL
lsr tempL
lsr tempL
ldi status, 250
sub status, tempL
out TCNT0, status
inc PwmCnt
tst PwmCnt
brne pwm_no_reload
lds tempL, (DMX_FIELD+1) ;refresh channels
sts PWM_FIELD, tempL
lds tempL, (DMX_FIELD+2)
sts (PWM_FIELD+1), tempL
lds tempL, (DMX_FIELD+3)
sts (PWM_FIELD+2), tempL
lds tempL, (DMX_FIELD+4)
sts (PWM_FIELD+3), tempL
lds tempL, (DMX_FIELD+5)
sts (PWM_FIELD+4), tempL
lds tempL, (DMX_FIELD+6)
sts (PWM_FIELD+5), tempL
lds tempL, (DMX_FIELD+7)
sts (PWM_FIELD+6), tempL
lds tempL, (DMX_FIELD+8)
sts (PWM_FIELD+7), tempL
lds tempL, (DMX_FIELD+9)
sts (PWM_FIELD+8), tempL
ldi PwmCnt, 1 ;reseed counter
sbr Flags, (1<<doIND) ;indicate in main
pwm_no_reload:
pop tempL
out SREG, SREGbuf
reti
; ***************************Strobo function ****************************************
strobe:
in SREGbuf, SREG
push tempL
push tempH
sbrs Flags, BLACK_OUT
rjmp str_blank
cbr Flags, (1<<BLACK_OUT) ;enable pwm
ldi tempL, low(FLASH_DURATION) ;load flash time
ldi tempH, high(FLASH_DURATION)
rjmp str_exit
str_blank:
sbr Flags, (1<<BLACK_OUT)
lds tempL, StrobeFreqL
lds tempH, StrobeFreqH
str_exit:
out OCR1AH, tempH
out OCR1AL, tempL
pop tempH
pop tempL
out SREG, SREGbuf
reti
.include "lib_dmx_in.asm"
nix: rjmp nix
// Strobo frequency table (damped logarithmic)
.org RATE
.dw 65532, 60407, 56368, 53017, 50170, 47708, 45546, 43626, 41904, 40345, 38925, 37623, 36423, 35311, 34277, 33311
.dw 32406, 31555, 30753, 29996, 29278, 28596, 27948, 27331, 26741, 26177, 25637, 25120, 24623, 24145, 23685, 23242
.dw 22814, 22402, 22003, 21617, 21244, 20882, 20531, 20191, 19861, 19540, 19228, 18924, 18629, 18341, 18061, 17788
.dw 17521, 17261, 17007, 16760, 16517, 16281, 16049, 15823, 15601, 15384, 15172, 14964, 14760, 14560, 14364, 14172
.dw 13983, 13798, 13617, 13438, 13263, 13091, 12922, 12756, 12593, 12432, 12274, 12119, 11966, 11815, 11667, 11522
.dw 11378, 11237, 11098, 10960, 10825, 10692, 10561, 10431, 10304, 10178, 10054, 9931, 9811, 9691, 9574, 9458
.dw 9343, 9230, 9119, 9008, 8899, 8792, 8686, 8581, 8477, 8375, 8273, 8173, 8074, 7976, 7880, 7784
.dw 7690, 7596, 7504, 7412, 7322, 7232, 7144, 7056, 6969, 6884, 6799, 6715, 6631, 6549, 6467, 6387
.dw 6307, 6227, 6149, 6071, 5994, 5918, 5843, 5768, 5694, 5620, 5548, 5475, 5404, 5333, 5263, 5193
.dw 5125, 5056, 4988, 4921, 4855, 4789, 4723, 4658, 4594, 4530, 4466, 4404, 4341, 4279, 4218, 4157
.dw 4097, 4037, 3978, 3919, 3860, 3802, 3744, 3687, 3631, 3574, 3518, 3463, 3408, 3353, 3299, 3245
.dw 3191, 3138, 3085, 3033, 2981, 2929, 2878, 2827, 2777, 2726, 2677, 2627, 2578, 2529, 2480, 2432
.dw 2384, 2337, 2289, 2242, 2196, 2149, 2103, 2057, 2012, 1967, 1922, 1877, 1833, 1789, 1745, 1701
.dw 1658, 1615, 1572, 1530, 1488, 1446, 1350, 1250, 1100, 1050, 1000, 950, 900, 850, 800, 750
.dw 700, 650, 600, 550, 500, 450, 400, 350, 300, 250, 200, 150
.org PAT0 ;on
.dw 0b0111111111
.dw 0b1111111111
.org PAT1 ;Lauflicht
.dw 0b0000000001
.dw 0b0000000010
.dw 0b0000000100
.dw 0b0000001000
.dw 0b0000010000
.dw 0b0000100000
.dw 0b0001000000
.dw 0b0010000000
.dw 0b1100000000
.org PAT2 ;ping pong
.dw 0b0000010000
.dw 0b0000100000
.dw 0b0000001000
.dw 0b0001000000
.dw 0b0000000100
.dw 0b0010000000
.dw 0b0000000010
.dw 0b0100000000
.dw 0b1000000001
.org PAT3 ;ping pong
.dw 0b0000011000
.dw 0b0000100100
.dw 0b0001000010
.dw 0b1010000001
.org PAT4 ;pfeil
.dw 0b0000011000
.dw 0b0000111100
.dw 0b0001111110
.dw 0b0011111111
.dw 0b0011100111
.dw 0b0011000011
.dw 0b1010000001
.org PAT5 ;RGB
.dw 0b0001001001
.dw 0b0011011011
.dw 0b0010010010
.dw 0b0110110110
.dw 0b0100100100
.dw 0b1101101101
.org PAT6 ;RGB spread
.dw 0b0100010001
.dw 0b0101110011
.dw 0b0001100010
.dw 0b0011101110
.dw 0b0010001100
.dw 0b1110011101
.org PAT7
.dw 0b0001001001 ;RGB single change
.dw 0b0001001011
.dw 0b0001011011
.dw 0b0011011011
.dw 0b0011011010
.dw 0b0011010010
.dw 0b0010010010
.dw 0b0010010110
.dw 0b0010110110
.dw 0b0110110110
.dw 0b0110110100
.dw 0b0110100100
.dw 0b0100100100
.dw 0b0100100101
.dw 0b0100101101
.dw 0b0101101101
.dw 0b0101101001
.dw 0b1101001001
.org CHS_SPD
.db 25, 10, 3, 2, 1, 2, 3, 5, 8, 12, 17, 22, 27, 35, 40, 48
-
Es un PWM por software, no trabaje nunca con micros de Atmel, pero el ASM es parecido en todo, solo cambia la forma de los nombres y la arquitectura, se me ocurren 4 cosas a probar:
1-
Parece que ya tiene incorporado algo para invertirlo, supuestamente el pin D4 sirve para invertir la señal de salida. Podrias probarlo, para empezar.
2-
Tal ves la mas compleja por que requiere tener en cuenta varias cosas, y sea mucho mas facil la otra opcion
Cambiar el formato del PWM, en ves de incrementar la variable que la reste, pero esto requiere el cambio de 3 lineas de codigo.
Lo bueno de este metodo es que no se agregan instrucciones ni ciclos. Las instrucciones a cambiar son:
inc PwmCnt
ldi PwmCnt, 0xFF
ldi PwmCnt, 1 ;reseed counter
3-
La opcion mas simple (ya que se encuentra confinado en un bloque y no en diversas partes del codigo) y no creo que afecte demasiado el cambio.
Ya esto deberias de agregar un par de instrucciones mas, en ves de contar a la inversa, deberias invertir lo guardado, en ves de modificar el index. simplemente haces el complemento y deberias cambiar:
lds tempL, (DMX_FIELD+1) ;refresh channels
sts PWM_FIELD, tempL
lds tempL, (DMX_FIELD+2)
sts (PWM_FIELD+1), tempL
lds tempL, (DMX_FIELD+3)
sts (PWM_FIELD+2), tempL
lds tempL, (DMX_FIELD+4)
sts (PWM_FIELD+3), tempL
lds tempL, (DMX_FIELD+5)
sts (PWM_FIELD+4), tempL
lds tempL, (DMX_FIELD+6)
sts (PWM_FIELD+5), tempL
lds tempL, (DMX_FIELD+7)
sts (PWM_FIELD+6), tempL
lds tempL, (DMX_FIELD+8)
sts (PWM_FIELD+7), tempL
lds tempL, (DMX_FIELD+9)
sts (PWM_FIELD+8), tempL
Por:
lds tempL, (DMX_FIELD+1) ;refresh channels
com tempL
sts PWM_FIELD, tempL
lds tempL, (DMX_FIELD+2)
com tempL
sts (PWM_FIELD+1), tempL
lds tempL, (DMX_FIELD+3)
com tempL
sts (PWM_FIELD+2), tempL
lds tempL, (DMX_FIELD+4)
com tempL
sts (PWM_FIELD+3), tempL
lds tempL, (DMX_FIELD+5)
com tempL
sts (PWM_FIELD+4), tempL
lds tempL, (DMX_FIELD+6)
com tempL
sts (PWM_FIELD+5), tempL
lds tempL, (DMX_FIELD+7)
com tempL
sts (PWM_FIELD+6), tempL
lds tempL, (DMX_FIELD+8)
com tempL
sts (PWM_FIELD+7), tempL
lds tempL, (DMX_FIELD+9)
com tempL
sts (PWM_FIELD+8), tempL
De esa forma cuando lo llegado del DMX le indique que es de 250, lo que luego se compara es con 255 - 250 = 5, es decir 5, cuando tu potenciometro este en 205, tu pwm va a usar el valor de 50.
Es decir ahi estarias invirtiendolo, no se si lo que recibe ya lo invierte y lo guarda en DMX_FIELD, pero con este caso, lo estariamos invirtiendo de nuevo.
De todas formas no tuve en cuenta el tiempo, pero solo llevaria mas tiempo el momento en que comienze en 0 pwmCnt ya que necesitaria recargar, y en tiempo me refiero a 8 ciclos mas de reloj.
4-
Buscar donde cambia el valor del puerto e invertirlo antes, es decir esto:
pwm_exit:
out PortA, status ;output
Por
pwm_exit:
com status
out PortA, status ;output
com status
Agregando 2 instrucciones, Y todo lo demas internamente funcionaria de la misma forma, es decir solo toco lo que va al puerto. invierto e invierto nuevamente por que luego se hace uso de "status" entonces debe mantener el valor sin invertir.
Sino habria que revisar todo el programa. Si solo quisiera invertirlo una ves
------------------------
De recomendar te recomiendo la primera opcion, luego la 4ta, luego la 3era y luego la 2da.
PD: Esto sin conocer los atmega ya que nunca trabaje con ellos, solo mire su set de intrucciones.
-
Buenas....
Te comento que use la Opción nº 4 y anduvo perfecto!!!!!!..
Muchas gracias por la información, soy muy duro para esto de la programación...
Mil Gracias!!!!..
-
hola
Es un PWM por software, no trabaje nunca con micros de Atmel, pero el ASM es parecido en todo, solo cambia la forma de los nombres y la arquitectura, se me ocurren 4 cosas a probar:
1-
Parece que ya tiene incorporado algo para invertirlo, supuestamente el pin D4 sirve para invertir la señal de salida. Podrias probarlo, para empezar.
2-
Tal ves la mas compleja por que requiere tener en cuenta varias cosas, y sea mucho mas facil la otra opcion
Cambiar el formato del PWM, en ves de incrementar la variable que la reste, pero esto requiere el cambio de 3 lineas de codigo.
Lo bueno de este metodo es que no se agregan instrucciones ni ciclos. Las instrucciones a cambiar son:
inc PwmCnt
ldi PwmCnt, 0xFF
ldi PwmCnt, 1 ;reseed counter
3-
La opcion mas simple (ya que se encuentra confinado en un bloque y no en diversas partes del codigo) y no creo que afecte demasiado el cambio.
Ya esto deberias de agregar un par de instrucciones mas, en ves de contar a la inversa, deberias invertir lo guardado, en ves de modificar el index. simplemente haces el complemento y deberias cambiar:
lds tempL, (DMX_FIELD+1) ;refresh channels
sts PWM_FIELD, tempL
lds tempL, (DMX_FIELD+2)
sts (PWM_FIELD+1), tempL
lds tempL, (DMX_FIELD+3)
sts (PWM_FIELD+2), tempL
lds tempL, (DMX_FIELD+4)
sts (PWM_FIELD+3), tempL
lds tempL, (DMX_FIELD+5)
sts (PWM_FIELD+4), tempL
lds tempL, (DMX_FIELD+6)
sts (PWM_FIELD+5), tempL
lds tempL, (DMX_FIELD+7)
sts (PWM_FIELD+6), tempL
lds tempL, (DMX_FIELD+8)
sts (PWM_FIELD+7), tempL
lds tempL, (DMX_FIELD+9)
sts (PWM_FIELD+8), tempL
Por:
lds tempL, (DMX_FIELD+1) ;refresh channels
com tempL
sts PWM_FIELD, tempL
lds tempL, (DMX_FIELD+2)
com tempL
sts (PWM_FIELD+1), tempL
lds tempL, (DMX_FIELD+3)
com tempL
sts (PWM_FIELD+2), tempL
lds tempL, (DMX_FIELD+4)
com tempL
sts (PWM_FIELD+3), tempL
lds tempL, (DMX_FIELD+5)
com tempL
sts (PWM_FIELD+4), tempL
lds tempL, (DMX_FIELD+6)
com tempL
sts (PWM_FIELD+5), tempL
lds tempL, (DMX_FIELD+7)
com tempL
sts (PWM_FIELD+6), tempL
lds tempL, (DMX_FIELD+8)
com tempL
sts (PWM_FIELD+7), tempL
lds tempL, (DMX_FIELD+9)
com tempL
sts (PWM_FIELD+8), tempL
De esa forma cuando lo llegado del DMX le indique que es de 250, lo que luego se compara es con 255 - 250 = 5, es decir 5, cuando tu potenciometro este en 205, tu pwm va a usar el valor de 50.
Es decir ahi estarias invirtiendolo, no se si lo que recibe ya lo invierte y lo guarda en DMX_FIELD, pero con este caso, lo estariamos invirtiendo de nuevo.
De todas formas no tuve en cuenta el tiempo, pero solo llevaria mas tiempo el momento en que comienze en 0 pwmCnt ya que necesitaria recargar, y en tiempo me refiero a 8 ciclos mas de reloj.
4-
Buscar donde cambia el valor del puerto e invertirlo antes, es decir esto:
pwm_exit:
out PortA, status ;output
Por
pwm_exit:
com status
out PortA, status ;output
com status
Agregando 2 instrucciones, Y todo lo demas internamente funcionaria de la misma forma, es decir solo toco lo que va al puerto. invierto e invierto nuevamente por que luego se hace uso de "status" entonces debe mantener el valor sin invertir.
Sino habria que revisar todo el programa. Si solo quisiera invertirlo una ves
------------------------
De recomendar te recomiendo la primera opcion, luego la 4ta, luego la 3era y luego la 2da.
PD: Esto sin conocer los atmega ya que nunca trabaje con ellos, solo mire su set de intrucciones.
bueno yo use ese codigo tal cual esta ., y no tube problemas de invercion en la consola
pero eso si ., segui la sujerencias del autor ., para conectar los led y use de 5W (que talvez alli este el problema del amigo )
yo lo que siempre intente ., pero no pude lograrlo es copiar o pasr las funciones de FADING o RAIMBON a C en AVRstuduo (sin DMX)
-
yo lo que siempre intente ., pero no pude lograrlo es copiar o pasr las funciones de FADING o RAIMBON a C en AVRstuduo (sin DMX)
Realmente yo jamas trabaje con un atmel (ni en C ni en ASM), asi que mi codigo solo fue por curiosidad de ver como era el ASM de los atmega. Debido a que todos los ASM manejan binario no fue dificil entenderlo
Tampoco trabaje con DMX para saber que es o cuales son las funciones FADING y RAIMBON ( o RAINBOW?) como para intentar decirte como pasarlo, lo que si veo es que los efectos parecen estar programados al final del codigo.
Si pasas el codigo en ASM e indicas cual es la parte se podria pasar tranquilamente creo.
-
hola ., y desde ya muchas gracias por enseñar
Si pasas el codigo en ASM e indicas cual es la parte se podria pasar tranquilamente creo.
bueno aca te paso el codigo de ASM que probe (el anterior ya tambien esta probado y funcionan los dos perfectamente )
esta parte esta solamente los efectos FADING y RAINBOW(corregido su escritura gracias ) pero todo esto sin DMX
tambien habria que aclarar que las funciones de FADING de la libreria anterior funcionan si se coloca la llave minidips numero 10 en ON (conectada) adjunto foto del montaje fisico por si tiene dudas
de esa manera desabilita la funcion DMX y queda en modo programado
este codigo que pongo solo es para tres (3) led o sea RGB ., el anterior es para nueve (9) divididos en RGB (8 del puerto A y 1 del puerto B )
y vuelvo a repetir., he probado los dos codigos originales ., el anterior y el simplificado (este) !!!! y funciona los dos perfectamente ¡¡¡
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=44207.0;attach=23382;image) este es la configuracion que uso (montaje )
; ***********************************************************************************************
; * RGB atenuador + mix colores + stroboscopico + luz discoteca-intermitente *
; * *
; * para ATMega 8515 *
; * *
; * Versión 3.0 - 22/03/2008 *
; * LED en el interruptor MOSFET al puerto B *
; * *
; * *
; * PortB0 = Rojo, PortB1 = Verde, PortB2 = Azul *
; ***********************************************************************************************
.include "m8515def.inc"
; ------------------------------------------------------------------------------------------------
; Definir los registros, etc.
; ------------------------------------------------------------------------------------------------
.def temp0 = R16 ;Definir registro
.def temp1 = R17
.def temp2 = R18
.def temp_ZL = R1
.def temp_ZH = R2
.def temp_Sreg = R3
.def Speed = R19
.def R = R20
.def V = R21
.def A = R22
.def R_Out = R4
.def V_Out = R5
.def A_Out = R6
.def PWM_Count = R23
.equ XTAL = 8000000 ; Sólo para información
; ------------------------------------------------------------------------------------------------
; Tabla de vectores de interrupción Mega8515
; ------------------------------------------------------------------------------------------------
.CSEG
.org 0x0000
rjmp Inicio ; Restablecer controlador
reti ; Interrupción externa Solicitud 0
reti ; Interrupción externa Solicitud 1
reti ; Temporizador / Captura de Counter1
reti ; Timer / Counter1 Comparar Partido A
reti ; Timer / Counter1 Comparar Partido B
reti ; Timer / Counter1 desbordamiento (overflow)
rjmp ISR_PWM ; Timer / Counter0 desbordamiento (Overflow) -> rutina PWM
reti ; Transferencia serial completa
reti ; Rx completa
reti ; Registro de datos vacía
reti ; Tx completa
reti ; Comparador analógico
reti ; Interrupción externa Solicitud 2
reti ; Timer / Counter0 Comparar Partido (match)
reti ; EEPROM Ready
reti ; almacenado memoria Ready Programa
; ------------------------------------------------------------------------------------------------
; Puntero de pila , puertos establecidos
; ------------------------------------------------------------------------------------------------
Inicio:
ldi temp0, LOW(RAMEND);Byte bajo de dirección superior RAM BAJA
out SPL, temp0
ldi temp0, HIGH(RAMEND);Byte alto de dirección superior RAM ALTA
out SPH, temp0
ldi temp0, 0b00000001;Conjunto CS00: 1 divisor
out TCCR0, temp0
ldi temp0, (1<<TOIE0);TOIE0: interrumpir el desbordamiento del temporizador
out TIMSK, temp0
sei ;Habilitar las interrupciones
ldi temp0, 0
out DDRC, temp0 ;Puerto C en la entrada (interruptor DIP)
ldi temp0, 0b00000001
out DDRE, temp0 ;PortE0 en la salida (LED), 1 y 2 en la entrada
sbi PORTE, 1 ;Pull-up resistencias
sbi PORTE, 2 ;Pull-up resistencias
ldi temp0, 0xff
out DDRB, temp0 ;PortA para establecer la salida (salida PWM)
out PORTC, temp0 ;Habilitar resistencias pull-up en PORTC
sbi DDRD, 7 ;PortD7 en la salida ("On" LED)
; ------------------------------------------------------------------------------------------------
; "Estado fundamental" - Colores y Strobo, ajustables mediante interruptores DIP switch
; ------------------------------------------------------------------------------------------------
Interruptor_Loop: ;Comprobar el interruptor DIP
sbis PINC, 6 ;El interruptor 7 está apagado, más
rcall RGB_Fader ;Cambie a -> RGB atenuador
sbis PINC, 5 ;El interruptor 6 está apagado, más
rcall Disco ;Cambie a -> Indicador de Disco
cbi PORTE, 0 ;LED de estado encendido
sbic PINC, 3 ;Comprobar el interruptor 4 (medio Verde / corrección de color rosa)
rjmp Mixcolores ;No se requiere corrección, "lo más normal"
in temp1, PINC ;Comprobar dip switch
andi temp1, 0b00000111 ;Caso especial "blanco"
brne Mixcolores ;no todos los interruptores (no blanco), por lo que otros colores
ldi R, 220 ;menos rojo porque ajustado a rosa rebelde
ldi V, 255
ldi A, 255
rcall Dimmercurva ;Corrección y de salida Brillo
rjmp Strobo ;Saltarse la configuración del color, además Strobo
Mixcolores:
ldi R, 255 ;encendido de rojo
sbic PINC, 0 ;Comprobar el interruptor 1 (Rojo)
ldi R, 0 ;El interruptor está apagado,apagado de rojo
ldi V, 0 ;apagado de verde
sbic PINC, 1 ;Comprobar el interruptor 2 (Verde)
rjmp azul ;El interruptor está apagado, más
ldi V, 255 ;encendido de verde
sbis PINC, 3 ;Comprobar el interruptor 4 (media Verde / corrección de color de rosa)
ldi V, 128 ;si el interruptor encendido , la mitad verde
azul:
ldi A, 255 ;encendido de Azul
sbic PINC, 2 ;Comprobar el interruptor 3 (azul)
ldi A, 0 ;El interruptor está apagado, apagado de azul
rcall Dimmercurva ;Corrección y de salida Brillo
Strobo:
sbic PINC, 4 ;Revise el interruptor 5 (estroboscópico)
rjmp Interruptor_Loop ;no Apagar,
;// ------------------------------------------------------------------------------------------------//
; Strobo - estroboscópica
;// ------------------------------------------------------------------------------------------------//
ldi Speed, 255 ;Strobo velocidad básica
sbic PINC, 7 ;Interruptor 8 chequea (Rojo / Azul Strobe)
rjmp Strobo_normal ;interuptor apagado, Strobo normales
ldi R, 255 ;Rojo
ldi V, 0 ;verde
ldi A, 0 ;azul
rcall Dimmercurva ;Corrección y de salida Brillo
cbi PORTE, 0 ;LED de estado encendido
ldi temp1, 2 ;durante 2 ciclos rojo
Strobo_rojo:
rcall esperar
dec temp1
brne Strobo_rojo
ldi R, 0 ;rojo apagado
ldi v, 0 ;verde apagado
ldi A, 0 ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo
sbi PORTE, 0 ;LED de estado apagado
ldi temp1, 10 ;y 10 ciclos de apagado
Strobo_rojo_desde:
rcall esperar
dec temp1
brne Strobo_rojo_desde
ldi R, 0 ;rojo apagado
ldi V, 0 ;verde apagado
ldi A, 255 ;azul encendido
rcall Dimmercurva ;Corrección y de salida Brillo
cbi PORTE, 0 ;LED de estado encendido
ldi temp1, 2 ;durante 2 ciclos azul
Strobo_azul:
rcall esperar
dec temp1
brne Strobo_azul
ldi R, 0 ;rojo apagado
ldi V, 0 ;verde apagado
ldi A, 0 ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo
sbi PORTE, 0 ;LED de estado apagado
ldi temp1, 10 ;y 10 ciclos de apagado
Strobo_azul_desde:
rcall esperar
dec temp1
brne Strobo_azul_desde
rjmp Interruptor_Loop
Strobo_normal:
ldi temp1, 2 ;durante 2 ciclos
Strobo_a:
rcall esperar
dec temp1
brne Strobo_a
ldi R, 0 ;rojo apagado
ldi V, 0 ;verde apagado
ldi A, 0 ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo
sbi PORTE, 0 ;LED de estado apagado
ldi temp1, 10 ;y 10 ciclos de apagado
Strobo_desde:
rcall esperar
dec temp1
brne Strobo_desde
rjmp Interruptor_Loop
; ------------------------------------------------------------------------------------------------
; Atenuacion o Fader General sin cambiar el valor del brillo(fading) rutina 1
; ------------------------------------------------------------------------------------------------
RGB_Fader:
ldi Speed, 127 ;Velocidad del módo básico en espera
RGB_Loop:
ldi R, 255 ;rojo encendido
ldi V, 0 ;verde apagado
ldi A, 0 ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo
cbi PORTE, 0 ;LED de estado encendido
rojo_amarillo: ;verde apagado -> pasa a amarillo
sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador
sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambie a seguir el programa 2
rcall esperar
sbi PORTE,0 ;LED de estado apagado
inc V
rcall Dimmercurva ;Corrección y de salida Brillo
cpi V, 255
brlo rojo_amarillo
cbi PORTE, 0 ;LED de estado encendido
amarillo_verde: ;amarillo apagado -> pasa a Verde
sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador
sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambie a seguir el programa 2
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec R
rcall Dimmercurva ;Corrección y de salida Brillo
brne amarillo_verde
cbi PORTE, 0 ;LED de estado encendido
verde_cyan: ;verde apagado -> pasa a Cyan
sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador
sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambio, a seguir el programa 2
rcall esperar
sbi PORTE,0 ;LED de estado apagado
inc A
rcall Dimmercurva ;Corrección y de salida Brillo
cpi A, 255
brlo verde_cyan
cbi PORTE, 0 ;LED de estado encendido
cyan_azul: ;cyan apagado -> pasa a Azul
sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador
sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambio a seguir el programa 2
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec V
rcall Dimmercurva ;Corrección y de salida Brillo
brne cyan_azul
cbi PORTE, 0 ;LED de estado en
azul_magenta: ;azul apagado -> pasar a Magenta
sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador
sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ; Cambio , a seguir el programa 2
rcall esperar
sbi PORTE,0 ;LED de estado apagado
inc R
rcall Dimmercurva ;Corrección y de salida Brillo
cpi R, 255
brlo azul_magenta
cbi PORTE, 0 ;LED de estado en
magenta_rojo: ;magenta apagado -> pasa a rojo
sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador
sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambio , a seguir el programa 2
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec A
rcall Dimmercurva ;Corrección y de salida Brillo
brne magenta_rojo
rjmp RGB_Loop ;Fader-ciclo repetitivo desde el principio
RGB_fin:
ret
; ------------------------------------------------------------------------------------------------
; Rainbow-Fader 2 -- "funcion Rainbow" atenuador 2
; ------------------------------------------------------------------------------------------------
Rainbow_Fader:
mov temp0, R ;definicion de Colores fijos para diferentes atenuaciones
mov temp1, V ;definicion de Colores fijos para diferentes atenuaciones
mov temp2, A ;definicion de Colores fijos para diferentes atenuaciones
ldi Speed, 254 ;Velocidad del módo básico en espera
Rainbow_Loop:
ldi R, 255 ;primero ,tiempo del colr rojo encendido
ldi V, 0 ;tiempo de verde CERO
ldi A, 0 ;tiempo de azul CERO
rcall Dimmercurva ;Corrección y de salida Brillo
cbi PORTE, 0 ;LED de estado encendido
rojo_verde: ;Ocultar Rojo, Mostrar Verde
sbic PINC, 7 ;Interruptor 8 está encendido, continúe con el fader 2
rjmp Rainbow_fin ;Switch -> volver a RGB-faders 1
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec R
inc V
rcall Dimmercurva ;Corrección y de salida Brillo
cpi V, 255
brlo rojo_verde
cbi PORTE, 0 ;LED de estado encendido
verde_azul: ;Ocultar Verde, mostrar Azul
sbic PINC, 7 ;Interruptor 8 está encendido, continúe con el fader 2
rjmp Rainbow_fin ;interuptor apagado -> volver a RGB-faders 1
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec V
inc A
rcall Dimmercurva ;Corrección y de salida Brillo
cpi A, 255
brlo verde_azul
cbi PORTE, 0 ;LED de estado encendido
azul_rojo: ;Ocultar Azul, Mostrar Rojo
sbic PINC, 7 ;Interruptor 8 está encendido, continúe con el fader 2
rjmp Rainbow_fin ;iteruptor apagado -> volver a faders RGB 1
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec A
inc R
rcall Dimmercurva ;Corrección y de salida Brillo
cpi R, 255
brlo azul_rojo
cbi PORTE, 0 ;LED de estado encendido
rjmp Rainbow_Loop ;LED de Estado encendido
Rainbow_fin:
mov R, temp0 ;Restaurar colores para diferentes atenuaciones
mov V, temp1 ;Restaurar colores para diferentes atenuaciones
mov A, temp2 ;Restaurar colores para diferentes atenuaciones
ret
; ------------------------------------------------------------------------------------------------
; "Disco-Blink"-Routine -- Rutina "Disco Blink"
; ------------------------------------------------------------------------------------------------
Disco:
in temp1, PINC ;Comprobar el interruptor DIP-swch
andi temp1, 0b00000011 ;sólo está interesado en los dos primeros, PC0 y PC1
mov temp2, temp1 ;lamado ,para ver si el interruptor cambió su estado
cpi temp1, 0b00000011 ;Programa 1
brne Disco_P2
ldi ZL, LOW(Disco_Mixcolores_1*2) ;Z-puntero, Cargar programa 1
ldi ZH, HIGH(Disco_Mixcolores_1*2)
rjmp Disco_Loop
Disco_P2:
cpi temp1, 0b00000001 ;Programa 2
brne Disco_P3
ldi ZL, LOW(Disco_Mixcolores_2*2) ;Z-puntero, Cargar programa 2
ldi ZH, HIGH(Disco_Mixcolores_2*2)
rjmp Disco_Loop
Disco_P3:
cpi temp1, 0b00000010 ;Programa 3
brne Disco_P4
ldi ZL, LOW(Disco_Mixcolores_3*2) ;Z-puntero, Cargar programa 3
ldi ZH, HIGH(Disco_Mixcolores_3*2)
rjmp Disco_Loop
Disco_P4:
ldi ZL, LOW(Disco_Mixcolores_4*2) ;Cargar programa Z-puntero 4
ldi ZH, HIGH(Disco_Mixcolores_4*2)
Disco_Loop:
lpm Speed, Z+ ;Compruebe la velocidad / "bandera final"
tst Speed ;Se ha llegado al final de la muestra de la mesa?
breq Disco ;Sí, empezar de nuevo
in temp1, PINC ;Comprobar el interruptor DIP
andi temp1, 0b00000011 ;sólo está interesado en los dos primeros
cp temp2, temp1 ;Si cambia el interruptor DIP?
brne Disco ;Sí, reiniciar con un nuevo programa
cbi PORTE, 0 ;LED de estado encendido
lpm R, Z+ ;Elija los colores de la tabla
lpm V, Z+
lpm A, Z+
rcall Dimmercurva ;Corrección de brillo
ldi temp0, 64 ;tiempo de la funcion Discoteca Básica intermitente
Disco_esperar:
sbic PINC, 5 ;El interruptor 6 está encendido, continúe con funcion "disco"
ret ;interuptor apagado -> Detener Disco
rcall esperar
sbi PORTE,0 ;LED de estado apagado
dec temp0
brne Disco_esperar
rjmp Disco_Loop ;Color siguiente
; ------------------------------------------------------------------------------------------------
; Las tablas de colores para los colores del indicador Disco
; Byte primero = velocidad / extremo (255), los bytes 2-4 = R, G, B
; ------------------------------------------------------------------------------------------------
Disco_Mixcolores_1:
.db 128,255,0,0 ;Rojo
.db 128,0,255,0 ;Verde
.db 128,0,0,255 ;Azul
.db 128,255,0,0 ;Rojo
.db 128,0,255,0 ;Verde
.db 128,0,0,255 ;Azul
.db 64,255,0,0 ;Rojo
.db 64,0,255,0 ;Verde
.db 64,0,0,255 ;Azul
.db 64,255,0,0 ;Rojo
.db 64,0,255,0 ;Verde
.db 64,0,0,255 ;Azul
.db 128,0,255,255 ;Cyan
.db 128,255,0,255 ;Magenta
.db 128,255,255,0 ;Amarillo
.db 128,0,255,255 ;Cyan
.db 128,255,0,255 ;Magenta
.db 128,255,255,0 ;Amarillo
.db 64,0,255,255 ;Cyan
.db 64,255,0,255 ;Magenta
.db 64,255,255,0 ;Amarillo
.db 64,0,255,255 ;Cyan
.db 64,255,0,255 ;Magenta
.db 64,255,255,0 ;Amarillo
.db 0,0 ;Fin de la Tabla
Disco_Mixcolores_2:
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,210,255,255 ;Blanco
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,210,255,255 ;Blanco
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 0,0 ;Fin de la Tabla
Disco_Mixcolores_3:
.db 255,255,90,0 ;Naranja
.db 255,0,0,255 ;Azul
.db 255,255,128,0 ;Naranja
.db 255,0,255,255 ;Cyan
.db 255,255,128,0 ;Naranja
.db 255,0,255,0 ;Verde
.db 255,255,128,0 ;Naranja
.db 255,255,0,255 ;Magenta
.db 255,0,0,255 ;Azul
.db 255,255,0,255 ;Magenta
.db 255,0,255,255 ;Cyan
.db 255,255,0,255 ;Magenta
.db 255,255,255,0 ;Amarillo
.db 255,0,255,0 ;Verde
.db 0,0 ;Fin de la Tabla
Disco_Mixcolores_4:
.db 64,255,0,0 ;Rojo
.db 64,0,0,0 ;empieza
.db 64,0,255,255 ;Cyan
.db 64,0,0,0 ;empieza
.db 64,255,128,0 ;Naranja
.db 64,0,0,0 ;empieza
.db 64,0,255,0 ;Verde
.db 64,0,0,0 ;empieza
.db 64,255,0,255 ;Magenta
.db 64,0,0,0 ;empieza
.db 64,255,255,0 ;Amarillo
.db 64,0,0,0 ;empieza
.db 64,0,0,255 ;Azul
.db 64,0,0,0 ;empieza
.db 64,255,255,0 ;Amarillo
.db 64,0,0,0 ;empieza
.db 0,0 ;Fin de la Tabla
; ------------------------------------------------------------------------------------------------
; ISR para PWM por software
; ------------------------------------------------------------------------------------------------
ISR_PWM: ;Salida PWM
push temp0
in temp0, SREG
push temp0
ldi temp0, 0b00000111 ;Estado fundamental 1 = LED encendido, 0 = LED apagado (porque FET)
inc PWM_Count ;el contador de PWM de 0 a ++++
cp PWM_Count, R_Out ;Si se alcanza el límite para el rojo?
brlo PWM_V ;no, pase a verde
andi temp0, 0b00000110 ;sí, LED rojo apagado
PWM_V:
cp PWM_Count, V_Out ;Si se alcanza el límite para el verde?
brlo PWM_A ;no, pase a azul
andi temp0, 0b00000101 ;Sí, LED verde apagado
PWM_A:
cp PWM_Count, A_Out ;Si se alcanza el límite para el azul?
brlo PWM_edicion ;Si no es así, seguir emitiendo
andi temp0, 0b00000011 ;sí, LED azul desde
PWM_edicion: ;Emisión de nueva asignación de bits
out PORTB, temp0
pop temp0
out SREG, temp0 ;Restaurar el registro de estado + temp0
pop temp0
reti
; ------------------------------------------------------------------------------------------------
; Conversión dimmer transferencia curva en el registro PWM
; ------------------------------------------------------------------------------------------------
Dimmercurva:
push temp0
in temp0, SREG ;Guardar registros
push temp0
mov temp_ZL, ZL
mov temp_ZH, ZH
ldi ZL, LOW(DC_Data*2) ;Carga Z-puntero empezar valores dimmer bajo
ldi ZH, HIGH(DC_Data*2) ;Carga Z-puntero empezar valores dimmer alto
add ZL, R ;Añadir valor de rojo, de 16 bit+
ldi temp0,0
adc ZH,temp0
lpm R_Out, Z ;Obtener el valor de la tabla
ldi ZL, LOW(DC_Data*2) ;Carga Z-puntero empezar valores dimmer bajo
ldi ZH, HIGH(DC_Data*2) ;Carga Z-puntero empezar valores dimmer alto
add ZL, V ;Añadir valor verde, 16 bits
ldi temp0,0
adc ZH,temp0
lpm V_Out, Z ;Obtener el valor de la tabla
ldi ZL, LOW(DC_Data*2) ;Carga Z-puntero empezar valores dimmer bajo
ldi ZH, HIGH(DC_Data*2) ;Carga Z-puntero empezar valores dimmer alto
add ZL, A ;Añadir valor azul, 16 bit
ldi temp0,0
adc ZH,temp0
lpm A_Out, Z ;Obtener el valor de la tabla
pop temp0
out SREG, temp0 ;Restaurar registro
pop temp0
mov ZL, temp_ZL
mov ZH, temp_ZH
ret
; ------------------------------------------------------------------------------------------------
; Los datos para la curva de dimmer -DIMERCURVA
; ------------------------------------------------------------------------------------------------
DC_Data:
.db 0, 0, 1, 1, 1, 1, 1, 2
.db 2, 2, 2, 3, 3, 3, 4, 4
.db 4, 5, 5, 5, 6, 6, 7, 7
.db 8, 8, 9, 9, 10, 10, 11, 11
.db 12, 12, 13, 13, 14, 14, 15, 15
.db 16, 16, 17, 17, 18, 18, 19, 19
.db 20, 20, 21, 21, 22, 22, 23, 23
.db 24, 24, 25, 25, 26, 27, 28, 29
.db 30, 30, 31, 32, 33, 34, 35, 36
.db 36, 37, 38, 39, 40, 41, 42, 43
.db 43, 44, 45, 46, 47, 48, 49, 50
.db 51, 52, 52, 53, 54, 55, 56, 57
.db 58, 59, 60, 61, 62, 63, 64, 65
.db 66, 67, 68, 69, 70, 71, 72, 73
.db 74, 75, 76, 77, 78, 79, 80, 81
.db 82, 83, 84, 85, 86, 88, 89, 90
.db 91, 92, 93, 94, 95, 96, 97, 98
.db 99, 100, 102, 103, 104, 105, 106, 107
.db 108, 109, 110, 112, 113, 114, 115, 116
.db 117, 119, 120, 121, 122, 123, 124, 126
.db 127, 128, 129, 130, 132, 133, 134, 135
.db 136, 138, 139, 140, 141, 142, 144, 145
.db 146, 147, 149, 150, 151, 152, 154, 155
.db 156, 158, 159, 160, 161, 162, 164, 165
.db 167, 168, 169, 171, 172, 173, 174, 176
.db 177, 178, 180, 181, 182, 184, 185, 187
.db 188, 189, 191, 192, 193, 195, 196, 197
.db 199, 200, 202, 203, 204, 206, 207, 208
.db 210, 211, 213, 214, 216, 217, 218, 220
.db 221, 223, 224, 226, 227, 228, 230, 231
.db 233, 234, 236, 237, 239, 240, 242, 243
.db 245, 246, 248, 249, 251, 252, 254, 255
; ------------------------------------------------------------------------------------------------
; Bucle de temporisacion de espera (delay)
; ------------------------------------------------------------------------------------------------
esperar: ;3 loops de espera (delay)
push temp2 ;Registro de estado Temp + asegurar
push temp1
push temp0
in temp0, SREG
push temp0
mov temp0, Speed ;Velocidad de registro "Speed"
loop0:
ldi temp1, 255 ;255 repeticiones
sbis PINE, 2 ;Dip en 9? -> Duración maxima
ldi temp1, 64
loop1:
ldi temp2, 2 ;2 repeticiones
sbis PINE, 1 ;Dip en 10? -> Duracion Medio tiempo
ldi temp2, 1
loop2:
dec temp2
brne loop2
dec temp1
brne loop1
dec temp0
brne loop0
pop temp0
out SREG, temp0 ;Estado del registro + Restaurar Temporizador
pop temp0
pop temp1
pop temp2
ret
; ------------------------------------------------------------------------------------------------
; ternminacion de programa y Cierre
; ------------------------------------------------------------------------------------------------
fin: rjmp fin
las funciones que tiene con las llaves son
- DIP 1-3: rojo, verde, azul, respectivamente, de encendido / apagado - es decir, 7 colores (. Incl Blanco) - (DIP 1 y 2)usados tambien en lafuncion "Disco", ver más abajo
- DIP 4: En colores mezclados aquí el verde se reduce para producir naranja, es en blanco ., de modo conmutado la corrección es a deshacerse ., del tinte rosado del rojo intenso principal (las líneas se comentan en el programa) , aquí puede introducir otros valores si, por ejemplo (como se muestra a continuación) si el led es de 5 mm .,con un débil el rojo ., tiene similares resultados .... resultado llegado más tarde: puede ser ell " Rosa blanco" ., de hecho se puede ajustar, y luego cambiar a este interruptor, por ejemplo, entre el blanco cálido y blanco frío ....
- DIP 5: Entra en el "Strobe" a - el color actualmente ajustado parpadea / parpadea en la velocidad establecida ... con un valor fijo de encendido / apagado proporción de 02:10, por lo que el "parpadeo" más es mas lento , podría cambiar, pero me ha gustado mucho como queda alli ...
Recuadro: aquí esta la funcion por si alguien quiere construir un Strobo con LEDs, este ejemplo se puede usar , que es probablemente demasiado débil por la potencia de los led (pero con varios juntos queda muy bien) - pero tengo que decir que los dos led RGB Estrella., en 200 mA puede mantener fácilmente un Strobo, por ejemplo, 3 de 750 mA debe ser lo suficientemente fácil para la sala de fiestas - de esta manera ., entonces sigue siendo facil que usted pueda "parpadear" ese color ....
- DIP 6: Cambia el "disco-programas" - con DIP 1 y 2 a continuación, puede seleccionar varios (4 combinaciones )
- DIP 7: se enciende el fader RGB
- DIP 8: si el fader RGB se activa , es por este contacto que se activa el "Time Adjust" (tiempo de ajuste ) - cuando el estrobo está funcionando, puede aquí (rojo y azul parpadean alternativamente) en un interruptor "programa especial" - que tenia que ser el modo fácil ...
- DIP 9 + 10: Velocidad (para Fader, Strobo, indicadores Disco) - ambos de = "velocidad de avance", 10 = el doble de rápido, a las 9 = 4x, 8x, tanto a =
-
No pase todo a C solo, la parte del fading y rainbow_fading, tampoco pase la parte del PWM por software, ya que eso es hacerlo con una interrupcion cada X tiempo ( dado por el valor que se le carga al timer ) y ahi usar V_out,R_out y A_out, para comparar con el PWM por soft
un poco burdo el programa y seguro que se puede mejorar mas:
const short int arraydimmer[256]={0,0,1,1,......,251,252,254,255}; // Lo que aparece como DC_Data
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
void main() {
if(!PINC6){ fading();}
if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void fading() {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva()
PORTE0 = 0;
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE0 = 1;
Verde++;
DimmerCurva();
}
PORTE0 = 0;
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo--;
DimmerCurva();
}
PORTE0 = 0;
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul++;
DimmerCurva();
}
PORTE0 = 0;
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Verde--;
DimmerCurva();
}
PORTE0 = 0;
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo++;
DimmerCurva();
}
PORTE0 = 0;
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul--;
DimmerCurva();
}
PORTE0 = 0;
}
}
void delay(int velocidad) {
delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Rojo--;
Verde++;
DimmerCurva();
}
PORTE0=0;
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Verde--;
Azul++;
DimmerCurva();
}
PORTE0=0;
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Azul--;
Rojo++;
DimmerCurva();
}
PORTE0=0;
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
R_out=arraydimmer[Rojo];
V_out=arraydimmer[Verde];
A_out=arraydimmer[Azul];
}
Si observas ahi donde puse el delay, eso depende de las llaves, el cual van a cambiar el valor de temp1 y temp2, si no me equivoque eso son los ciclos que requieren segun cada caso.
esperar: ;3 loops de espera (delay)
push temp2 ; 3 ciclos rcall
push temp1
push temp0
in temp0, SREG
push temp0
mov temp0, Speed ; 10 ciclos
loop0:
ldi temp1, 255 ; 3 ciclos
sbis PINE, 2 ;
ldi temp1, 64
loop1:
ldi temp2, 2 ; 3 ciclos
sbis PINE, 1 ;
ldi temp2, 1
loop2:
dec temp2 ; (temp2-1)*3+2
brne loop2
dec temp1 ; (temp1-1)*3+2 ( acumulado esto multiplicado por lo de temp2)
brne loop1
dec temp0 ; (temp0-1)*3+2
brne loop0
pop temp0
out SREG, temp0 ; 9 ciclos
pop temp0
pop temp1
pop temp2
ret ; 4 ciclos
Hacer una formula para eso se llenaria de parentesis, asi que no la pongo.
-
hola y gracias
No pase todo a C solo, la parte del fading y rainbow_fading, tampoco pase la parte del PWM por software, ya que eso es hacerlo con una interrupcion cada X tiempo ( dado por el valor que se le carga al timer ) y ahi usar V_out,R_out y A_out, para comparar con el PWM por soft
un poco burdo el programa y seguro que se puede mejorar mas:
const short int arraydimmer[256]={0,0,1,1,......,251,252,254,255}; // Lo que aparece como DC_Data
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
void main() {
if(!PINC6){ fading();}
if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void fading() {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva()
PORTE0 = 0;
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE0 = 1;
Verde++;
DimmerCurva();
}
PORTE0 = 0;
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo--;
DimmerCurva();
}
PORTE0 = 0;
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul++;
DimmerCurva();
}
PORTE0 = 0;
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Verde--;
DimmerCurva();
}
PORTE0 = 0;
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo++;
DimmerCurva();
}
PORTE0 = 0;
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul--;
DimmerCurva();
}
PORTE0 = 0;
}
}
void delay(int velocidad) {
delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Rojo--;
Verde++;
DimmerCurva();
}
PORTE0=0;
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Verde--;
Azul++;
DimmerCurva();
}
PORTE0=0;
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Azul--;
Rojo++;
DimmerCurva();
}
PORTE0=0;
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
R_out=arraydimmer[Rojo];
V_out=arraydimmer[Verde];
A_out=arraydimmer[Azul];
}
Si observas ahi donde puse el delay, eso depende de las llaves, el cual van a cambiar el valor de temp1 y temp2, si no me equivoque eso son los ciclos que requieren segun cada caso.
Hacer una formula para eso se llenaria de parentesis, asi que no la pongo.
Bueno amigo tome tu codigo y le agrege lo que me parece que falta ., y aclaro que la parte fisica esta armada
solo armar esta libreria ., para que compile y probar ., yo uso el wachdog por que si te fijas el esquematico no esta conectado el "reset"
aca te muestro para que veas y revices si esta bien
#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include <avr/wdt.h>
//*********************************//
const short int arraydimmer[256]={0,0,0.0.0.0.0.0.0.0.0.1.1.1.1.1.1.1.1.1,1,1,1,1,2.2,2,2,3,3,3,4,4.4,5,5,5,6,6,7,7.8,8,9,9,10,10,11,11.12,12,13,13,14,14,15,15.16,16,17,17,18,18,19,19.20,20,21,21,22,22,23,23.24,24,25,25,26,27,28,29.30,30,31,32,33,34,35,36.36,37,38,39,40,41,42,43.43,44,45,46,47,48,49,50.51,52,52,53,54,55,56,57.58,59,60,61,62,63,64,65.66,67,68,69,70,71,72,73.74,75,76,77,78,79,80,81.82,83,84,85,86,88,89,90.91,92,93,94,95,96,97,98.99,100,102,103,104,105,106,107.108,109,110,112,113,114,115,116,117,119,120,121,122,123,124,126.127,128,129,130,132,133,134,135.136,138,139,140,141,142,144,145.146,147,149,150,151,152,154,155.156,158,159,160,161,162,164,165.167,168,169,171,172,173,174,176.177,178,180,181,182,184,185,187.188,189,191,192,193,195,196,197.199,200,202,203,204,206,207,208.210,211,213,214,216,217,218,220.221,223,224,226,227,228,230,231.233,234,236,237,239,240,242,243.245,246,248,249,251,252,254,255 }; // Lo que aparece como DC_Data
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
//************* Inicialización pines / port *****************//
void init_pinouts(){
//#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
// #endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE |= (1<<PE0);
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
}
void main()
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
sei(); // habilitar las interupciones globales ???
int PWM_timer; // inicializar el timer PWM
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
if(!PINC6){ fading();}
if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void fading() {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva()
PORTE0 = 0;
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE0 = 1;
Verde++;
DimmerCurva();
}
PORTE0 = 0;
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo--;
DimmerCurva();
}
PORTE0 = 0;
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul++;
DimmerCurva();
}
PORTE0 = 0;
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Verde--;
DimmerCurva();
}
PORTE0 = 0;
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo++;
DimmerCurva();
}
PORTE0 = 0;
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul--;
DimmerCurva();
}
PORTE0 = 0;
}
}
void delay(int velocidad) {
delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Rojo--;
Verde++;
DimmerCurva();
}
PORTE0=0;
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Verde--;
Azul++;
DimmerCurva();
}
PORTE0=0;
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Azul--;
Rojo++;
DimmerCurva();
}
PORTE0=0;
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
R_out=arraydimmer[Rojo];
V_out=arraydimmer[Verde];
A_out=arraydimmer[Azul];
}
te vuelvo a agradecer y espero tus comentarios
-
Ojo que faltan cosas...
Cosas que imagino que van a fallar:
1-
PINC6
PINC7
PORTE0
PINC6 es en ASM, pero en C tal ves debas hacer un (PINC & (1<<6)) , que es lo mismo que PINC & 0x20
De la misma forma que si quiero cambiar el bit 0 del PORTE:
Para ponerlo a 0
PORTE &= 0xFE;
PORTE &= ~(1<<0);
Para ponerlo a 1
PORTE |= 0x01;
PORTE |= (1<<0);
Para hacer un toggle
PORTE ^= 0x01;
PORTE ^= (1<<0);
No se si C tiene acceso directo a esos pines como para llamarlos PINC6 y PORTE0, recorda que yo no se del entorno de programacion de los ATmega.
2-
Este estoy seguro que va a fallar
En mi codigo "faltaron" unas cosas
if(!PINC5){ disco();}
Esa parte deberia quitarse, solo lo hice por que asi era el ASM, pero no hice la funcion disco() ya que me dijiste de las otras 2 funciones nomas.
3-
La funcion delay() esta incompleta, yo ahi di las formulas para sacar cuantos ciclos de espera son segun las opciones y la velocidad. No se si hay uan libreria que permita hacer un delay de ciclos en ves de tiempo. Por eso mismo no la escribi.
Sino vas a tener que pasar esos ciclos a tiempos y seguir usando la formula.
4-
El array posee puntos ( . ) en ves de comas ( , ) en algunos valores
5-
Falta el PWM por software el cual pense que ya estaba implementado, pero que eso se puede buscar en cualquier otro lado.
Jusatmente en la interrupcion del timer se cambia los valores del los puertos segun V_out,R_out y A_out.
-
hola amigo ¡¡¡¡¡ muchisimas gracias por enceñarme!!!!!
Ojo que faltan cosas...
Cosas que imagino que van a fallar:
1-
PINC6
PINC7
PORTE0
PINC6 es en ASM, pero en C tal ves debas hacer un (PINC & (1<<6)) , que es lo mismo que PINC & 0x20
De la misma forma que si quiero cambiar el bit 0 del PORTE:
Para ponerlo a 0
PORTE &= 0xFE;
PORTE &= ~(1<<0);
Para ponerlo a 1
PORTE |= 0x01;
PORTE |= (1<<0);
Para hacer un toggle
PORTE ^= 0x01;
PORTE ^= (1<<0);
No se si C tiene acceso directo a esos pines como para llamarlos PINC6 y PORTE0, recorda que yo no se del entorno de programacion de los ATmega.
2-
Este estoy seguro que va a fallar
En mi codigo "faltaron" unas cosas
if(!PINC5){ disco();}
Esa parte deberia quitarse, solo lo hice por que asi era el ASM, pero no hice la funcion disco() ya que me dijiste de las otras 2 funciones nomas.
3-
La funcion delay() esta incompleta, yo ahi di las formulas para sacar cuantos ciclos de espera son segun las opciones y la velocidad. No se si hay uan libreria que permita hacer un delay de ciclos en ves de tiempo. Por eso mismo no la escribi.
Sino vas a tener que pasar esos ciclos a tiempos y seguir usando la formula.
4-
El array posee puntos ( . ) en ves de comas ( , ) en algunos valores
5-
Falta el PWM por software el cual pense que ya estaba implementado, pero que eso se puede buscar en cualquier otro lado.
Jusatmente en la interrupcion del timer se cambia los valores del los puertos segun V_out,R_out y A_out.
bueno amigo ., yo arme esto pero todavia no compile., porque se que hay muchos errores
bueno muchos de ellos son los que tu amablemente me señalas
pero tranquilo ., el C para atmega no difiere mucho del C para pic ., basicamente son los cambio de nombres par las sentencias
- 1° . si te fijas en lo que agregue ., estan definidos los MINIDIPS en el inicio de PINOUTS
//************* Inicialización pines / port *****************//
void init_pinouts(){
//#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
// #endif a tener en cuenta que la sentencia USE_DIP la comente y asi la desbilite bueno en mis compilaciones se puede llamar ala lectura de los MINI-DIPS con esta sentencia get_dips();
de esa manera podemos leer todas las llaves de los 10 puertos (los 8 de C y los de E ., tal cual esta en la compilacion de ASM
eso tendrias que fiajarte si es correto a tu modo de ver
- 2° :
bueno en cuanto ala definicion de los puerto y su manejo me parece que esta correcto ., si no te es mucha molestia fijate por aca http://www.todopic.com.ar/foros/index.php?topic=44207.msg366067#msg366067 ese proyecto lo arme yo con las librerias base de H.Hölscher
claro que con la diferencia que alli manejo DMX pero las formas del compilador par atmega son iguales (el mismo compilador maneja ASM y C) o seatiene que andar lode ASM en C (basicamente claro)
tambien tome en cuenta que la parte de if(!PINC5){ disco();} no va afuncionar porque no tiene nigundesarrollo del programa ., pero la deje igual (se comenta y con eso arreglado el asunto )
- 3° : por eso inclui la libreria util_ delay ., en la compilacion ., en ASM la toma ., pero no se si en C ., no hay que cambiar los atributos
- 4° : no me di cuenta de eso., yo para no cambiar nada ., tome el DC_data como estaba y sacque las leyendas db en cada renglon , pero como soy una persona mayor ., ya no veo bien ., he confundido el punto con la coma ya lo arreglare en la proxima edicion (mis 53 años no vienen solos jajajajajajaja)
- 5° : yo implemente y defini un timer por si no lo viste
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción y tambien un PWM por sofware
int PWM_timer; // inicializar el timer PWM for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenadopero obiamente no lo implemente en la compilacion ., ademas ya tiene los pin de salidas declarados del puerto B y el LED del puero E
- 6° : en la compilacion actual yo implemente el timerO asi TCCR0|= (1<<CS02) ; ahora en la compilacion ASM esta asi
ldi temp0, 0b00000001; Conjunto CS00: 1 divisor
out TCCR0, temp0 o sea tendria que ser CS00 y yo lo cabie por CS02., porque habia un pequeño "parpadeo" en los led., en las compilaciones que yo usaba antes en C ., y con esta configuracion CS02., casi no se nota
yo no se como cambiar esa sentencia o sea "0b00000001" en binario para aplicarla por la que yo cambie CS02 ., y probarla en ASM
y vuelvo a repetir., muchas gracias por tu tiempo y tus ganas de enseñarme ., espero tus comentarios
-
Como te habia adelantado jamas programe en C/ASM ni un ATmega, ni un arduino, por lo cual estoy un poco perdido.
No sabia que hacer:
variable = (PINC & (1<<6));
era equivalente a
variable = PINC6;
Y cuando habia que cambiar o leer unicamente un pin, pense que podria haber problemas, por eso lo nombre.
-----------------------------------
Con respecto a los delays, ahi vi que usas esa libreria y que posee 2 funciones
_delay_ms();
_delay_us();
Tomando la tabla que deje donde se cuentan los ciclos, y tomando en consideracion que 1 ciclo es justamente 1 / Fosc, entonces el ciclo de reloj es de 0.125us (Para 8 Mhz)
teniendo en cuenta eso
PINE1 => temp2 , si 0 temp2=1 , si 1 temp2=2
PINE2 => temp1 , si 0 temp1=64 si 1 temp2=255
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
Podemos hacer la funcion de espera (o delay como habia puesto):
void espera(short int velocidad){
int tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
default:
break;
}
}
6° : en la compilacion actual yo implemente el timerO asi TCCR0|= (1<<CS02) ; ahora en la compilacion ASM esta asi
La traduccion directa del ASM al C de esas intrucciones que me pasaste es:
TCCR0 = 0x01;
Pero supongamos que no queres afectar a los otros bits, entonces mejor un:
TCCR0 &= 0x7; // Para limpiar si habia otro valor
TCCR0 |=0x1; // Escribimos el bit CS0
o directamente:
TCCR0 = ((TCCR0 & 0x7) | 0x01);
Lo que me parece raro. Por que como esta significa que el Timer no posee preescaler y por eso mismo se va a producir la interrupcion mas rapido, es decir los ultimos 3 bits del TCCR0 corresponden a CSn2:0, estos indican que preescaler va encima. Y esto va afectar al PWM por software, Mientras mas rapido, quiere decir que es mas rapida la frecuencia del PWM, por lo que no deberias notar nunca un parpadeo, Haber si me explico..
Tu PWM por soft usa una interrupcion, en esa interrupcion incrementa el valor del PWM en 1 hasta llegar a 255 y volver a comenzar de 0. entonces cuando pasa 255, es decir 255 interrupciones la señal subio y bajo. es decir hizo un ciclo completo.
Si vos agrandas el preescaler (dividis mas la señal del clock) quiere decir que va a contar mucho mas lento, por lo tanto mas tiempo para la interrupcion y en consecuencia va a estar mucho mas tiempo encendido y tambien apagado la salida.
Segun el datasheet con un valor de 001b de esos bits la frecuencia del reloj entra directamente al timer. Mientras que si pones un 100b como vos queres la frecuencia del reloj se encuentra disminuida por 256.
De todas formas si queres poner el preescaler asi:
TCCR0|= (1<<CS02)
es equivalente a
TCCR0 &= 0x7; // Limpio los bits por si otra instruccion antes los cambio, esto detiene el timer
TCCR0 |= 0x4; // Activo el bit CS02 el cual le da reloj al timer con un preescaler de 1/256
y tambien un PWM por sofware
int PWM_timer; // inicializar el timer PWM for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
Eso no es un PWM por software y esta mal realizado. No deberias tener nunca un for ahi. Ni si quiera en la interrupcion, solamente en la interrupcion deberia quedarte algo asi:
// *************** Soft PWM ****************
ISR (TIMER0_OVF_vect)
{
salida=0x7;
if (R_out>=PWM_timer) { salida &= 0x06; } // Esta es la traduccion directa del ASM , por eso lo puse asi.
if (V_out>=PWM_timer) { salida &= 0x05; }
if (A_out>=PWM_timer) { salida &= 0x03; }
PORTB = salida;
}
Y tu main como dije no deberia tener el for, sino que simplente el while y estar continuamente llamando a las funciones que debe.
El por que no deberias tener un for actuando de PWM en el main, es por que tenes delays involucrados. esto hace que cada cuenta del PWM_timer (PWMCnt en el ASM) sea distinto, y la idea es que cada seccion de las 256 secciones ( al contar de 0 a 255 ) tengan el mismo tiempo, asi tener una buena definicion de duty cicle
-
¡¡¡¡¡¡ MUCHISIMAS GRACIAS !!!!!!
Como te habia adelantado jamas programe en C/ASM ni un ATmega, ni un arduino, por lo cual estoy un poco perdido.
No sabia que hacer:
variable = (PINC & (1<<6));
era equivalente a
variable = PINC6;
Y cuando habia que cambiar o leer unicamente un pin, pense que podria haber problemas, por eso lo nombre.
-----------------------------------
Con respecto a los delays, ahi vi que usas esa libreria y que posee 2 funciones
_delay_ms();
_delay_us();
Tomando la tabla que deje donde se cuentan los ciclos, y tomando en consideracion que 1 ciclo es justamente 1 / Fosc, entonces el ciclo de reloj es de 0.125us (Para 8 Mhz)
teniendo en cuenta eso
PINE1 => temp2 , si 0 temp2=1 , si 1 temp2=2
PINE2 => temp1 , si 0 temp1=64 si 1 temp2=255
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
Podemos hacer la funcion de espera (o delay como habia puesto):
void espera(short int velocidad){
int tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
default:
break;
}
}
6° : en la compilacion actual yo implemente el timerO asi TCCR0|= (1<<CS02) ; ahora en la compilacion ASM esta asi
La traduccion directa del ASM al C de esas intrucciones que me pasaste es:
TCCR0 = 0x01;
Pero supongamos que no queres afectar a los otros bits, entonces mejor un:
TCCR0 &= 0x7; // Para limpiar si habia otro valor
TCCR0 |=0x1; // Escribimos el bit CS0
o directamente:
TCCR0 = ((TCCR0 & 0x7) | 0x01);
Lo que me parece raro. Por que como esta significa que el Timer no posee preescaler y por eso mismo se va a producir la interrupcion mas rapido, es decir los ultimos 3 bits del TCCR0 corresponden a CSn2:0, estos indican que preescaler va encima. Y esto va afectar al PWM por software, Mientras mas rapido, quiere decir que es mas rapida la frecuencia del PWM, por lo que no deberias notar nunca un parpadeo, Haber si me explico..
Tu PWM por soft usa una interrupcion, en esa interrupcion incrementa el valor del PWM en 1 hasta llegar a 255 y volver a comenzar de 0. entonces cuando pasa 255, es decir 255 interrupciones la señal subio y bajo. es decir hizo un ciclo completo.
Si vos agrandas el preescaler (dividis mas la señal del clock) quiere decir que va a contar mucho mas lento, por lo tanto mas tiempo para la interrupcion y en consecuencia va a estar mucho mas tiempo encendido y tambien apagado la salida.
Segun el datasheet con un valor de 001b de esos bits la frecuencia del reloj entra directamente al timer. Mientras que si pones un 100b como vos queres la frecuencia del reloj se encuentra disminuida por 256.
De todas formas si queres poner el preescaler asi:
TCCR0|= (1<<CS02)
es equivalente a
TCCR0 &= 0x7; // Limpio los bits por si otra instruccion antes los cambio, esto detiene el timer
TCCR0 |= 0x4; // Activo el bit CS02 el cual le da reloj al timer con un preescaler de 1/256
y tambien un PWM por sofware
int PWM_timer; // inicializar el timer PWM for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
Eso no es un PWM por software y esta mal realizado. No deberias tener nunca un for ahi. Ni si quiera en la interrupcion, solamente en la interrupcion deberia quedarte algo asi:
// *************** Soft PWM ****************
ISR (TIMER0_OVF_vect)
{
salida=0x7;
if (R_out>=PWM_timer) { salida &= 0x06; } // Esta es la traduccion directa del ASM , por eso lo puse asi.
if (V_out>=PWM_timer) { salida &= 0x05; }
if (A_out>=PWM_timer) { salida &= 0x03; }
PORTB = salida;
}
Y tu main como dije no deberia tener el for, sino que simplente el while y estar continuamente llamando a las funciones que debe.
El por que no deberias tener un for actuando de PWM en el main, es por que tenes delays involucrados. esto hace que cada cuenta del PWM_timer (PWMCnt en el ASM) sea distinto, y la idea es que cada seccion de las 256 secciones ( al contar de 0 a 255 ) tengan el mismo tiempo, asi tener una buena definicion de duty cicle
bueno amigaso ., por empezar., aunque parezca que se mucho ., no se engañe ., NO es asi
Y viendo eso ., esperando que no lo tome a mal ., " lo declaro mi maestro " ., soy una persona que por cuestiones de la vida ., no pudo ir ala escuela.,
el aprender aleer y escribir ., aun mas el manejo de la informatica ., lo aprendi solo y por mis propios medios
yo empece con los micros a mediados del 2013 ., y al contrario de la mayoria ., directamente con atmega
intente aprender ASM .,(y puse mucho empeño ) ., tengo tres tutoriales traducidos al español por mi ., pero no hay caso no entiendo muchisimas cosas
En cambio con C (aunque todavia hay cosas que me confunden ) me llevo mejor ., es mas entendible ( para mi )
esto lo cuento par que sepa que tipo de persona "esta" ., enfrente
bueno como a mi me encanta el DMX ., "juego" con los led y motorcitos PAP
Vi y acepte que en estos casos para tener multifunciones ., se debe implementar el PWM por sotfware., y no por hardware
pues el PWM ., se puede usar en mas de una funcion ( ¿¿¿ o estoy equivocado ??? ) ., igual menra que la IRS
por el simple hecho ., que por lo general se controlan todas las salidas de un PORT
como en este caso que tengo 3 PORT ( portb ) ., para los led y me quedan 5 libres ( que podria colocar un motor tranquilamente y que funcione con otro timer )
por eso uso el PWM asi
en la compilacion DMX., que indique mas arriba ., funciona con las dos configuraciones de timer ( TCCR0|= (1<<CS00 ) y TCCR0|= (1<<CS02) )
L e pido mil perdones , por no entenderlo ., pero se me hace dificil comprender cuando usa definiciones asi
int tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break; concretamente cuando usa por ejemplo: "" case 0x04:" ., la definicion CASE si la entiendo pero 0x04 ., no
bueno aca le publico lo que mas o menos arme ( no esta compilado todavia ) solo el bosquejo
tambien prepare las llaves MINI-DIPS para poder poner alli las escala de tiempos y demas
con la llave N° 10 ( PINE=1) en ON tendriamos funcionamiento ., en OFF apagado
de alli nos pasa a otra funcion (PINE=2) ., en ON es fading y en OFF es rainbow
aparte en las que quedan (PINC=0 a PINC=7) se puede agregar las velocidades u otra funcion que nesesites ., ( por ahora esta definido los valores DMX ) ., pero eso se puede cambiar y tenes 8 posisciones., que tambien se suman
el valor de la suma o resultado lo puede alojar en ADRRESTEMP
tambien esta la posibilidad que nesesitas otra funcion de las MINI-DIPS la numero 10 (PINE=1) en OFF ., tenga otras funciones a definir .,
bueno aca te pongo lo que arme y vamos viendo
#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include <avr/wdt.h>
// *** establecer valor de WHILE ***//
enum {FALSE=0, TRUE=1}; //*********************************//
uint8_t count= 1; // contador del soft PWM
enum {FADING,RAINBOW_FADER,} mode;
//*********************************//
const short int arraydimmer[256]={0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1.1,1,1,1,1,1,1,2.2,2,2,3,3,3,4,4.4,5,5,5,6,6,7,7,8,8,9,9,10,10,11,11.12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19.20,20,21,21,22,22,23,23.24,24,25,25,26,27,28,29.30,30,31,32,33,34,35,36.36,37,38,39,40,41,42,43,43,44,45,46,47,48,49,50,51,52,52,53,54,55,56,57,58,59,60,61,62,63,64,65.66,67,68,69,70,71,72,73.74,75,76,77,78,79,80,81,82,83,84,85,86,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,112,113,114,115,116,117,119,120,121,122,123,124,126,127,128,129,130,132,133,134,135.136,138,139,140,141,142,144,145,146,147,149,150,151,152,154,155.156,158,159,160,161,162,164,165,167,168,169,171,172,173,174,176,177,178,180,181,182,184,185,187,188,189,191,192,193,195,196,197,199,200,202,203,204,206,207,208,210,211,213,214,216,217,218,220,221,223,224,226,227,228,230,231,233,234,236,237,239,240,242,243,245,246,248,249,251,252,254,255 }; // Lo que aparece como DC_Data
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE |= (1<<PE0);
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
Address= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
//if (Temp != 0)
// {
// Address= Temp;
// }
#endif
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
sei(); // habilitar las interupciones globales ???
int PWM_timer; // inicializar el timer PWM
while(1) // bucle principal (LOOP)
{
get_dips(); // Comprobar dip-switch y habilitar la funcion
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
// if(!PINC6){ fading();}
// if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void fading() {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva()
PORTE0 = 0;
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE0 = 1;
Verde++;
DimmerCurva();
}
PORTE0 = 0;
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo--;
DimmerCurva();
}
PORTE0 = 0;
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul++;
DimmerCurva();
}
PORTE0 = 0;
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Verde--;
DimmerCurva();
}
PORTE0 = 0;
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo++;
DimmerCurva();
}
PORTE0 = 0;
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul--;
DimmerCurva();
}
PORTE0 = 0;
}
}
void delay(int velocidad) {
delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Rojo--;
Verde++;
DimmerCurva();
}
PORTE0=0;
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Verde--;
Azul++;
DimmerCurva();
}
PORTE0=0;
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Azul--;
Rojo++;
DimmerCurva();
}
PORTE0=0;
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
R_out=arraydimmer[Rojo];
V_out=arraydimmer[Verde];
A_out=arraydimmer[Azul];
}
if (count == 0xFF)
{ // Llamado con 122Hz
count= 1;
}
else count++;
}
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER:
count = OV_COUNT + Address;
break;
case FADING :
count = OV_COUNT + Address * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;
if (mode==FADING){
}
}else{ timer_counter++; }
{
}
bueno espero tus comentarios tan educativos para mi ., aunque no lo creas ., eres la primer persona que me explica ., algo de C ., que no usa ese lenguaje ( partiendo del conosimiento del ASM )., y para colmo no usa atmega., y eso es muy destacable ., infinitas gracias
-
directamente con atmega intente aprender ASM .,(y puse mucho empeño )
Tenes 2 caminos concretamente:
Usar un lenguaje de alto nivel como C, el cual te abstrae un poco del hardware y sus funciones, hace que programar sea mas facil.
Por otro lado tenes el ASM que es ideal en tema del provecho que le podes sacar al micro, pero que te ocupa mucho tiempo para hacer algo simple. Lo que si te lleva a aprender bien el manejar el binario y saber bien como se maneja por dentro el microcontrolador asi de esa forma luego cuando pasas a C podes aprovecharlo mas.
Vi y acepte que en estos casos para tener multifunciones ., se debe implementar el PWM por sotfware., y no por hardware
Las principales razones de por que se usa un PWM por software y no uno por hardware son varias.
Si es de elegir se prefiere siempre un PWM por Hardware y no uno por software, por que de esa forma el micro se encuentra libre ejecutando otras instrucciones mientras que el Hardware solo genera el PWM.
Aunque esto tiene algunos problemas segun el micro que sea. Uno de estos por la cantidad de salidas. Por cada pin se requiriria el Hardware para el mismo, entonces por ahi no se tienen 8 salidas con PWM por hardware. Entonces te fuerza a usar un PWM por Software.
Otra de las razones es que algunos PWM por Hardware no son lo suficientemente lentos. Tal ves el maximo periodo es de 1ms y vos necesitas un periodo de 20ms, entonces no queda otra que usar uno por Software a pesar que significa que el micro tenga que ponerse a hacer el PWM y no solo el programa en cuestion.
concretamente cuando usa por ejemplo: "" case 0x04:" ., la definicion CASE si la entiendo pero 0x04
Hay distintas formas de expresar los numeros, ya sea binario, decimal, hexadecimal, octal(realmente nunca lo use), esto va a depender a veces del compilador usado, algunos formatos que eh visto:
Binario (8bits):
0b00100101
b'00100101'
Decimal
30
.30
30d
Hexadecimal
0x20
20h
Lo interesante del Hexadecimal y el binario es que tienen una forma facil de pasar de uno a otro
0 4
0x04 = 0000 0100 = 4 decimal
0x2A = 0010 1010 = 42 decimal
2 A
Si observas al numero binario de 8 bits lo separe en 4 bit, y cada 4 bits es representado por un solo valor en hexadecimal. En esa parte hago:
(PINE&0x06)
es igual a ( separo los bits para que sea mas legible nada mas )
PINE & 0000 0110
entonces eso me va a dejar los bits de los pines 1 y 2.
Segun el valor que salga de ahi, el resultado de esa AND, va a ser donde entre el case. Si por ejemplo tengo que
PINE = 0101 1101
Entonces tendria -> PINE & 0000 0110 -> 0101 1101 & 0000 0110 -> 0000 0100
Eso en hexadecimal seria 0x04
bueno espero tus comentarios tan educativos para mi ., aunque no lo creas ., eres la primer persona que me explica ., algo de C ., que no usa ese lenguaje ( partiendo del conosimiento del ASM )., y para colmo no usa atmega., y eso es muy destacable ., infinitas gracias
El lenguaje C es igual en todos los micros, sea de microchip / atmel / renesas / ti / nxp, etc. Lo unico que cambian son los registros a configurar, y modulos. Y eso es lo bueno de C. Una funcion en un micro puede ser usada en otro, siempre y cuando no modifique registros, ya que vas a tener que buscar equivalentes entre los micros. Si haces:
tiempo=((568 * (velocidad-1)+3)/1000);
En cualquier micro eso va a servir. Esto no pasa con ASM ya que el manejo de memoria es distinto, las instrucciones son distintas incluso de cada marca de microcontrolador y vas a tener que aprender todo de ese micro nuevamente.
Y una ves que viste algunos microcontroladores, vas a notar que TODOS son casi iguales, si usas un timer, tenes que buscar los registros a modificar y listo, llenas esos registros y tenes andando tu timer sea cual sea tu micro.
-
bueno amigaso ., a vuelto a responder magistralmente
((:-)) ((:-)) ((:-)) ((:-)) muchisimas gracias ., por el tiempo y la voluntad puesta de manifiesto
espero que tenga tiempo (y ganas de leer el bosquejo de programacion que hice
viendo de esa manera mis posibles "horrores"
aca subo varios tutos ., de ASM par atmega., (incluida la hoja de datos resumida del 8515 traducida
si algun moderador considera que tienen que publicarce en otro lugar que lo corrija (gracias )
quedo ala espera de su comentario ., muchas gracias NOTA AL MODERADOR : quedaron sin subir 4 archivos con los tutos traducidos ., por el limite de tamaño
-
Por lo que leo, veo que estais saliendo del Tema DMX512 y tutoriando de Lenguaje , para este caso seria mejor abrir el tema en el Subforo de Atmel.
Querido amigo Locodelafonola, quizas te ha pasado por el Subforo de Atmel, pues alli hay muchos tutoriales de todos los lenguaje de programacion y de Assemble mas aun. por favor respectar el orden de los Subforo , asi se facilita a la hora de buscar Informaciones. para esto esta el foro Clasificado, no siendo asi seria dificil para Usuarios que usen el Buscador encontrar la Info que busquen.
Saludos
-
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas
http://www.todopic.com.ar/foros/index.php?topic=44884.0
-
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas
http://www.todopic.com.ar/foros/index.php?topic=44884.0
Si lo se, pero el Tema al principio trataba sobre DMX512, por eso lo pase para aca,
lo que aconsejaria al Amigo Locodelafonola que abra un tema en el Subforo de Atmel,
Saludos
-
hola
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas
http://www.todopic.com.ar/foros/index.php?topic=44884.0
Si lo se, pero el Tema al principio trataba sobre DMX512, por eso lo pase para aca,
lo que aconsejaria al Amigo Locodelafonola que abra un tema en el Subforo de Atmel,
Saludos
gracias a los dos ., basicamente espero poder compilar y que funcione
luego pasrlo a DMX ., en mi libreria base que funciona
En los comandos de recepcion y accionamiento no tengo problema ., por que basicamente trabajamos con valores de 0 a 255
Voy a aclarar un poco la cuestion ., esta funcion que quiero implementar (aprenderla mas que todo )., esta en los equipos DMX profecionales
ya sea que tenga el comando DMX ., o cuando funcionan en manual o audioritmico ., si se fijan el esquematico de mi montaje !!!!! es DMX ¡¡¡¡¡
igual que las funciones de la libreria que dio origen a este hilo., no se desvirtua (al menos eso creo)
asi que no creo que alla problemas ., mientras pueda lograr algo y se comparta ., no importa el lugar ., gracias a los dos
-
Disculpa que por la falta de tiempo solo me limite a contestar algunas preguntas rapidas. Si podes poner los errores que te dan es mas facil solucionarlo.
-
ok amigo y muchas gracias
Disculpa que por la falta de tiempo solo me limite a contestar algunas preguntas rapidas. Si podes poner los errores que te dan es mas facil solucionarlo.
bueno aqui va ., aclaro que lo que arme es pensando usar esta finciones de fading y rainbow., en dmx y standalone (que seria esta)
es reparado los errores del armado ., de la compilacion hasta donde yo se ., y como veras los errores que me larga son del agregado de estas funiones .,
//#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include <avr/wdt.h>
// *** establecer valor de WHILE ***//
enum {FALSE=0, TRUE=1};
//*********************************//
uint8_t count= 1; // contador del soft PWM
enum {FADING,RAINBOW_FADER,} mode; //funciones de muestr
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out; //
//*********************************//
const short int arraydimmer[256]={0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1.1,1,1,1,1,1,1,2.2,2,2,3,3,3,4,4.4,5,5,5,6,6,7,7,8,8,9,9,10,10,11,11.12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19.20,20,21,21,22,22,23,23.24,24,25,25,26,27,28,29.30,30,31,32,33,34,35,36.36,37,38,39,40,41,42,43,43,44,45,46,47,48,49,50,51,52,52,53,54,55,56,57,58,59,60,61,62,63,64,65.66,67,68,69,70,71,72,73.74,75,76,77,78,79,80,81,82,83,84,85,86,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,112,113,114,115,116,117,119,120,121,122,123,124,126,127,128,129,130,132,133,134,135.136,138,139,140,141,142,144,145,146,147,149,150,151,152,154,155.156,158,159,160,161,162,164,165,167,168,169,171,172,173,174,176,177,178,180,181,182,184,185,187,188,189,191,192,193,195,196,197,199,200,202,203,204,206,207,208,210,211,213,214,216,217,218,220,221,223,224,226,227,228,230,231,233,234,236,237,239,240,242,243,245,246,248,249,251,252,254,255 }; // Lo que aparece como DC_Data
// ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE |= (1<<PE0);
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
Address= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
//if (Temp != 0)
// {
// Address= Temp;
// }
#endif
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
sei(); // habilitar las interupciones globales ???
int PWM_timer; // inicializar el timer PWM
while(1) // bucle principal (LOOP)
{
get_dips(); // Comprobar dip-switch y habilitar la funcion
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
// if(!PINC6){ fading();}
// if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void fading() {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva()
PORTE0 = 0;
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE0 = 1;
Verde++;
DimmerCurva();
}
PORTE0 = 0;
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo--;
DimmerCurva();
}
PORTE0 = 0;
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul++;
DimmerCurva();
}
PORTE0 = 0;
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Verde--;
DimmerCurva();
}
PORTE0 = 0;
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo++;
DimmerCurva();
}
PORTE0 = 0;
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul--;
DimmerCurva();
}
PORTE0 = 0;
}
}
void delay(int velocidad) {
delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Rojo--;
Verde++;
DimmerCurva();
}
PORTE0=0;
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Verde--;
Azul++;
DimmerCurva();
}
PORTE0=0;
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Azul--;
Rojo++;
DimmerCurva();
}
PORTE0=0;
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
R_out=arraydimmer[Rojo];
V_out=arraydimmer[Verde];
A_out=arraydimmer[Azul];
}
if (count == 0xFF)
{ // Llamado con 122Hz
count= 1;
}
else count++;
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER:
count = OV_COUNT + Address;
break;
case FADING :
count = OV_COUNT + Address * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;
if (mode==FADING){
}
}else{ timer_counter++; }
{
}
}
los errores que me larga el compilador son estos
Build started 19.8.2015 at 20:21:43
avr-gcc.exe -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d -c ../fading_raibow.c
../fading_raibow.c:1:1: warning: "F_CPU" redefined
<command-line>: warning: this is the location of the previous definition
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c: In function 'main':
../fading_raibow.c:97: warning: implicit declaration of function 'cli'
../fading_raibow.c:101: warning: implicit declaration of function 'sei'
../fading_raibow.c: In function 'fading':
../fading_raibow.c:122: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:122: error: (Each undeclared identifier is reported only once
../fading_raibow.c:122: error: for each function it appears in.)
../fading_raibow.c:126: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:127: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:128: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:130: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:131: error: expected ';' before numeric constant
../fading_raibow.c:136: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c:137: warning: implicit declaration of function 'delay'
../fading_raibow.c:137: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:138: error: lvalue required as left operand of assignment
../fading_raibow.c:142: error: lvalue required as left operand of assignment
../fading_raibow.c:149: error: lvalue required as left operand of assignment
../fading_raibow.c:153: error: lvalue required as left operand of assignment
../fading_raibow.c:160: error: lvalue required as left operand of assignment
../fading_raibow.c:164: error: lvalue required as left operand of assignment
../fading_raibow.c:171: error: lvalue required as left operand of assignment
../fading_raibow.c:175: error: lvalue required as left operand of assignment
../fading_raibow.c:182: error: lvalue required as left operand of assignment
../fading_raibow.c:186: error: lvalue required as left operand of assignment
../fading_raibow.c:193: error: lvalue required as left operand of assignment
../fading_raibow.c:197: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'delay':
../fading_raibow.c:203: warning: implicit declaration of function 'delay_ciclos'
../fading_raibow.c: In function 'rainbow_fader':
../fading_raibow.c:231: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:232: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:233: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:234: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:242: error: lvalue required as left operand of assignment
../fading_raibow.c:247: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:253: error: lvalue required as left operand of assignment
../fading_raibow.c:264: error: lvalue required as left operand of assignment
../fading_raibow.c:275: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'DimmerCurva':
../fading_raibow.c:286: error: 'R_out' undeclared (first use in this function)
../fading_raibow.c:286: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:287: error: 'V_out' undeclared (first use in this function)
../fading_raibow.c:287: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:288: error: 'A_out' undeclared (first use in this function)
../fading_raibow.c:288: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c: At top level:
../fading_raibow.c:300: warning: return type defaults to 'int'
../fading_raibow.c: In function 'ISR':
../fading_raibow.c:300: warning: type of '__vector_7' defaults to 'int'
../fading_raibow.c:304: error: 'Address' undeclared (first use in this function)
make: *** [fading_raibow.o] Error 1
Build failed with 36 errors and 20 warnings...
con los "WARNINGS" no hay problema ., si no son graves ., compila igual., pero son solo advertencias de forma., nada mas
he tratado de hacerlo solo., pero sinceramente me confudi mas ., son los "ERROR" ., los que hay que tener en cuenta ( pero me parece que falta definir las funciones o funcion de cad cosa
gracias y perdona la molestia
-
Voy a hacer un resumen, disculpa si no me explayo mucho en la explicacion:
../fading_raibow.c:1:1: warning: "F_CPU" redefined
Esto es por que tenias el #define F_CPU y en otro lado tenes escrito lo mismo, es decir solo necesitas ponerlo 1 sola ves
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
Esto es por que el arraydimmer tiene cerca de 270 y algo mas valores y vos intenta ponerlo en un array de 256 valores, aca hay valores de mas, si observas el archivo ASM ni siquiera hay tantos ceros.
../fading_raibow.c:97: warning: implicit declaration of function 'cli'
../fading_raibow.c:101: warning: implicit declaration of function 'sei'
Mas claro que nunca, basicamente esas funciones no existen, no se si tenes que agregar algun archivo para usarlas. Creo que es:
#include <avr/interrupt.h>
../fading_raibow.c:122: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:122: error: (Each undeclared identifier is reported only once
../fading_raibow.c:122: error: for each function it appears in.)
../fading_raibow.c:126: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:127: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:128: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:231: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:232: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:233: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:234: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:247: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:286: error: 'R_out' undeclared (first use in this function)
../fading_raibow.c:286: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:287: error: 'V_out' undeclared (first use in this function)
../fading_raibow.c:287: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:288: error: 'A_out' undeclared (first use in this function)
../fading_raibow.c:288: error: 'Azul' undeclared (first use in this function)
Otro error muy simple... una cosa a notar que existe la variable "velocidad" y Velocidad" intenta hacer que sea una u otra y no ambas. es decir poneles a todos "Velocidad" o todos "velocidad"
Luego hay que declararlas. Aunque las veo declaradas:
Short int Velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
../fading_raibow.c:138: error: lvalue required as left operand of assignment
../fading_raibow.c:142: error: lvalue required as left operand of assignment
../fading_raibow.c:149: error: lvalue required as left operand of assignment
../fading_raibow.c:153: error: lvalue required as left operand of assignment
../fading_raibow.c:160: error: lvalue required as left operand of assignment
../fading_raibow.c:164: error: lvalue required as left operand of assignment
../fading_raibow.c:171: error: lvalue required as left operand of assignment
../fading_raibow.c:175: error: lvalue required as left operand of assignment
../fading_raibow.c:182: error: lvalue required as left operand of assignment
../fading_raibow.c:186: error: lvalue required as left operand of assignment
../fading_raibow.c:193: error: lvalue required as left operand of assignment
../fading_raibow.c:197: error: lvalue required as left operand of assignment
Corresponde a estas lineas:
PORTE0 = 0;
PORTE0 = 1;
Tal ves no se modifican asi, es como que no reconociera el PORTE0, asi que lo mas seguro es que tengas que reemplazarlo por un PORTE |= 0x01 ( Para ponerlo en 1 ) y un PORTE &=0xFE ( Para ponerlo en 0 ).
../fading_raibow.c:130: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:131: error: expected ';' before numeric constant
../fading_raibow.c:136: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c:137: warning: implicit declaration of function 'delay'
../fading_raibow.c:203: warning: implicit declaration of function 'delay_ciclos'
Los mensajes es por que no se crearon los prototipos de las funciones, y el error es por que falta un punto y coma en el codigo
Tambien notar que en un lado usamos el nombre "delay" y en otro lado "delay_ciclos", Cuando solo deberia haber el "delay" que es la funcion que nosotros creamos
../fading_raibow.c:300: warning: return type defaults to 'int'
../fading_raibow.c:300: warning: type of '__vector_7' defaults to 'int'
Por que no se declaro el tipo de funcion
ISR(TIMER0_OVF_vect){
....
}
por
void ISR(TIMER0_OVF_vect){
......
}
../fading_raibow.c:304: error: 'Address' undeclared (first use in this function)
Obviamente no definio esa variable tampoco, esta usada en la interrupcion, asi que por eso el error.
-------------
Solucionado todo esto deberia compilar o salir nuevos errores
-
Bueno amigo ., esto va por muy buen camino., gracias a usted ¡¡¡¡ infinitas Gracias !!!!
bueno alli acomode un poco las cosas
Agregue la libreria #include"fading_raibow.h" ., repare lo del ocilador ( estaba definido 2 veces en la optimizacion de codigo)., y el potE0 ., yo creo que va a funcionar., como estaba., desde un pricipio ., tenia mal dedinido el port en "pinouts" ., por eso largaba error
Bueno lo que larga ahora., creo que son errores de forma., no de funcionamiento
yo creo que para mi ver., son la formas que estan escritas las funciones nada mas que eso
por ejemplo : while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();} Bien yo esa funcion la defini en el array de llaves PINE2., ahora la duda que tengo es que al parecer ., PINC6 y PINC7 ., trabajen en conjunto o separadamente ., no lo defini ni cambie para confirmar eso
Tal vez., no presto atencion., a lo que yo arme (!!! ojo ¡¡¡¡ puede estar mal ) ., porque ya esta definido la funcion de la llave OFF/ON ., que lee GET_DIPS() ., en cada ciclo del While
Por eso digo ., que talvez entendi mal el funcionamiento
En el array de llaves esta con valores de DMX ., pero alli se pueden poner valores del delay (esta armado par que se sumen las llaves., y tome el total en DMXADRRDES = Temp
Como lo que esta puesto aca : //temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/ Otra cosa que hice fue ., declarar las salidas de los LED R,G,B
Ahora lo que no se ., es que valor toma de la compilacion para el PWM ., como tampoco entiendo como se ejecuta la salida en la compilacion ASM
Esto como dije ., aparte de aprender como funciona un fading por software ., quiero aplicarlo al DMX
En la configuracion fisica., que tengo armada ., solo usa los tres puertos de B y tengo los puertos libres de A
Yo pesaba agregar mas llaves en puertos A ( las que sean necesarias) y que trabajen en conjunto con las de los puetos C y E
Por eso las forma del bosquejo., pero por ahora ., esta armado de acuerdo al esquema fisico que ya tengo construido y asi probar
Bueno ahora lo que quedo es asi
//#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include"fading_raibow.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
// *** establecer valor de WHILE ***//
enum {FALSE=0, TRUE=1};
//*********************************//
uint8_t count= 1; // contador del soft PWM
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out; //
//*********************************//
const short int arraydimmer[256]={0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155, 156, 158, 159, 160, 161, 162, 164, 165, 167, 168, 169, 171, 172, 173, 174, 176, 177, 178, 180, 181, 182, 184, 185, 187, 188, 189, 191, 192, 193, 195, 196, 197, 199, 200, 202, 203, 204, 206, 207, 208, 210, 211, 213, 214, 216, 217, 218, 220, 221, 223, 224, 226, 227, 228, 230, 231, 233, 234, 236, 237, 239, 240, 242, 243, 245, 246, 248, 249, 251, 252, 254, 255}; // Lo que aparece como DC_Data
// ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
//if (Temp != 0)
// {
// Address= Temp;
// }
#endif
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
sei(); // habilitar las interupciones globales ???
int PWM_timer; // inicializar el timer PWM
while(1) // bucle principal (LOOP)
{
get_dips(); // Comprobar dip-switch y habilitar la funcion
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
if (R_out>PWM_timer) //red
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
}
if (V_out>PWM_timer) //green
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}
if (V_out>PWM_timer) //blue
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}
// if(!PINC6){ fading();}
// if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void fading(); {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE0 = 1;
Verde++;
DimmerCurva();
}
PORTE0 = 0;
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo--;
DimmerCurva();
}
PORTE0 = 0;
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul++;
DimmerCurva();
}
PORTE0 = 0;
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Verde--;
DimmerCurva();
}
PORTE0 = 0;
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Rojo++;
DimmerCurva();
}
PORTE0 = 0;
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE0 = 1;
Azul--;
DimmerCurva();
}
PORTE0 = 0;
}
}
void delay(int velocidad) {
delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader();{
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE0 = 0;
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Rojo--;
Verde++;
DimmerCurva();
}
PORTE0=0;
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Verde--;
Azul++;
DimmerCurva();
}
PORTE0=0;
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE=1;
Azul--;
Rojo++;
DimmerCurva();
}
PORTE0=0;
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
R_out=arraydimmer[Rojo];
V_out=arraydimmer[Verde];
A_out=arraydimmer[Azul];
}
if (count == 0xFF)
{ // Llamado con 122Hz
count= 1;
}
else count++;
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER;
count = OV_COUNT + DMXAddress;
break;
case FADING ;
count = OV_COUNT + DMXAddress * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;
if (mode==FADING){
}
}else{ timer_counter++; }
{
}
}
La libreria H que arme es esta
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define USE_DIP
#define F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {RAINBOW_FADER,FADING,} mode;
volatile uint16_t DmxAddress; // Dirección inicial
extern void get_dips(void);
Ahora lo que me larga error
Build started 20.8.2015 at 15:17:31
avr-gcc.exe -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d -c ../fading_raibow.c
../fading_raibow.c:14: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
../fading_raibow.c: In function 'main':
../fading_raibow.c:112: error: 'R_out' undeclared (first use in this function)
../fading_raibow.c:112: error: (Each undeclared identifier is reported only once
../fading_raibow.c:112: error: for each function it appears in.)
../fading_raibow.c:119: error: 'V_out' undeclared (first use in this function)
../fading_raibow.c:143: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:147: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:148: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:149: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:151: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:152: error: lvalue required as left operand of assignment
../fading_raibow.c:157: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c:158: warning: implicit declaration of function 'delay'
../fading_raibow.c:158: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:159: error: lvalue required as left operand of assignment
../fading_raibow.c:163: error: lvalue required as left operand of assignment
../fading_raibow.c:170: error: lvalue required as left operand of assignment
../fading_raibow.c:174: error: lvalue required as left operand of assignment
../fading_raibow.c:181: error: lvalue required as left operand of assignment
../fading_raibow.c:185: error: lvalue required as left operand of assignment
../fading_raibow.c:192: error: lvalue required as left operand of assignment
../fading_raibow.c:196: error: lvalue required as left operand of assignment
../fading_raibow.c:203: error: lvalue required as left operand of assignment
../fading_raibow.c:207: error: lvalue required as left operand of assignment
../fading_raibow.c:214: error: lvalue required as left operand of assignment
../fading_raibow.c:218: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'delay':
../fading_raibow.c:224: warning: implicit declaration of function 'delay_ciclos'
../fading_raibow.c: In function 'main':
../fading_raibow.c:249: warning: conflicting types for 'rainbow_fader'
../fading_raibow.c:157: warning: previous implicit declaration of 'rainbow_fader' was here
../fading_raibow.c:263: error: lvalue required as left operand of assignment
../fading_raibow.c:274: error: lvalue required as left operand of assignment
../fading_raibow.c:285: error: lvalue required as left operand of assignment
../fading_raibow.c:296: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'DimmerCurva':
../fading_raibow.c:309: error: 'A_out' undeclared (first use in this function)
../fading_raibow.c: In function '__vector_7':
../fading_raibow.c:324: error: expected ':' or '...' before ';' token
../fading_raibow.c:325: error: 'DMXAddress' undeclared (first use in this function)
../fading_raibow.c:327: error: expected ':' or '...' before ';' token
make: *** [fading_raibow.o] Error 1
Build failed with 31 errors and 6 warnings...
Bueno espero tus comentarios e ideas (estan buenisimas para mi) cuando puedas con tu tiempo y desde ya gracias
-
Bueno no voy a profundizar en el tema de los DIPS que agregaste. Ya que realmente no se que hacen, solo me limite a pasarte el ASM de la funcion que me diste a C.
Pero Voy a decirte 2 cosas sobre eso ( esto nomas incluye el codigo que te pase).
1 - PORTE1 , PORTE2 se utilizan para la rapidez con que cambian los colores (fading), eso tenes que tenerlo en cuenta.
2 - PORTC6, PORTC7 se utilizan para seleccionar los modos, es decir entre fading y ademas agregarle el rainbow_fading, PC6 te habilita a que se produzca el fading. SI ademas tenes habilitado PC7 se produce lo "rainbow" ademas del fading.
- El codigo de tus pines, funcion init_pinout() , le falta un #else, sino cuando pones el define USE_DIP, se ejecuta ambos codigos: y deberia ser asi:
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#else
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
#endif
}
- Tenes un problema en la definicion de las variables, decia Short int, estaba en mayusculas, directamente podes reemplazarlo por:
uint8_t velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
- Reemplaza todos los PINC7 y PINC6 por sus correspondientes, estos no daban errores pero mejor asegurarse.
(PINC & (1<<PC6))
(PINC & (1<<PC7))
- Reemplaza lso PORTE0 =0 y PORTE = 1 por sus correspondientes, claramente esta dando errores, asi que mejor cambiarlos:
PORTE &= ~(1<<PE0);
PORTE |= (1<<PE0);
- La funcion de delay te la habia pasado ya. Deberia quedar:
void delay(uint8_t Velocidad) {
uint16_t tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
}
}
- Tenes un error en el switch...case en la interrupcion
Le pusiste un ; en ves de un :
- Tenes tal ves un error al tener una coma de mas aca (luego del FADING):
enum {RAINBOW_FADER,FADING,} mode;
- Lo mas importante:
Sigo sin entender por que estas poniendo el for() en el main, sigo sin entender por que estas tocando la interrupcion del timer. A pesar que te pase como deberia ser y te dije como era un PWM por software, seguis implementando un concepto equivocado.
La idea de un PWM por software es que las porciones de tiempo sean fijas y que ademas tenga un periodo fijo, vos con tu for estas evitando todo eso. Por eso dije que las comparaciones deberian ir en la interrupcion y sin el for.
No se para que el switch case que agregaste en la interrupcion. realmente no se. por que esa interrupcion es del timer. la que te genera ese PWM.
Corrigiendo eso deberia creo yo eliminar todos los errores que tenes.
-
hola y gracias por tanta deferencia
bueno como dije por aca
hola stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas
http://www.todopic.com.ar/foros/index.php?topic=44884.0
Si lo se, pero el Tema al principio trataba sobre DMX512, por eso lo pase para aca,
lo que aconsejaria al Amigo Locodelafonola que abra un tema en el Subforo de Atmel,
Saludos
gracias a los dos ., basicamente espero poder compilar y que funcione
luego pasarlo a DMX ., en mi libreria base que funciona
En los comandos de recepcion y accionamiento no tengo problema ., por que basicamente trabajamos con valores de 0 a 255
Voy a aclarar un poco la cuestion ., esta funcion que quiero implementar (aprenderla mas que todo )., esta en los equipos DMX profecionales
ya sea que tenga el comando DMX ., o cuando funcionan en manual o audioritmico ., si se fijan el esquematico de mi montaje !!!!! es DMX ¡¡¡¡¡
igual que las funciones de la libreria que dio origen a este hilo., no se desvirtua (al menos eso creo)
asi que no creo que alla problemas ., mientras pueda lograr algo y se comparta ., no importa el lugar ., gracias a los dos
Bueno tal vez esto desoriente un poco ., pero con prestar atencion., uno se da cuenta enseguida de como funcionan esto
Y tal vez la confucion viene dada ., por la libreria que yo subi en asm ., que es para tres led solamente
Por que si nos fijamos en la primer libreria ., que dio origen al hilo
En ella se nota claramente la funcion DMX y MANUAL-PROGRAMADO
Si hubieras traspasado al C esa libreria de ASM ., no hubiera habido problemas ., porque los pin/port y funciones son iguales al montaje que tengo ., y las librerias de USART en DMX son iguales
El problema que radica en esa compilacion ., es que maneja tres gupos de led rgb ., no un fading y rainbow-fader independiente
Ahora lo que desorienta ., es esta libreria que yo subi y comparti ., es que al aplicar las funciones de ASM pasado a C ., no me da la posibilidad de aplicar la funcin alternativa en DMX ., como lo tiene la primera libreria originaria de este hilo
Yo a medida que se fue traduciondo la libreria ., me fui dando cuenta de eso ., es muy simple., las funciones de tiempo ., se ocupa en las dos pociciones ON / OFF del mini dips de puerto PE1
Bueno que problema tengo alli ., si uso ese dips-swich ., para la funcion de tiempo y en sus dos variantes ( ON / OFF ) no puedo despues usar esa funcion para commutar a DMX
aca muestro el circuito esquematico de los dos librerias ASM de este hilo
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=44207.0;attach=23381;image) y como tengo el ARRAY de llaves sin ocupar (por la reforma que hice ) asi con los valores de DMX ., me da como maximo un valor de 256 (puesto que se suman los valores )., no puedo obtener el valor de 512 ., porque uso PE2 (valor de 256 en DMX =TABLA ) para el cambio de funciones
bueno pero eso no es problema ., porque los valores que se maneja en la compilacion., para manejar el PWM es con un maximo de 256 (0 a 255)
Ahora si se da el caso de necesitar valores mas altos para el fading ., tenemos la opcion aca
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER :
count = OV_COUNT + DmxAddress;
break;
case FADING :
count = OV_COUNT + DmxAddress * 10;
break;
default:
count = OV_COUNT;
} Donde tomamos el valor de 0V_COUNT mas el valor de DmxAddress ., en el caso de rainbow fader o como en fading., que aparte de las dos anteriores mutiplica por 10
Bueno alli talvez ., habria que acomodar los valores ., que se suman y los que se multiplican ( tal vez sea al revez )
los valores que me arroja por aca ., la "Velocidad" sigo sin entenderlos
void delay(uint8_t Velocidad) {
uint16_t tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
}
}
sigo sin poder entender las "case " con valores exadecimales ., (no entiendo a que puertos se refiere ni a que BITS afecta
En cuanto al "FOR" del PWM ., si no lo coloco ., no me funciona con los potenciometros virtuales de DMX ( DmxRxField[DMX_CHANNELS] )
En cuanto a la asignacion de pines en PINUT esta corecta ( tengo que declara asi para que funciona las llaves y no podria ir nunca un ELSE ., porque los otros puertos que estan declarados alli son la salida y trabajan al mismo tiempo
aparte con esa configuracion de PWM tan basica ., con el mismo he podido manejar motores PAP y de C.C (obiamente con un poco de electronica asociada)
tambien modifique ( o sea tratar de volver al original de esta libreria ) ., estas sentencias V_out,R_out,A_out; las cambie por estas DmxRxField[0] , DmxRxField[1] , DmxRxField[2]
porque fueron de DMX llevadas a manual solamente ., pero usando la base delesquema electronico de DMX
Bueno con ese cambio de nombre a la sentencia ., ya me funciona ., de las dos maneras la salida , obiamente agregando la libreria usart ., de recepcion DMX
Tratando de que esto funcione ., se lograria que funcione en dos modos .,el programado ., y aqui habria que hacer incapie en algo importante
Hasta ahora no he podido usar la libreria de Tx (transmicion) que poseo ., pues no tengo nada desarrollado (secuencias o cuadros o esenas .o como queran llamarle ) dentro del programa., para que funcione de modo MANUAL AUTOMATICO MASTER ., como lo es en este caso ., el FADING y y el RAINBOW_FADER
Porque si se fijan en el esquema ., este no es solamente un receptor !!!! es un tranceptor ¡¡¡¡ ( puede recibir y emitir) por ahora una funcion a la vez ., pero con una pequeña reforma electronica ., puede hacer las dos cosas al mismo tiempo y tiene grandes ventajas
Estoy tratando de explicarte ., lo mejor que puedo para no causar tu enojo ., y el porque de esto ., si te causa alguna molestia te pido mil disculpas
yo sigo entendiendo las lecciones que encuentro por alli., y de cada uno ., que es mi profesor., pues mi ignorancia y analfabetismo ., me impiden ser critico de nadie ., y menos un maestro
Tal vez es una cuestion de entender ., que no todos tiene conociento en DMX ., y que muchos prefieren armar .,equipos audiortnicos ( que bien podria ser otra opcion mas para esto )
Se va haciendo dificil aprenderlo ., porque no se integra a aquellos que bien podrian usar estos equipos sin DMX
Te pido mil perdones si en algo te confundi y a causado tu enojo .,no es esa mi intencion ., aca te pongo la compilacion nueva
//#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include"fading_raibow.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
// *** establecer valor de WHILE ***//
enum {FALSE=0, TRUE=1};
//*********************************//
uint8_t count= 1; // contador del soft PWM
uint8_t velocidad,Rojo,Verde,Azul;
//*********************************//
const short int arraydimmer[256]={0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 28, 29, 30, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155, 156, 158, 159, 160, 161, 162, 164, 165, 167, 168, 169, 171, 172, 173, 174, 176, 177, 178, 180, 181, 182, 184, 185, 187, 188, 189, 191, 192, 193, 195, 196, 197, 199, 200, 202, 203, 204, 206, 207, 208, 210, 211, 213, 214, 216, 217, 218, 220, 221, 223, 224, 226, 227, 228, 230, 231, 233, 234, 236, 237, 239, 240, 242, 243, 245, 246, 248, 249, 251, 252, 254, 255}; // Lo que aparece como DC_Data
volatile uint16_t DmxAddress; // Dirección inicial
volatile uint8_t DmxRxField[DMX_CHANNELS];
// ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // MODO : ON FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
return;
}
mode=DMX; // funcionamiento en DMX
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
if (Temp != 0)
{
DmxAddress= Temp;
}
#endif
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
sei(); // habilitar las interupciones globales ???
int PWM_timer; // inicializar el timer PWM
while(1) // bucle principal (LOOP)
{
get_dips(); // Comprobar dip-switch y habilitar la funcion
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
if (DmxRxField[0]>PWM_timer) //red
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
}
if (DmxRxField[1]>PWM_timer) //green
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}
if (DmxRxField[2]>PWM_timer) //blue
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}
// if(!PINC6){ fading();}
// if(!PINC5){ disco();}
/*
Aca mas codigo que realmente no influye en nada
*/
}
void delay(uint8_t Velocidad) {
uint16_t tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
}
}
void fading() {
Velocidad = 127;
while(!PINC6)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE &= ~(1<<PE0);
//rojo_amarillo
while(Verde!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad);
PORTE |= (1<<PE0);
Verde++;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//amarillo_verde
while(Rojo && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE |= (1<<PE0);
Rojo--;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//verde_cyan
while(Azul!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE |= (1<<PE0);
Azul++;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//cyan_azul
while(Verde && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE |= (1<<PE0);
Verde--;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//azul_magenta
while(Rojo!=255 && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE |= (1<<PE0);
Rojo++;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//magenta_rojo
while(Azul && !PINC6)
{
if(PINC7) { rainbow_fader();}
delay(velocidad); //esperar
PORTE |= (1<<PE0);
Azul--;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
}
}
// void delay (int velocidad) {
// delay_ciclos(); // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
// Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
//temp2 = 1 si PINE1 = 0 sino temp2=2
//temp1 = 64 si PINE2 = 0 sino temp1=255
/*
Ciclos a esperar
temp2=1 temp1=255
11445 * (velocidad-1) +28
temp2=1 temp1=64
2895 * (velocidad -1) +28
temp2=2 temp1=255
18303 * (velocidad-1) +28
temp2=2 temp1=64
4551 * (velocidad-1) +28
*/
}
void rainbow_fader();{
int Temp_R,Temp_A,Temp_V;
Velocidad = 254;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
while(PINC7)
{
Rojo = 255;
Verde = 0;
Azul = 0;
DimmerCurva();
PORTE &= ~(1<<PE0);
//rojo_verde
while(Verde!=255 && PINC7)
{
delay(velocidad);
PORTE |= (1<<PE0);
Rojo--;
Verde++;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//verde_azul
while(Azul!=255 && PINC7)
{
delay(velocidad);
PORTE |= (1<<PE0);
Verde--;
Azul++;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
//azul_rojo
while(Rojo!=255 && PINC7)
{
delay(velocidad);
PORTE |= (1<<PE0);
Azul--;
Rojo++;
DimmerCurva();
}
PORTE &= ~(1<<PE0);
}
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
}
void DimmerCurva(){
DmxRxField[0]=arraydimmer[Rojo];
DmxRxField[1]=arraydimmer[Verde];
DmxRxField[2]=arraydimmer[Azul];
}
if (count == 0xFF)
{ // Llamado con 122Hz
count= 1;
}
else count++;
}
// }
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER :
count = OV_COUNT + DmxAddress;
break;
case FADING :
count = OV_COUNT + DmxAddress * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;
if (mode==FADING){
}
}else{ timer_counter++; }
{
}
}
tambien la libreria .H #include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define USE_DIP
#define F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
#define DMX_CHANNELS (14)
enum {RAINBOW_FADER,FADING,DMX,} mode;
//
extern void get_dips(void);
y estos son los eerores que me larga tan solo 4 ., que creo que seria cuestion de redefinir las formas (creo) Build started 24.8.2015 at 20:39:54
avr-gcc.exe -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d -c ../fading_raibow.c
../fading_raibow.c: In function 'fading':
../fading_raibow.c:166: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:166: error: (Each undeclared identifier is reported only once
../fading_raibow.c:166: error: for each function it appears in.)
../fading_raibow.c:174: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:180: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c: In function 'main':
../fading_raibow.c:272: warning: conflicting types for 'rainbow_fader'
../fading_raibow.c:180: warning: previous implicit declaration of 'rainbow_fader' was here
../fading_raibow.c:275: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:291: warning: implicit declaration of function 'delay'
make: *** [fading_raibow.o] Error 1
Build failed with 4 errors and 5 warnings...
[/code ]
-
Primero que nada pedirte disculpas si me excedi de tono.
Me encontre confundido, por que un tema es el codigo del primer post, y el otro es el codigo que me pasaste.
El codigo del primer post es de DMX pero que yo realmente no tengo la menor idea de como es el DMX. Por eso simplemente me limite a modificar la salida luego de estudiar el codigo por encima.
Es mas en el primer codigo todo lo de DMX esta en una libreria que no se incluye.
Por otro lado el codigo que me pasaste hace uso de un PWM por software tal cual lo hace el primer codigo, no hay libreria ni se aplica DMX, y pense que tu problema era que no podias pasar el programa de ASM a C.
El principal desencuentro que tuvimos es que vos pensabas agruparlo con el DMX y yo seguia pensando en el programa tal como estaba (Solamente PWM por soft). Entonces mientras vos ibas para un lado yo iba para el otro. Uno intentaba hacer una cosa y el otro otra.
Como no se DMX, nunca lo use, aunque no creo que sea complicado no puedo ayudarte mucho en esa parte, por eso mismo me limite a pasar el codigo de ASM a C. Con lo cual te voy a poder ayudar a resolver algunas dudas, pero no voy a poder con todas.
sigo sin poder entender las "case " con valores exadecimales ., (no entiendo a que puertos se refiere ni a que BITS afecta
switch((PINE&0x06))
PINE & 0000 0110
Ejemplo si PINE es 1010 0101 al hacerle una AND con 0000 0110 queda:
1010 0101
0000 0110
--------------
0000 0100
Es decir solo dejo los pines PINE1 y PINE2, los valores de esa operacion (recorda que una AND con un 0 logico es 0 siempre, y una AND con 1 logico es 1 o 0 segun el estado que tenia) puede darme 4 formas
0000 0000 - Caso que PINE1=0 y PINE2=0 - En hexa 0x00 - case 0x00
0000 0010 - Caso que PINE1=1 y PINE2=0 - En hexa 0x02 - case 0x02
0000 0100 - Caso que PINE1=0 y PINE2=1 - En hexa 0x04 - case 0x04
0000 0110 - Caso que PINE1=1 y PINE2=1 - En hexa 0x06 - case 0x06
Los demas bits quedan en 0 por que al hacerle justamente una AND van a quedar en 0 sea cual fuese su valor anterior.
En cuanto al "FOR" del PWM ., si no lo coloco ., no me funciona con los potenciometros virtuales de DMX ( DmxRxField[DMX_CHANNELS] )
Es por que seguro que tenes mal hecho el codigo. Como te digo no podes tener un for ahi, un for es muy aleatorio en tiempos, a pesar que pueda parecer un PWM por soft no lo es, es muy inconsistente. Yo imagino a DMX como algo que le envia los valores y el micro debe usar esos valores. Si vamos a que se necesita un PWM por software no podes tenerlo en el main, vuelvo a repetir que es un error de concepto/implementacion, deberias tenerlo en la interrupcion ( para eso es esa interrupcion, me refiero a la del timer ) y sin for() obviamente.
En cuanto a la asignacion de pines en PINUT esta corecta ( tengo que declara asi para que funciona las llaves y no podria ir nunca un ELSE ., porque los otros puertos que estan declarados alli son la salida y trabajan al mismo tiempo
Tal ves me confundi con eso, al ver los 2 valores asignados a un mismo registro me parecio que habias cometido un error. Estoy mas acostumbrado a ver algo como:
#ifdef xxxx
//conf Puertos si tuviera DIP
#else
//conf de Puertos si no tuviera DIP
#endif
Tal ves un poco de locura de parte mia
, estas sentencias V_out,R_out,A_out; las cambie por estas DmxRxField[0] , DmxRxField[1] , DmxRxField[2]
Ahi hay un error, en si todo el programa como creo que vos dijiste es imposible aplicarlo, no se cuales son las entradas de datos de DMX, ya que el fading modifica siempre esos valores que luego son usados en el PWM por soft. los colores ya estan preseleccionados en el codigo, es decir no tenes ninguna "variable" que puedas modificar. Si vos por ejemplo queres que por DMX llegue los valores de los colores y se produzca el fading, entonces eso es una cosa distinta a lo que el codigo estaba haciendo(que me pasaste). Reemplazar lo que reemplazaste no creo que sea lo correcto.
La seleccion de modo imagino tambien que vendra por algun comando. asi que no se por que esta hecho en la interrupcion del timer.
Si llegan los datos por UART entonces deberia haber una interrupcion de la UARt y ahi producirse el cambio de modo.
Con respecto a los errores que obtuviste es por que:
Velocidad no es lo mismo que velocidad, es case-sensitive asi que para quitarlo le cambias la V mayuscula por la minuscula.
Esto te va a solucionar los errores de sintaxis, pero esto no quiere decir que el codigo funcione. Ya que como dije el codigo esta realizado para hacer una cosa y yo recien ahora me entero que estas pidiendo otra totalmente distinta.
-
yo hace tiempo leo estos mensaje y debo decir que es una sopa de letras, creo que el amigo locodelafonola no ha leido lo que es el Protocologo DMX512, el codigo en si es para hace una funcion comandada por otros DMX512 Transmisor, recordar que el protocolo se compone de DMX512 Maestros y Esclavo, los Esclavos como es logico reciben Comando del Maestros , pero hay casos Tambien donde el Maestros hace las dos funciones.
Esta imagen le ha dado la vuelta a internet para aquellos que desconocen el protocologo.
(http://www.todopic.com.ar/foros/imgtiny/28ire54.jpg)
El amigo locodelafonola quiere cambiar un protocologo que no tiene nada que ver con DMX512 y es por eso que he dicho que abra un temas nuevos en el Subforo correspondiente.
Amigo Killerjc como ver en la imagen no es nada dificil y si te fija de algunos projectos de DMX512 en este Subforos lo Capta enseguidas.
otras aclaracion el Master o lo que hacen DMX512 como Maestros , programan la mesa con muchas secuencias de comandos.
Espero que me hayan comprendido. ;-)
Saludos
-
Gracias stk500, yo me imaginaba algo asi. Ya que en fin era recibir un dato y hacer algo con ese dato. Sea cual sea el protocolo eso no cambiaba.
No tenia claro como es que se enviaba.
Por cierto aca el AN
http://ww1.microchip.com/downloads/en/AppNotes/01076A.pdf
Ya con eso me queda claro cuales son los valores de dimming. Es decir con la direccion que se le asigna al receptor este toma el byte que le corresponde de la trama (512bytes).
Ahora como es que se pueden enviar 3 valores o por ejemplo elegir el modo. Ejemplo yo quisiera elegir los 3 valores de RGB y elegir entre fading/fijo/rainbow_fading , como se discriminan los comandos ( como para cambiar el modo ) y los 3 datos de los colores?
O se envian todos en secuencia
512bytes con el comando
512bytes con R
512bytes con G
512bytes con B
Asi ? y eso se repite ?
O los 512 bytes pertenece a un solo receptor y el Start Code es el que selecciona el "esclavo(receptor)" ?
-
hola y gracias de nuevo
yo hace tiempo leo estos mensaje y debo decir que es una sopa de letras, creo que el amigo locodelafonola no ha leido lo que es el Protocologo DMX512, el codigo en si es para hace una funcion comandada por otros DMX512 Transmisor, recordar que el protocolo se compone de DMX512 Maestros y Esclavo, los Esclavos como es logico reciben Comando del Maestros , pero hay casos Tambien donde el Maestros hace las dos funciones.
Esta imagen le ha dado la vuelta a internet para aquellos que desconocen el protocologo.
(http://www.todopic.com.ar/foros/imgtiny/28ire54.jpg)
El amigo locodelafonola quiere cambiar un protocologo que no tiene nada que ver con DMX512 y es por eso que he dicho que abra un temas nuevos en el Subforo correspondiente.
Amigo Killerjc como ver en la imagen no es nada dificil y si te fija de algunos projectos de DMX512 en este Subforos lo Capta enseguidas.
otras aclaracion el Master o lo que hacen DMX512 como Maestros , programan la mesa con muchas secuencias de comandos.
Espero que me hayan comprendido. ;-) Saludos
a ver ., yo creo a mi entender que alli esta el problema de todo esto
yo no se si no me explico bien o no me hago enteder .,YO NO QUIERO CAMBIAR EL PROTOCOPLO DMX 512 .,¿¿¿ donde escribi eso o donde lo pedi ????
Yo lo que pedi es pasar esas funciones de comando manual a DMX
no entiendo cual es el enpecinamiento en confundir las cosas ., si lo plantie bien claro ., primero que funcione en MNUAL (llaves mini-dips) y luego en DMX
aca esta el link del proyecto de mi libreria
http://www.ledstyles.de/index.php/Thread/3928-Rainbow-Fader-mit-Zusatzfunktionen-Neu-mit-Dimmerkurve/?pageNo=1&s=bb5cd6c43d7e00c4ba4095728791824bd3ec56ae alli se nita claramente en una foto el montaje DMX de Hendrik Hoelscher
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=44880.0;attach=24311;image) y aclaremos algo ., ¿¿¿¿ como puedo usar la funcion de MAESTRO en STANDALONE ., si no tengo nada para enviar ???
Esto es programaion DMX ., donde se tiene que respetar ciertos parametros para que funcione
Yo al poner la llave mini-dips N° 10 en ON desabilito la recepcion ., y habilito la trasmicion (obiamente hay que colocar una instruccion como init_DMX_RX(); aca muestro las librerias que tengo
Esta es la lib_dmx_out.C
/**** A P P L I C A T I O N N O T E ************************************
*
* Title : DMX512 transmission library
* Version : v1.1
* Last updated : 30.07.07
* Target : Transceiver Rev.3.01 [ATmega8515]
* Clock : 8MHz, 16MHz
*
* written by hendrik hoelscher, www.hoelscher-hi.de
***************************************************************************
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
If you have no copy of the GNU General Public License, write to the
Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For other license models, please contact the author.
***************************************************************************/
#include "globals.h"
#include "lib_dmx_out.h"
// ********************* local definitions *********************
uint16_t gCurDmxCh; //current DMX channel
#define TX_BRK (0xFFFF)
#define TX_SC (0)
#define TX_DATA (1)
// *************** DMX Reception Initialisation ****************
void init_DMX_TX(void)
{
//Ports
DDRD |= (1<<2)|(1<<1);
PORTD |= (1<<2)|(1<<1); //enable transmission
//USART
UBRRH = 0;
UBRRL = ((F_OSC/4000)-1); //250kbaud, 8N2
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB = (1<<TXEN)|(1<<TXCIE);
UDR = 0; //start USART
//Data
gCurDmxCh= TX_BRK; //start with break
}
// ****************** DMX Transmission ISR ********************
ISR (UART_TX_vect)
{
uint16_t DmxCh= gCurDmxCh;
if (DmxCh == TX_BRK) //start break
{
UBRRH = 0;
if (Flags &(1<<SLOW_TX))
{
UBRRL = 17;
}
else
{
UBRRL = 9;
UCSRC = (1<<URSEL)|(3<<UCSZ0); //8n1
}
UDR = 0; //send break
gCurDmxCh= TX_SC;
}
else if (DmxCh == TX_SC)
{
UBRRH = 0;
UBRRL = ((F_OSC/4000)-1); //250kbaud
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UDR = 0; //send start byte
gCurDmxCh= TX_DATA;
}
else
{
if (Flags &(1<<SLOW_TX))
{
_delay_us(20); //inter byte gap in slow mode
}
if (DmxCh &(1<<0)) UDR= TxVal; //send data
else UDR= (0xFF -TxVal);
gCurDmxCh++;
if (Flags &(1<<SLOW_TX))
{
if (DmxCh == 511) gCurDmxCh= TX_BRK;
}
else
{
if (DmxCh == 48) gCurDmxCh= TX_BRK;
}
}
}
esta es la lib_dmx_out.H
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile uint8_t TxVal; //array of DMX vals
extern void init_DMX_TX(void);
Ahora bien., si se sigue pensando que la programacion de standalone ., no tiene que seguir los protocolos DMX ., !!! alli esta el error ¡¡¡¡
Eso por el lado de la trasmicion ., por el lado de la recepcion ¿¿¿ qque pasaria si yo coloco esta intruccion dentro del WHILE(es donde trabaja el programa sin salir de alli ) ejemplo :
if (DmxRxField[3]> 10 < 255) // comando del FADING
{
int FADING; // inicio del fading
}
if (DmxRxField[4]> 10 < 255) // comando del RAINBOW_FADER
{ int RAINBOW_FADER; // inicio del rainbow_fader
} Tal vez., las sentencias esten mal definidas en sus formas pero .,en si tendria que funcionar ., de hecho he probado experimentalmente algo parecido y funciono
Y para aclarar ., el protocolo DMX512 creo que lo entiendo bien (puedo estar equivocado porque aprendi solo )., aca la cuestion es ., hacer funcionar algo y que respete los lineamientos del protocolo de trasmicion y recepcion DMX 512 ., SIN CAMBIAR EL PROTOCOLO
sigo sin entender lo de los numeros binarios y exadecimales
Tambien el hecho de que no se cambien los PIN / PORT PE1 y PE2 ., esos no se pueden usar ., porque me imposibilita el uso de el DMX ., tengo sin usar los puertos con las llaves desde el PC0 a PC7
SI fuera el caso como esto ( esta mal porque no entiendo de alli mi confucion ) ejemplo : void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER /DMX OUT
init_DMX_RX(); Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) 362 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC1)) 568 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC2)) 1430 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC3)) 2287 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC4)) *0) +
(!(PINC &(1<<PC5)) *0) +
(!(PINC &(1<<PC6)) *0) +
(!(PINC &(1<<PC7)) *0);
DmxAddress= Temp=_delay_ms(tiempo);
if (!(PINE &(1<<PE2))) // MODO : ON FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
UCSRB &= ~(1<<RXCIE);// Receptor Desactivar si la dirección de inicio = 0 }
return;
}
mode=DMX; // funcionamiento en DMX
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
if (Temp != 0)
{
DmxAddress= Temp;
} telf oca 0260 442-5403
Y alli agregue (que no viene al caso., de lo que tratamos ) como se habilita la trasmicion y como se desabilita la recepcion ( con el pin PD0) algo que muchos no toman en cuenta ., pero eso es otra historia
Como dije puede ser que este mal la definicion ., en cuanto a funcion velocidad
estuve viendo que se ha compilcado mucho al no entenderme
Entonces pence ., que como uso el atmega 8515-16pu ., tengo los puertos libres de A (estan al lado de los puertos E y C colocar aunque sea dos llaves mini-dips alli
el problema que tengo es que no tengo mas llaves mini_DIPS disponibles (aca en mi pueblo no se consiguen ., solo en Bs.As)
Pero buendo dejando de lado las llaves., como veras tampoco me compila .,ni siquiera copiando textualmemte lo que diseñaste
si le prestas atencion ., a la compilacion que hice esta todo declarado ., igual asi maraca error ., no sera que la funcion velocidad tendria que tener un INIT aparte
como no se ASM ., no me doy cuenta ., si influye algo mas ., de la compilacion original
en cuanto al autor aca hay un video de lo que hace
http://www.noisepop.de/led-forum/RGB-Fader/Rainbow-Fader-3.mov hola Gracias stk500, yo me imaginaba algo asi. Ya que en fin era recibir un dato y hacer algo con ese dato. Sea cual sea el protocolo eso no cambiaba.
No tenia claro como es que se enviaba.
Por cierto aca el AN
http://ww1.microchip.com/downloads/en/AppNotes/01076A.pdf
Ya con eso me queda claro cuales son los valores de dimming. Es decir con la direccion que se le asigna al receptor este toma el byte que le corresponde de la trama (512bytes).
Ahora como es que se pueden enviar 3 valores o por ejemplo elegir el modo. Ejemplo yo quisiera elegir los 3 valores de RGB y elegir entre fading/fijo/rainbow_fading , como se discriminan los comandos ( como para cambiar el modo ) y los 3 datos de los colores?
O se envian todos en secuencia
512bytes con el comando
512bytes con R
512bytes con G
512bytes con B
Asi ? y eso se repite ?
O los 512 bytes pertenece a un solo receptor y el Start Code es el que selecciona el "esclavo(receptor)" ?
bueno se envian en secuencia pero quedate tranquilo ., empieza en el 1 DmxRxField[0] , 2 DmxRxField[1] ., 3 DmxRxField[2], la informacion llega desde la consola por la USART., del circuito integrado y se aloja en esta variable uint8_t DmxBuf[DMX_CHANNELS]; (
alli manejamos el valor del bufer total recibido (RAW) ., pero estan separados por (de un dmxchanel o otro dmxchanel ) por dos bit de para (que se ve en la trama que mostro STK500 )
tambien esta defino por la cantidad de canales que recibo de acuerdo alas funciones por esta variable #define DMX_CHANNELS (5 ) ., que serian en este caso R,G,B, fading y rainbow-fader
aver site aclro un poco ., en un universo de 512 canales se envia la trama des 0 a 511 ., pero en cada canal el valor maximo es 255
ejemplo : el primer canal es la direcion de inicio ., la menor que puede se es 1 (el cero se reserva para desabilitacion de recepcion ) ., a partir de alli tenemos nuestros 5 canales que son los que manejamos
si tuvieramos otro equipo en la serie(dentro del mismo universo de 512) se tendria que colocar la direccion de inicio en 6 y luego vendrian los 5 canales que se usan y asi susesivamente
Pero quedate tranquilo ., que con eso no estamos trabajando ., lo que hice fue enparejar los comandos para que funcionen en las dos maneras (o al menos el intento d hacerlo)
la verdad que si funciona lo vamos a saber en lo fisico., cuando lo pueda probar
-
Hola KillerJC,
Las mesas de luces DMX512 algunas llevan muchos parametros para tu asignar a cada canal diferente comandos o individual o en grupos,
por ejemplo, luz que caminan, Flashig,Strobos, secuenciales y un sin fin, para implementar todos esos necesitas de un micro que tenga muchas RAM y claro EEprom para almacenar los parametros.
lo unico que he hecho yo como mesa de luces fue muy simple, usando el ADC de un Atmega8
mira aqui
http://www.todopic.com.ar/foros/index.php?topic=37357.0
eso me llevo muchos meses de trabajos y investigacion ya que nunca lo habia hechos.
para que tenga mas ideas de todos lo que te digo mira esta
estos esta hechos con el programa Madrix.
Saludos
-
Bueno para solucionar todo esto..
locodelafonola
Explicame exactamente que necesitas que haga el programa. El efecto de fading esta. Ahora hay que unirlo al DMX, por eso necesito que me expliques como queres hacerlo.
Nombreame uno por uno los parametros que llegan, ejemplo:
DmxRxField[0] -> Modo, de 0 a 120 fijo, de 121 a 255 fading
DmxRxField[1] -> Color R
DmxRxField[2] -> Color G
......
Se que son 512 pero no creo que uses 512 para esto al menos por ahora.
-
Bueno para solucionar todo esto..
locodelafonola
Explicame exactamente que necesitas que haga el programa. El efecto de fading esta. Ahora hay que unirlo al DMX, por eso necesito que me expliques como queres hacerlo.
Nombreame uno por uno los parametros que llegan, ejemplo:
DmxRxField[0] -> Modo, de 0 a 120 fijo, de 121 a 255 fading
DmxRxField[1] -> Color R
DmxRxField[2] -> Color G
......
Se que son 512 pero no creo que uses 512 para esto al menos por ahora.
bueno alli me gusta la cosa
DmxRxField[0] , DmxRxField[1],DmxRxField[2], dejalos como estan ., ( DmxRxField[0] ., es elcanal rojo y ya lo cambiaste)., lo qu hay que hacer es habilitar uno nuevo (o dos) ejemplo : DmxRxField[3 ] -> Modo, de 0 a 120 fijo, de 121 a 255 fading y si queres DmxRxField[4 ]-> raibonw_fader
ya con esa simple sentecia tenes el comando del bufer de recepcion sin que declares mas nada (una vez que se finaliza y todo funciona como se debe ., se define en la libreria .H cuantos se usan y listo) como te explique mas arriba
y algo para clarar., estas fuciones que quiero aprender ., son la que tiene los "tachos" o lampara par 64 o 56 , de led comerciales
si te sirve aca te subo lo que que me funciona a mi (bastante probado ) y funciona joya
int PWM_timer; // inicializar el timer PWM
char strobo = FALSE; // valor de strobo
unsigned int strobo_timer=0; // Contador Strobo igual a cero
while(1) // bucle principal (LOOP)
{
get_dips(); // Comprobar dip-switch y descargar la dirección DMX
//************************************* PWM leds *********************************//
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
if(DmxRxField[4]>10){ // Si el canal de luz estroboscópica es menor a 10 es siempre mayor que los LED ,el estroboscópico está apagado,
if( strobo_timer>(unsigned int)((255-DmxRxField[4])*16)){// Dmx CH4 igual a 11, es el tiempo máximo , o igual a 255 es el Tiempo min
strobo_timer=0;// Restablecer el temporizador
if(strobo){ strobo=FALSE;}else{ strobo=TRUE;} // Cambiar autorización para ILUMINACIÓN
}else{
strobo_timer+=1;
}
}else{
strobo=TRUE; // la Stroboscopica está apagada,
}
if ( ((unsigned int)((DmxRxField[0]*DmxRxField[3])/255)>PWM_timer) && strobo ) //ROJO
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}
if ( ((unsigned int)((DmxRxField[1]*DmxRxField[3])/255)>PWM_timer) && strobo ) //VERDE
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}
if ( ((unsigned int)((DmxRxField[2]*DmxRxField[3])/255)>PWM_timer) && strobo ) //AZUL
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
} Tiene los tras canales RGB , mas el DIMMERMASTER ., mas el STROBO ., esto a mi me funciona correctamente
-
Listo los datos son:
DmxRxField[0] -> R
DmxRxField[1] -> G
DmxRxField[2] -> B
DmxRxField[3] -> Modo -> 0..63 Fijo, 64..127 Fading_Color_Fijo , 128..191 Fading Automatico, 192..255 Rainbow_Fading
DmxRxField[4] -> Velocidad
Ahora solo me queda una cosa por hacer. Pasar la funcion que es "manual" como le decis a una que use los comandos esos.
Entonces los modos van a quedar:
Fijo ->
En este modo se usan los valores RGB del DMX, ya que es el unico que realmente cumple con esa funcion
Fading Color fijo ->
En este modo se va a producir el fading pero solo del color RGB, el cual va a ser un estilo "pulsante", Unicamente en el color que se le indique desde la consola DMX. Usa el valor de Velocidad
Fading Automatico ->
En este modo va a ir alternando los colores pero no va a hacer caso a los valores RGB ya que no tiene sentido aplicarlo. Si defino solo un color de comienzo luego va a ser modificado por el mismo "fading" a no ser que quieras que sea un color unico y que se produsca el fading solo de ese color y no que vaya pasando de colores
Rainbow_Fading ->
Una extension al Fading Automatico que en ves de navegar por los colores comunes Solo R, solo G y solo B, hace uso de varios colores. Tambien hace caso a Velocidad. Pero no a RGB
En fin creo que esto es lo que buscas
La velocidad se va a controlar desde el DMX por lo cual se le quita el soporte a los DIPs sobre eso. Y PINE1/PINE2 no deberian influir en eso.
-
Listo los datos son:
DmxRxField[0] -> R
DmxRxField[1] -> G
DmxRxField[2] -> B
DmxRxField[3] -> Modo -> 0..63 Fijo, 64..127 Fading_Color_Fijo , 128..191 Fading Automatico, 192..255 Rainbow_Fading
DmxRxField[4] -> Velocidad
Ahora solo me queda una cosa por hacer. Pasar la funcion que es "manual" como le decis a una que use los comandos esos.
Entonces los modos van a quedar:
Fijo ->
En este modo se usan los valores RGB del DMX, ya que es el unico que realmente cumple con esa funcion
Fading Color fijo ->
En este modo se va a producir el fading pero solo del color RGB, el cual va a ser un estilo "pulsante", Unicamente en el color que se le indique desde la consola DMX. Usa el valor de Velocidad
Fading Automatico ->
En este modo va a ir alternando los colores pero no va a hacer caso a los valores RGB ya que no tiene sentido aplicarlo. Si defino solo un color de comienzo luego va a ser modificado por el mismo "fading" a no ser que quieras que sea un color unico y que se produsca el fading solo de ese color y no que vaya pasando de colores
Rainbow_Fading ->
Una extension al Fading Automatico que en ves de navegar por los colores comunes Solo R, solo G y solo B, hace uso de varios colores. Tambien hace caso a Velocidad. Pero no a RGB
En fin creo que esto es lo que buscas
La velocidad se va a controlar desde el DMX por lo cual se le quita el soporte a los DIPs sobre eso. Y PINE1/PINE2 no deberian influir en eso.
!!!!! grande maestro ¡¡¡¡ listo asi es corecto ., fijate en lo que subi en el mesaje anterior ., esas funciones no usan nada de desarrollo., todo lo que es ., es lo que ves escrito alli ., y funcionan dentro del Loop de WHILE ., no hay mas nada que eso para que te des idea ., pero como yo no se como se implementa eso del ASM sugeri lode las llaves ., pero esta bien asi eso es lo que busco GRACIAS MIL !!!!!
-
#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include"fading_raibow.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
// Dato proveniente de la consola DMX
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
//*********************************//
volatile uint16_t DmxAddress; // Dirección inicial
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[]={ // Indice y valor a modificar {Resta,Suma}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
//if (Temp != 0)
// {
// Address= Temp;
// }
#endif
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones globales ???
while(1) // bucle principal (LOOP)
{
get_dips(); // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
switch(mode)
{
case FIXED:
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
void fading_fijo(){
}
void fading_auto(){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(DMX_Velocidad); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
void DimmerCurva(){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(uint8_t DMX_Velocidad) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
void ISR(TIMER0_OVF_vect){
if (R_out>=PWM_timer) { salida &= 0x06; }
if (V_out>=PWM_timer) { salida &= 0x05; }
if (A_out>=PWM_timer) { salida &= 0x03; }
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
Cambiarmodo();
}
PWM_timer++;
}
void Cambiarmodo(){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
if(mode!=RAINBOW_FADING) //Reviso que ya no este en este modo.
{
mode=RAINBOW_FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
}
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
if(mode!=FADING) // Si ya esta en el modo, que no lo modifique.
{
mode=FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
}
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
Ahi va mi codigo... tiene una forma distinta de aplicacion. Tiene una forma distinta de como es que funciona el programa.
Por eso tuve que modificar completamente las funciones fading_auto y rainbow_fader, ya que de intentar cambiar rapidamente de modo, implicaba grandes demoras del micro hasta que realmente pudiera hacerlo.
Si observas el while del main esta continuamente entrando al modo que le corresponde, se hace lo que se debe y vuelve a salir al while de afuera.
El PWM esta corriendo siempre y es independiente de todo. Unicamente se cambia de modo Y de color si es que termino el ciclo del PWM, para evitar glitches
Lo que llegue desde el DMX, va a cargarse segun se requiera:
Modo Fijo (FIXED):
El programa arranca en este modo y colores RGB 0,0,0
El color se carga desde los valores del DMX, y se procede a actualizar lo que va a ir en la salida. Cuando el PWM termina el ciclo procede a cargar esos nuevos valores, asi por un ciclo mas.
Modo Fading Fijo (FADING_FIXED):
Este no lo hice, no esta realizado el codigo, deberia tomar el color y hacer un fading con el color que le manda el DMX. Creo que aca deberia aplicar un alpha asi afectar a todos los colores. Como no tengo seguro como hacerlo todavia no lo hice.
Modo Fading (FADING):
Este modo cuando se selecciona cuando el PWM llega a 255, esto hace que se le asignen los valores que deben ser para que inicie el modo fading tal cual estaba en el codigo anterior. Ademas pone los estados en 0 del fading para el nuevo codigo.
Modo Rainbow_Fading (RAINBOW_FADING):
Este modo utilizaba varias formas se producia el RAINBOW completo y luego se procedia a hacer 1 sola etapa del FADING. Asi hasta completar todas las etapas de FADING.
La Velocidad en que cambian los colores esta dado por el valor del DMX, el cual se actualiza al instante.
Tambien cambie la forma, queria hacer un cambio lineal de 3us a 580ms que era lo que tenia el programa en ASM, pero hacer una ecuacion lineal para eso era ridiculo ya que me encontraba con rangos de 0.003 a 580ms o de 3us a 580000ms
Entonces procedi a dividirlo en 2 rectas. 1 para los microsegundos para cuando DMX_Velocidad es de 0 a 127 y la otra para los milisegundos cuando DMX_Velocidad es de 128 a 255. Esto valores exigian operaciones con numeros flotantes. Por lo tanto me incline a hacerlo lo mas entero posible, por eso mismo la primera recta va desde 3us a 890us y luego pasa de 1ms a 508ms. Lo unico malo es que de 127 a 128 hay un salto de 100us, pero que espero no afecte demasiado.
Consideraciones que tuve:
El DIP solo entrega la direccion nada mas, esta puesto en el while asi de esa forma uno puede cambiar a direccion del equipo mientras esta encendido.
Quite seguramente algunas cosas como para poder programar mejor, seguro que vos luego se los vas a agregar de vuelta, tal como el WDT.
Y espero no haberle errado mucho.
Los valores de Rojo,Verde,Azul los puse todos en un array llamado ArrayColores, esto me permitio crear otros arrays mas para simplificar el programa. Ejemplo:
const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
El Fading (solo este sin rainbow) hacia:
0- Incrementaba verde hasta 255
1- Decrementaba rojo hasta 0
2- Incrementaba azul hasta 255
3- Decrementaba verde
4- Incrementaba rojo
5- Decrementa Azul
Si observas los pares 0,2,4 son todos incrementos y los impares 1,3,5 decrementos
Si observas tambien los numeros del array que cree solo hay numeros de 0 a 2, esto me indica el indice {R,G,B} el 0 es Rojo, 1 Verde, 2 Azul.
Entonces se que si tengo un 0 en la posicion 2, entonces debo INCREMENTAR rojo.
El mismo principio se aplica al Rainbow, nomas que alli se incrementa y decrementa a la misma ves, por lo tanto procedi a crear otro array distinto para ese.
Esto ultimo es por si me preguntabas que habia realizado. No quise meterme con punteros para no complicarle la vida a nadie.
Creo que estaria todo terminado a excepcion de la funcion de fading fijo (que seguro la termino dentro de poco). todo lo demas agregado que no sea parte de la implementacion del codigo ya creo que va a pasar a ser un tema tuyo.
Si no me equivoco deberia funcionar masomenos correctamente. Me preocupan un par de detalles minusciosos pero que tal ves me este rompiendo mas la cabeza de lo que debo.
(Como crear otro valor de modo para que solo se cambie en cierta ocasion de esa forma evitar cualquier posible error)
PD: Si observas y el por que de mi enojo es que es muy distinto un programa hecho de forma lineal como teniamos, a uno realizado de la forma que esta ahora. Tal ves demasiado, a pesar que "hacen lo mismo" la aplicacion es totalmente distinta.
-
hola
#define F_CPU 8000000
#include<util\delay.h>
#include<stdio.h>
#include<stdlib.h>
#include"fading_raibow.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
// Dato proveniente de la consola DMX
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
//*********************************//
volatile uint16_t DmxAddress; // Dirección inicial
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[]={ // Indice y valor a modificar {Resta,Suma}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
//if (Temp != 0)
// {
// Address= Temp;
// }
#endif
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones globales ???
while(1) // bucle principal (LOOP)
{
get_dips(); // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
switch(mode)
{
case FIXED:
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
void fading_fijo(){
}
void fading_auto(){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(DMX_Velocidad); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
void DimmerCurva(){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(uint8_t DMX_Velocidad) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
void ISR(TIMER0_OVF_vect){
if (R_out>=PWM_timer) { salida &= 0x06; }
if (V_out>=PWM_timer) { salida &= 0x05; }
if (A_out>=PWM_timer) { salida &= 0x03; }
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
Cambiarmodo();
}
PWM_timer++;
}
void Cambiarmodo(){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
if(mode!=RAINBOW_FADING) //Reviso que ya no este en este modo.
{
mode=RAINBOW_FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
}
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
if(mode!=FADING) // Si ya esta en el modo, que no lo modifique.
{
mode=FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
}
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
Ahi va mi codigo... tiene una forma distinta de aplicacion. Tiene una forma distinta de como es que funciona el programa.
Por eso tuve que modificar completamente las funciones fading_auto y rainbow_fader, ya que de intentar cambiar rapidamente de modo, implicaba grandes demoras del micro hasta que realmente pudiera hacerlo.
Si observas el while del main esta continuamente entrando al modo que le corresponde, se hace lo que se debe y vuelve a salir al while de afuera.
El PWM esta corriendo siempre y es independiente de todo. Unicamente se cambia de modo Y de color si es que termino el ciclo del PWM, para evitar glitches
Lo que llegue desde el DMX, va a cargarse segun se requiera:
Modo Fijo (FIXED):
El programa arranca en este modo y colores RGB 0,0,0
El color se carga desde los valores del DMX, y se procede a actualizar lo que va a ir en la salida. Cuando el PWM termina el ciclo procede a cargar esos nuevos valores, asi por un ciclo mas.
Modo Fading Fijo (FADING_FIXED):
Este no lo hice, no esta realizado el codigo, deberia tomar el color y hacer un fading con el color que le manda el DMX. Creo que aca deberia aplicar un alpha asi afectar a todos los colores. Como no tengo seguro como hacerlo todavia no lo hice.
Modo Fading (FADING):
Este modo cuando se selecciona cuando el PWM llega a 255, esto hace que se le asignen los valores que deben ser para que inicie el modo fading tal cual estaba en el codigo anterior. Ademas pone los estados en 0 del fading para el nuevo codigo.
Modo Rainbow_Fading (RAINBOW_FADING):
Este modo utilizaba varias formas se producia el RAINBOW completo y luego se procedia a hacer 1 sola etapa del FADING. Asi hasta completar todas las etapas de FADING.
La Velocidad en que cambian los colores esta dado por el valor del DMX, el cual se actualiza al instante.
Tambien cambie la forma, queria hacer un cambio lineal de 3us a 580ms que era lo que tenia el programa en ASM, pero hacer una ecuacion lineal para eso era ridiculo ya que me encontraba con rangos de 0.003 a 580ms o de 3us a 580000ms
Entonces procedi a dividirlo en 2 rectas. 1 para los microsegundos para cuando DMX_Velocidad es de 0 a 127 y la otra para los milisegundos cuando DMX_Velocidad es de 128 a 255. Esto valores exigian operaciones con numeros flotantes. Por lo tanto me incline a hacerlo lo mas entero posible, por eso mismo la primera recta va desde 3us a 890us y luego pasa de 1ms a 508ms. Lo unico malo es que de 127 a 128 hay un salto de 100us, pero que espero no afecte demasiado.
Consideraciones que tuve:
El DIP solo entrega la direccion nada mas, esta puesto en el while asi de esa forma uno puede cambiar a direccion del equipo mientras esta encendido.
Quite seguramente algunas cosas como para poder programar mejor, seguro que vos luego se los vas a agregar de vuelta, tal como el WDT.
Y espero no haberle errado mucho.
Los valores de Rojo,Verde,Azul los puse todos en un array llamado ArrayColores, esto me permitio crear otros arrays mas para simplificar el programa. Ejemplo:
const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
El Fading (solo este sin rainbow) hacia:
0- Incrementaba verde hasta 255
1- Decrementaba rojo hasta 0
2- Incrementaba azul hasta 255
3- Decrementaba verde
4- Incrementaba rojo
5- Decrementa Azul
Si observas los pares 0,2,4 son todos incrementos y los impares 1,3,5 decrementos
Si observas tambien los numeros del array que cree solo hay numeros de 0 a 2, esto me indica el indice {R,G,B} el 0 es Rojo, 1 Verde, 2 Azul.
Entonces se que si tengo un 0 en la posicion 2, entonces debo INCREMENTAR rojo.
El mismo principio se aplica al Rainbow, nomas que alli se incrementa y decrementa a la misma ves, por lo tanto procedi a crear otro array distinto para ese.
Esto ultimo es por si me preguntabas que habia realizado. No quise meterme con punteros para no complicarle la vida a nadie.
Creo que estaria todo terminado a excepcion de la funcion de fading fijo (que seguro la termino dentro de poco). todo lo demas agregado que no sea parte de la implementacion del codigo ya creo que va a pasar a ser un tema tuyo.
Si no me equivoco deberia funcionar masomenos correctamente. Me preocupan un par de detalles minusciosos pero que tal ves me este rompiendo mas la cabeza de lo que debo.
(Como crear otro valor de modo para que solo se cambie en cierta ocasion de esa forma evitar cualquier posible error)
PD: Si observas y el por que de mi enojo es que es muy distinto un programa hecho de forma lineal como teniamos, a uno realizado de la forma que esta ahora. Tal ves demasiado, a pesar que "hacen lo mismo" la aplicacion es totalmente distinta.
bueno amigo alli compile y agregue algunas cosas que faltaban al juntako con DMX
pero me largo error ., y calculo que los errores tiene el mismo origen que es el PWM en e lIRS
y te vuelvo a repetir en DMX se tiene que ejecitar en WHILE o FOR pero fuera del IRS
la razon es que te afecta la recepcion del USAT como te explique antes
aca te subo las tres librerias la de recepcion" lib_dmx_in.c " ," lib_dmx_in.h" y "fading_raibow.c "
LIB_DMX_IN.C #include "lib_dmx_in.h"
#include "lib_indicator.h"
// ********************* definiciones locales*********************
enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX
uint8_t gDmxState;
uint8_t *gDmxPnt;
uint16_t DmxCount;
//volatile uint8_t gDmxState;
// *************** DMX recepción de inicialización ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRD |= (1<<2);
PORTD &= ~(1<<2);
UBRRH = 0; // Habilitar recepción
UBRRL = ((F_OSC/4000)-1);// 250kBaud, 8N2
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;
uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
{
DmxRxField[i]= 0;
}
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo Manual
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // Manual,
{
mode= FADING;
}else{
mode= RAINBOW_FADER;
}
UCSRB &= ~(1<<RXCIE);// Receptor Desactivar si la dirección de inicio = 0
return;
}
mode=DMX;
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
if (Temp != 0)
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE)))// Si el receptor esta desabilitado -> habilitar y esperar descanso
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);
}
}
else
{
UCSRB &= ~(1<<RXCIE); // Receptor Desactivar si la dirección de inicio = 0
uint8_t i;
for (i=0; i<sizeof(DmxRxField); i++)
{
DmxRxField[i]= 0;
}
}
#endif
}
// *************** DMX recepción ISR ****************//
ISR (UART_RX_vect)
{
static uint16_t DmxCount;
uint8_t USARTstate= UCSRA; // Obtener estado antes de los datos!
uint8_t DmxByte = UDR; // Obtener los datos
uint8_t DmxState = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
IndFlags |= (1<<SIGNAL_COMING);// Recibir somedata
if (DmxState == BREAK)
{
UCSRA &= ~(1<<FE); // Cambiar Posible FE: a causa de MAB
if (DmxByte == 0)
{
gDmxState= STARTB;// Código de inicio normal detectado
gDmxPnt= ((uint8_t*)DmxRxField +1);
}
else
{
gDmxState= IDLE;
}
}
else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
{
UCSRA &= ~(1<<FE); // Restablecer bandera
if (DmxByte == 0) // Los datos de descanso debe ser 0
{
gDmxState= BREAK;
DmxCount= DmxAddress; // Restablecer contador de fotogramas
}
else
{
gDmxState= IDLE; // Bien es FE -> esperar descanso
}
}
else if (DmxState == STARTB)
{
if (--DmxCount == 0)// Dirección inicial alcanzada?
{
gDmxState= STARTADR;
DmxRxField[0]= DmxByte;
}
}
else if (DmxState == STARTADR)
{
uint8_t *DmxPnt;
DmxPnt= gDmxPnt;
*DmxPnt= DmxByte;
if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
{
Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
gDmxState= IDLE;
}
else
{
gDmxPnt= DmxPnt;
}
}
}
aca LIB_DMX_IN.H #include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define DMX_CHANNELS (13)
#define USE_DIP
#define F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {EVAL_DMX, IND};
volatile uint8_t Flags;
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
volatile uint16_t DmxAddress; // Dirección inicial
volatile int color_number;// numero de la tabla de Color del sonido / manual actual
volatile uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
extern void init_DMX_RX(void);
extern void get_dips(void);
extern void set_color(int color);
aca el MAIN o FADING_RAIBOW.C // #define F_CPU 8000000
#include<util\delay.h>
#include "lib_dmx_in.h"
#include<stdio.h>
#include<stdlib.h>
// #include"fading_raibow.h"
#include <avr/interrupt.h>
#include <avr/wdt.h>
//************************************************************//
volatile uint8_t DmxRxField[DMX_CHANNELS];
uint8_t DmxBuf[DMX_CHANNELS];
//**********************************************************//
#define OV_COUNT 14 // 161 , 7 = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
// Dato proveniente de la consola DMX
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
//*********************************//
volatile uint16_t DmxAddress; // Dirección inicial
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[]={ // Indice y valor a modificar {Resta,Suma}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
init_DMX_RX(); // Inicializar recpcion DMX
mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones globales ???
while(1) // bucle principal (LOOP)
{
get_dips(); // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
switch(mode)
{
case FIXED:
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
void fading_fijo(){
}
void fading_auto(){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(DMX_Velocidad); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
void DimmerCurva(){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(uint8_t DMX_Velocidad) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
void ISR(TIMER0_OVF_vect){
if (R_out>=PWM_timer) { salida &= 0x06; }
if (V_out>=PWM_timer) { salida &= 0x05; }
if (A_out>=PWM_timer) { salida &= 0x03; }
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
Cambiarmodo();
}
PWM_timer++;
}
void Cambiarmodo(){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
if(mode!=RAINBOW_FADING) //Reviso que ya no este en este modo.
{
mode=RAINBOW_FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
}
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
if(mode!=FADING) // Si ya esta en el modo, que no lo modifique.
{
mode=FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
}
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
aca los errores Build started 26.8.2015 at 22:08:44
avr-gcc.exe -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d -c ../fading_raibow.c
../fading_raibow.c:87: warning: braces around scalar initializer
../fading_raibow.c:87: warning: (near initialization for 'ArrayColorFadingRainbow[0]')
../fading_raibow.c:87: warning: excess elements in scalar initializer
../fading_raibow.c:87: warning: (near initialization for 'ArrayColorFadingRainbow[0]')
../fading_raibow.c:88: warning: braces around scalar initializer
../fading_raibow.c:88: warning: (near initialization for 'ArrayColorFadingRainbow[1]')
../fading_raibow.c:88: warning: excess elements in scalar initializer
../fading_raibow.c:88: warning: (near initialization for 'ArrayColorFadingRainbow[1]')
../fading_raibow.c:89: warning: braces around scalar initializer
../fading_raibow.c:89: warning: (near initialization for 'ArrayColorFadingRainbow[2]')
../fading_raibow.c:89: warning: excess elements in scalar initializer
../fading_raibow.c:89: warning: (near initialization for 'ArrayColorFadingRainbow[2]')
../fading_raibow.c: In function 'main':
../fading_raibow.c:145: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:148: warning: implicit declaration of function 'fading_fijo'
../fading_raibow.c:151: warning: implicit declaration of function 'fading_auto'
../fading_raibow.c:154: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c: At top level:
../fading_raibow.c:162: warning: conflicting types for 'fading_fijo'
../fading_raibow.c:148: warning: previous implicit declaration of 'fading_fijo' was here
../fading_raibow.c:168: warning: conflicting types for 'fading_auto'
../fading_raibow.c:151: warning: previous implicit declaration of 'fading_auto' was here
../fading_raibow.c: In function 'fading_auto':
../fading_raibow.c:173: warning: implicit declaration of function 'delay'
../fading_raibow.c: At top level:
../fading_raibow.c:187: warning: conflicting types for 'rainbow_fader'
../fading_raibow.c:154: warning: previous implicit declaration of 'rainbow_fader' was here
../fading_raibow.c: In function 'rainbow_fader':
../fading_raibow.c:201: error: subscripted value is neither array nor pointer
../fading_raibow.c:202: error: subscripted value is neither array nor pointer
../fading_raibow.c:203: error: subscripted value is neither array nor pointer
../fading_raibow.c: At top level:
../fading_raibow.c:213: warning: conflicting types for 'DimmerCurva'
../fading_raibow.c:145: warning: previous implicit declaration of 'DimmerCurva' was here
../fading_raibow.c:220: warning: conflicting types for 'delay'
../fading_raibow.c:173: warning: previous implicit declaration of 'delay' was here
../fading_raibow.c:242: error: two or more data types in declaration specifiers
../fading_raibow.c: In function '__vector_7':
../fading_raibow.c:244: error: 'salida' undeclared (first use in this function)
../fading_raibow.c:244: error: (Each undeclared identifier is reported only once
../fading_raibow.c:244: error: for each function it appears in.)
../fading_raibow.c:254: warning: implicit declaration of function 'Cambiarmodo'
../fading_raibow.c: At top level:
../fading_raibow.c:259: warning: conflicting types for 'Cambiarmodo'
../fading_raibow.c:254: warning: previous implicit declaration of 'Cambiarmodo' was here
make: *** [fading_raibow.o] Error 1
Build failed with 7 errors and 30 warnings...
bueno espero que te alla aclarado eso ., o al menos hice el intento de explicartelo
-
Bueno aca te subo para que veas (en el otro mensaje no me entraba) es para que veas, es un proyecto que estoy armando ., son lo tres led y dos motores PAP (funciona con 8 y 16 bits )., me funciona perfecto
El problema lo tengo con los motores (todos recuperados )., pero las vueltas y los pasos son ditintos en todos ., pero de funcionar., funciona perfectamente
El motivo es para que veas como trabajan los IRS ., si te fijas NO hay ningun PWM en los IRS ( uso los dos timer del integado ) todos los PWM estan en el WHILIE
Aparte probe con la libreria reformada ., compilo sin error ( tuve que declarar FADING y RAIBOW_FADER
y desabilita perfectamente la recepcion al poner el mini-dips N°10 en ON la consola DMX dice "desabilitado"
o sea que esa parte esta perfecta ., cuando la coloco en OFF mi montaje funciona perfectamente ., de la otra manera ., como es obio ., no funciona PORQUE NO HAY NADA
/**** A P P L I C A T I O N N O T E ************************************
*
* Title : DMX512 2 axis microstep controller
* Version : v1.1
* Last updated : 03.04.08
* Target : Transceiver Rev.3.01 [ATmega8515]
* Clock : 8MHz
*
* written by hendrik hoelscher, www.hoelscher-hi.de
***************************************************************************
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
If you have no copy of the GNU General Public License, write to the
Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
For other license models, please contact the author.
;***************************************************************************/
#include<stdio.h>
#include "lib_indicator.h"
#include "lib_dmx_in.h"
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h>
//*********************************//
uint8_t count= 1; //counter für soft PWM
uint8_t IndiCnt= 1; //counter für LED indicator
uint8_t DmxBuf[DMX_CHANNELS]; enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
//*** Inicialización pines / port ***//
void init_pinouts(){
//DDRA= 0xFF; // salidas bajas
//PORTA= 0;
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRD |= (1<<PD2); // El selector de la transmisión de salida colocación
PORTD |= (1<<PD2); // Establecer el estado de la RX 0 - entrada de transmisión
// Temporizador de inicialización para evitar cortar efecto estroboscópico
#define OV_COUNT 14 // 161 metros, 7 no repleta? = 0.25ms
#define OV_SIZE 161 // Worth ?? comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// Restablecer el temporizador
void reset_timer(){
TCNT0= OV_SIZE; // Worth ?? comenzando Contador inicial
timer_counter=0;
}
// *** establecer valor de WHILE y sound_time ***//
enum {FALSE=0, TRUE=1};
volatile char sound_time=TRUE;
//
uint16_t Accel;
volatile uint8_t Flags;
uint16_t IndCnt= 1000;
volatile uint8_t BasePat;
struct axis{ //all private data for X and Y axes
uint16_t Ist; //current position
uint16_t Soll; //destination pos
uint16_t Max; //max position
uint8_t State; //status flags
int8_t Speed; //current speed (raw)
uint16_t StpRate;
uint8_t TopPat; //PWM pattern
};
struct axis X;
struct axis Y;
enum {TICK, POS_CHANGED};
enum {POS};
#define OFFSET (4)
#define IND_TIME (2200)
#define X_MAX_H (1) //EEPROM usage
#define X_MAX_L (2)
#define Y_MAX_H (3)
#define Y_MAX_L (4)
#define ACC_H (5)
#define ACC_L (6)
const uint8_t bStep[] PROGMEM = { //halfsteps (DCBA DCBA)
0b00010001,
0b01010101,
0b01000100,
0b01100110,
0b00100010,
0b10101010,
0b10001000,
0b10011001,
0b00010001
};
const uint8_t buStep[] PROGMEM = { //1/8 steps
0b00010001,
0b01010001,
0b01010001,
0b01010001,
0b01010101,
0b01010100,
0b01010100,
0b01010100,
0b01000100,
0b01100100,
0b01100100,
0b01100100,
0b01100110,
0b01100010,
0b01100010,
0b01100010,
0b00100010,
0b10100010,
0b10100010,
0b10100010,
0b10101010,
0b10101000,
0b10101000,
0b10101000,
0b10001000,
0b10011000,
0b10011000,
0b10011000,
0b10011001,
0b10010001,
0b10010001,
0b10010001,
0b00010001
};
const uint8_t Step[] PROGMEM = { //halfsteps
0b00010001,
0b00110011,
0b00100010,
0b01100110,
0b01000100,
0b11001100,
0b10001000,
0b10011001,
0b00010001
};
const uint8_t uStep[] PROGMEM = { //1/8 steps
0b00010001,
0b00110001,
0b00110001,
0b00110001,
0b00110011,
0b00110010,
0b00110010,
0b00110010,
0b00100010,
0b01100010,
0b01100010,
0b01100010,
0b01100110,
0b01100100,
0b01100100,
0b01100100,
0b01000100,
0b11000100,
0b11000100,
0b11000100,
0b11001100,
0b11001000,
0b11001000,
0b11001000,
0b10001000,
0b10011000,
0b10011000,
0b10011000,
0b10011001,
0b10010001,
0b10010001,
0b10010001,
0b00010001
};
const uint16_t uAngle[] PROGMEM = {
0xF0, 176, 90, 41, 0xF0, 41, 90, 176
};
const uint16_t Ramp[] PROGMEM = {//acceleration, deceleration (step durations)
27145, 20829, 17560, 15471, 13987, 12862, 11972, 11244, 10635, 10115, 9665, 9270, 8920, 8606,
8324, 8068, 7834, 7619, 7421, 7238, 7067, 6908, 6760, 6620, 6489, 6366, 6249, 6138,
6033, 5933, 5839, 5748, 5662, 5579, 5500, 5424, 5351, 5281, 5214, 5149, 5087, 5026,
4968, 4912, 4858, 4805, 4754, 4705, 4657, 4611, 4566, 4522
};
// *************** Stepper Homing ****************
void home_stepper(void)
{
//postion reset (homing)
uint8_t tmp, tmpA= 0, tmpB= 0;
X.Ist= (X.Max>>1) +20 +OFFSET;
Y.Ist= (Y.Max>>1) +20 +OFFSET;
uint16_t delay;
while ((X.Ist != OFFSET) || (Y.Ist != OFFSET))
{
if (X.Ist > OFFSET)
{
if (PIND &(1<<PD4))
{
if (PIND &(1<<PD6)) tmpA= pgm_read_byte(&Step[(--X.Ist &7)]); //move through full range (open loop)
else tmpA= pgm_read_byte(&bStep[(--X.Ist &7)]);
tmpA &= 0b00001111;
}
else X.Ist= OFFSET; //Anschlag detected (closed loop reference)
}
if (Y.Ist > OFFSET)
{
if (PIND &(1<<PD5))
{
if (PIND &(1<<PD6)) tmpB= pgm_read_byte(&Step[(--Y.Ist &7)]);
else tmpB= pgm_read_byte(&bStep[(--Y.Ist &7)]);
tmpB &= 0b11110000;
}
else Y.Ist= OFFSET;
}
tmp= tmpA;
tmp |= tmpB;
PORTA= tmp;
wdt_reset();
delay= Accel>>1;
while (delay != 0)
{
_delay_us(35);
delay--;
}
}
}
// *************** Initialization ****************
void init_system(void)
{
wdt_reset();
wdt_enable(WDTO_500MS); //enable watchdog (Timeout= 0.5s)
wdt_reset();
DDRA= 0xFF; //low outputs
PORTA= 0;
DDRD= 0b10000110; //DMX, spare, LED1
PORTD= 0b01111010;
TCCR1A = (1<<WGM10);
TCCR1B = (1<<CS10)|(1<<WGM12); //set T1 @clock freq, 8bit fast PWM
TIMSK |= (1<<TOIE1)|(1<<OCIE1A)|(1<<OCIE1B); //enable compare and overflow interrupts (u-step, system)
if (eeprom_read_byte(0) == 1)
{
X.Max= (uint16_t)(eeprom_read_byte(X_MAX_H)<<8) +(uint16_t)eeprom_read_byte(X_MAX_L);
Y.Max= (uint16_t)(eeprom_read_byte(Y_MAX_H)<<8) +(uint16_t)eeprom_read_byte(Y_MAX_L);
Accel= (uint16_t)(eeprom_read_byte(ACC_H)<<8) +(uint16_t)eeprom_read_byte(ACC_L);
}
else
{
X.Max= 1600;
Y.Max= 1600;
Accel= 256;
}
home_stepper();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
init_DMX_RX();
}
// *************** Stepper speed control ****************
void check_speed(struct axis* Stp)
{
if (abs(Stp->Soll -Stp->Ist) <= abs(Stp->Speed)) //decel speed short before target position
{
if (Stp->Speed < 0) Stp->Speed++;
else if (Stp->Speed > 0) Stp->Speed--;
}
else if (Stp->Ist < Stp->Soll)//shall move in positive direction
{
if (Stp->Speed < 50) Stp->Speed++; //accel speed
}
else if (Stp->Ist > Stp->Soll) //shall move in negative direction
{
if (Stp->Speed > -50) Stp->Speed--; //accel speed
}
if (Stp->Speed > 0) Stp->Ist++;
else if (Stp->Speed < 0) Stp->Ist--;
uint32_t tmp= (uint32_t)pgm_read_word(&Ramp[abs(Stp->Speed)]);
Stp->StpRate= (tmp * Accel)>>16;
}
//*************** PROGRAMA PRINCIPAL ************//
int main(void)
{
cli();
init_system(); // iniciar sistema
sei();
int PWM_timer; // inicializar el timer PWM
char strobo = FALSE; // valor de strobo
unsigned int strobo_timer=0; // Contador Strobo igual a cero
while(1) // bucle principal (LOOP)
{
get_dips(); // establecer direccion de inicio
//************************************* PWM leds *********************************//
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++) // Loop timer general en un ciclo de llenado
{
if(DmxRxField[4]>20){ // Si el canal de luz stroboscópica es menor a 10 es siempre mayor que los LED ,el estroboscópico está apagado,
if( strobo_timer>(unsigned int)((255-DmxRxField[4])*16)){// Dmx CH4 igual a 11, es el tiempo máximo , o igual a 255 es el Tiempo min
strobo_timer=0;// Restablecer el temporizador
if(strobo){ strobo=FALSE;}else{ strobo=TRUE;} // Cambio habilitacion para ILUMINACIÓN
}else{
strobo_timer+=1; // base de tiempo strobo
}
}else{
strobo=TRUE; // la Stroboscopica está apagada,
}
if ( ((unsigned int)((DmxRxField[0]*DmxRxField[3])/255)>PWM_timer) && strobo ) //ROJO
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
}
if ( ((unsigned int)((DmxRxField[1]*DmxRxField[3])/255)>PWM_timer) && strobo ) //VERDE
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}
if ( ((unsigned int)((DmxRxField[2]*DmxRxField[3])/255)>PWM_timer) && strobo ) //AZUL
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}
if (Flags &(1<<TICK))
{
Flags &= ~(1<<TICK);
wdt_reset();
if (IndCnt-- == 0)
{
IndCnt= IND_TIME;
indicate();
}
if (X.StpRate-- == 0)
{
uint32_t tmp= ((uint32_t)DmxRxField[5]<<8) +(uint32_t)DmxRxField[6];
tmp= OFFSET +((tmp * X.Max)>>16);
if (tmp != X.Soll)
{
X.Soll= tmp;
IndFlags |= (1<<DATA_REFRESHED);
}
check_speed(&X);
Flags |= (1<<POS_CHANGED);
}
if (Y.StpRate-- == 0)
{
uint32_t tmp= ((uint32_t)DmxRxField[7]<<8) +(uint32_t)DmxRxField[8];
tmp= OFFSET +((tmp * Y.Max)>>16);
if (tmp != Y.Soll)
{
Y.Soll= tmp;
IndFlags |= (1<<DATA_REFRESHED);
}
check_speed(&Y);
Flags |= (1<<POS_CHANGED);
}
if (Flags &(1<<POS_CHANGED))
{
Flags &= ~(1<<POS_CHANGED);
uint8_t PatBuf;
if (PIND &(1<<PD6))
{
PatBuf= pgm_read_byte(&uStep[(X.Ist &31)]);//get new X pattern
}
else PatBuf= pgm_read_byte(&buStep[(X.Ist &31)]);
OCR1A= pgm_read_word(&uAngle[(X.Ist &0b111)]);
X.TopPat = (PatBuf>>4);
PatBuf= (PatBuf &0b00001111);
uint8_t Ytmp;
if (PIND &(1<<PD6))
{
Ytmp= pgm_read_byte(&uStep[(Y.Ist &31)]);//get new Y pattern
}
else Ytmp= pgm_read_byte(&buStep[(Y.Ist &31)]);
OCR1B= pgm_read_word(&uAngle[(Y.Ist &0b111)]);
Y.TopPat = (Ytmp &0b11110000);
PatBuf |= (Ytmp<<4);
BasePat= PatBuf;
}
if (count == 0xFF)
{ // Llamado con 122Hz
count= 1;
Flags |= (1<<IND); // señalizar
}
else count++;
}
}
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case FADING;
count = OV_COUNT + DmxAddress;
break;
case RAINBOW_FADER;
count = OV_COUNT + DmxAddress * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;
if (mode==RAINBOW_FADER){
indicate(); // señalizar con led azul
}
}else{ timer_counter++; }
if (Flags &(1<<EVAL_DMX)) // Universo DMX se actualiza
{
Flags &= ~(1<<EVAL_DMX);
IndFlags |= (1<<VALID_DMX); // Señal DMX Válida llegada
uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
{
if (DmxRxField[i] != DmxBuf[i]) // Un valor DMX ha cambiado?
{
DmxBuf[i]= DmxRxField[i];
IndFlags |= (1<<DATA_REFRESHED); // Sí -> borrar y actualizar dato!
}
}
}
if (Flags &(1<<IND)) // indicador LED, DIP
{
Flags &= ~(1<<IND);
wdt_reset(); // Restablecer perro guardián
if (--IndiCnt == 0)
{
IndiCnt= 8;
indicate(); // señalizar con led azul
}
}
}
// *************** ISRs ****************
ISR (TIMER1_OVF_vect)
{ //half step
Flags |= (1<<TICK); //tick system
PORTA= BasePat;
}
ISR (TIMER1_COMPA_vect) //X-axis µ-Stepping
{
uint8_t buf;
buf = PORTA;
buf &= 0b11110000;
buf |= X.TopPat;
PORTA= buf;
}
ISR (TIMER1_COMPB_vect) //Y-Axis µ-Stepping
{
uint8_t buf;
buf = PORTA;
buf &= 0b00001111;
buf |= Y.TopPat;
PORTA= buf;
}
ac se ve claramente como funcionan los IRS en DMX .,toma en consideracion que estan los dos timer usandose
-
pero me largo error ., y calculo que los errores tiene el mismo origen que es el PWM en e lIRS
Ninguno de los errores/warning es debido a eso. Si lees claramente que dice cada uno.
y te vuelvo a repetir en DMX se tiene que ejecitar en WHILE o FOR pero fuera del IRS
la razon es que te afecta la recepcion del USAT como te explique antes
Estas muy equivocado. Obviamente puedo hacer un "PWM" en el while. haciendo un for como vos pedis, es TOTALMENTE posible, pero practicamente insano hacerlo. tratar de que cada vuelta del for dure exactamente lo mismo para todos los modos, o posibilidades com oque tome un salto o no es realmente para sacarse el sombrero el que lo hace asi, vuelvo a decir, se puede, pero olvidate que alguien se va a complicar tanto para hacerlo cuando lo puede hacer mas facil, no se como estaras pensandolo vos pero yo me estoy fijando hasta la diferencia en micro segundos. Y lo pienso hasta el punto de ASM y ciclos de reloj.
A continuacion voy a darte una comparacion entre los 2:
Para darte un ejemplo, supongamos un PWM de 2 bits, es decir tenes 25% 50% 75% 100% duty. Esto para ser mucho mas simple y no de 8 bits con 255 pasos.
Que tenga un periodo de 1 segundo la señal de PWM ( Si tiene un periodo, este periodo es FIJO ), Cada seccion deberia poner a 0 o dejarla a 1 a la señal cada 0.25s
Nuestro caso es que tenemos un timer que lo hace cada 0.25s, entonces cuando ocurre eso nos fijamos y listo. si tuvieramos 25% de duty seleccionado, a los 0.25s exactamente verias la señal irse de 1 a 0. Genial. Se cumple con lo previsto
Cambiamos de modo. esto NO afecta al timer. sigue ejecutandose con su periodo inalterable y su duty perfecto.
Ahora imaginate un for(), en el que el primer paso por el for (valores tomados al azar pero que si lo haces en los 255 vas a ver que hay diferencia), le toma 200 instrucciones, el segundo paso le toma 240, el tercero le toma 210, el cuarto 220.
Bueno genial tenemos nuestro periodo, por que va a durar 200+240+210+220 (870) instrucciones, la primer vuelta para vos seria un 25% si usamos la logica que esta planteada. PERO realmente no es un 25% de duty sino que es 200/870 un 23%
Y bueno pero es una diferencia de 2%, nadie lo va a notar. Pero eso es por que yo seleccione valores cercanos, si esa primer vuelta hubiera sido de 50 instrucciones ( y no 200, ahora el total seria de 740 instrucciones ) tu duty (que vos supones de 25%) es de solo 50/740 = 7%. Ahora tenes un error de 18%.
Ahora si vos me aseguras que ese que lo hizo en C ( un lenguaje en el que no tiene control sobre la cantidad de instrucciones en ASM que se traduce en ciclos y tiempo a utilizar ) conto 1 por 1 las instrucciones de ASM por cada vuelta y por cada condicion si es que entra a algun IF o no, o lo que se le ocurra al compilador poner realmente tengo que creer que estas mintiendo.
Sigamos analizando el ejemplo que te di antes. Supone que dentro de ese for() tenes varios modos, no solo 1, tal cual tenemos en nuestro ejemplo FADING, FIJO, etc. el modo anterior duraba en total 740 instrucciones, ahora vamos a un modo mucho mas simple como es el de tener un valor fijo de color. Esto deberia llevar unas 20+20+20+20= 80 ( si todos iguales por que no se pregunta nada, simplemente se asigna y listo), Genial al no tener IF ni nada es fijo en cada una de las vueltas, lo cual mi 25% de duty es realmente mi 25%. Pero tengo que ahora dura un total de 80 instrucciones hacer todo el ciclo. Y exactamente aca le cambie el periodo/frecuencia de mi PWM. Que deberia ser un valor FIJO.
Peor aun y siendo mas estricto, una ves que se termino de hacer las 4 (o 255 si haces de 8 bits) vueltas del for. hay que hacer varias instrucciones mas hasta volver a entrar al for, esto puede tener una duracion fija o varaible, Supongamos que es fija. Analizemos los casos que presentamos ya
50+240+210+230= 740
20+20+20+20=80
Pero ahora tenemos eso y que supongamos sean unos 30 instrucciones mas entre que termina todo el for y vuelve a entrar a otro for
740 + 30
80 + 30
Aun mas GENIAL. estamos modificando aun mas el periodo de la señal, y sorpresa, ya nuestro 100% de duty ni siquiera es 100%.
740/770 = 96%
80/110 = 72%
Y ya no estamos hablando de DMX o lo que sea, sino que estamos hablando ya de no saber que es un PWM ( tanto Software como Hardware ). Por eso te vengo diciendo que es un error de concepto.
------------------
Ya con esto te explique claramente el por que NO debe usarse el for como vos opinas o crees para crear un PWM al menos no para algo tan complejo, lo que esta en ese codigo me parece es una aberracion como esta ejecutado el PWM.
Estoy mas que seguro que cualquier persona aca deberia decirte exactamente lo mismo. Sino sos libre de preguntar en
http://www.todopic.com.ar/foros/index.php?board=8.0
Y pregunta si un PWM deberia hacerse con un for(), por si crees que estoy loco ( aunque un poco no lo niego )
Espero que hasta con este ejemplo veas lo mal que esta aplicado por mas que vos creas que esta bien.
la razon es que te afecta la recepcion del USAT como te explique antes
JAMAS, la UART deberia recibir el dato completo pasarlo a un buffer ( en el caso del ATmega8515 es el UDR) y luego seguir recibiendo el otro envio sin molestia al procesador. Cuando se ubica el dato en el buffer, ocurren 2 cosas, se sigue recibiendo datos por la UART y se activa la interrupcion de la UART el cual ubica el dato en donde corresponde, si existen 2 interrupciones juntas como la de la UART y el timer, se atenderia primero una y luego la otra (a no ser que tengan prioridades es una condicion de carrera y no se puede decir cual es primero).Sin afectar a nadie. Si tomara demasiado tiempo la interrupcion de la UART entonces estaria modificando los valores del periodo de la señal. Pero nada mas
Normalmente una interrupcion deberia contener el minimo de codigo para realizar lo que deba y continuar.
El ultimo codigo que me pasaste claramente usa los timers para los motores, estara bien o estara mal? Eso depende. Pero tranquilamente podria haber usado 1 timer al menos y con eso controlar todo.
--------------------------------------------------------
Otra cosa mas a recalcar con respecto a esto:
Aparte probe con la libreria reformada ., compilo sin error ( tuve que declarar FADING y RAIBOW_FADER
Que compile significa que el codigo esta bien escrito. NADA MAS
Que funcione como debe el codigo es otra cosa, podes tener un codigo que esta bien escrito semanticamente y sintacticamente pero no haga lo que uno trato de hacer estrictamente hablando.
Para terminar esto una consideracion mas.
El programa que te pase si posee errores como que puse Array[] en ves de Array [3][2] y algunos mas ( que en realidad son 7 errores ) mas unos warning por no tener los prototipos de funciones.
En fin ese programa se abstrae completamente de lo que es el DMX, el DMX deberia funcionar tranquilamente aparte del programa y no afectarlo en ningun motivo.
Se podria separar en 2 partes independientes entre una y otra.
- Hacer el fading con los tiempos que deben ser. (Aqui uso los valores del DMX, y cuando me refiero a valores me refiero a cualquier cosa, podria haber definido 3 registros que me lleguen por SPI y aun asi funcionaria igual)
- Hacer el PWM por software (El cual se actualiza cuando debe y no depende de nadie, toma los valores y hace su trabajo)
El codigo del DMX deberia hacer lo mismo, solamente tomar los valores de la UART y ubicarlos donde deberia. FIN
Con eso tenes una independencia entre cada uno de los codigos, tal ves no se llegue a tal grado de independencia pero aun asi se logra bastante.
Es tu decisión final de como vas a terminar haciendolo al programa y el objetivo de mi post fue hacerte ver (con ejemplos) que estaba mal tu idea de como es un PWM por software. Aun asi sos libre de hacerlo como quieras.
Estoy por igual para responder cualquier duda que se te presente.
-
hola bueno
la verdad que no sabria que desirte amigo. por que eres la primer persona ., que me enseña desde 2013 que empece con los microsy la programacion
En ningun momento pongo en duda o contradigo lo que dices.,
porque me regalas tu experiencia y tu tiempo al compartir lo que apendio
pero le aclaro que no pongo en duda lo que dice.,(y explica con tanto detalle)
y le cuento por que .,yo aprendi solo y adquiri los conosimientos de acuerdo a lo que vi lei y razone
pero son trabjos de otras persionas ., yo jamas podria hacer eso ni mucho menos ( tengo muchisimo que aprender
yo lo pocoque se lo lo se por http://www.hoelscher-hi.de/hendrik/light/ressources.htm alli tiene varios ejemplos para mirar ., y tambien del mismo autor http://www.hoelscher-hi.de/hendrik/light/openrdm.htm en la parte que dice DMX (a la izquierda) son ejemplos practicos con monyajes y librerias
tambien esta este señor http://www.ulrichradig.de/home/index.php/dmx (aunque aqui hat muchas cosa que no comprendo)
tambien consuto por aca http://www.mikrocontroller.net/forum/mikrocontroller-elektronik?filter=Henne%C2%B4s+DMX+Transceiver
y aca tambien http://www.avrfreaks.net/search/site/dmx?solrsort=ds_created%20desc
Pero principal inconveniente que tengo ., si yo a medias se el español ., menos otros idiomas ., como el aleman , ingles , ruso o polaco
Por mas que use el traductor del navegador., las explicaciones me resultan incoerentes y menos entendible ., por no ser tecnico
Ahora al mirar los ejemplos de la red., los configuro como estan., si ellos se equivocan ., por supuesto que yo tambien
le suplico que le pegue una mirada ., talvez de esa manera me pueda explicar mejor
porque yo le digo sinseramente no ew visto ningun PWM en el IRS solo los COUNT que los manejan (hay otras formas como la de los motores pero no son PWM)
siseramente he quedado muy confundido ., pero es el precio que paga la ignorancia de las masa
todo lo que usted me explico lo encuentro razonable y logico
es lo otro lo que ya no entiendo
-
Si, los comentarios cuando son en otro idioma son dificiles de agarrar, lo bueno es que el codigo funciona de la misma forma.
Puede que estes confundido por que ya habias asumido que se realizaba asi. Creo que con el ejemplo que te di aunque tal ves exagerado ves cual es la diferencia entre uno y otro. Y el por que se realiza de esa forma.
Por si las dudas, revise las paginas que me pasaste por si alguno cometia el error de hacerlo con un for, y saque estos ejemplos
De las paginas que me pasaste:
http://www.ulrichradig.de/home/index.php/avr/avr-rgb-leds
El codigo tiene esto:
ISR (TIMER0_OVF0_vect)
{
if (pwm_counter++ > 63)
{
PORTB = 0x00;
pwm_counter = 0;
}
if (pwm_counter > pwm_r) PORTB |= LED_R;
if (pwm_counter > pwm_g) PORTB |= LED_G;
if (pwm_counter > pwm_b) PORTB |= LED_B;
}
Ese no usa DMX, es solo un PWM pero que recibe datos desde la UART, pero ahora vamos a ver un proyecto que usa DMX y realiza un "PWM" parecido ya que en realidad es un control de angulo de fase, pero tiene el mismo principio.
http://www.ulrichradig.de/home/index.php/avr/dmx-dimmer
Aqui lo que usa el codigo:
Ademas del ISR de la UART, tiene esta (Notaras la aplicacion que es identica o igual):
ISR (TIMER2_COMPA_vect)
//############################################################################
{
phase_off_count++;
if(phase_off_count > 90) phase_off_count = 0;
#if SSR_RELAIS1
if(phase_off_count>val1)
{
SSR1_ON
}
else
{
SSR1_OFF
}
#endif
#if SSR_RELAIS2
if(phase_off_count>val2)
{
SSR2_ON
}
else
{
SSR2_OFF
}
#endif
#if SSR_RELAIS3
if(phase_off_count>val3)
{
SSR3_ON
}
else
{
SSR3_OFF
}
#endif
if(dmx_lost<DMX_LOST_TIMEOUT)
{
dmx_lost++;
}
}
de AVRFreaks:
http://www.avrfreaks.net/projects/8-channel-soft-pwm-dmx-receiver?skey=dmx%20pwm
DMX y un PWM por software de 8 canales ( es decir 8 salidas), Usa el Timer0
// Interrupt Service Routine
SIGNAL (SIG_TIMER0_OVF)
{
static unsigned char pinlevelB=0xFF; // was portmask
static unsigned char softcount=0xFF;
PORTB = pinlevelB; // update outputs
if(++softcount == 0){ // increment modulo 256 counter and update
// the compare values only when counter = 0.
compare[0] = compbuff[0]; // verbose code for speed
compare[1] = compbuff[1];
compare[2] = compbuff[2];
compare[3] = compbuff[3];
compare[4] = compbuff[4];
compare[5] = compbuff[5];
compare[6] = compbuff[6];
compare[7] = compbuff[7]; // last element should equal CHMAX - 1
pinlevelB = 0xFF; // set all port pins high
}
// clear port pin on compare match (executed on next interrupt)
if(compare[0] == softcount) CH0_CLEAR;
if(compare[1] == softcount) CH1_CLEAR;
if(compare[2] == softcount) CH2_CLEAR;
if(compare[3] == softcount) CH3_CLEAR;
if(compare[4] == softcount) CH4_CLEAR;
if(compare[5] == softcount) CH5_CLEAR;
if(compare[6] == softcount) CH6_CLEAR;
if(compare[7] == softcount) CH7_CLEAR;
} // end of ISR ...
// *************** DMX Reception ISR ****************
ISR (USART_RX_vect)
No busque muchos proyectos para encontrar eso, directamente busque aquellos con las siglas DMX y PWM, los primeros que abri me encontre con eso. Con esto quiero decirte que no estoy buscando si o si la excusa sino que realmente fueron los primeros que abri.
De la primer pagina que me pasaste ( http://www.hoelscher-hi.de/hendrik/light/dmxled.htm ) ya estan en ASM. pero incluso busque a la izquierda LED y abri el zip para encontrar esto:
;interrupt vectors
.org 0
rjmp init ;reset vector address
reti ;External Interrupt0 Vector Address
reti ;External Interrupt1 Vector Address
reti ;Input Capture1 Interrupt Vector Address
rjmp strobe ;Output Compare1A Interrupt Vector Address
reti ;Output Compare1B Interrupt Vector Address
reti ;Overflow1 Interrupt Vector Address
rjmp pwm ;Overflow0 Interrupt Vector Address
reti ;SPI Interrupt Vector Address
rjmp get_byte ;UART Receive Complete Interrupt Vector Address
Utiliza la interrupcion ( por overflow ) del timer0 para generar el PWM. Y la interrupcion de la UART para los datos que llegan.
Y ahora que lo veo tiene un codigo parecido o el mismo al que inicio este hilo. En el que el PWM esta realizado con la interrupcion del Timer0 y aplicado de la misma forma que en todos los demas.
Es decir un contador que cuando llega a un punto se retea , en nuestro caso 255, algunos lo hacen con menos resolucion es decir pasos mas grandes y lo hacen 64. Eso depende de cada uno y el grado de variacion que va a poder tener.
es lo otro lo que ya no entiendo
Como te dije, sos libre de preguntar que si se la respuesta te la voy a intentar contestar, si no la conozco voy a buscarla, si realmente no me queda claro o no lo se, no me queda otra que decirte que no lo conozco, tal cual hice con lo de DMX. El cual no conocia como era el protocolo hasta que stk500 me dio ese empuje con la Nota de Applicacion.
-
!!!! perfecto mi amigo mas claro imposible ¡¡¡¡
la verdad que talvez habria convenido traducir la primer libreria de este hilo, porque son las mismas librerias DMX ., que yo uso (esta en ASM y la mia en C., pero son del mismo autor)
bueno aca te paso los errores que me da ahora en el primer caso NO ES el PWM ., sino que falta definir la funcion lo que es la palabra "salida" alli tengo tres errores
//***** inicio del ocilador Temporizador de interrupción ****//
// void ISR(TIMER0_OVF_vect){
ISR(TIMER0_OVF_vect){
if (R_out>=PWM_timer) { salida &= 0x06; }
if (V_out>=PWM_timer) { salida &= 0x05; }
if (A_out>=PWM_timer) { salida &= 0x03; }
if (PWM_timer==255)
{ y los errores son estos
../fading_raibow.c:244: error: 'salida' undeclared (first use in this function)
../fading_raibow.c:244: error: (Each undeclared identifier is reported only once
../fading_raibow.c:244: error: for each function it appears in.)
La verdad que mire y pense la compilacion., y se que alli queres definir los puertos de salida ., estoy en la duda si te referis a PORTB (PORTB0 ,PORTB1 y PORTB2)
bueno los otros errores que me larga son aca (lo escribiste antes pero no entendi como cambialos
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
} esto es lo que dice el compilador
../fading_raibow.c:201: error: subscripted value is neither array nor pointer
../fading_raibow.c:202: error: subscripted value is neither array nor pointer
../fading_raibow.c:203: error: subscripted value is neither array nor pointer
Espero que pueda compilar., asi probar y trato de hacer un video ., (por ahora pruebo con tras led de 5mm de 30°
pero ya compre 2 led de 20w rgb y estoy esperando que me lleguen
-
../fading_raibow.c:201: error: subscripted value is neither array nor pointer
../fading_raibow.c:202: error: subscripted value is neither array nor pointer
../fading_raibow.c:203: error: subscripted value is neither array nor pointer
Esos imagino que fueron por que lo defini mal, si observas este es el codigo que tengo:
const uint8_t ArrayColorFadingRainbow[]={ // Indice y valor a modificar {Resta,Suma}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
Cambialo por :
const uint8_t ArrayColorFadingRainbow[3][2]={ // Indice y valor a modificar {Resta,Suma}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
La verdad que mire y pense la compilacion., y se que alli queres definir los puertos de salida ., estoy en la duda si te referis a PORTB (PORTB0 ,PORTB1 y PORTB2)
Con respecto a salida, fue un error de copy paste, tome el codigo que habia puesto anteriormente en el post y lo pegue, Vos elegis que salidas vas a usar ahi. Basicamente ahi lo que deberia hacer es poner a 0 cada una de los pin de salida. Si supongamos tenes el PORTB0 como salida del rojo
if (R_out>=PWM_timer) { PORTB &= ~(1<<PB0); } // AND 1111 1110 (0xFE) , pone a 0 PORTB0
-
Bueno amigo ., alli probe ., no me funciona., los sintomas son
- las llaves mini-dips no funcionan., o sea no produce ningun cambio
- tampoco hay cambio a la funcion DMX ., (al no cambiar no funciona)
- los led (encienden los tres) ocila su encendido (pestañeo) tambien enciende PE0
- en el traceo de avrstudio ., pasa de las nini-dips a switch(mode)
si nesesita otra indicacion que pueda aportar para guiarlo ., aviceme
asi quedo el codigo
// #define F_CPU 8000000
#include<util\delay.h>
#include "lib_dmx_in.h"
#include<stdio.h>
#include<stdlib.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
//************************************************************//
volatile uint8_t DmxRxField[DMX_CHANNELS];
uint8_t DmxBuf[DMX_CHANNELS];
//**********************************************************//
// Dato proveniente de la consola DMX
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
//*********************************//
volatile uint16_t DmxAddress; // Dirección inicial
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[3][2]={ // Indice y valor a modificar {Resta,Suma}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
//************* Inicialización pines / port *****************//
void init_pinouts(){
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE |= (1<<PE0); //LED2 azul indicador
PORTE = 0;
}
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
}
int main(void)
{
//***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
init_DMX_RX(); // Inicializar recpcion DMX
mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones globales ???
while(1) // bucle principal (LOOP)
{
get_dips(); // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
switch(mode)
{
case FIXED:
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
void fading_fijo(){
}
void fading_auto(){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(DMX_Velocidad); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
void DimmerCurva(){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(uint8_t DMX_Velocidad) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
//***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
if (R_out>=PWM_timer) { PORTB &= ~(1<<PB0); } // AND 1111 1110 (0xFE) , pone a 0 PORTB0
if (V_out>=PWM_timer) { PORTB &= ~(1<<PB1); } // AND 1111 1110 (0xFE) , pone a 0 PORTB0
if (R_out>=PWM_timer) { PORTB &= ~(1<<PB2); } // AND 1111 1110 (0xFE) , pone a 0 PORTB0
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
Cambiarmodo();
}
PWM_timer++;
}
void Cambiarmodo(){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
if(mode!=RAINBOW_FADING) //Reviso que ya no este en este modo.
{
mode=RAINBOW_FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
}
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
if(mode!=FADING) // Si ya esta en el modo, que no lo modifique.
{
mode=FADING;
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
}
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
la libreria de dmx .C
#include "lib_dmx_in.h"
//#include "lib_indicator.h"
// ********************* definiciones locales*********************
enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX
uint8_t gDmxState;
uint8_t *gDmxPnt;
uint16_t DmxCount;
//volatile uint8_t gDmxState;
// *************** DMX recepción de inicialización ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
DDRC = 0; // establecer DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRD |= (1<<2);
PORTD &= ~(1<<2);
UBRRH = 0; // Habilitar recepción
UBRRL = ((F_OSC/4000)-1);// 250kBaud, 8N2
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;
uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
{
DmxRxField[i]= 0;
}
}
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
if (!(PINE &(1<<PE1))){ // Modo Manual
Temp= // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // Manual,
{
mode= FADING;
}else{
mode= RAINBOW_FADING;
}
UCSRB &= ~(1<<RXCIE);// Receptor Desactivar si la dirección de inicio = 0
return;
}
mode=DMX;
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
if (Temp != 0)
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE)))// Si el receptor esta desabilitado -> habilitar y esperar descanso
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);
}
}
else
{
UCSRB &= ~(1<<RXCIE); // Receptor Desactivar si la dirección de inicio = 0
uint8_t i;
for (i=0; i<sizeof(DmxRxField); i++)
{
DmxRxField[i]= 0;
}
}
#endif
}
// *************** DMX recepción ISR ****************//
ISR (UART_RX_vect)
{
static uint16_t DmxCount;
uint8_t USARTstate= UCSRA; // Obtener estado antes de los datos!
uint8_t DmxByte = UDR; // Obtener los datos
uint8_t DmxState = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
if (DmxState == BREAK)
{
UCSRA &= ~(1<<FE); // Cambiar Posible FE: a causa de MAB
if (DmxByte == 0)
{
gDmxState= STARTB;// Código de inicio normal detectado
gDmxPnt= ((uint8_t*)DmxRxField +1);
}
else
{
gDmxState= IDLE;
}
}
else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
{
UCSRA &= ~(1<<FE); // Restablecer bandera
if (DmxByte == 0) // Los datos de descanso debe ser 0
{
gDmxState= BREAK;
DmxCount= DmxAddress; // Restablecer contador de fotogramas
}
else
{
gDmxState= IDLE; // Bien es FE -> esperar descanso
}
}
else if (DmxState == STARTB)
{
if (--DmxCount == 0)// Dirección inicial alcanzada?
{
gDmxState= STARTADR;
DmxRxField[0]= DmxByte;
}
}
else if (DmxState == STARTADR)
{
uint8_t *DmxPnt;
DmxPnt= gDmxPnt;
*DmxPnt= DmxByte;
if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
{
Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
gDmxState= IDLE;
}
else
{
gDmxPnt= DmxPnt;
}
}
}
y la libreria dmx.H
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define DMX_CHANNELS (13)
#define USE_DIP
#define F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {EVAL_DMX, IND};
volatile uint8_t Flags;
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING,DMX} mode;
volatile uint16_t DmxAddress; // Dirección inicial
volatile int color_number;// numero de la tabla de Color del sonido / manual actual
volatile uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
extern void init_DMX_RX(void);
extern void get_dips(void);
extern void set_color(int color);
-
Ya voy a ver cual es el problema. Se me ocurren algunas cosas que puede haber mal.
las llaves mini-dips no funcionan., o sea no produce ningun cambio
tampoco hay cambio a la funcion DMX ., (al no cambiar no funciona)
Algun conflicto en como se toman los datos, ademas veo que usas el "mode" ahi dentro del codigo del DMX, el cual no deberias, la libreria de DMX deberia ser totalmente ajena a como es el programa principal, sino cada vez que compilas un codigo tenes que reformar la libreria, tambien cada uno de los codigos hace uso de variables que no me parecen estar bien definidas. Ya que el .hex lo esta definiendo en el main.c y en la libreria de DMX .c y poseen un scope de file por lo que a no ser que se use un extern no podrias acceder a la otra. Por otro lado tampoco deberias. Tampoco se por que estan definidas las funciones con "extern" en el .h.
En fin ya voy a verla y lo modifico y ves como queda.
Una pregunta El DIP
Los bits de 0 a 6 es la direccion y el 7 lo queres poner manual/dmx ?
Por que si es asi tengo que reformar el programa :P un poquito
los led (encienden los tres) ocila su encendido (pestañeo) tambien enciende PE0
Yo le quite todo el soporte a PE0 , antes encendia y apagaba a cada ratito. simplmente opte por quitarlo. debe encenderse al comienzo del programa sino no se por que lo hace.
Con respecto a que los leds pestañeen puede ser que este mal configurado el tiempo del timer. ya que no le preste atencion a los tiempos de carga ni preescalers.
Otra causa puede ser el WDT, se podria quitar para probar inicialmente el codigo. Tenes que recordar que hay delays que duran hasta 580ms y vos tenes un WDT de 0.5s ( si es que llega a ese tiempo )
en el traceo de avrstudio ., pasa de las nini-dips a switch(mode)
Realmente no se por que.
Ahora simplemente tengo que ver todos los codigos para ver que esta pasando.
-
hola
bueno yo tambientenia dudas de eso y compile con otra libria dmx_in pero paso lo mismo ., el pin N° 10 no desabilita ni habilita
no se enque parte de tu codigo esta esa llave talves como compilo tenga dos funciones y no una
la libreria que probe que te dije es esta
/**** A P P L I C A T I O N N O T E ************************************
*
* Title : DMX512 reception library
* Version : v1.3
* Last updated : 13.04.09
* Target : Transceiver Rev.3.01 [ATmega8515]
* Clock : 8MHz, 16MHz
*
*
***************************************************************************
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version2 of
the License, or (at your option) any later version.
;***************************************************************************/
#include "lib_dmx_in.h"
// ********************* local definitions *********************
enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states
volatile uint8_t gDmxState;
// *************** DMX Reception Initialisation ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
DDRC = 0; //set up DIPs
PORTC = 0xFF;
DDRE &= ~((1<<PE2)|(1<<PE1));
PORTE |= (1<<PE2)|(1<<PE1);
#endif
DDRD |= (1<<2);
PORTD &= ~(1<<2);
UBRRH = 0; //enable reception
UBRRL = ((F_OSC/4000)-1); //250kbaud, 8N2
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;
}
// ************* get DMX start address **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp= (0xFF-PINC);//invert DIP state
if (!(PINE &(1<<2)))
{
Temp += 256; //9th bit
}
if (Temp != 0)
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE))) //if receiver was disabled -> enable and wait for break
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);
}
}
else
{
UCSRB &= ~(1<<RXCIE);//disable Receiver if start address = 0
uint8_t i;
for (i=0; i<sizeof(DmxRxField); i++)
{
DmxRxField[i]= 0;
}
}
#endif
}
// *************** DMX Reception ISR ****************
ISR (UART_RX_vect)
{
static uint16_t DmxCount;
uint8_t USARTstate= UCSRA;//get state before data!
uint8_t DmxByte = UDR;//get data
uint8_t DmxState = gDmxState; //just load once from SRAM to increase speed
if (USARTstate &(1<<FE))//check for break
{
UCSRA &= ~(1<<FE); //reset flag (necessary for simulation in AVR Studio)
DmxCount = DmxAddress; //reset channel counter (count channels before start address)
gDmxState= BREAK;
}
else if (DmxState == BREAK)
{
if (DmxByte == 0) gDmxState= STARTB;//normal start code detected
else gDmxState= IDLE;
}
else if (DmxState == STARTB)
{
if (--DmxCount == 0) //start address reached?
{
DmxCount= 1;//set up counter for required channels
DmxRxField[0]= DmxByte;//get 1st DMX channel of device
gDmxState= STARTADR;
}
}
else if (DmxState == STARTADR)
{
DmxRxField[DmxCount++]= DmxByte;//get channel
if (DmxCount >= sizeof(DmxRxField)) //all ch received?
{
gDmxState= IDLE; //wait for next break
}
}
}
corregi lo dela libreria .H quedo asi #include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define DMX_CHANNELS (13)
#define USE_DIP
#define F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING,DMX} mode;
volatile uint16_t DmxAddress; // Dirección inicial
enum {EVAL_DMX, IND};
volatile uint8_t Flags;
volatile uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
extern void init_DMX_RX(void);
extern void get_dips(void);
Y hace lo mismo ., En cuanto a lo MINI-DIPS si te fijas el la ultima libreria que subi (es distinta a la otra ., esta es la original sin reformas) prestale atencion a los dips., porque esta dedinidos a GND ., ojo (la otra tambien ) pero eran del PINC0 a PINC7 y PINE1 , PINE2 tiene dos posiciones definidas !!!!pero ojo son 9 llaves la de dmx NO 8 ¡¡¡
la llave N° 10 no se usa como direccion sino que se usa como conmutador , (en off DMX y en on (lo que quiera hacer manual ) ., si o si es reservada funcion DMX NO se TOCA porque es la que desabilita la recepcion """ if (!(UCSRB &(1<<RXCIE))) //if receiver was disabled -> enable and wait for break """ ., sin pasa lo que ahora., no funciana dmx (peroesta habilitado
Esa era mi incitencia ., que usaras las llaves del primer array ., porque el segundo era para dmx .,y se leen con la funcion GEP_dip ., asi de facil (se use o no la recepcion de DMX., igual te las lee
el WDT lo desgrabe de la configuracion de fuses """"" wdt_enable(WDTO_500MS);""" y son 500ms .,pero no es alli el problema ., pero hace el mismo defecto .(fijate que no esta puesto o conectado el pin RESET del uC)
cualquier otro dato que nesesites te lo aporto
-
Por fin termine el codigo, no se que tal estara ya que no se TODOS los errores que pueden salir, debido a que no lo compile :P. A partir de aca creo que estas solo pero no voy a poder dedicarle mucho tiempo como ya lo hice, por que necesito dedicarme a otras cosas que tengo que hacer. Pero cuando tenga un tiempo te doy una mano.
main.c
/*
* DMX_RGB FADING/FIXED/RAINBOW
*
* Created on: 23/08/2015
* Author:
*/
/*
* SECCION DE INCLUDES
*
*/
// Include para la definicion de las variables
#include <stdint.h>
// Include liberias del micro, Interrupcion / WDT / delay
#include <util\delay.h>
#include <avr/interrupt.h>
//#include <avr/wdt.h>
// Include funcione de DMX
#include "dmx.h"
/*
*
* PROTOTIPOS DE FUNCIONES
*
*
*/
// Funciones de inicializacion de modulos
void vInitPinout(void);
void vInitTimer0(void);
//Funciones Auxiliares
void DimmerCurva(void);
void delay(void);
void Cambiarmodo(void);
// Modos
void fixed_color(void);
void fading_fijo(void);
void fading_auto(void);
void rainbow_fader(void);
/*
*
*
* DEFINICION DE VARIABLES
*
*
*/
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode,last_mode;
// Dato proveniente de la consola DMX
extern uint8_t DmxRxField[DMX_CHANNELS]; // Valores externos tomados desde la libreria.
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
// Definicion de salidas para los colores
#define DDR_PWM DDRB
#define PORT_PWM PORTB
#define PWM_R PB0
#define PWM_G PB1
#define PWM_B PB2
//*********************************//
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0,Alpha;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[6]={ // Indice y valor a modificar {0,1,2} = {R,G,B} ; indice par = incremento ; indice impar = decremento
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[3][2]={ // Indice y valor a modificar {Decremento,Incremento}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
/*
*
*
* CODIGOS DE INICIALIZACION DE MODULOS
*
*
*/
//************* Inicialización pines / port *****************//
void vInitPinout(void){
// Configuracion de las llaves DIP para el DMX
// Configuracion de salidas
DDR_PWM |= (1<<PWM_R) | (1<<PWM_G) | (1<<PWM_B); // Salida pin LEDs , PB0 = Rojo, PB1 = Verde, PB2 = Azul
PORT_PWM = 0;
DDRE |= (1<<PE0); // LED indicador de funcionamiento en PE0
PORTE = 0;
}
// ***** inicializacion del timer****//
void vInitTimer0(void){
TCCR0= (1<<CS00) ; // Preescaler 1:1
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
}
/*
*
*
* PROGRAMA PRINCIPAL
*
*
*/
int main(void)
{
vInitPinout(); // Establecer los puertos de E / S
vInitTimer0(); // Establecer el timer
vInit_DMX_RX(); // Iniciar la UART y puertos para la llave DIP
last_mode = mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones, Timer/UART(DMX) habilitados
while(1) // bucle principal (LOOP)
{
if(!bGetDips()){last_mode=mode=FADING;} // Pregunto si esta activo el DMX y Toma la direccion y la actualiza, tambien desabilita el DMX de ser necesario
if(last_mode!=mode){Cambiarmodo();} // Caso que desde el DMX se pida cambiar el modo, cambia unicamente cuando termino la rutina
switch(last_mode)
{
case FIXED:
fixed_color();
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
/*
*
*
* MODOS DE OPERACION
*
* fixed_color() - Color fijo, tomado desde el DMX.
* fading_fijo() - Produce el efecto de fading con el color tomado del DMX, pero solo ese color, de 0 a 255.
* fading_auto() - Comienza la ejecucion de fading de distintos colores, solo toma en cuenta la velocidad, solo 1 color a la ves.
* rainbow_fading() - Agregado al fading_auto(), en caso que se seleccione este, se modificaran 2 colores en ves de 1.
*/
void fixed_color(void){
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
}
void fading_fijo(void){
Rojo = DMX_R * (Alpha/255); // Colores tomados directamente del DMX para fijo
Verde = DMX_G * (Alpha/255);
Azul = DMX_B * (Alpha/255);
DimmerCurva();
Alpha++;
delay();
}
void fading_auto(void){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(void){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
/*
*
*
* UTILIDADES
*
*
* DimmerCurva() - Actualiza los colores para que el PWM tome los valores nuevos
* delay() - Demora introducida para modificar la velocidad de los efectos
* Cambiarmodo() - Funcion usada que toma el valor del DMX, traduciendolo y efectua el cambio.
*/
void DimmerCurva(void){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(void) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
void Cambiarmodo(void){
last_mode=mode;
switch(mode) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case RAINBOW_FADING: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
break;
case FADING: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
break;
default: //Case FADING_FIX, de 64 a 127, y FIXED, de 0 a 63. Bits de mayor peso quedan siempre en 01 y 00
break;
}
}
void SetMode(void){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
mode=RAINBOW_FADING;
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
mode=FADING;
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
/*
*
*
* ESPACIO PARA INTERRUPCIONES
*
*
* Timer0 - Por Overflow - Para el PWM por software
* UART - RX - Para el DMX
*/
void ISR(TIMER0_OVF_vect){
if (!PWM_timer) PORT_PWM |= ((1<<PWM_R)|(1<<PWM_R)|(1<<PWM_R)); // Si es 0 el PWM_timer pone a 1 las salidas
if (R_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_R); } // Cuando se cumple el tiempo las pone a 0, es decir cuando tenga 255 es el maximo que van a estar encendidas
if (V_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_G); }
if (A_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_B); }
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, si cambio el modo cargo el nuevo modo y espero que el programa principal termine lo que estaba haciendo para comenzar con el nuevo modo
SetMode();
}
PWM_timer++;
}
void ISR (UART_RX_vect)
{
vHook_DMX_UART();
}
dmx.h
/*
* dmx.h
*
* Created on: 30/08/2015
* Author:
*/
#ifndef DMX_H_
#define DMX_H_
// Definiciones para el DMX
#define F_OSC (8000) // Frec oscilador, para setear la UART
#define DMX_CHANNELS 6 // Cantidad de canales usados en el DMX
// Habilita el uso del DIP en caso no NO estar habilitado es necesario definir una direccion
#define USE_DIP
#define DMX_ADDRESS 0x1FF
// Definicion de pines para el DIP del DMX
#define PORT_DIP_C PORTC // Puerto Completo
#define DDR_DIP_C DDRC
#define PIN_DIP_C PINC
#define PORT_DIP_I PORTE // Puerto incompleto , Pines que faltan para completar el DIP
#define DDR_DIP_I DDRE
#define PIN_DIP_I PINE
#define PIN_DIP_ADD PE2 // Pin que tiene el bit de mayor peso de la direccion
#define PIN_DIP_MAN PE1 // Pin que tiene la seleccion Manual/DMX
// Prototipos de funciones
void vInit_DMX_RX(void);
uint1_t bGetDips(void);
#endif /* DMX_H_ */
dmx.c
/*
* dmx.c
*
* Para que funcione este codigo en otros proyectos es necesario crear 1 funcion en el main
* Esta funcion es para el ISR de la UART y que llame a vHook_DMX_UART()
*
*/
#include "dmx.h"
#include <avr/io.h>
#include <stdint.h>
// ********************* definiciones locales*********************
enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX
enum {EVAL_DMX, IND};
uint8_t gDmxState;
uint8_t *gDmxPnt;
uint8_t Flags;
uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
uint16_t DmxCount;
uint16_t DmxAddress; // Dirección inicial
// *************** DMX recepción de inicialización ****************
void vInit_DMX_RX(void)
{
#ifdef USE_DIP
// Configuracion de salidas
DDR_DIP_C = 0; // Todas entradas port completo
PORT_DIP_C = 0xFF; // Activo Pull-up
DDR_DIP_I &= ~((1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN)); // Port Incompleto, solo esas entradsa
PORT_DIP_I |= (1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN); // Activo sus Pull-up
#endif
// Configuracion de la UART
DDRD |= (1<<2);
PORTD &= ~(1<<2);
UBRRH = 0; // Habilitar recepción
UBRRL = ((F_OSC/4000)-1);// 250kBaud, 8N2
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;
uint8_t i;
for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
}
// ************* obtener DMX dirección de inicio **************
uint1_t bGetDips(void)
{
uint8_t i;
uint16_t Temp;
#ifdef USE_DIP
Temp= (!(PIN_DIP_I &(1<<PIN_DIP_ADD)) *256) + PIN_DIP_C; //Tomo la direccion desde los DIPs PORT_INCOPLETO:PORT_COMPLETO_7-0 (9 bits)
i = (PIN_DIP_I &(1<<PIN_DIP_MAN));
#else
Temp= DMX_ADDRESS;
i=0;
#endif
if (!i && Temp != 0) //Si es Manual deshabilito DMX, si PIN_DIP_MAN=0 activo DMX solo si la direccion es distinta de 0.
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE))) // Si el receptor esta desabilitado -> habilitar y setear modo de DMX en espera (IDLE).
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);
}
return 1;
}
else
{
UCSRB &= ~(1<<RXCIE); // Manual o Direccion=0, Deshabilito la UART y limpio los valores del DMX ( no se para que )
for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
return 0;
}
}
// *************** DMX recepción ISR ****************//
void vHook_DMX_UART(void)
{
static uint16_t DmxCount;
uint8_t USARTstate= UCSRA; // Obtener estado antes de los datos!
uint8_t DmxByte = UDR; // Obtener los datos
uint8_t DmxState = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
if (DmxState == BREAK)
{
UCSRA &= ~(1<<FE); // Cambiar Posible FE: a causa de MAB
if (DmxByte == 0)
{
gDmxState= STARTB;// Código de inicio normal detectado
gDmxPnt= ((uint8_t*)DmxRxField +1);
}
else
{
gDmxState= IDLE;
}
}
else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
{
UCSRA &= ~(1<<FE); // Restablecer bandera
if (DmxByte == 0) // Los datos de descanso debe ser 0
{
gDmxState= BREAK;
DmxCount= DmxAddress; // Restablecer contador de fotogramas
}
else
{
gDmxState= IDLE; // Bien es FE -> esperar descanso
}
}
else if (DmxState == STARTB)
{
if (--DmxCount == 0)// Dirección inicial alcanzada?
{
gDmxState= STARTADR;
DmxRxField[0]= DmxByte;
}
}
else if (DmxState == STARTADR)
{
uint8_t *DmxPnt;
DmxPnt= gDmxPnt;
*DmxPnt= DmxByte;
if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
{
Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
gDmxState= IDLE;
}
else
{
gDmxPnt= DmxPnt;
}
}
}
Creo que esta lo suficientemente documentado con los comentarios que hay. Y espero que funcione a la primera, seria lo ideal.
Luego contas como te fue y si lo solucionaste o diste marcha atras :)
Hay muchas cosas que cambie, hice nuevas funciones, modifique funciones, etc.
Como por ejemplo, ahora los pines para los DIPs se configuran desde dmx.h , ahi tenes el puerto completo (PORTC) y el puerto incompleto (PORTE) para formar la direccion, aunque intente darle un poco de flexibilidad si es que moves las llaves a otro puerto. Aun asi todavia el del puerto incompleto es el bit de mayor peso de los 9. Esta tambien separado cual es el pin que hace que pase a ser manual o no.
Ahora la funcion de ISR se encuentra en el main. y se llama a la funcion del DMX
Al actualizar la direccion del DMX si se cumple que la direccion es 0 o que esta en manual retorna un valor dejandolo en fading_auto.
Cambie la velocidad del timer, tenia preescaler 1/256 lo puse con 1/1 como estaba en el ejemplo que pasaste.
Modifique un poco el codigo del PWM por soft, de esa forma se pone a 1 cuando comienza en 0 y luego se desactiva de ser necesario. ( Aunque no es lo ideal y que tenia pensado hacer )
Tambien se puede modificar las salidas modificando los define al comienzo del main.
Y ya no recuerdo mas que otras cositas toque. Parece un programa corto pero no lo es tanto. xD
Tambien modifique le codigo para cuando no queres usar el DIP y que tenga una direccion FIJA, esto te va a inhabilitar que puedas pasarlo de Manual a DMX o viceversa. Aunque se puede modificar eso con facilidad para dejar que se pueda usar 1 llave sola y no le preste atencion a lo demas.
-
joder Killer !!! como te lo hace!!
ahora mismo estoy liado con un projectos pero cuando tenga Tiempo lo voy a probar y te comento.
Podria poner una emplanacion de los pines que usas y funciones?
asi podria hacer un Esquemas subirlo por aqui. no cree?
Saludos
-
Realmente stk, estoy haciendolo todo en el "aire" no tengo nada concreto. No utilizo el compilador de Atmel, no tengo placa para probarlo. No tengo nada.
Solo agarre un editor como es el Code Composer Studio, basado en elipse, cree 3 archivos y lo hice desde alli y los codigos que me dio locodelafonola, por mas que no puedo compilarlo me iba a ayudar a quitar algunos errores de tipeo.
En fin todo comenzo por que locodelafonola queria pasar una funcion que estaba en ASM a C. El cual accedi a ayudar. Yo a todo esto sin conocimiento de DMX, sin conocimiento del circuito y por si fuera poco sin haber tocado nunca un micro de Atmel.
Comence a pasarlo cuando tuvimos el primer problema. El programa pasado del ASM al C no permitia un "correcto" manejo y cambio de modos. Ya que si usabamos el codigo de antes al intentar cambiar de modo el programa tenia que terminar el modo anterior y eso podia llevar unos cuantos segundos. Por eso mismo reescribi las funciones para que pueda ser usado y cambiado desde la interrupcion, con un delay maximo de unos 580ms que es el maximo delay que podia ocurrir en el ASM aproximadamente.
Con esto quiero decir. No hay nada concreto, no tome ningun valor y dije "voy a comenzar desde aqui" o "tiene que cumplir estos valores", sino que el pasarlo desde uno a otro termino con ese codigo por lo cual no se que tan exacto o correcto funcionara. No se si habra que modificar el valor del timer para el PWM eso no lo se, tambien otra cosa que puede necesitar modificarse es la formula de delay. No me puse a hacer las matematicas ni nada por el estilo. Pero la programacion es la programacion y solo afectara unos pequeños detalles o partes del codigo, asi que es lo mismo.
Con respecto al HW, locodelafonola colgo el esquema en la 2da pagina, sino aqui te proveo del link:
http://www.todopic.com.ar/foros/index.php?topic=44880.msg373782#msg373782
El cual pertenece al codigo antiguo sino me equivoco. pero que tome como referencia para lo demas.
Aca tambien los modos (Aunque esta explicado en los comentarios):
http://www.todopic.com.ar/foros/index.php?topic=44880.msg373824#msg373824
Los modos a excepcion del fijo y fading de un solo color que los cree yo como para "agregarle" algo mas, los demas son traducidos del programa que dio en ASM.
Hay muchas cosas que se pueden hacer para que quede mas limpio y ordenado, como todas las definiciones y declaraciones de variables podrian tranquilamente ir en un .h
Tambien las funciones que declare como auxiliares y modos en otro archivo, asi de esa forma solo queda el main() y los ISR en el main.c y queda un poco mas ordenado.
Pero hacer eso aqui en el foro significa 5/6 partes de codigo que deberian luego unirse y pienso que es mas comlpejo hacerlo que solo 3. Asi que lo deje asi.
-
Ok! :)
-
estoy probando tu codigo killer y me sale 3 Errores y 3 Avisos, los aviso no le doy importancia ya que no lo Optimos tu codigo.
Mira la imagen
(http://www.todopic.com.ar/foros/imgtiny/jrbktd.jpg)
ojos hay que definir el CPU- Crystal , le he puesto 8Mhz
Saludos
-
bueno no veo que puede ser en algunos casos por que parece que esta corrido el tema del numero de lineas. Pero por lo que parece es:
por haber puesto:
void ISR (xxxx)
en ves de
ISR (xxx)
Parece que ya ISR define un tipo. Eso quitaria 2 errores, los de las lineas 385/404 que tenes
Me falto definir en el .h la funcion vHook_DMX_UART, esto quitaria el warning en la linea 406, ademas permite usarlo
No se por que el warning de la linea 196, esta definido en el .h
Ahi cambie los uint1_t por bool y agregue la libreria stdbool.h
Para solucionar el error de la linea 37 en el .h
Agregue un define F_CPU 8000000
Dejo el codigo de nuevo, vas a tener que ponerle nuevamente la frecuencia del cristal o acomodarlo si es que lo puse mal (me refiero a la linea que puse antes).
Y la proxima copialo y pegalo asi puedo leerlo completo al error y me guio un poco mas, por ejemplo el primer warning no se de que es.
main.c
/*
* DMX_RGB FADING/FIXED/RAINBOW
*
* Created on: 23/08/2015
* Author:
*/
/*
* SECCION DE INCLUDES
*
*/
// Include para la definicion de las variables
#include <stdint.h>
// Include liberias del micro, Interrupcion / WDT / delay
#define F_CPU 8000000 //Para que funcione el delay
#include <util\delay.h>
#include <avr/interrupt.h>
//#include <avr/wdt.h>
// Include funcione de DMX
#include "dmx.h"
/*
*
* PROTOTIPOS DE FUNCIONES
*
*
*/
// Funciones de inicializacion de modulos
void vInitPinout(void);
void vInitTimer0(void);
//Funciones Auxiliares
void DimmerCurva(void);
void delay(void);
void Cambiarmodo(void);
// Modos
void fixed_color(void);
void fading_fijo(void);
void fading_auto(void);
void rainbow_fader(void);
/*
*
*
* DEFINICION DE VARIABLES
*
*
*/
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode,last_mode;
// Dato proveniente de la consola DMX
extern uint8_t DmxRxField[DMX_CHANNELS]; // Valores externos tomados desde la libreria.
#define DMX_R DmxRxField[1] //Canal R
#define DMX_G DmxRxField[2] //Canal G
#define DMX_B DmxRxField[3] //Canal B
#define DMX_Modo DmxRxField[4] //Seleccion de Modo
#define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
// Para simplificar los datos del array de colores que estoy usando.
// ArrayColores contiene los valores RGB del momento
#define Rojo ArrayColores[0]
#define Verde ArrayColores[1]
#define Azul ArrayColores[2]
// Definicion de salidas para los colores
#define DDR_PWM DDRB
#define PORT_PWM PORTB
#define PWM_R PB0
#define PWM_G PB1
#define PWM_B PB2
//*********************************//
uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
uint8_t PWM_timer=0,Alpha;
uint8_t estado=0,estador=0; // Estado de los fading
const uint8_t arraydimmer[256]={
0, 0, 1, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 4, 4,
4, 5, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13, 14, 14, 15, 15,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 27, 28, 29,
30, 30, 31, 32, 33, 34, 35, 36,
36, 37, 38, 39, 40, 41, 42, 43,
43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 102, 103, 104, 105, 106, 107,
108, 109, 110, 112, 113, 114, 115, 116,
117, 119, 120, 121, 122, 123, 124, 126,
127, 128, 129, 130, 132, 133, 134, 135,
136, 138, 139, 140, 141, 142, 144, 145,
146, 147, 149, 150, 151, 152, 154, 155,
156, 158, 159, 160, 161, 162, 164, 165,
167, 168, 169, 171, 172, 173, 174, 176,
177, 178, 180, 181, 182, 184, 185, 187,
188, 189, 191, 192, 193, 195, 196, 197,
199, 200, 202, 203, 204, 206, 207, 208,
210, 211, 213, 214, 216, 217, 218, 220,
221, 223, 224, 226, 227, 228, 230, 231,
233, 234, 236, 237, 239, 240, 242, 243,
245, 246, 248, 249, 251, 252, 254, 255
};
uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
const uint8_t ArrayColorFading[6]={ // Indice y valor a modificar {0,1,2} = {R,G,B} ; indice par = incremento ; indice impar = decremento
1, // Rojo -> Amarillo
0, // Amarilo -> Verde
2, // Verde -> Cyan
1, // Cyan -> Azul
0, // Azul -> Magenta
2 // Magenta -> Rojo
};
const uint8_t ArrayColorFadingRainbow[3][2]={ // Indice y valor a modificar {Decremento,Incremento}
{0,1}, // Rojo- -> Verde+
{1,2}, // Verde- -> Azul+
{2,0} // Azul- -> Rojo+
};
/*
*
*
* CODIGOS DE INICIALIZACION DE MODULOS
*
*
*/
//************* Inicialización pines / port *****************//
void vInitPinout(void){
// Configuracion de las llaves DIP para el DMX
// Configuracion de salidas
DDR_PWM |= (1<<PWM_R) | (1<<PWM_G) | (1<<PWM_B); // Salida pin LEDs , PB0 = Rojo, PB1 = Verde, PB2 = Azul
PORT_PWM = 0;
DDRE |= (1<<PE0); // LED indicador de funcionamiento en PE0
PORTE = 0;
}
// ***** inicializacion del timer****//
void vInitTimer0(void){
TCCR0= (1<<CS00) ; // Preescaler 1:1
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
}
/*
*
*
* PROGRAMA PRINCIPAL
*
*
*/
int main(void)
{
vInitPinout(); // Establecer los puertos de E / S
vInitTimer0(); // Establecer el timer
vInit_DMX_RX(); // Iniciar la UART y puertos para la llave DIP
last_mode = mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
Rojo = 0;
Verde = 0;
Azul = 0;
sei(); // habilitar las interupciones, Timer/UART(DMX) habilitados
while(1) // bucle principal (LOOP)
{
if(!bGetDips()){mode=FADING;} // Pregunto si esta activo el DMX y Toma la direccion y la actualiza, tambien desabilita el DMX de ser necesario
if(last_mode!=mode){Cambiarmodo();} // Caso que desde el DMX se pida cambiar el modo, cambia unicamente cuando termino la rutina
switch(last_mode)
{
case FIXED:
fixed_color();
break;
case FADING_FIX:
fading_fijo();
break;
case FADING:
fading_auto();
break;
case RAINBOW_FADING:
rainbow_fader();
break;
default:
break;
}
}
}
/*
*
*
* MODOS DE OPERACION
*
* fixed_color() - Color fijo, tomado desde el DMX.
* fading_fijo() - Produce el efecto de fading con el color tomado del DMX, pero solo ese color, de 0 a 255.
* fading_auto() - Comienza la ejecucion de fading de distintos colores, solo toma en cuenta la velocidad, solo 1 color a la ves.
* rainbow_fading() - Agregado al fading_auto(), en caso que se seleccione este, se modificaran 2 colores en ves de 1.
*/
void fixed_color(void){
Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
Verde = DMX_G;
Azul = DMX_B;
DimmerCurva(); // Actualizo colores para el PWM
}
void fading_fijo(void){
Rojo = DMX_R * (Alpha/255); // Colores tomados directamente del DMX para fijo
Verde = DMX_G * (Alpha/255);
Azul = DMX_B * (Alpha/255);
DimmerCurva();
Alpha++;
delay();
}
void fading_auto(void){
// Valores iniciales seteados cuando se cambia de modo
//Espera
delay(); //esperar
//Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
if(estado%2)
{ //Caso impar
if(++ArrayColores[estado]==255) estado++;
}
else
{ //Caso par
if(--ArrayColores[estado]==0) estado++;
}
if(estado>=6) estado=0;
DimmerCurva();
}
void rainbow_fader(void){
int Temp_R,Temp_A,Temp_V;
Temp_R = Rojo;
Temp_A = Azul;
Temp_V = Verde;
if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
Rojo = 255;
Verde = 0;
Azul = 0;
}
DimmerCurva();
ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
Rojo = Temp_R;
Azul = Temp_A;
Verde = Temp_V;
if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
}
/*
*
*
* UTILIDADES
*
*
* DimmerCurva() - Actualiza los colores para que el PWM tome los valores nuevos
* delay() - Demora introducida para modificar la velocidad de los efectos
* Cambiarmodo() - Funcion usada que toma el valor del DMX, traduciendolo y efectua el cambio.
*/
void DimmerCurva(void){
R_aux=arraydimmer[Rojo];
V_aux=arraydimmer[Verde];
A_aux=arraydimmer[Azul];
}
void delay(void) {
// Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
// Tiempo Minimo = 3us
// Tiempo Maximo = 580ms
// Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
uint16_t tiempo;
if (DMX_Velocidad>127)
{ //Tiempo en milisegundos, Recta de 1ms a 508ms
tiempo = 4*DMX_Velocidad - 511;
//_delay_ms(tiempo);
}
else
{ //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
tiempo = 7*DMX_Velocidad +3;
//_delay_us(tiempo);
}
}
void Cambiarmodo(void){
last_mode=mode;
switch(mode) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case RAINBOW_FADING: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
estador=0; // Set de estado inicial para el rainbow_fading
break;
case FADING: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
Rojo=255; // Set de colores iniciales
Verde=0;
Azul=0;
estado=0; // Set de estado inicial para el fading
break;
default: //Case FADING_FIX, de 64 a 127, y FIXED, de 0 a 63. Bits de mayor peso quedan siempre en 01 y 00
break;
}
}
void SetMode(void){
switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
{
case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
mode=RAINBOW_FADING;
break;
case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
mode=FADING;
break;
case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
break;
}
}
/*
*
*
* ESPACIO PARA INTERRUPCIONES
*
*
* Timer0 - Por Overflow - Para el PWM por software
* UART - RX - Para el DMX
*/
ISR(TIMER0_OVF_vect){
if (!PWM_timer) PORT_PWM |= ((1<<PWM_R)|(1<<PWM_R)|(1<<PWM_R)); // Si es 0 el PWM_timer pone a 1 las salidas
if (R_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_R); } // Cuando se cumple el tiempo las pone a 0, es decir cuando tenga 255 es el maximo que van a estar encendidas
if (V_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_G); }
if (A_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_B); }
if (PWM_timer==255)
{
//Cargo los colores nuevos ya que finalizo el ciclo del PWM
R_out = R_aux;
V_out = V_aux;
A_out = A_aux;
//Observo si se cambio el modo, si cambio el modo cargo el nuevo modo y espero que el programa principal termine lo que estaba haciendo para comenzar con el nuevo modo
SetMode();
}
PWM_timer++;
}
ISR (UART_RX_vect)
{
vHook_DMX_UART();
}
dmx.h
/*
* dmx.h
*
* Created on: 30/08/2015
* Author:
*/
#ifndef DMX_H_
#define DMX_H_
// Definiciones para el DMX
#define F_OSC (8000) // Frec oscilador, para setear la UART
#define DMX_CHANNELS 6 // Cantidad de canales usados en el DMX
// Habilita el uso del DIP en caso no NO estar habilitado es necesario definir una direccion
#define USE_DIP
#define DMX_ADDRESS 0x1FF
// Definicion de pines para el DIP del DMX
#define PORT_DIP_C PORTC // Puerto Completo
#define DDR_DIP_C DDRC
#define PIN_DIP_C PINC
#define PORT_DIP_I PORTE // Puerto incompleto , Pines que faltan para completar el DIP
#define DDR_DIP_I DDRE
#define PIN_DIP_I PINE
#define PIN_DIP_ADD PE2 // Pin que tiene el bit de mayor peso de la direccion
#define PIN_DIP_MAN PE1 // Pin que tiene la seleccion Manual/DMX
// Prototipos de funciones
void vInit_DMX_RX(void);
uint8_t bGetDips(void);
void vHook_DMX_UART(void);
#endif /* DMX_H_ */
dmx.c
/*
* dmx.c
*
* Para que funcione este codigo en otros proyectos es necesario crear 1 funcion en el main
* Esta funcion es para el ISR de la UART y que llame a vHook_DMX_UART()
*
*/
#include "dmx.h"
#include <avr/io.h>
#include <stdint.h>
// ********************* definiciones locales*********************
enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX
enum {EVAL_DMX, IND};
uint8_t gDmxState;
uint8_t *gDmxPnt;
uint8_t Flags;
uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
uint16_t DmxCount;
uint16_t DmxAddress; // Dirección inicial
// *************** DMX recepción de inicialización ****************
void vInit_DMX_RX(void)
{
#ifdef USE_DIP
// Configuracion de salidas
DDR_DIP_C = 0; // Todas entradas port completo
PORT_DIP_C = 0xFF; // Activo Pull-up
DDR_DIP_I &= ~((1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN)); // Port Incompleto, solo esas entradsa
PORT_DIP_I |= (1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN); // Activo sus Pull-up
#endif
// Configuracion de la UART
DDRD |= (1<<2);
PORTD &= ~(1<<2);
UBRRH = 0; // Habilitar recepción
UBRRL = ((F_OSC/4000)-1);// 250kBaud, 8N2
UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;
uint8_t i;
for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
}
// ************* obtener DMX dirección de inicio **************
uint8_t bGetDips(void)
{
uint8_t i;
uint16_t Temp;
#ifdef USE_DIP
Temp= (!(PIN_DIP_I &(1<<PIN_DIP_ADD)) *256) + PIN_DIP_C; //Tomo la direccion desde los DIPs PORT_INCOPLETO:PORT_COMPLETO_7-0 (9 bits)
i = (PIN_DIP_I &(1<<PIN_DIP_MAN));
#else
Temp= DMX_ADDRESS;
i=0;
#endif
if (!i && Temp != 0) //Si es Manual deshabilito DMX, si PIN_DIP_MAN=0 activo DMX solo si la direccion es distinta de 0.
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE))) // Si el receptor esta desabilitado -> habilitar y setear modo de DMX en espera (IDLE).
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);
}
return 1;
}
else
{
UCSRB &= ~(1<<RXCIE); // Manual o Direccion=0, Deshabilito la UART y limpio los valores del DMX ( no se para que )
for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
return 0;
}
}
// *************** DMX recepción ISR ****************//
void vHook_DMX_UART(void)
{
static uint16_t DmxCount;
uint8_t USARTstate= UCSRA; // Obtener estado antes de los datos!
uint8_t DmxByte = UDR; // Obtener los datos
uint8_t DmxState = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
if (DmxState == BREAK)
{
UCSRA &= ~(1<<FE); // Cambiar Posible FE: a causa de MAB
if (DmxByte == 0)
{
gDmxState= STARTB;// Código de inicio normal detectado
gDmxPnt= ((uint8_t*)DmxRxField +1);
}
else
{
gDmxState= IDLE;
}
}
else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
{
UCSRA &= ~(1<<FE); // Restablecer bandera
if (DmxByte == 0) // Los datos de descanso debe ser 0
{
gDmxState= BREAK;
DmxCount= DmxAddress; // Restablecer contador de fotogramas
}
else
{
gDmxState= IDLE; // Bien es FE -> esperar descanso
}
}
else if (DmxState == STARTB)
{
if (--DmxCount == 0)// Dirección inicial alcanzada?
{
gDmxState= STARTADR;
DmxRxField[0]= DmxByte;
}
}
else if (DmxState == STARTADR)
{
uint8_t *DmxPnt;
DmxPnt= gDmxPnt;
*DmxPnt= DmxByte;
if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
{
Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
gDmxState= IDLE;
}
else
{
gDmxPnt= DmxPnt;
}
}
}
Una cosa que no me di cuenta fue el maximo de _delay_ms()
Creo que lo mejor va a ser reemplazarlo por:
__builtin_avr_delay_cycles(unsigned long)
-
hola
a mi el unico error que me larga es
avr-gcc.exe -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT lib_dmx_in.o -MF dep/lib_dmx_in.o.d -c ../lib_dmx_in.c
In file included from ../lib_dmx_in.c:11:
../lib_dmx_in.h:58: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'bGetDips'
make: *** [lib_dmx_in.o] Error 1
Build failed with 1 errors and 0 warnings...
-
parece que no tiene soporte para devolver un booleano. es decir un true false.
Es simple arreglarlo, cambiar el bool por un uint8_t en dmx.h y dmx.c y listo. se arreglaria con eso.
EDIT: Ya actualize el ultimo codigo, para no poner TODO de vuelta.
-
bueno alli lo solucione
la parte de .H creo nque estarabien asi., o me estoy equivocando
// Prototipos de funciones
void vInit_DMX_RX(void);
extern void bGetDips(void);
void vHook_DMX_UART(void);
puse eso , saque esto // Prototipos de funciones
void vInit_DMX_RX(void);
uint8_t bGetDips(void);
void vHook_DMX_UART(void);
otro cosa que cambie fue esto // ************* obtener DMX dirección de inicio **************
void bGetDips(void)
{
uint8_t i;
uint16_t Temp;
y saque esto // ************* obtener DMX dirección de inicio **************
uint8_t bGetDips(void)
{
uint8_t i;
uint16_t Temp;
Ahora el error que me aparece es este ., y no entiendo bien esa funcion
-
no se de donde sacaste ese codigo que pusiste.
Pero yo modifique el codigo para ponerle el uint8_t
Antes daba error por que tenia un
bool bGetDips(void);
Ya que imagino que no estaba definido bool, o que no lo soporta el compilador.
Lo que hiciste esta mal. no hay necesidad de definirlo como extern, realmente nunca vi la necesidad de definir como extern una funcion cuando estas usando el .h para acceder a la misma.
Tambien estas usando un void cuando la funcion esta devolviendo un valor. Ese es otro error.
Usa el codigo que puse al ultimo. Yo lo habia modificado para arreglar eso.
Seguro que hay muchos mas errores con respecto al funcionamiento pero al menos error de sintaxis/compilacion no deberia haber.
-
no se de donde sacaste ese codigo que pusiste.
Pero yo modifique el codigo para ponerle el uint8_t
Antes daba error por que tenia un
bool bGetDips(void);
Ya que imagino que no estaba definido bool, o que no lo soporta el compilador.
Lo que hiciste esta mal. no hay necesidad de definirlo como extern ( realmente nunca vi la necesidad de definir como extern una funcion ) cuando estas usando el .h para acceder a la misma.
Tambien estas usando un void cuando la funcion esta devolviendo un valor. Ese es otro error.
Usa el codigo que puse al ultimo. Yo lo habia modificado para arreglar eso.
Seguro que hay muchos mas errores con respecto al funcionamiento pero al menos error de sintaxis/compilacion no deberia haber.
cuando llamas una variable de otra libreria., se tiene que usar la sentecia extern ., y el inicio de la funcion es void., fijate en la librias originales ., lo IRS son los que no se llaman ., de esa manera el compilador no me dice error
-
cuando llamas una variable de otra libreria., se tiene que usar la sentecia extern ., y el inicio de la funcion es void., fijate en la librias originales ., lo IRS son los que no se llaman ., de esa manera el compilador no me dice error
Justamente una variable. Y esa variable no debe estar definida en el .h por eso mismo yo puse en el main.c:
extern uint8_t DmxRxField[DMX_CHANNELS]; // Valores externos tomados desde la libreria.
Pero en el .h tenemos definidos los prototipos nomas de las funciones. Luego el Linker va a ser capaz de ubicar el dmx.c si es que las rutas de acceso estan bien configuradas y agarrar la funcion necesaria. no hay necesidad de marcarla como extern como ya dije.
Ahora si tu programa no posee realmente un .h, como por ejemplo omitieramos el dmx.h, entonces ahi si en el main.c pondrias:
extern void vInit_DMX_RX(void);
extern uint8_t bGetDips(void);
extern void vHook_DMX_UART(void);
Ahora... el por que no poner void y ponerle uin8_t o int como mas te guste. La libreria original es esa libreria y su funcion no devuelve nada, yo modifique simplemente la funcion para que sea un poco mas flexible para mi.
Ya que necesito saber si es que realmente esta en manual o no la llave. entonces hago que retorne un valor.
El por que no poner void Es por que la funcion esta devolviendo un valor, si te fijas en bGetDips() hay 2 instrucciones que dicen:
return 1;
return 0;
Si defino a esa funcion como void no puedo devolver ese valor. como era un 1 o 0, entonces me bastaba con 1 bit, pero veo que el compilador se vuelve loco cuando usas "bool" que es lo que C posee y te tira error. entonces prefiero pasar un valor de 8 bits y dejar de complicarme la vida, aunque solo necesite 1 bit solo.
Entonces si yo en mi main.c hago:
a = bGetDips();
en "a" voy a tener el valor 1 o 0 dependiendo si esta activo o no. para eso lo hice. Sino deberia haber creado otra funcion que me indicara si esta o no activo.
Si por ejemplo yo quisera que mi funcion me devuelva una variable un float deberia ser:
float fGetPi()
{
return 3.14159;
}
main() {
float Pi;
Pi = fGetPi();
}
Si quisiera que me devuelva una estructura
struct Coords {
uint8_t x,
uint8_t y
};
struct Coords sGetCoordenadas() {
struct Coords a;
a.x = 10;
a.y = 20;
return a;
}
main() {
struct Coords MiCoordenada;
MiCoordenada = sGetCoordenada();
// MiCoordenada.x va a ser igual a 10 e y igual a 20
}
-
Que tal caballeros del foro me acabo de inscribir y es el primer mensaje, e estado leyendo el post y me intereso mucho el proyecto, me parece que lo podría implementar para modificar unas luces led que no tienen DMX y poder crearle secuencias y efectos nuevos al estilo de las luces comerciales.
Me pregunto si ya alguno de los dos caballeros tiene trabajando el código en alguno de los compiladores y claro saber si ya esta trabajando en físico.
en mi opinión es un excelente proyecto que quedo quieto y me gustaría ponerlo en practica.
-
Yo no lo toque mas por que fue simplemente un desafio de pasar el ASM a C, pero no se si locodelafonola siguio con el proyecto, ya que a el no le funcionaba el codigo que habia presentado, puedo tener errores ya que jamas lo compile.
El codigo esta y puede ser modificado, asi ver tambien que es lo que esta fallando y arreglarlo. Alguien con un poco de experiencia en C podria hacerlo.
-
hola
Que tal caballeros del foro me acabo de inscribir y es el primer mensaje, e estado leyendo el post y me intereso mucho el proyecto, me parece que lo podría implementar para modificar unas luces led que no tienen DMX y poder crearle secuencias y efectos nuevos al estilo de las luces comerciales.
Me pregunto si ya alguno de los dos caballeros tiene trabajando el código en alguno de los compiladores y claro saber si ya esta trabajando en físico.
en mi opinión es un excelente proyecto que quedo quieto y me gustaría ponerlo en practica.
bueno ., si presisas algunos de los dos codigos que subi ., te los puedo facilitar cimpletos
he probado los dos ., y armado con exito en lo fisico
eso si son compilaciones en ASM ( nunca pude hacer funcionar lo del C)
querido amigo KILLERJC Yo no lo toque mas por que fue simplemente un desafio de pasar el ASM a C, pero no se si locodelafonola siguio con el proyecto, ya que a el no le funcionaba el codigo que habia presentado, puedo tener errores ya que jamas lo compile.
El codigo esta y puede ser modificado, asi ver tambien que es lo que esta fallando y arreglarlo. Alguien con un poco de experiencia en C podria hacerlo.
yo sigo muy agradesido ., por el tiempo y la enseñanza que pusiste ., en este codigo
lastima ., que recien ahora ., entiendo un poco mas como funciona ., como por ejemplo que las librerias de DMX ., ya estaban ., pero no entendia como asociarlas
y lo que hoy se ., es que solo tendriamos que haberlos enfocado ., en las funciones de las llaves ., nada mas
porque los valores de señal de cada canal ., ya estan separados y guardadas ., en el bufer (DmxRxField (x) ., donde la x coresponde al numero de canal
cualquier cosa siempre ando en el foro ., y si hay que seguir con esto ., soy materia dispuesta ., tengo la parte fisica para probar y compilacion para aportar
tambien nuevas ideas que fui probando ., funciones simples sobre todo
y vuelvo ., a dar las gracias ., al amigo KILLERJC ., es muy dificil ., que alguien se tome el tiempo de enseñar ( y menos a alguien de 53 años y bastante ignorante en esto ) y que hace poco empezo con los micros ., gracias amigo por tu tiempo y dedicacion
.... juan
-
Gracias a los dos caballeros por responder, en cuanto al ofrecimiento de "locodelafonola" estaría agradecido por códigos y librerías que me pueda facilitar vi en el mensaje numero 35 un código que subió de control RGB y motores PAP ese codigo seria para un estilo de luz Movie Head estoy en lo correcto? solo faltaría control de un servo adicional o PAP para controlar una plantilla te figuras y quedaría perfecto!
Volviendo al tema también estaría agradecido por material de lo que se trabajo poder manipular efectos ya preestablecidos en el código y asignados a un canal en especifico por medio de DMX.
esto para lo que les comentaba de actualizar luces led que no tienen DMX al estilo de miniflower o duomoon led.
-
hola
Gracias a los dos caballeros por responder, en cuanto al ofrecimiento de "locodelafonola" estaría agradecido por códigos y librerías que me pueda facilitar vi en el mensaje numero 35 un código que subió de control RGB y motores PAP ese codigo seria para un estilo de luz Movie Head estoy en lo correcto? solo faltaría control de un servo adicional o PAP para controlar una plantilla te figuras y quedaría perfecto!
Volviendo al tema también estaría agradecido por material de lo que se trabajo poder manipular efectos ya preestablecidos en el código y asignados a un canal en especifico por medio de DMX.
esto para lo que les comentaba de actualizar luces led que no tienen DMX al estilo de miniflower o duomoon led.
bueno esa libreria que indicas., nunca me enduvo muchos errores al funcionar (lectura de bucle) ., aunque si me compilo ., yo no uso simulador pruebo siempre en lo fisico ., eso fue una prueba nada mas ., tome la libreria delos STEPEER ., de http://www.hoelscher-hi.de/hendrik/english/stepper.htm ., y sobre ella hice el agregado ., en realidad par hacer lo que vos queres ., hay que empezar de cero ., con esta libreria (mensaje N° 5)., que NO tiene DMX ., son funciones con las llaves solamente ., eso lo he probado y re-probado funciona expectacularmente ., y esa serian las funcines que buscas., pero claro estan en ASM para ATMEGA8515 ., tambien subi el esquematico y tambien tengo el PCB ., vos diras