What's wrong with this ?

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying to make a IR-beam barrier using tiny15 and normal ir-receiver.
The code I have uses timer 1 PWM for the 38kHz ir pulse. Also it's switched on and off every 500 us. The ir-receiver is connected to ext int 0 pin and set for falling edge. When interrupted timer 0 is started and interrupt set to rising edge. When interrupted again timer 0 is stopped and it's value read and compared to a constant. If it's lower, PB3 will be cleared and PB4 set and if higher vice versa.

On paper it works and simulates (perhaps a bug in avr studio 4, timer 1 overflow int isn't cleared, makes a bit hard to simulate properly), but IRL something is wrong. PB4 will be cleared even if no signal is given, which shouldn't happen.

As this is my first project i've written in assembly I'm desperately in need of help.

Here's my code:

.include "tn15def.inc"

.def TEMP	=	R16
.def LED	=	R17
.def ON		=	R18
.def TIMES	=	R19
.def EDGE	=	R20

.equ MIN_TIMES	=	48
.equ MIN_DUTY	=	0x55

.org 0x0000
    rjmp RESET
.org 0x0001
	rjmp EXT_INT0
.org 0x0004
	rjmp TIM1_OVF
						
EXT_INT0:
	tst  EDGE			;Test for rising EDGE
	brne H_EDGE			;and jump
	ldi  TEMP, 0x02		;Start Timer 0
	out  TCCR0, TEMP	
	ldi  TEMP, 0x03		;Set for INT0 for rising EDGE
	out  MCUCR, TEMP
	ser  EDGE			;Set EDGE 1
	reti
H_EDGE:
	clr  TEMP			;Stop Timer 0
	out  TCCR0, TEMP
	clr  EDGE			;Clear EDGE
	ldi  TEMP, 0x02		;Set INT0 for falling EDGE
	out  MCUCR, TEMP
	in   TEMP, TCNT0	;Read Timer 0 value to TEMP
	subi TEMP, MIN_DUTY	;Subtract MIN_DUTY from TEMP
	brlo LOWER			;If TEMP is lower than MIN_DUTY, jump
	clr  TEMP			;Clear TCNT0
	out  TCNT0, TEMP
	cbi  PORTB, 4		;PB4 On
	sbi  PORTB, 3		;PB3 Off
	reti
LOWER:
	clr  TEMP			;Clear TCNT0
	out  TCNT0, TEMP
	cbi  PORTB, 3		;PB3 On
	sbi  PORTB, 4		;PB4 Off
	reti

TIM1_OVF:
	inc  TIMES
	cpi  TIMES, MIN_TIMES
	breq TOGGLE
	reti
TOGGLE:
	tst  ON				;Test if ON
	breq OFF			;If not, jump
	ldi  TEMP, 0x45		;TIMER1 PWM, CK, OC1A discONnected
	out  TCCR1, TEMP	
	clr  ON				;Off
	sbi  PORTB, 1
	clr  TIMES
	reti
OFF:
	ldi  TEMP, 0x75
	out  TCCR1, TEMP
	ser  ON				;On
	clr  TIMES
	reti

RESET:                   ;Reset Label
    ldi  TEMP, 0xDB      
    out  DDRB, TEMP      
	ldi  TEMP, 0xDF
	out  PORTB, TEMP	

	ldi  TEMP, 0x75		;TIMER1 PWM, CK, Inverted PWM
	out  TCCR1, TEMP
	ldi  TEMP, 0x15		;50% Duty cycle
	out  OCR1A, TEMP
	ldi  TEMP, 0x2A		;38kHz
	out  OCR1B, TEMP
	
	ldi  TEMP, 0x60		;INT0 enable
	out  GIMSK, TEMP
	
	ldi  TEMP, 0x02		;INT0 interrupt ON falling EDGE
	out  MCUCR, TEMP

	ldi  TEMP, 0x04		;Timer 1 overflow interrupt
	out  TIMSK, TEMP

	ser  ON

	sei

MAIN:
	rjmp MAIN

-Extin[/code]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I didn't really look at your code too hard so I am not really sure what it is supposed to do but from your description it appears the IR beam is connected (via amplifier) to INT0 which is PB2. I do not see any instruction to input PINB into EDGE.

IN  EDGE,PINB

I am fairly new to this so I hope I am not barking up the wrong tree.

Regards,
Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

If I am anywhere in the ballpark perhaps you could use the SBIC/SBIS instructions such as this:

Your code:

EXT_INT0: 
   tst  EDGE         ;Test for rising EDGE 
   brne H_EDGE         ;and jump 
   ldi  TEMP, 0x02      ;Start Timer 0 

Proposed code:

EXT_INT0: 
   sbis PINB,2        ;Test for rising EDGE on PB2 (signal is high)
   rjmp H_EDGE         ;and jump 
   ldi  TEMP, 0x02      ;Start Timer 0 

Anyway, hope I am not wasting your time (or the forum members)

Regards,
Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The period for a 38kHz cycle is about 26us, or 13us for a half-cycle. From
your constants it looks as though the MCU is running at 4MHz (?), so you
have about 52 CPU cycles to work with (for each half cycle). During this
time you need to take one external (edge) interrupt, and (I'm less clear
on this) one timer interrupt.

Just counting instructions, it looks as though the longest path through
the external interrupt ISR is just under 30 cycles, and the longest path
through the timer ISR is about 25 cycles, so I'm wondering if you're
over budget on CPU cycles (55 out of a possible 52)? This is the sort of
thing which might not show up in simulation.

The symptom would presumably be that you would lose edges, so some
of the pulses would look impossibly long. I don't know how to tie this into
your observed symptom.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, after a "good" 5 hours sleep one thing came clear. If the pulses stop after last rising edge and PB4 is on, which signals that pulse is present, my code leaves it on because it doesn't check that there is pulses present every 500 us. I think this can be fixed by running timer0 when theres break in the pulse, and have it's overflow set PB4 off and PB3 on.

EXT_INT0:
   tst  EDGE         ;Test for rising EDGE
   brne H_EDGE         ;and jump
   ldi  TEMP, 0x02      ;Start Timer 0 

Above checks if int0 is set for rising edge, my bad comment is a bit confusing :oops:

What I want to do is to check whether there is 500 us on/off pulse in PB2 (INT0).

Quote:

The period for a 38kHz cycle is about 26us, or 13us for a half-cycle. From
your constants it looks as though the MCU is running at 4MHz (?), so you
have about 52 CPU cycles to work with (for each half cycle). During this
time you need to take one external (edge) interrupt, and (I'm less clear
on this) one timer interrupt.

Just counting instructions, it looks as though the longest path through
the external interrupt ISR is just under 30 cycles, and the longest path
through the timer ISR is about 25 cycles, so I'm wondering if you're
over budget on CPU cycles (55 out of a possible 52)? This is the sort of
thing which might not show up in simulation.


38kHz is the carrier frequency for IR pulse, and IR receiver outs 400 to 800 us high or low depending on how long the carrier signal is present, so I have 500 us to do what I have. Tiny15 runs on 1.6 MHz internal clock, so that makes 800 cycles.
What I don't understand is why MIN_TIMES has to be that high, timer1 overflow should happen every 26,3 us and 19 * 26.3 us = 500 us so 48 makes no sense. This is the hard part to simulate as timer 1 interrupts aren't cleared so it keeps interrupting continuously.

Thanks for the help.
-Extin