Countdown timer errors moving from UNO to ATTiny85

Hi,

Trying to program a 5 minute Yacht Race Countdown Timer that can either run a single 5 minute sequence (5,4,1,Go), a repeating (5,4,1,Go,4,1,Go 4,1,GO....) a 3 minute sound sequence with many more horns and beeps or a 3 minute repeating sequence.

The 5 minute sequences are of particular interest as there is an error in the interval between horns that accumulates after several repeats that would be unacceptable (>1sec) on the race course.

I'm working to identify why there is a difference when running the below on an ATTiny85 vs. a similar code adapted to run on a standard UNO (a couple pins were changed) in terms of the timing of the RELAY_HORN at the 4 min, 1 minute and start or 0 min. times in the array. The timing works out exact on Tinkercad

(Login | Tinkercad)

using the exact replica set up and works well when run on an UNO. Don;t know if sharing this link is OK or not but hopefully it works.

The code uses several arrays and several functions to set the type of sound, the timing of the sound and whether to repeat or not based upon setting of two selector switches. (fn is called read_LCD_buttons sorry it was reading buttons originally)

I have noticed differences between two different ATTiny85 chips as well. Sticking to one chip only for time being.

let me know if there is a better way a better place or a resource I should be researching as I have not been able to find an answer as yet.

Thanks,

#include <avr/io.h>
int p4 = LOW;   // used to store button state
int p1 = LOW;   // used to store button state

const int pin4 = PB4; //input pin for SW1 state read
const int pin1 = PB1; //input pin for SW2 state read

const int RELAY_HORN = 3;  // horn relay 
const int RELAY_BEEP = 2;  // beeper output 
const int WARNING_BEEP = 0;

int TM=3;                   //Timer Mode select indicator, added =3
int index;                  //array position indicator
int ctdwn;                  //total duration of individual sequence including warning beeps
unsigned long start;        //time when sequence started

const int *h_or_b;          //array containing type and length of sounds
const uint16_t *sch;        //array containing timing of sounds

bool sound_on = false;      //status of sound indicator 
unsigned long sound_start;  //time when sound started


//Rule 26 3 minute sound signal sequence 
const PROGMEM uint16_t sch__3[] = {0,100,200,300,400,500, 1000,  1900,2000,  2800,2900,3000,   5900, 6000, 6100,6200,6300,6400,6500,   8600,8700,8800,9000,9100,9200,9300,9400,9500,   11800,12000,12100,12200,12300,12400,12500,   17600,17800,18000,18100,18200,18300,18400,18500,18600,18700,18800,18900,19000,19100,19200,19300,19400,19500};
const PROGMEM int   h_or_b__3[] = {2,1,  1,  1,  1,  1,   1,     1,   1,     1,   1,   1,      2,    2,    0,   0,   0,   0,   0,      1,   1,   1,   2,   0,   0,   0,   0,   0,      2,    2,    0,    0,    0,    0,    0,       2,    2,    2,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0    };
                            //  start1,2,3,4,5  10s    20s      30s      1min(1 x-long)                     90s(1 long 3 short)      2min                               3min          

int index__3 =   53-1;          // 53 items in the array starting at 0
int ctdwn__3 = 3 * 60 + 16;     //16 seconds from power on to first horn + duration of schedule

// Rule 26 5 minute sequence 
const PROGMEM uint16_t sch__5[] ={0,100,200,300,400,500,  5900,6000,6100,6200,6300,6400,6500,  24000,24100,24200,24300,24400,24500,  30000,30100,30200,30300,30400,30500,30600,30700,30800,30900,31000,31100,31200,31300,31400,31500};
const PROGMEM int   h_or_b__5[] ={2, 0,  0,  0,  0,  0,    2,   2,   0,   0,   0,   0,   0,     2,    0,    0,    0,    0,    0,      2,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0    };

int index__5 = 35-1;  // 35 items in the array starting at 0
const int ctdwn__5 = 5 * 60 + 16; //16 seconds from power on to first horn    

   
unsigned long  len_of_note[] = {500000, 500000, 1000000, 2000000};    // length of tone in microseconds

int read_LCD_buttons(){    
  p4 = digitalRead(pin4);
  p1 = digitalRead(pin1);

  if (p1 == HIGH){ 
    if(p4 == HIGH){
      return 3;  // if two high, return 3 (5 Minute repeating)
    }
    else {    // if one (left) high return 2 (5 Minute Start)
      return 2;
          }
  }
  else if (p4 == HIGH){
    return 1;   // if the other (right) high return 1 (3 Minute Repeating)
    }
    else{
    return 0;   // when all others fail, return this. (3 Minute Start)
    } 

} 



void activate_sound(int HRB) {                            // this function checks what sound to make
      int what_beep = RELAY_HORN;                         // default to horn relay pin
      if (HRB==WARNING_BEEP) { what_beep = RELAY_BEEP;}   // decide if warning beep or horn, if HRB = 0 then what_beep = RELAY_BEEP
      digitalWrite(what_beep, HIGH);                      //turn appropriate pin HIGH to make sound
      sound_start = micros();                             //start timers for horn duration
}

void horn_or_beep(unsigned long seq_on){          //this function decides if sound on long enough
    if (sound_on) {
         if ( ((micros()-sound_start) > len_of_note[pgm_read_word_near(h_or_b + index)] ) ) {      //if sound on is longer than value in len_of_note array at position "index" in h_or_b array
            sound_on = false;                     //indicate that sound is off, (de_activate_sound(h_or_b[index];)            
            index = index - 1;                    //move to next sound in h_or_b array
            //digitalWrite(RELAY_HORN,LOW);       //turn horn pin off
            //digitalWrite(RELAY_BEEP,LOW);       //turn beep pin off
            PORTB &=~(1<<PB3);                    //turn horn pin off  digitalWrite(RELAY_HORN,LOW);
            PORTB &=~(1<<PB2);                    //turn beep pin off  digitalWrite(RELAY_BEEP,LOW);
            
            if (index <0 && TM==3 ){              //used to reset the index to start of P-Flag up warnings, start and ctdwn for 5 min rolling start mode TM=3
              index = 18;                         // resets index to position befor P-flag warning beeps
              ctdwn = 5*60-1;                     //resets ctdwn to 5 min -1
              sound_on = false;
              start = micros();
            }
            if (index <0 && TM==1 ){              //used to reset the index to start of 2 minute warnings, start and ctdwn for 3 min rolling start mode TM=1
              index = 34;                         // resets index to position befor P-flag warning beeps
              ctdwn = 3*60-1;                     //resets ctdwn to 3 min -1
              sound_on = false;
              start = micros();
            }              
         }
    }
    else{    
      unsigned long v = ((pgm_read_word_near(sch + index)*10UL*1000UL));   //sets v to value in sch array and converts to micros, removed "*1000UL"
         if ( seq_on < v+1000UL) {                                         // sets tone or horn duration to 1000 milliseconds , why +1000???
             sound_on = true;
             activate_sound (pgm_read_word_near(h_or_b + index ));        //returns 0,1,2,3 from h_or_b array from position "index" and uses value in activate_sound function
         }
     }
}


void setup(){
  //pinMode(RELAY_HORN, OUTPUT);  
  DDRB |=(1<<PB3);
  //pinMode(RELAY_BEEP, OUTPUT);  
  DDRB |= (1<<PB2);
  //pinMode(pin4, INPUT);     
  DDRB &=~(1<<PB4);
  //pinMode(pin1, INPUT);     
  DDRB &=~(1<<PB1);

  //digitalWrite(RELAY_HORN,LOW); //turn horn pin off  
  PORTB &=~(1<<PB4);
  TM = read_LCD_buttons(); //1 for 3 minute repeating 3 for 5 minute repeating
 
 if (TM==1||TM==0) {
     ctdwn = ctdwn__3;   //set ctdwn to 196
     sch = sch__3;
     h_or_b = h_or_b__3;
     index = index__3;   //set index to 52
     }
   if (TM==2||TM==3) {
     ctdwn = ctdwn__5;    //set ctdwn to 316
     sch = sch__5;
     h_or_b = h_or_b__5;
     index = index__5;    //set index to 34
   }
  sound_on = false;
  start = micros();
}

void loop(){
   unsigned long seq_on =  micros()-start ;    
   unsigned long dur = ctdwn*1000UL*1000UL -seq_on ;// adjust by 1000*1000 for Micros use, was d

  horn_or_beep( dur );    //go to horn_or_beep with value "dur" was d

  unsigned long v = (pgm_read_word_near(sch + index));
}