Problem with guitar tuner- metronome.

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

I'm working on a project for the university: i have to build something with an ATMega8535. I use an STK500. I chose to build a metronome-guitar tuner. I built this circuit:

http://s1.postimage.org/ynyvzz1r...

There's an incorrect part. The secondo 7segment is drawm wrong but on the circuiti i mounted it in the right way

I didn't test yet the tuner but i've got problems with the metronome.

When i tests it with avr studio it work perfectly but on the circuit...

What it should do:

Turn the power on. The two 7segments show --. It's in tuner mode. I press SW1. The two 7segments show 40. It's in metronome mode at 40 bpm so we have 40 beeps in one minutes. Pressing sw2 or sw3 the 7 segments show respectiveli 50 (with sw2) and 40 (sw1). Pressing sw2 continously we get 50, 60, 70, ... ,2.1.(that is 210). With sw3 2.1.(210), 2.0. (200),1.9 (190)..., 40. Pressing again sw1 the program goes back to the tuner mode.

What really happens:

Turn the power on. The two 7segments show --. It's in tuner mode. I press SW1. The two 7segments show 40. Pressing sw2 doesn't happen anything, with sw3 it turn to 2.1. and then , pressing sw2, back to 40.

The code is long and contains also tuner parts but i think it's clear and simple, anyway here's a short explaination:

Quote:

Target contains the information about the BPM and it's set to 40.
The external interrupt on PD3 turns stato to FF if it's 0 and to 0 if it's ff.
When stato = FF we are in metronome mode and it jumps to metronomo then to uscita_led.

This subrutine compare target with 40, 50, 60,...,210.
Then it changes the led pattern and jumps to uscita_pwm.

Here the subritine takes informations about the beep from the eeprom. When it's on the last value (132) it jumps to contatore, in order to wait the right time before the next beep.

At the bottom of this subrutine there's rjmp controllo_t. Here it should control if we're still in metronome mode and then if sw2 or sw3 are pressed. If one of them is pressed it changes Target value and goes back to uscita_led.

that's the code:

device atmega8535
.nolist
.include "m8535def.inc"
.list

;***********************************************
;METTERE MANUALMENTE I VALORI NELLA EEPROM
;***********************************************


;============
;Declarations

;Numeri
.equ zero =0b10001000
.equ one = 0b11101011
.equ two = 0b11000100
.equ three = 0b11000001
.equ four = 0b10110010
.equ five = 0b10010001
.equ six = 0b10001001
.equ seven = 0b10011100
.equ eight = 0b10000000
.equ nine = 0b10010000
.equ zerod =0b00001000
.equ oned = 0b01101011
.equ twod = 0b01000100

;Lettere
.equ LA= 0b10101000
.equ LAx= 0b00101000
.equ SI= 0b10000110
.equ DO= 0b11001001
.equ DOx= 0b01001001
.equ RE= 0b11000011
.equ REx= 0b01000011
.equ MI= 0b11000001
.equ FA= 0b11100001
.equ FAx= 0b01100001
.equ SOL= 0b10000001
.equ SOLx= 0b00000001

;Altro

.equ nn= 0b11110111
.equ su= 0b11111101
.equ giu= 0b11011111

.equ k=65
 

;Interrupt vector table ---------------------------------------

.cseg
.org 0x00



rjmp INIT				;RESET
rjmp calcolo_nota		;External Interrupt0 Vector Address
rjmp tasto				;External Interrupt1 Vector Address
rjmp pwm_4				;Timer2 compare match Vector Address
reti					;Timer2 overflow Vector Address
reti					;Timer1 Input Capture Vector Address
reti					;Timer1 Output Compare A Interrupt Vector Address
reti					;Timer1 Output Compare B Interrupt Vector Address
reti					;Overflow1 Interrupt Vector Address
reti					;Overflow0 Interrupt Vector Address
reti					;SPI Interrupt Vector Address
reti					;UART Receive Complete Interrupt Vector Address
reti					;UART Data Register Empty Interrupt Vector Address
reti					;UART Transmit Complete Interrupt Vector Address
reti					;ADC Conversion Complete Interrupt Vector Address
reti					;EEPROM Write Complete Interrupt Vector Address
reti					;Analog Comparator Interrupt Vector Address

;Subrutines --------------------------------------------------------


;=============
;Start Program


INIT:


;SRAM va da $0060 a $025F

.def temp=r16
.def stato=r17		;0=accordatore 1=metronomo
.def nota=r18
.def periodo=r19
.def cn=r20
.def target=r21
.def temp2 = r22
.def romreg1=r23
.def romreg2=r24
.def controllo_pind=r25

clr controllo_pind
clr temp2
clr temp
clr stato
clr nota
clr periodo
clr cn
clr target
clr romreg1
clr romreg2


sei	;Sets the Global Interrupt flag

ldi		temp,low(ramend)		;Inizializzazione stack pointer
out		SPL,temp
ldi		temp,high(ramend)
out		SPH,temp

		ldi temp,0b10000000
		out pind, temp
		out	DDRD, temp	;PortD is input
		out	PortD, temp	;pull-up ON PortD pins
		
		ser temp
		out	DDRA, temp	;PortA is output
		out	PortA, temp ;turn off all LEDs
		
		ser temp
		out	DDRC, temp	;PortC is output
		out	PortC, temp ;turn off all LEDs

;Alla porta D son connessi 3 switch: 
		;PD3 Metronomo
		;PD5 Tasto +
		;PD6 Tasto -
;gli altri pin non sono usati


ldi target, 40  ;carica in target il valore minimo


ldi temp, nn				;********Forse va eliminato ******
out porta, temp				;********					******
out portc, temp				;********					******

ldi temp, 0b00000011		;interrupt abilitato sul fronte di salita per PD2
out MCUCR, temp				;e interrupt abilitato su qualunque cambio di stato per PD3

ldi stato, 0b00000000		;modalità accordatore


ldi temp, 0b11000000		;attiva l'interrupt request
out GICR, temp



;****MAIN*****

main:




cpi stato, 0x00
brne pc+2

rjmp main


rjmp metronomo


Calcolo_nota:

cpi nota, 0b00000000			;controlla se nota è uguale a 0b00000000
breq pc+2						;se son uguali pc+2
rjmp calcolo_periodo

ldi temp, 0
out tcnt0, temp
ldi temp, 0b00000100			;timer counter' attivo CLK/256
out TCCR0, temp

ldi nota, 0b11111111


reti


Calcolo_periodo:


ldi nota, 0
ldi temp, 0b00000000			;stop timer counter
out TCCR0, temp
in periodo, TCNT0


;*************
;Abbiamo il periodo posto nel registro periodo

ldi cn, 0b00000000

ldi romreg1, 0x3c
out eearl, romreg1		;impostiamo il puntatore della eeprom alla prima allocazione

nota2:


out eedr, temp			;carichiamo in temp i valori della eeprom
						;nell'allocazione indicata da romreg1
cp periodo, temp		;si comparano il registro temp e periodo

brlo pc+3
out eedr,controllo_pind	;copiamo il valore
rjmp led				;se temp è minore di periodo rjmp led

inc cn					;se temp è maggiore si incrementano il puntatore e cn
inc romreg1
rjmp nota2

;****in controllo_pind è salvato il valore teorico del periodo
;****mentre nel registro periodo il periodo effettivo del nostro segnale

led:

ldi romreg1, 0x78
out eearl, romreg1	;romreg1 punta all'allocazione 0x78 della eeprom


cpi cn, 12			;compara cn con 12
brsh pc+18

add romreg1, cn		;se è minore di 12
out eedr, temp
out porta, temp



;******************************************************
cp controllo_pind, periodo	;compara temp e periodo
brne pc+4					;se sono esattamente uguali
clr temp
out portc, temp				;*FORSE VA ELIMINATO*
reti
;******************************************************


		cp controllo_pind, periodo	;compara temp e periodo
		brlo pc+3
		
		ldi temp, giu			;se il valore misurato è maggiore di quello
		out portc, temp			;teorico il led punta giu
		
		cp controllo_pind, periodo	;altrimenti
		brlo pc+3
		
		ldi temp, su			;se il valore misurato è minore di quello
		out portc, temp			;teorico il led punta su
								
								;altrimenti non punta a niente
reti

subi cn, 12			;se è maggiore di 12
add romreg1, cn
out eedr, temp
out porta, temp

		
;******************************************************
cp controllo_pind, periodo	;compara temp e periodo
brne pc+4					;se sono esattamente uguali
clr temp
out portc, temp				;*FORSE VA ELIMINATO*
reti
;******************************************************

		
		cp controllo_pind, periodo	;compara temp e periodo
		brlo pc+3
		
		ldi temp, giu			;se il valore misurato è maggiore di quello
		out portc, temp			;teorico il led punta giu
		
		cp periodo,temp			;altrimenti
		brlo pc+3
		
		ldi temp, su			;se il valore misurato è minore di quello
		out portc, temp			;teorico il led punta su
								
								;altrimenti non punta a niente
ldi temp,0b00000000
out TCNT0, temp
reti



;*********************METRONOMO

tasto:

ldi temp, 0xff					;********Forse va eliminato ******
out porta, temp				;********					******
out portc, temp				;********					******


sbis pind, 3
rjmp tasto


cpi stato, 0x00				;controlla se stato è 0 (accordatore)
brne pc+5
ldi stato, 0xff				;se stato è 0 lo porta a 1 (metronomo)
ldi temp, 0b10000000		;disattiva l'interrupt di pd2
out GICR, temp
reti


ldi stato, 0x00				;se stato è 1 lo porta a 0 (accordatore)

ldi temp, 0b0000000			;stoppa il timer counter2
out tccr2, temp

ldi temp, 0b11000000		;attiva l'interrupt di pd2
out GICR, temp
reti

Metronomo:

rjmp uscita_led	




;**************controllo_tasti

up:

cpi target, 210		;controlla se sono arrivato a max
brne pc+2

rjmp uscita_led			;se ci sono salta ad uscita

ldi temp, 10		; se non ci sono +10 e salta ad uscita
add target, temp
rjmp uscita_led


down:

cpi target, 40		;controlla se sono al minimo
brne pc+2

rjmp uscita_led			;se ci sono salta ad uscita

ldi temp, 10		; se non ci sono -10 e salta ad uscita
sub target, temp
rjmp uscita_led







uscita_led:				;controlla terget e manda in uscita i led

cpi target, 40
brne pc+7
ldi temp, four
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo


cpi target, 50
brne pc+7
ldi temp, five
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 60
brne pc+7
ldi temp, six
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 70
brne pc+7
ldi temp, seven
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 80
brne pc+7
ldi temp, eight
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 90
brne pc+7
ldi temp, nine
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 100
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 110
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, one
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 120
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, two
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 130
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, three
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 140
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, four
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 150
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, five
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 160
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, six
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 170
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, seven
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 180
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, eight
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 190
brne pc+7
ldi temp, oned
out porta, temp
ldi temp, nine
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 200
brne pc+7
ldi temp, twod
out porta, temp
ldi temp, zero
out portc, temp
rjmp uscita_pwm
rjmp metronomo

cpi target, 210
brne pc+6
ldi temp, twod
out porta, temp
ldi temp, one
out portc, temp
rjmp uscita_pwm
rjmp metronomo




;*************CONTATORE


contatore:

clr temp2
clr temp
out tcnt0, temp
ldi temp, 0b00000101			;timer counter' attivo CLK/1024
out TCCR0, temp

step1:
in temp, tcnt0
cpi temp, k
brne pc+8						;controlla se temp =k


	cp temp2, target			;se sono uguali controlla se temp2=target
	brne pc+2
	rjmp temporaneo						;	**se lo sono è passato il giusto temp e ritorna

	inc temp2					;	**se non lo sono incrementa temp 2 e resetta tctn0
	ldi temp, 0
	out tcnt0, temp
	rjmp step1

rjmp controllo_t						;se son diversi torna a contare





controllo_t:

cpi stato, 0b11111111			;controlla se sono in modalità metronomo
breq pc+2						;se non ci sono salta a main
rjmp main						;se ci sono continua


sbis pind,0	;controlla se è stato premuto il tasto +
rjmp up


sbis pind,1	;controlla se è stato premuto il tasto -
rjmp down


rjmp step1

;***************************************
;USCITA SUONO



uscita_pwm:


ldi romreg2, 0x00

ldi temp, 0xff					;per evitare che scatti subito l'interrupt	
out ocr2, temp



ldi temp, 0x80					;abilitiamo l'interupt per il compare match
out timsk, temp

pwm_2:
rcall eeprom_read				;leggiamo la eeprom

clr temp
out tcnt2, temp
ldi temp, 0b00001001			;PWM in ctc mode & timer counter 2 4mhz
out tccr2, temp


out ocr2, cn					;Il valore del duty cycle dipende dal valore di cn


pwm_3:


in temp, tccr2
cpi temp, 0b00001000			;se il timer counter è attivo (i due registri sono diversi e quindi l'interrupt non è avvenuto)
brne pc+6
cpi cn, 0b10000100		; se sono uguali controlla se siamo all'ultimo valore
brne pc+3
rjmp contatore			;se ci siamo conta e poi torniamo a uscita_pwm

temporaneo:

rjmp uscita_pwm
						;altrimenti aggiorniamo il campione
rjmp pwm_2


rjmp pwm_3

pwm_4:


ldi temp, 0b00001000			;stoppa il timer counter
out tccr2, temp

reti							;no, passa al prossimo valore
								


;***********************
;LETTURA ROM

EEPROM_read:



clr temp

;*settare l'indirizzo della eprom in romreg1 (H) e romreg2 (L)

out EEARL, romreg2

sbi EECR,EERE			;abilita la lettura dell'allocazione posta all'indirizzo specificato

in cn,EEDR			;informazione salvata in cn
inc romreg2
ret


and that's the eeprom mapping

*0 to 32 sampled data

*3c to 71 frequency value

*78 to 84 notes

I don't know where the error could be :(

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

Written in Italian and .asm, it all looks Greek to me! :) Where are you JS!
In the interim, to the OP, you need to do some debugging, using the "divide and conquer" technique. Also, a logic probe will come in handy!

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

Well for one thing there is nothing to read in EEPROM as far as I can tell. Then there is the power supply circuit that gives me a bit of acid reflux.

How are you putting the values into eeprom manually? Shouldn't you have an eeprom look up table generated by the code?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Yeah i put the value manually but i genereted an eeprom file. The power supply circuit work well 5.1 V stable. I don't know hot to debug the code

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

For a starter I would disable the pullups in the switches' pins, replace the 150R resistors with 100K and put 100nF caps on the input pins to eliminate any switch bounce particularly in the tasto switch.

However you either use the interrupt to check that switch or you scan it. Only one tasto is connected to an interrupt pin so I'm a bit confused as to what the code is doing. I would not use any interrupts at all with the switches.

I would just strip the code down to just detecting the switches and maybe turn on a led for each switch detected then implement one function at a time.

Unfortunately the are no readily available debuggers for the 8535 apart from the old ICE200.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Quote:
i have to build something with an ATMega8535. I use an STK500.

I presume that is because the STK500 has an ATmega8535, but IIRC an ATmega16 is pin compatible, so buy one of those.
Are you permitted to develop in C. It would be a backward university if they constrained you to ASM.

Looking at ASM code is a total turn of for me. I have better things to do with my life!

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

Quote:
I have better things to do with my life!
Like what? Catching mices? :wink:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Quote:
It would be a backward university if they constrained you to ASM.

Perhaps it's a course in assembly language programming? Probably not, but they do exist.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

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

It's a course in assebly. We must use an atmega8535 and the assebly. However i resolved the problem. Now it works perfectly but after one minute! It's not a code problem because if i turn the power off and then on in less than a minute it still works.

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

Quote:
It's not a code problem

The fact that you think this probably means it's a code problem.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

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

I know, i don't speak english very good and maybe you don't understand what i want to say...

@Zbaird

The circuit doesn't work right? But after a minute it starts working. If it was a code problem, turning off and on the power the problem should be there again right? In this case turning off and the on the power (in less than a minute) it still works. Like a capacitors. So, do you think it's a code problem?

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

Quote:
do you think it's a code problem?
I can see some possible problems like doing a "sei" early in the startup instead of doing it AFTER EVERYTHING is set up.
;Init stack as the first thing
    ldi      temp,low(ramend)      ;Inizializzazione stack pointer 
    out      SPL,temp 
    ldi      temp,high(ramend) 
    out      SPH,temp 

;this and other init would be ok here
    clr controllo_pind 
    clr temp2 
    clr temp 
    clr stato 
    clr nota 
    clr periodo 
    clr cn 
    clr target 
    clr romreg1 
    clr romreg2
 
;Other init stuff here
.
.
;do a sei as the last thing beforte main
    sei   ;Sets the Global Interrupt flag 
;****MAIN***** 

main: 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I edited the code as you said.

.device atmega8535
.nolist
.include "m8535def.inc"
.list

;***********************************************
;METTERE MANUALMENTE I VALORI NELLA EEPROM
;***********************************************


;============
;Declarations

;Numeri
.equ zero =0b10001000
.equ one = 0b10111110
.equ two = 0b11000100
.equ three = 0b10010100
.equ four = 0b10110010
.equ five = 0b10010001
.equ six = 0b10000001
.equ seven = 0b10111100
.equ eight = 0b10000000
.equ nine = 0b10010000
.equ zerod =0b00001000
.equ oned = 0b00111110
.equ twod = 0b01000100

;Lettere
.equ LA=  0b10100000
.equ LAx= 0b00100000
.equ SI=  0b10000011
.equ DO=  0b11001001
.equ DOx= 0b01001001
.equ RE=  0b10000110
.equ REx= 0b00000110
.equ MI= 0b11000001
.equ FA=  0b11100001
.equ FAx= 0b01100001
.equ SOL=  0b10001001
.equ SOLx= 0b00001001

;Altro

.equ nn= 0b11110111
.equ su= 0b11111101
.equ giu= 0b11011111

.equ k=65
 

;Interrupt vector table ---------------------------------------

.cseg
.org 0x00



rjmp INIT				;RESET
rjmp calcolo_nota		;External Interrupt0 Vector Address
rjmp tasto				;External Interrupt1 Vector Address
rjmp CP_MATCH			;Timer2 compare match Vector Address
reti					;Timer2 overflow Vector Address
reti					;Timer1 Input Capture Vector Address
reti					;Timer1 Output Compare A Interrupt Vector Address
reti					;Timer1 Output Compare B Interrupt Vector Address
reti					;Overflow1 Interrupt Vector Address
reti					;Overflow0 Interrupt Vector Address
reti					;SPI Interrupt Vector Address
reti					;UART Receive Complete Interrupt Vector Address
reti					;UART Data Register Empty Interrupt Vector Address
reti					;UART Transmit Complete Interrupt Vector Address
reti					;ADC Conversion Complete Interrupt Vector Address
reti					;EEPROM Write Complete Interrupt Vector Address
reti					;Analog Comparator Interrupt Vector Address

;Subrutines --------------------------------------------------------


;=============
;Start Program


INIT:


;SRAM va da $0060 a $025F

.def temp=r16
.def stato=r17		;0=accordatore 1=metronomo
.def nota=r18
.def periodo=r19
.def cn=r20
.def target=r21
.def temp2 = r22
.def romreg1=r23
.def romreg2=r24
.def controllo_pind=r25



ldi		temp,low(ramend)		;Inizializzazione stack pointer
out		SPL,temp
ldi		temp,high(ramend)
out		SPH,temp



clr controllo_pind
clr temp2
clr temp
clr stato
clr nota
clr periodo
clr cn
clr target
clr romreg1
clr romreg2



		ldi temp,0b10000000
		out pind, temp
		out	DDRD, temp	;PortD is input
		out	PortD, temp	;pull-up ON PortD pins
		
		ser temp
		out	DDRA, temp	;PortA is output
		out	PortA, temp ;turn off all LEDs
		
		ser temp
		out	DDRC, temp	;PortC is output
		out	PortC, temp ;turn off all LEDs

;Alla porta D son connessi 3 switch: 
		;PD3 Metronomo
		;PD5 Tasto +
		;PD6 Tasto -
;gli altri pin non sono usati


ldi target, 40  ;carica in target il valore minimo



ldi temp, 0b00000011		;interrupt abilitato sul fronte di salita per PD2
out MCUCR, temp				;e interrupt abilitato su qualunque cambio di stato per PD3

ldi stato, 0b00000000		;modalità accordatore


ldi temp, 0b11000000		;attiva l'interrupt request
out GICR, temp


sei	;Sets the Global Interrupt flag


pre_main:
ldi temp, nn				;********Forse va eliminato ******
out porta, temp				;********					******
out portc, temp				;********					******


;****MAIN*****

main:
cpi stato, 0x00				;controlla se siamo in modalità accordatore
brne pc+2
	rjmp main				;se ci siamo continua a ciclare
rjmp uscita_led				;se non ci siamo passa a uscita_led




;*****MODALITA METRONOMO*****


uscita_led:				;controlla terget e manda in uscita i led

cpi target, 40
brne pc+6
	ldi temp, four
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm



cpi target, 50
brne pc+6
	ldi temp, five
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 60
brne pc+6
	ldi temp, six
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 70
brne pc+6
	ldi temp, seven
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 80
brne pc+6
	ldi temp, eight
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 90
brne pc+6
	ldi temp, nine
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 100
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 110
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, one
	out portc, temp
	rjmp uscita_pwm


cpi target, 120
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, two
	out portc, temp
	rjmp uscita_pwm


cpi target, 130
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, three
	out portc, temp
	rjmp uscita_pwm


cpi target, 140
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, four
	out portc, temp
	rjmp uscita_pwm


cpi target, 150
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, five
	out portc, temp
	rjmp uscita_pwm


cpi target, 160
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, six
	out portc, temp
	rjmp uscita_pwm


cpi target, 170
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, seven
	out portc, temp
	rjmp uscita_pwm


cpi target, 180
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, eight
	out portc, temp
	rjmp uscita_pwm


cpi target, 190
brne pc+6
	ldi temp, oned
	out porta, temp
	ldi temp, nine
	out portc, temp
	rjmp uscita_pwm


cpi target, 200
brne pc+6
	ldi temp, twod
	out porta, temp
	ldi temp, zero
	out portc, temp
	rjmp uscita_pwm


cpi target, 210
brne pc+6
	ldi temp, twod
	out porta, temp
	ldi temp, one
	out portc, temp
	rjmp uscita_pwm


rjmp uscita_led



;***************************************
;USCITA SUONO



uscita_pwm:


ldi romreg2, 0x00				;reset posizione eeprom

ldi temp, 0xff					;per evitare che scatti subito l'interrupt	
out ocr2, temp


ldi temp, 0x80					;abilitiamo l'interupt per il compare match
out timsk, temp

pwm_2:

;LEGGIAMO DALLA EEPROM

clr temp
out EEARL, romreg2
sbi EECR,EERE			;abilita la lettura dell'allocazione posta all'indirizzo specificato
in cn,EEDR			;informazione salvata in cn
inc romreg2				;leggiamo la eeprom

clr temp
out tcnt2, temp
ldi temp, 0b00001001			;PWM in ctc mode & timer counter 2 4mhz
out tccr2, temp

out ocr2, cn					;Il valore del duty cycle dipende dal valore di cn


pwm_3:
cpi stato, 0b11111111			;controlla se sono in modalità metronomo
breq pc+2						;se non ci sono salta a main
	rjmp pre_main					;se ci sono continua


in temp, tccr2
cpi temp, 0b00001000	;se il timer counter è attivo (i due registri sono diversi e quindi l'interrupt non è avvenuto)
brne pc+6
	cpi cn, 0b10000100		;se il TC è attivo controlla se siamo all'ultimo valore
	brne pc+3
		rjmp contatore			;se ci siamo conta e poi torniamo a uscita_pwm
		temporaneo:
		rjmp uscita_pwm			;altrimenti aggiorniamo il campione
	rjmp pwm_2
rjmp pwm_3





;*************CONTATORE


contatore:

clr temp2
clr temp
out tcnt0, temp
ldi temp, 0b00000101			;timer counter' attivo CLK/1024
out TCCR0, temp

step1:
in temp, tcnt0
cpi temp, k
brne pc+8						;controlla se temp =k


	cp temp2, target			;se sono uguali controlla se temp2=target
	brne pc+2
	rjmp temporaneo				;**se lo sono è passato il giusto temp e ritorna

	inc temp2					;**se non lo sono incrementa temp 2 e resetta tctn0
	ldi temp, 0
	out tcnt0, temp
	rjmp step1


cpi stato, 0b11111111			;controlla se sono in modalità metronomo
breq pc+2						;se non ci sono salta a main
	rjmp pre_main						;se ci sono continua


sbis pind,0	;controlla se è stato premuto il tasto +
rjmp up


sbis pind,1	;controlla se è stato premuto il tasto -
rjmp down


rjmp step1






;**************controllo_tasti

up:

sbis pind,0	;controlla se è stato lasciato il tasto +
rjmp up

cpi target, 210		;controlla se sono arrivato a max
brne pc+2
	rjmp uscita_led			;se ci sono salta ad uscita
ldi temp, 0xa		; se non ci sono +10 e salta ad uscita
add target, temp
rjmp uscita_led


down:

sbis pind,1	;controlla se è stato lasciato il tasto +
rjmp down

cpi target, 40		;controlla se sono al minimo
brne pc+2
	rjmp uscita_led			;se ci sono salta ad uscita
subi target, 0xa		; se non ci sono -10 e salta ad uscita
rjmp uscita_led









;*******************************************************************
;*******************************************************************
;****************************INTERRUPT******************************
;*******************************************************************
;*******************************************************************



;===================================================================
;COMPARE MATCH

CP_MATCH:

ldi temp, 0b00001000			;stoppa il timer counter
out tccr2, temp
reti
;====================================================================

;*****************************************************************************

;====================================================================
;EXTERNAL GUITAR IN


Calcolo_nota:

cpi nota, 0b00000000			;controlla se nota è uguale a 0b00000000
breq pc+2						;se son uguali pc+2
	rjmp calcolo_periodo
ldi temp, 0
out tcnt0, temp
ldi temp, 0b00000100			;timer counter' attivo CLK/256
out TCCR0, temp
ldi nota, 0b11111111
reti


Calcolo_periodo:


ldi nota, 0
ldi temp, 0b00000000			;stop timer counter
out TCCR0, temp
in periodo, TCNT0

;Abbiamo il periodo posto nel registro periodo

ldi cn, 0b00000000
ldi romreg1, 0x3c
out eearl, romreg1		;impostiamo il puntatore della eeprom alla prima allocazione

nota2:


out eedr, temp			;carichiamo in temp i valori della eeprom
						;nell'allocazione indicata da romreg1
cp periodo, temp		;si comparano il registro temp e periodo
brlo pc+3
	out eedr,controllo_pind	;copiamo il valore
	rjmp led				;se temp è minore di periodo rjmp led
inc cn					;se temp è maggiore si incrementano il puntatore e cn
inc romreg1
rjmp nota2

;in controllo_pind è salvato il valore teorico del periodo
;mentre nel registro periodo il periodo effettivo del nostro segnale

led:

ldi romreg1, 0x78
out eearl, romreg1	;romreg1 punta all'allocazione 0x78 della eeprom

led_2:

cpi cn, 12			;compara cn con 12
brsh pc+20
	add romreg1, cn		;se è minore di 12
	out eedr, temp
	out porta, temp

	cp controllo_pind, periodo	;compara temp e periodo
	brne pc+3					;se sono esattamente uguali
		clr temp
		out portc, temp			;non  mostra niente sul secondo led

	cp controllo_pind, periodo	;compara temp e periodo
	brlo pc+3
		ldi temp, giu			;se il valore misurato è maggiore di quello
		out portc, temp			;teorico il led punta giu
		
	cp periodo, controllo_pind	;altrimenti
	brlo pc+3	
		ldi temp, su			;se il valore misurato è minore di quello
		out portc, temp			;teorico il led punta su
	
	
	ldi temp,0b00000000
	out TCNT0, temp						;altrimenti non punta a niente
	rcall contatore2
	reti

subi cn, 12			;se è maggiore di 12
rjmp led_2







contatore2:

ldi target, 30					;aspettiamo 0,5 sec
clr temp2
clr temp
out tcnt0, temp
ldi temp, 0b00000101			;timer counter' attivo CLK/1024
out TCCR0, temp

step1_1:
in temp, tcnt0
cpi temp, k
brne pc+10						;controlla se temp =k


	cp temp2, target			;se sono uguali controlla se temp2=target
	brne pc+5
	ldi temp, 0					;disattiva timer counter
	out TCCR0, temp
	out tcnt0, temp				;reset timer counter
	ret							;**se lo sono è passato il giusto temp e ritorna

	inc temp2					;**se non lo sono incrementa temp 2 e resetta tctn0
	ldi temp, 0
	out tcnt0, temp
	
rjmp step1_1












;======================================================================

;*****************************************************************************

;======================================================================
;EXTERNAL INTERRUPT SWITCH

tasto:

ldi temp, 0xff				;********Forse va eliminato ******
out porta, temp				;********					******
out portc, temp				;********					******


sbis pind, 3
rjmp tasto


cpi stato, 0x00				;controlla se stato è 0 (accordatore)
brne pc+6
ldi stato, 0xff				;se stato è 0 lo porta a 1 (metronomo)
ldi temp, 0b10000000		;disattiva l'interrupt di pd2
out GICR, temp
ldi target, 40
reti


ldi stato, 0x00				;se stato è 1 lo porta a 0 (accordatore)

ldi temp, 0b0000000			;stoppa il timer counter2
out tccr2, temp

ldi temp, 0b11000000		;attiva l'interrupt di pd2
out GICR, temp
reti
;==============================================================================

But the problem is still there.

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

I tried following the code and make the following comments.
1. The code looks like spaghetti to me and go do with better structuring (something that C forces you to do).
2. The comments & labels being in a foreign language don't add to the clarity.
3. Using statements like this

brne pc+5 

amongst others, so as you don't have to allocate a label is pretty dangerous and error prone for a newbie. By not using a proper label you are hiding information as to what is going on. Labels cost nothing and do not increase your code length or execution time!

4. Your ISR's seem to be too long and have loops & spaghetti code in them.
ISR's should be short and quick and activities when triggered by them
should be done in the main loop. The reti's seem to be all over the
place!
5. Try goto'less programming! The problem with goto's is that they dont come with a comefrom.

I have no other magic suggestions!

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

Quote:

By not using a proper label you are hiding information as to what is going on.

More to the point, if an opcode is added just ahead of this then the calculation is wrong and it branches to the wrong place. Use of PC relative branching went out in about the 1970's

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

Ah yes, Thanks Cliff, PC relative addressing, the tems just would not come to me.

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

So should I delete all the relative branch and use insted RJMP to a label?

I've never thought about that. Assebly was taught to me this way :(

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

Quote:
So should I delete all the relative branch and use insted RJMP to a label?

Absolutely!
Quote:
Assembly was taught to me this way

Was the spaghetti style taught as well. :wink:

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

Quote:

Assebly was taught to me this way

In which decade? As I say you'd have to go a long way back to find an assembler that did not support labels!

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

I studied it at university from september to january. The course finisced and I have to realize a prototype of something with atmega8535

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

They taught you to PC+n in 2011? Utterly incredible!

(but the course tutor was about 60+, with a beard, corduroy jacket, sandals and a pipe!)

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

AHhahaha no no he's about 40 with beard but without the jack, the sandals and the pipe XD.

Anyway, i've got some problem to do that. Can you make me an example?

If i have

cpi temp, 0
brne pc+5
etc
etc
etc
etc
rjmp main

what it sould become?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  cpi temp, 0
  brne skip_etc
  etc
  etc
  etc
  etc
skip_etc:
  rjmp main 

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

I corrected the program but before that I put another subrutine to control if switch1 or switch2 is pressed. Now it works perfectly. Thanks to everybody :D

But now there's another problem. The tuner doesn't work. Probably because the signal the microcontroller recives is not a square wave and has a lot of noise. Do i post it here or i do i open another topic?

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

Assuming you are right and it is not a software issue.

Quote:
not a square wave
A comparator will fix that. Some AVR MCU have them built in otherwise LM339 or similar.
Quote:
has a lot of noise.
Not so easy fixed and more a topic for General Electronics. Let Google be your friend

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

The program now is simple. With the first rising edge starts an interrupt. Starts a timer counter too. With the second interrupt it stops the interrupt and measure compare the value of TCNT0 with a lookup table in the eeprom. The problem is that the out of the comparator lm393 is:

So i think the problem is here. The circuit is in the first post.

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

OK, you need to work out where the noise is coming from. I would have thought that a big fat signal from a guitar should have NO noise, beats or harmonics when you are only plucking one string.

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

The "noise" may be upper harmonics in the signal.
If you want to find the frequency, you have to measure interval between two subsequent zero crossing.

But the task is not easy, because of harmonics.
It was discussed here in the forum.
In guitar signal the 2nd harmonic is often bigger than the first one (and thus also crosses the zero).

The low pass filter on input must sufficiently supress higher harmonics. With a scope on filter output watch if only the first harmonic crosses zero .
A low pass filter for each string would be the best.

Edit:
Now I see your oscilogram.
The signal is ok.
If you manage to detect the zero-crossing points, you can easily count the frequency.
But the frequency in your picture is over 2kHz?
That does not match any string.

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

Remember also that the only signal that has NO harmonics is a pure sinewave. A human whistle comes close.

Guitar tuner front end info here:
http://pictureofgoodelectronicci...

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

Now my circuit works. It was a problem with the solder. Now I have a perfect square wave but the program's still not working. I set the external interrupt on the rising edge. What could be the problem? Should i set it in different way?

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

Quote:
It was a problem with the solder.

More likely it was the soldering which was the problem!
Quote:
but the program's still not working.

But does the interrupt work? Once you get that working you can look further. Life is too short to try & debug programs written in asm, so I won't be much help there.

I think I spotted a loop in the ISR. ISR's should be as short as possible and generally have no loops or subroutine calls.

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

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

The interrupt works. Something happens when the string is hit. What is an ISR?

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

Quote:

What is an ISR?

Interrupt service routine. It's the code you provide to handle a given interrupt by putting a JMP/RJMP at the vector location and some handling code ending in RETI that it jumps to.

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

Ok I'll try to correct the code. Anyway thanks to all. I'm learning a lot of usefull things