a timer that goes logic high or low every 15mins ( using tiny85 chip)

LesJones

Joined Jan 8, 2017
4,511
Here is some code to run on an ATtiny85 with a 4Mhz crystal. I first tried using the internal oscillator but thet was running about 4% fast. I suspect that the version with the crystal will be good enough but only you willl know as you won' t tellus HOW accurate your application requires. The software has three outputs . 1 second active high pulse on pin 5. 1 second active low pulse on pin 6. And a 0.5 hz square wave on pin 7 to check the timming accuracey. I have written this in assembler as I find it easier than C.
Just program it using a usbasp programmer (Or similar.) and avrdude software. Note you need to change the low fuse setting from the default of 62 to 6A to use an external crystal. Let me know if you want me to post the source code.
 

Attachments

Thread Starter

timtim1234

Joined Nov 30, 2023
246
So 1 microsecond is better than 1 millisecond?

Note that one of these is easy to achieve, the other requires some clever programming.
come on really? i need to answer that!! i think you are being a smart a** now..lol :) but i will answer it OF COURSE the easy way!!!
 

Thread Starter

timtim1234

Joined Nov 30, 2023
246
Here is some code to run on an ATtiny85 with a 4Mhz crystal. I first tried using the internal oscillator but thet was running about 4% fast. I suspect that the version with the crystal will be good enough but only you willl know as you won' t tellus HOW accurate your application requires. The software has three outputs . 1 second active high pulse on pin 5. 1 second active low pulse on pin 6. And a 0.5 hz square wave on pin 7 to check the timming accuracey. I have written this in assembler as I find it easier than C.
Just program it using a usbasp programmer (Or similar.) and avrdude software. Note you need to change the low fuse setting from the default of 62 to 6A to use an external crystal. Let me know if you want me to post the source code.

cool thanks for doing that, I don't know how to do the fuse setting yet. so if you could post the INO (aduino) code that would be great :)
 

Thread Starter

timtim1234

Joined Nov 30, 2023
246
ohhh for how accurate question i think in the other post i said plus/minus 30 seconds. i don't want to use external crystal
 

MrChips

Joined Oct 2, 2009
34,824
Hi every one, :)make a timer that goes logic high or low every 15 mins.
Let's be realistic here.
15 min is 900 sec.
1 sec in 1000 sec is 0.1% error
1 sec in 60 sec is less than 2% error.
Thus a 1 second error would be acceptable unless this is for some very special scientific experiment.
 

Thread Starter

timtim1234

Joined Nov 30, 2023
246
Let's be realistic here.
15 min is 900 sec.
1 sec in 1000 sec is 0.1% error
1 sec in 60 sec is less than 2% error.
Thus a 1 second error would be acceptable unless this is for some very special scientific experiment.
i agree sorry I don't know programming so what ever is the easiest. But i said in the other post 30 seconds,, so 1 sec is prefect :)
 

MrChips

Joined Oct 2, 2009
34,824
When it comes to MCU timing accuracy, 100 ns counting is not unusual. Many MCUs can do 1 μs. Hence 1 sec accuracy is a walk in the park, with or without quartz crystal clocks.
 

be80be

Joined Jul 5, 2008
2,395
I have just one more thing to say about the atinny one more time the 2.3.2 arduino ide don't like them. You have to use older ide like 1.6.2
The atinny you can trim the clock to get the error lower but then my programmer wouldn't work for reprogramming because of avedude couldn't find the chip.
This because of changes in the newer software. If you use a crystal osc there gos your two of ADC pins only leaves A1

Long story short you'll have a lot to learn with this.
 

Thread Starter

timtim1234

Joined Nov 30, 2023
246
I have just one more thing to say about the atinny one more time the 2.3.2 arduino ide don't like them. You have to use older ide like 1.6.2
The atinny you can trim the clock to get the error lower but then my programmer wouldn't work for reprogramming because of avedude couldn't find the chip.
This because of changes in the newer software. If you use a crystal osc there gos your two of ADC pins only leaves A1

Long story short you'll have a lot to learn with this.
ok where can i download that version at? Also, if it's that bad maybe better to uses a different chip instead?
 

LesJones

Joined Jan 8, 2017
4,511
If you work out the 4% error in 15 minutes you wil realise that this is more than 30 sconds in 15 minutes.
I told you in post #41 that I wrote the code in assembler. The Arduino IDE uses a version of C. So I have would find i difficult to write the code in C.
Here is the source code so you can try to use it as a guide to writing the code in C.
This a how it works. With the way prescalers are set up the 8 bit counter is incremented every 2048 uS. so the counter would overflow at 2048 * 256 uS = 524288 uS (524.288 mS) 500 mS would be a nice baisc time referance. So 500000 uS/2048 = 244.140625. So if we pre load the counter with 256 - 244 = 12 it will give an overflow interrupt in 244 *2048 = 499712 uS
This is close to 500mS. (We could add a small delay with a program loop to correct this but I have not done so.)
Now for every 2 of these interrupts we increment the seconds counter. When the seconds counter reaches 60 the second count is set back to zero and the minutes counter is incremented. When the minutes counter reaches 15 the output is swtched on and the minutes counter set back to zero. Now on bit I did not mention about the sconds counter is that when it increments it also switches the output off. So on the next second after the minute counter has reached 15 and switched on the output it is switched off by the seconds counter, So we have generated the 1 second pulse.

Code:
/*
* Att85timer.asm
*
*  Created: 05/08/2024 08:46:41
*   Author: Les
*/


/*
* Generate 1 second pulse every 15 minutes
*   Author: Les
*/


;    using ATTINY85

; Fuse bit settings
; Low            0x6A  This is for external crystal   (0x62 if internal oscillator is used)
; High         0xDF
; Extended     0xFF
; Lock            0xFF

;
;With internal clock at 8.0 Mhz   (Default value) and divide by 8 by setting CKDIV8 fuse bit (These are the default setting on a new chip.)
; 8.0 Mhz/8 = 1.0 Mhz
;(So Instruction time = 1.0 uS)
; So for 50 uS delay requires 50/1.0 = 50 instructions

;With at 4.0 Mhz  crystal and divide by 8 by setting CKDIV8 fuse bit (These are the default setting on a new chip.)
; 4.0 Mhz/8 = 0.5 Mhz
;(So Instruction time = 2.0 uS)
; So for 100 uS delay requires 100/2.0 = 50 instructions


;
;**************************************************************************
.nolist
.include    <tn85def.inc>    ; ATtiny 13
.list
.listmac

;***************************************************************************
;*
;* Global Register Variables
;*
;***************************************************************************
; Note register number is in decimal

.def    N500mS        = r17    ;Number of 500 mS
.def    Seconds        = r18    ;Number of seconds
.def    Minutes        = r19    ;Number of minutes
.def    count_L        = r22    ;Used for time delay
;
.equ    Pulse_period = 15    ;Time between pulses in minutes.
;
;
;******************************** INTERRUPT VECTORS ***********************
.CSEG
.ORG    $00
        rjmp    reset
        reti
        reti
        reti 
        reti
        rjmp    TC_overflow    ;Timer/Counter0 Overflow
        reti
        reti
        reti
        reti
        reti
        reti
        reti
        reti
        reti
;
;******************************* RESET *************************************
;
; Initialise the stack-pointer
reset:
                ldi    R16,low(RAMEND)
                out    SPL,R16
    
; initialize PORTB
;    Bit 0    Output  (pin 5)   Pulse out active high
;    Bit 1    Output    (Pin 6)   Pulse out active low
;    Bit 2    Output  (Pin 7)      0.5 hz square wave to check the timming accuracy
;    Bit 3    Input   (Pin 2)   This wiil be used for crystal on ATtiny85 version
;    Bit 4    Input    (Pin 3)   This wiil be used for crystal on ATtiny85 version
;    Bit 5    Input    (Pin1)    Reset pin

                    ldi    R16,0x07    ; Bits 0,1,2  as outputs.
                    out    DDRB,R16    ;
                    ldi    R16,0x02
                    out    PORTB,R16    ; PORTB Bit 0,2, low  1 high


;Initialize timer / counter

                    ldi R16,0x00            ;Normal operation
                    Out TCCR0A,R16

                    ldi R16,0x05            ;  Prescale value 1024 (Inc counter every 2.0 uS x 1024 = 2048 uS  488.28  hz
                    Out TCCR0B,R16            ; Counter will overflow every 524.288 mS  (1.9073 hz
                                            ; Counting to 244 would give 499.712 mS  ( 256 - 244 = 12 = 0x0C)

                    ldi R16,0x02            ;TOV0 (Bit1) : Timer/Counter0 Overflow Interrupt Enable
                    Out TIMSK,R16

;Init time counters
                    ldi N500mS,0x02            ; Number of 500mS in one second
                    ldi Seconds,0x00
                    ldi Minutes,0x00

                    bset 7        ;Enable global interrupst.

                    rjmp Main    ;

;Timer/Counter Overflow interrupt handler.
TC_overflow:
                    ldi R20,0x0C        ;Preset timer so interrupt occures every 499.712 mS
                    out    TCNT0,R20

                    dec    N500mS ;500mS
                    breq TC01
                    RETI
TC01:
                    ldi N500mS,0x02

Inc_Sec:
                    in R20,PORTB
                    andi R20, 0xFE        ;Set active high output low  (Bit 0)    
                    ori R20,0x02        ;Set active low output high  (Bit 1)

                    ldi R21,0x04        ;Bit 2
                    eor R20,R21            ; Toggle bit 2 (Pin 7) (Every second)
                    out PORTB,R20

                    ldi R20,0x3C        ;60 decimal (number of seconds in one minute.)

                    inc    Seconds            ;Increment seconds counter
                    cpse Seconds,R20
                    rjmp TC_End
                    CLR Seconds

Inc_Min:
                    ldi R20, Pulse_period

                    inc    Minutes            ;Increment minute counter
                    cpse Minutes,R20
                    rjmp TC_End
                    CLR Minutes

                    in R20,PORTB
                    ori  R20, 0X01        ;Set active high output high (Bit 0)             
                    andi R20, 0XFD        ;Set active low output low (Bit 1)
                    out PORTB,R20

TC_End:
                    RETI


;        ------------------------------------- End of interrupt handlers --------------------------------------

;
;                    Main program code This does nothing. Everyting is done in interrupt code.
;
Main:
            nop
            nop
            nop
            nop
            nop
            rjmp Main    ; Just loop waiting for interrupt
I don't see how you can achive your 30 seconds in 15 minutes accuracy (3.33%) without a crystal unless you can find a microcontroller with a more accurate internal oscillator. I think surface mount crystals are available if size is the reason for not using a crystal.

Les.
 

Thread Starter

timtim1234

Joined Nov 30, 2023
246
If you work out the 4% error in 15 minutes you wil realise that this is more than 30 sconds in 15 minutes.
I told you in post #41 that I wrote the code in assembler. The Arduino IDE uses a version of C. So I have would find i difficult to write the code in C.
Here is the source code so you can try to use it as a guide to writing the code in C.
This a how it works. With the way prescalers are set up the 8 bit counter is incremented every 2048 uS. so the counter would overflow at 2048 * 256 uS = 524288 uS (524.288 mS) 500 mS would be a nice baisc time referance. So 500000 uS/2048 = 244.140625. So if we pre load the counter with 256 - 244 = 12 it will give an overflow interrupt in 244 *2048 = 499712 uS
This is close to 500mS. (We could add a small delay with a program loop to correct this but I have not done so.)
Now for every 2 of these interrupts we increment the seconds counter. When the seconds counter reaches 60 the second count is set back to zero and the minutes counter is incremented. When the minutes counter reaches 15 the output is swtched on and the minutes counter set back to zero. Now on bit I did not mention about the sconds counter is that when it increments it also switches the output off. So on the next second after the minute counter has reached 15 and switched on the output it is switched off by the seconds counter, So we have generated the 1 second pulse.

Code:
/*
* Att85timer.asm
*
*  Created: 05/08/2024 08:46:41
*   Author: Les
*/


/*
* Generate 1 second pulse every 15 minutes
*   Author: Les
*/


;    using ATTINY85

; Fuse bit settings
; Low            0x6A  This is for external crystal   (0x62 if internal oscillator is used)
; High         0xDF
; Extended     0xFF
; Lock            0xFF

;
;With internal clock at 8.0 Mhz   (Default value) and divide by 8 by setting CKDIV8 fuse bit (These are the default setting on a new chip.)
; 8.0 Mhz/8 = 1.0 Mhz
;(So Instruction time = 1.0 uS)
; So for 50 uS delay requires 50/1.0 = 50 instructions

;With at 4.0 Mhz  crystal and divide by 8 by setting CKDIV8 fuse bit (These are the default setting on a new chip.)
; 4.0 Mhz/8 = 0.5 Mhz
;(So Instruction time = 2.0 uS)
; So for 100 uS delay requires 100/2.0 = 50 instructions


;
;**************************************************************************
.nolist
.include    <tn85def.inc>    ; ATtiny 13
.list
.listmac

;***************************************************************************
;*
;* Global Register Variables
;*
;***************************************************************************
; Note register number is in decimal

.def    N500mS        = r17    ;Number of 500 mS
.def    Seconds        = r18    ;Number of seconds
.def    Minutes        = r19    ;Number of minutes
.def    count_L        = r22    ;Used for time delay
;
.equ    Pulse_period = 15    ;Time between pulses in minutes.
;
;
;******************************** INTERRUPT VECTORS ***********************
.CSEG
.ORG    $00
        rjmp    reset
        reti
        reti
        reti
        reti
        rjmp    TC_overflow    ;Timer/Counter0 Overflow
        reti
        reti
        reti
        reti
        reti
        reti
        reti
        reti
        reti
;
;******************************* RESET *************************************
;
; Initialise the stack-pointer
reset:
                ldi    R16,low(RAMEND)
                out    SPL,R16
   
; initialize PORTB
;    Bit 0    Output  (pin 5)   Pulse out active high
;    Bit 1    Output    (Pin 6)   Pulse out active low
;    Bit 2    Output  (Pin 7)      0.5 hz square wave to check the timming accuracy
;    Bit 3    Input   (Pin 2)   This wiil be used for crystal on ATtiny85 version
;    Bit 4    Input    (Pin 3)   This wiil be used for crystal on ATtiny85 version
;    Bit 5    Input    (Pin1)    Reset pin

                    ldi    R16,0x07    ; Bits 0,1,2  as outputs.
                    out    DDRB,R16    ;
                    ldi    R16,0x02
                    out    PORTB,R16    ; PORTB Bit 0,2, low  1 high


;Initialize timer / counter

                    ldi R16,0x00            ;Normal operation
                    Out TCCR0A,R16

                    ldi R16,0x05            ;  Prescale value 1024 (Inc counter every 2.0 uS x 1024 = 2048 uS  488.28  hz
                    Out TCCR0B,R16            ; Counter will overflow every 524.288 mS  (1.9073 hz
                                            ; Counting to 244 would give 499.712 mS  ( 256 - 244 = 12 = 0x0C)

                    ldi R16,0x02            ;TOV0 (Bit1) : Timer/Counter0 Overflow Interrupt Enable
                    Out TIMSK,R16

;Init time counters
                    ldi N500mS,0x02            ; Number of 500mS in one second
                    ldi Seconds,0x00
                    ldi Minutes,0x00

                    bset 7        ;Enable global interrupst.

                    rjmp Main    ;

;Timer/Counter Overflow interrupt handler.
TC_overflow:
                    ldi R20,0x0C        ;Preset timer so interrupt occures every 499.712 mS
                    out    TCNT0,R20

                    dec    N500mS ;500mS
                    breq TC01
                    RETI
TC01:
                    ldi N500mS,0x02

Inc_Sec:
                    in R20,PORTB
                    andi R20, 0xFE        ;Set active high output low  (Bit 0)   
                    ori R20,0x02        ;Set active low output high  (Bit 1)

                    ldi R21,0x04        ;Bit 2
                    eor R20,R21            ; Toggle bit 2 (Pin 7) (Every second)
                    out PORTB,R20

                    ldi R20,0x3C        ;60 decimal (number of seconds in one minute.)

                    inc    Seconds            ;Increment seconds counter
                    cpse Seconds,R20
                    rjmp TC_End
                    CLR Seconds

Inc_Min:
                    ldi R20, Pulse_period

                    inc    Minutes            ;Increment minute counter
                    cpse Minutes,R20
                    rjmp TC_End
                    CLR Minutes

                    in R20,PORTB
                    ori  R20, 0X01        ;Set active high output high (Bit 0)            
                    andi R20, 0XFD        ;Set active low output low (Bit 1)
                    out PORTB,R20

TC_End:
                    RETI


;        ------------------------------------- End of interrupt handlers --------------------------------------

;
;                    Main program code This does nothing. Everyting is done in interrupt code.
;
Main:
            nop
            nop
            nop
            nop
            nop
            rjmp Main    ; Just loop waiting for interrupt
I don't see how you can achive your 30 seconds in 15 minutes accuracy (3.33%) without a crystal unless you can find a microcontroller with a more accurate internal oscillator. I think surface mount crystals are available if size is the reason for not using a crystal.

Les.

ok a crystal not that big of problem i can use one. i see your code is in Assembly? i think that is the language can you please convert that to INO?
 

Jerry-Hat-Trick

Joined Aug 31, 2022
826
I ran the timer for delay(900000); on the ATtiny85 and it was less than 3 seconds out. This is surprisingly good - perhaps not as good with every IC but easily corrected by using a number more or less than 900,000. That may vary a bit with time/temperature but I have the impression that the specified 30 second tolerance is not so critical. It may be interesting to debate how to optimise the timing accuracy but not really germane.

The DIP switch alternative to a pot was mentioned in the previous thread. A rotary DIP switch with 16 positions with binary output could be connected to four I/O lines to give up to 15 different times, or suitable resistance values in parallel using analogRead(); on one pin
 

MrChips

Joined Oct 2, 2009
34,824
Do you really need 16 time options?
Maybe 6 options are enough, 1, 2, 3, 5, 10, 15 minutes.
What is the application?

A simple 2-digit readout and an analog pot to select 1-30 minutes is a simple solution.
 

BobTPH

Joined Jun 5, 2013
11,524
I was not suggesting you learn two different micros. Use the AVR and a crystal if needed. You still have not told us how accurate you need it, so any answer we give is just guesswork.
 
Top