Define variablbe.
.equ sensor_pin = PB3 ; we call pin PB3 a sensor pin
.equ charge_pin = PB4 ; PB4 is our charge pin
.def sensor_value_high = R23 ; temporary storage for sensor value (here we store our sensor values (because we have 10 bit value, here we have the higher value)
.def sensor_value_low = R24 ; temporary storage for sensor value (here we store our sensor values (because we have 10 bit value, here we have the lower value)
; set Chargepin to output
;
cbi PORTB, charge_pin (the charge_pin is set to low)
sbi DDRB, charge_pin ( charge pin is output
Next we define measuring method.
; init A/D
;
cbi ADMUX, REFS2 ; use Vcc as reference
cbi ADMUX, REFS1 ; "
cbi ADMUX, REFS0 ; "
cbi ADMUX, ADLAR ; right-adjust result
cbi ADMUX, MUX3 ; set MUX to ADC2 (PB4) here we decide what pin we use for measurement
cbi ADMUX, MUX2 ; "
sbi ADMUX, MUX1 ; "
cbi ADMUX, MUX0 ; "
sbi ADCSRA, ADEN ; enable A/D
cbi ADCSRA, ADPS2 ; set prescaler to /2 (here we define at what speed we measure)
cbi ADCSRA, ADPS1 ; "
cbi ADCSRA, ADPS0 ; "
Mistakes that we made:
First we defined PB4 as a sensor pin and a charge pin, we fixed that by defining PB3 as a charge pin and PB4 as a sensor pin.
Then we started to get some response from the sensor.
At first we only used lower value.
;==First version==
;
; hello.speaker.45.pwm.asm
;
; software PWM speaker hello-world program
;
; Neil Gershenfeld MIT CBA 8/2/07
;
; (c) Massachusetts Institute of Technology 2007
; Permission granted for experimental and personal use;
; license for commercial sale available from MIT.
;
.include "tn45def.inc"
.equ mosfet_pin = PB1 ; MOSFET pin
.equ max_pwm = 20 ; maximum PWM on value
.equ pwm_length = 40 ; PWM loop length
.equ sensor_pin = PB4 ; we call pin PB4 a sensor pin
.equ charge_pin = PB3 ; PB3 is our charge pin
.def temp = R16 ; temporary storage
.def temp1 = R17 ; temporary storage
.def pwm = R18 ; PWM value
.def pwm_count = R19 ; PWM counter
.def pwm_cycle = R20 ; PWM cycle count
.def pwm_cycle_count = R21 ; number of PWM cycles per audio cycle
.def cycle_count = R22 ; audio cycle count
.def sensor_value_high = R23 ; temporary storage for sensor value
.def sensor_value_low = R24 ; temporary storage for sensor value
.cseg
.org 0
rjmp reset
;
; main program
;
reset:
;
; initialization
;
; set clock divider to /1
;
ldi temp, (1 << CLKPCE)
ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0)
out CLKPR, temp
out CLKPR, temp1
;
; set stack pointer to top of RAM
;
ldi temp, high(RAMEND)
out SPH, temp
ldi temp, low(RAMEND)
out SPL, temp
;
; set MOSFET to output
;
cbi PORTB, mosfet_pin
sbi DDRB, mosfet_pin
;
; set Chargepin to output
;
cbi PORTB, charge_pin
sbi DDRB, charge_pin
;
; init A/D
;
cbi ADMUX, REFS2 ; use Vcc as reference
cbi ADMUX, REFS1 ; "
cbi ADMUX, REFS0 ; "
cbi ADMUX, ADLAR ; right-adjust result
cbi ADMUX, MUX3 ; set MUX to ADC2 (PB4) here we decide what pin we use for measurement
cbi ADMUX, MUX2 ; "
sbi ADMUX, MUX1 ; "
cbi ADMUX, MUX0 ; "
sbi ADCSRA, ADEN ; enable A/D
cbi ADCSRA, ADPS2 ; set prescaler to /2 (here we define at what speed we measure)
cbi ADCSRA, ADPS1 ; "
cbi ADCSRA, ADPS0 ; "
; infinite main loop
;
main_loop:
;first we fetch one measurement
; read response
;
sbi ADCSRA, ADSC ; start conversion
adloopup:
sbic ADCSRA, ADSC ; loop until complete
rjmp adloopup
;
; save conversion
;
in sensor_value_low, ADCL ; get low byte from sensor
in sensor_value_high, ADCH ; get high byte from sensor
ldi pwm_cycle_count, 5
frequency_loop:
; we will not use this line ldi cycle_count, sensor_value_low
mov cycle_count, sensor_value_low
cycle_count_loop:
ldi pwm, max_pwm
cycle_loop:
mov pwm_cycle, pwm_cycle_count
pwm_loop:
mov pwm_count, pwm
sbi PORTB, mosfet_pin
pwm_on_loop:
dec pwm_count
brne pwm_on_loop
ldi pwm_count, pwm_length
sub pwm_count, pwm
cbi PORTB, mosfet_pin
pwm_off_loop:
dec pwm_count
brne pwm_off_loop
dec pwm_cycle
brne pwm_loop
dec pwm
brne cycle_loop
dec cycle_count
brne cycle_count_loop
dec pwm_cycle_count
brne frequency_loop
rjmp main_loop
Code second version
;
; hello.speaker.45.pwm.asm
;
; software PWM speaker hello-world program
;
; Neil Gershenfeld MIT CBA 8/2/07
;
; (c) Massachusetts Institute of Technology 2007
; Permission granted for experimental and personal use;
; license for commercial sale available from MIT.
; changed by Fab Academy students in Vestmannaeyjar
.include "tn45def.inc"
.equ mosfet_pin = PB1 ; MOSFET pin
.equ max_pwm = 20 ; maximum PWM on value
.equ pwm_length = 40 ; PWM loop length
.equ sensor_pin = PB4 ; we call pin PB4 a sensor pin
.equ charge_pin = PB3 ; PB3 is our charge pin
.def temp = R16 ; temporary storage
.def temp1 = R17 ; temporary storage
.def pwm = R18 ; PWM value
.def pwm_count = R19 ; PWM counter
.def pwm_cycle = R20 ; PWM cycle count
.def pwm_cycle_count = R21 ; number of PWM cycles per audio cycle
.def cycle_count = R22 ; audio cycle count
.def sensor_value_high = R23 ; temporary storage for sensor value
.def sensor_value_low = R24 ; temporary storage for sensor value
.DEF rd1l = R0 ; LSB 16-bit-number to be divided
.DEF rd1h = R1 ; MSB 16-bit-number to be divided
.DEF rd1u = R2 ; interim register
.DEF rd2 = R3 ; 8-bit-number to divide with
.DEF rel = R4 ; LSB result
.DEF reh = R5 ; MSB result
.DEF rmp = R25; multipurpose register for loading
.cseg
.org 0
rjmp reset
;
; main program
;
reset:
;
; initialization
;
; set clock divider to /1
;
ldi temp, (1 << CLKPCE)
ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0)
out CLKPR, temp
out CLKPR, temp1
;
; set stack pointer to top of RAM
;
ldi temp, high(RAMEND)
out SPH, temp
ldi temp, low(RAMEND)
out SPL, temp
;
; set MOSFET to output
;
cbi PORTB, mosfet_pin
sbi DDRB, mosfet_pin
;
; set Chargepin to output
;
cbi PORTB, charge_pin
sbi DDRB, charge_pin
;
; init A/D
;
cbi ADMUX, REFS2 ; use Vcc as reference
cbi ADMUX, REFS1 ; "
cbi ADMUX, REFS0 ; "
cbi ADMUX, ADLAR ; right-adjust result
cbi ADMUX, MUX3 ; set MUX to ADC2 (PB4) here we decide what pin we use for measurement
cbi ADMUX, MUX2 ; "
sbi ADMUX, MUX1 ; "
cbi ADMUX, MUX0 ; "
sbi ADCSRA, ADEN ; enable A/D
cbi ADCSRA, ADPS2 ; set prescaler to /2 (here we define at what speed we measure)
cbi ADCSRA, ADPS1 ; "
cbi ADCSRA, ADPS0 ; "
; infinite main loop
;
main_loop:
;first we fetch one measurement
; read response
;
sbi ADCSRA, ADSC ; start conversion
adloopup:
sbic ADCSRA, ADSC ; loop until complete
rjmp adloopup
;
; save conversion
;
in sensor_value_low, ADCL ; get low byte from sensor
in sensor_value_high, ADCH ; get high byte from sensor
;Here we divide the results from the sensor Devision starts
; Load the test numbers to the appropriate registers
;
mov rd1h,sensor_value_high ; use the high sensor value
mov rd1l,sensor_value_low ; use the low sensor value
ldi rmp,0x4 ; 0x4 to be divided with
mov rd2,rmp
;
; Divide rd1h:rd1l by rd2
;
div8:
clr rd1u ; clear interim register
clr reh ; clear result (the result registers
clr rel ; are also used to count to 16 for the
inc rel ; division steps, is set to 1 at start)
;
; Here the division loop starts
;
div8a:
clc ; clear carry-bit
rol rd1l ; rotate the next-upper bit of the number
rol rd1h ; to the interim register (multiply by 2)
rol rd1u
brcs div8b ; a one has rolled left, so subtract
cp rd1u,rd2 ; Division result 1 or 0?
brcs div8c ; jump over subtraction, if smaller
div8b:
sub rd1u,rd2; subtract number to divide with
sec ; set carry-bit, result is a 1
rjmp div8d ; jump to shift of the result bit
div8c:
clc ; clear carry-bit, resulting bit is a 0
div8d:
rol rel ; rotate carry-bit into result registers
rol reh
brcc div8a ; as long as zero rotate out of the result
; registers: go on with the division loop
; End of the division reached
ldi pwm_cycle_count, 5
frequency_loop:
; we will not use this line ldi cycle_count, sensor_value_low
mov cycle_count, rel ; we use the result from the devision, lower value
cycle_count_loop:
ldi pwm, max_pwm
cycle_loop:
mov pwm_cycle, pwm_cycle_count
pwm_loop:
mov pwm_count, pwm
sbi PORTB, mosfet_pin
pwm_on_loop:
dec pwm_count
brne pwm_on_loop
ldi pwm_count, pwm_length
sub pwm_count, pwm
cbi PORTB, mosfet_pin
pwm_off_loop:
dec pwm_count
brne pwm_off_loop
dec pwm_cycle
brne pwm_loop
dec pwm
brne cycle_loop
dec cycle_count
brne cycle_count_loop
dec pwm_cycle_count
brne frequency_loop
rjmp main_loop
Using AVR Studio
Build and Run
Create .hex file
Attention -> Remember to unplug the speaker before you program the micro controler.