time function millis does interfere with other code

Hello!

I am using this piece of code that seems to interfere with the millis function:

void f_meter_start() {
  f_ready=0;                      // reset period measure flag
  i_tics=0;                        // reset interrupt counter
  sbi (GTCCR,PSRASY);              // reset presacler counting
  TCNT2=0;                         // timer2=0
  TCNT1=0;                         // Counter1 = 0
  cbi (TIMSK0,TOIE0);              // dissable Timer0 again // millis and delay
  sbi (TIMSK2,OCIE2A);             // enable Timer2 Interrupt
  TCCR1B = TCCR1B | 7;             //  Counter Clock source = pin T1 , start counting now
}

// Timer2 Interrupt Service is invoked by hardware Timer2 every 2ms = 500 Hz
//  16Mhz / 256 / 125 / 500 Hz
// here the gatetime generation for freq. measurement takes place: 
//******************************************************************
ISR(TIMER2_COMPA_vect) {

  if (i_tics==50) {         // multiple 2ms = gate time = 100 ms
                            // end of gate time, measurement ready
    TCCR1B = TCCR1B & ~7;   // Gate Off  / Counter T1 stopped
    cbi (TIMSK2,OCIE2A);    // disable Timer2 Interrupt
    sbi (TIMSK0,TOIE0);     // ensable Timer0 again // millis and delay
    f_ready=1;              // set global flag for end count period

                            // calculate now frequeny value
    freq_in=0x10000 * mlt;  // mukt #ovverflows by 65636
    freq_in += TCNT1;       // add counter1 value
    mlt=0;

  }
  i_tics++;                 // count number of interrupt events
  if (TIFR1 & 1) {          // if Timer/Counter 1 overflow flag
    mlt++;                  // count number of Counter1 overflows
    sbi(TIFR1,TOV1);        // clear Timer/Counter 1 overflow flag
  }

}

does anyone knows a workaround or how I can use (another) millis timer? I would like use this code for a theremin sensor and at the same time open more solenoid valves. so I cannot use delay.

thank you very much!

Comment out this line:

  cbi (TIMSK0,TOIE0);              // dissable Timer0 again // millis and delay

You'll get more jitter on what its measuring, but it's going allow millis() and delay to work.

Why are you interfering with Timer0 ?

...R

It looks like they're interfering with timer zero solely to prevent the interrupts from throwing off some sort of time sensitive code. Since you only posted a small part of the code, I can't say how important doing that is. Try commenting out that line, and see what it does to the existing functionality

Thanks for your help guys! I have commented out that line but still without result. here is the whole code. I am using the blink without delay for testing. I just started using the arduino (again) for a small art project I am working on. eventually I have six solenoid to control. as sensors I use theremins, that is also why I have this code. I am not a programmer but try to put some pieces together and learn via that way.

#include "Statistic.h"

Statistic myStats; 

#include <Stdio.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

//! Macro that clears all Timer/Counter1 interrupt flags.
#define CLEAR_ALL_TIMER1_INT_FLAGS    (TIFR1 = TIFR1)

//states
#define s_idle_1 1
#define s_push_1 2
#define s_waitOn_1 3
#define s_pull_1 4
#define s_waitOff_1 5


//Pins
int stalag_1 = 13;


#define thereM_1 5


long previousMillis = 0;
const unsigned long interval = 2000;
int ledState = LOW; 

void setup() {

  Serial.begin(57600);
  myStats.clear(); //explicitly start clean
  
  pinMode(stalag_1, OUTPUT);
//  pinMode(stalag_2, OUTPUT);
//  pinMode(stalag_3, OUTPUT);
//  pinMode(stalag_4, OUTPUT);
//  pinMode(stalag_5, OUTPUT);
//  pinMode(stalag_6, OUTPUT);

  pinMode(thereM_1, INPUT);
//  pinMode(thereM_2, INPUT);
//  pinMode(thereM_3, INPUT);
//  pinMode(thereM_4, INPUT);
//  pinMode(thereM_5, INPUT);
//  pinMode(thereM_6, INPUT);

  // hardware counter setup ( refer atmega168.pdf chapter 16-bit counter1)
  TCCR1A=0;                   // reset timer/counter1 control register A
  TCCR1B=0;                   // reset timer/counter1 control register A
  TCNT1=0;                    // counter value = 0
  // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino pin 5)
  // normal mode, wgm10 .. wgm13 = 0
  sbi (TCCR1B ,CS10);         // External clock source on T1 pin. Clock on rising edge.
  sbi (TCCR1B ,CS11);
  sbi (TCCR1B ,CS12);

  // timer2 setup / is used for frequency measurement gatetime generation
  // timer 2 presaler set to 256 / timer 2 clock = 16Mhz / 256 = 62500 Hz
  cbi (TCCR2B ,CS20);
  sbi (TCCR2B ,CS21);
  sbi (TCCR2B ,CS22);

  //set timer2 to CTC Mode
  cbi (TCCR2A ,WGM20);
  sbi (TCCR2A ,WGM21);
  cbi (TCCR2B ,WGM22);
  OCR2A = 124;                  // CTC at top of OCR2A / timer2 interrupt when coun value reaches OCR2A value

  // interrupt control

  sbi (TIMSK2,OCIE2A);          // enable Timer2 Interrupt

}

volatile byte i_tics;
volatile byte f_ready ;
volatile byte mlt ;
unsigned int ww;

int cal;
int cal_max;

char st1[32];
long freq_in;
long freq_zero;
long freq_cal;

unsigned int dds;
int tune;

int cnt=0;



void loop() {


cnt++;

f_meter_start();

  tune=tune+1;
  while (f_ready==0) {            // wait for period length end (100ms) by interrupt
    PORTB=((dds+=tune) >> 15);    // kind of DDS tonegenerator / connect speaker to portb.0 = arduino pin8
  }
 tune = freq_in-freq_zero;
 // use the tune value here for your own purposes like control of servos, midi etc.

  // startup
  if (cnt==60) {
    freq_zero=freq_in;
    freq_cal=freq_in;
    cal_max=0;
    //Serial.print("** START **");
  }

//  //---------------------------------------------------------------------- autocalibration
  if (cnt % 20 == 10) {   // try autocalibrate after n cycles
    Serial.print("*");
    if (cal_max <= 400) {
      freq_zero=freq_in;
      //serial.print(" calibration");
    }
    freq_cal=freq_in;
    cal_max=0;
    Serial.println("");
  }
  cal = freq_in-freq_cal;
  if ( cal < 0) cal*=-1;  // absolute value
  if (cal > cal_max) cal_max=cal;

  Serial.print(cnt);
  Serial.print("  "); 

  if ( tune < 0) tune*=-1;  // absolute value
   sprintf(st1, " %04d",tune);

//---------------------------------------------------------Standard abweichung wird hier unten berechnet:  
  long rn = cal;
  myStats.add(rn/5.0);
  
  Serial.print("  Count: ");
  Serial.print(myStats.count()); 
  Serial.print("  Average: ");
  Serial.print(myStats.average(), 4);
  Serial.print("  Std deviation: ");
  Serial.print(myStats.pop_stdev(), 4);
  Serial.println();

  if (myStats.count() == 12)
  {
   myStats.clear();
   delay(2);
   }

//----------------------------------------------------------verhalten stalagmites
 

//stalagmites_1();
//delay(2);
stalagmites_2();
//delay(2);
//stalagmites_3();
//delay(2);
//stalagmites_4();
//delay(2);
//stalagmites_5();
//delay(2);
//stalagmites_6();
//delay(2);

}



//-----------------------------------------------------------------------STALAGMITES_1 START------------
void stalagmites_1() {
  
  unsigned long currentMillis_1 = millis();
  static int state = s_idle_1; //initial state is 1, the "idle" state.
    
  switch (state) {
    case s_idle_1:
            {
            Serial.print("Time from switch_idle_1:  ");
            Serial.println(currentMillis_1); 
            if ((myStats.pop_stdev() > 40) && (myStats.count() > 4)) {
            Serial.println("sensor activated");
            state = s_push_1;
            }
            break;
    case s_push_1:
            digitalWrite(stalag_1, HIGH);
            currentMillis_1 = millis();
            state = s_waitOn_1;
            Serial.print("Time from the switch_s_push_1:  ");
            //Serial.println(currentMillis_1);
            break;
    case s_waitOn_1:
          //if a certain amoung of time has passed, goto.
          Serial.print("Time from switch_s_waitOn_1:  ");
          
          Serial.println(currentMillis_1);
          if(currentMillis_1 - previousMillis > interval) { 
          //save the last time the intervall has happened
          state = s_pull_1;
          Serial.print("Waiting.....");
          previousMillis = currentMillis_1;}
          break;
    case s_pull_1:
          digitalWrite(stalag_1, LOW); //turn off
          //time = millis(); //remember the current time  
          state = s_waitOff_1;
          Serial.print("Time from the switch_s_pull_1");
          state = s_idle_1;
          //Serial.println(time);
          break;

  }
}}
//-----------------------------------------------------------------------STALAGMITES_1 END------------
//-----------------------------------------------------------------------STALAGMITES_2 START------------
void stalagmites_2()
{

  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(stalag_1, ledState);
  }
}

//-----------------------------------------------------------------------STALAGMITES_2 END------------

void f_meter_start() {
  f_ready=0;                      // reset period measure flag
  i_tics=0;                        // reset interrupt counter
  sbi (GTCCR,PSRASY);              // reset presacler counting
  TCNT2=0;                         // timer2=0
  TCNT1=0;                         // Counter1 = 0
  //cbi (TIMSK0,TOIE0);              // dissable Timer0 again // millis and delay
  sbi (TIMSK2,OCIE2A);             // enable Timer2 Interrupt
  TCCR1B = TCCR1B | 7;             //  Counter Clock source = pin T1 , start counting now
}

// Timer2 Interrupt Service is invoked by hardware Timer2 every 2ms = 500 Hz
//  16Mhz / 256 / 125 / 500 Hz
// here the gatetime generation for freq. measurement takes place: 
//******************************************************************
ISR(TIMER2_COMPA_vect) {

  if (i_tics==50) {         // multiple 2ms = gate time = 100 ms
                            // end of gate time, measurement ready
    TCCR1B = TCCR1B & ~7;   // Gate Off  / Counter T1 stopped
    cbi (TIMSK2,OCIE2A);    // disable Timer2 Interrupt
    sbi (TIMSK0,TOIE0);     // ensable Timer0 again // millis and delay
    f_ready=1;              // set global flag for end count period

                            // calculate now frequeny value
    freq_in=0x10000 * mlt;  // mukt #ovverflows by 65636
    freq_in += TCNT1;       // add counter1 value
    mlt=0;

  }
  i_tics++;                 // count number of interrupt events
  if (TIFR1 & 1) {          // if Timer/Counter 1 overflow flag
    mlt++;                  // count number of Counter1 overflows
    sbi(TIFR1,TOV1);        // clear Timer/Counter 1 overflow flag
  }

}

thanks again,
best regards
Tom