Simple Medication Tracking: using ATTINY85
Link to the project : https://www.instructables.com/id/Goal-Habit-Medication-Tracker-Using-ATTINY85/
Will post updates and trials here.
People forget if they had their medication or not and this often leads to an overdose or skipping it. Both are dangerous in most cases.
This project aims to solve that problem. It will be a tiny device with 7 LED’s that signify the 7 days of the week.
The LED’s turn on one after the other when an increment button is pressed.
that light up sequentially as a potentiometer is turned. The user has to turn the pot and light up one LED daily.
Quite sadly there is hardly any clear documentation on how to burn assembly language code into ATTINY85. Many sites point to avrdude.
I’ve also downloaded Atmel Studio 7
Three people code assembly code:
/*
* Shift register demo #1
*
* ATTiny13A Running @9.6MHz
* ADC running @150kHz
*
* PIN ASSIGNMENT:
* PB0 - Shift Register Clock
* PB1 - Shift Register Serial Data
* PB2 - Shift Register Latch(Store)
* PB3 - ADC3 (Potentiometer input)
* PB4 - [NOT USED]
* PB5 - RESET
*/
.include "tn13Adef.inc"
.def A = R16 ; g.p. variable and/or function argument
.def B = R17 ; Used in SEND_BYTE and ADC_START as temporary storage
.def LED1 = R18 ; stores current LED1 output
.def LED2 = R19 ; stores current LED2 output
.def LED3 = R20 ; stores current LED3 output
.def BUT1 = R22 ; stores button counter1
.def BUT2 = R23 ; stores button counter2
.def BUT3 = R24 ; stores button counter3
add button code here
.def BCT = R21 ; Bit counter for SEND_BYTE
.equ SRCK = 0 ; PB0 = Clock
.equ SRDA = 1 ; PB1 = Serial Data
.equ SRLC = 2 ; PB2 = Latch
/* INTERRUPT VECTORS */
.org 0x0000
rjmp RESET ; Reset interrupt
.org 0x0003
rjmp TC0_OV ; Timer1 interrupt
/*
* START!!!
*/
RESET:
/* SETUP STACK */
ldi A, low(RAMEND) ; Set stack pointer
out SPL, A
/* SETUP PINS */
ldi A,0b0000_0111 ; Set output pins PB0..PB2
out DDRB,A
/* SETUP TIMER1 */
ldi A,0b0000_0101 ; Set Timer Prescaler (1024)
out TCCR0B,A ; This will cause Timer Interrupt every ~27ms
ldi A,0b00000010 ; Enable Timer0 Overflow Interrupt
out TIMSK0,A
/* SETUP ADC3 */
ldi A,0
out ADCSRB,A ; Disable autotrigger(Free running)
ldi A,0b00001000 ; Disable Digital Input on PB3(ADC3)
out DIDR0,A
ldi A,0b00000011
out ADMUX,A ; Source:ADC3, Align:RIGHT, Reference:VCC.
ldi A,0b10000110
out ADCSRA,A ; Enable ADC with prescale 1/64
/* RESET REGISTERS */
ldi A,0x00 ; clear A
ldi LED1,0xFF ; Set all LED's to OFF(1-off, 0-on)
ldi LED2,0xFF ; Set all LED's to OFF(1-off, 0-on)
ldi LED3,0xFF ; Set all LED's to OFF(1-off, 0-on)
rcall SEND_BYTE1 ; Clear display1
rcall SEND_BYTE2 ; Clear display2
rcall SEND_BYTE3 ; Clear display3
sei ; Enable interrupts
/* Main loop */
MAIN:
rjmp MAIN
/*
* Sends 8-bit data from LED register to Shift Register
*/
SEND_BYTE1:
ldi BCT,0b1000_0000 ; Set Bit counter
next_bit:
mov B,LED1 ; Move data byte to temp
and B,BCT ; Check bit
breq zero ; Set Data to 0
sbi PortB,SRDA ; Set Data to 1
rjmp shift ; shift
zero:
cbi PortB,SRDA
shift:
sbi PortB,SRCK ; CLK up
nop
cbi PortB,SRCK ; CLK down
clc ; Clear Carry flag
ror BCT ; Shift bit counter
brne next_bit ; Next iteration
sbi PortB,SRLC ; When done, Latch
nop
cbi PortB,SRLC
ret ; Done
SEND_BYTE2:
ldi BCT,0b1000_0000 ; Set Bit counter
next_bit:
mov B,LED2 ; Move data byte to temp
and B,BCT ; Check bit
breq zero ; Set Data to 0
sbi PortB,SRDA ; Set Data to 1
rjmp shift ; shift
zero:
cbi PortB,SRDA
shift:
sbi PortB,SRCK ; CLK up
nop
cbi PortB,SRCK ; CLK down
clc ; Clear Carry flag
ror BCT ; Shift bit counter
brne next_bit ; Next iteration
sbi PortB,SRLC ; When done, Latch
nop
cbi PortB,SRLC
ret ; Done
SEND_BYTE3:
ldi BCT,0b1000_0000 ; Set Bit counter
next_bit:
mov B,LED3 ; Move data byte to temp
and B,BCT ; Check bit
breq zero ; Set Data to 0
sbi PortB,SRDA ; Set Data to 1
rjmp shift ; shift
zero:
cbi PortB,SRDA
shift:
sbi PortB,SRCK ; CLK up
nop
cbi PortB,SRCK ; CLK down
clc ; Clear Carry flag
ror BCT ; Shift bit counter
brne next_bit ; Next iteration
sbi PortB,SRLC ; When done, Latch
nop
cbi PortB,SRLC
ret ; Done
/* Start ADC conversion. Saves result to A */
ADC_START:
sbi ADCSRA,ADSC ; Start ADC conversion
adc_wait:
sbic ADCSRA,ADSC ; Check conversion status
rjmp adc_wait ; Skip jump if completed
in A,ADCL ; Get low bits
in B,ADCH ; Get high bits
lsr B ; Shift 2 bits to the right
ror A ; through Carry
lsr B
ror A
ret
/* Timer 0 overflow interrupt */
TC0_OV:
rcall ADC_START ; start ADC0 Conversion
/* Compare Input, Set output */
cpi A,0xC8 ; A>=200?
brlo gt_80
ldi LED1,0b11100000
rjmp sr_write1
gt_80: ; A>=80?
cpi A,0x50
brlo lt_40
ldi LED2,0b11111100
rjmp sr_write2
lt_40: ; A<40
ldi LED3,0b11111111
rjmp sr_write3
sr_write1:
rcall SEND_BYTE1 ; Send byte to shift reg.
reti ; return
sr_write2:
rcall SEND_BYTE2 ; Send byte to shift reg.
reti ; return
sr_write3:
rcall SEND_BYTE3 ; Send byte to shift reg.
reti ; return
Comments