Interrupts and millis() HELP!

Hello all! I’ll preface my question by stating that I am a relatively new user to arduino.

The problem I am having is with regard to millis() and timing interrupts. From what I can tell, the prescaler I am using in my code is affecting the the operation of millis(). However, I am using timer1 and it is my understanding that millis() works off of timer0.

Quesion: Is there a way I can use millis() with timer1?

My code for reference - simplified.

#define pwmOut 9

unsigned long newt;

void setup()
{
Serial.begin(9600);

noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;

OCR1A = 64000;
OCR1B = 63000;

TCCR1B |= (1 << WGM12)|(1 << CS10);//TCCR1B |= (1 << WGM12)|(1 << CS12)|(1 << CS10);
TIMSK1 |= (1 << OCIE1A)|(1 << OCIE1B);

interrupts();
}

void loop()
{
newt=millis();

Serial.print(newt);
Serial.print("\t");
}

Actually, the problem may be more fundamental than I had previously thought. The following code gives me an output of zeros with the occasional 1 in the serial monitor.

void setup()
{
Serial.begin(9600);

noInterrupts(); // disable all interrupts

interrupts(); // enable all interrupts
}

void loop()
{
newt=micros();

Serial.print(newt);
Serial.print("\t");

}

Please read the sticky post, “How to use this forum - please read,” posted near the top of the subject listings for each section of the forum. Please read the part about using “code tags.” You can edit your original post to enclose the code in code tags. If you don’t use code tags, the software that the forum uses to display messages may interpret some of your code as formatting directives, and garble your program.

When I run the sketch from the original post, I get characters 0 and 1 separated, apparently, by tabs.

This line of your sketch

TIMSK1 |= (1 << OCIE1A)|(1 << OCIE1B);

enables the OCR1A and OCR1B Compare Match interrupts. But, there are no interrupt service routines defined in the program to service those interrupts. The compiler inserts jump instructions for those interrupts that eventually reach program memory location zero, the restart location. Therefore, whenever one of those interrupts occurs, your program vectors to the reset location, and starts all over again. In particular, it sets the counter that determines the value of millis() to zero.

That’s not all that will cause trouble. loop() prints something at 9600 bps, and then starts over. loop() will execute much faster than the Serial.print()'s, so the code will wind up waiting for the Serial buffer to clear enough space for the next output. For this test code, that may not matter.

gt1212:
The following code gives me an output of zeros with the occasional 1 in the serial monitor.

That’s not what it did when I compiled it. With the sketch from the second post, I get a compilation error, complaining that “newt” isn’t declared. Adding that declaration, the sketch Serial.print()'s numbers that increase at a rate I’d expect from micros().

You will want to make sure that the code you post compiles, and does what you say it does. Otherwise, you’ll get a lot of replies saying, “It doesn’t compile,” or, “That’s not what I got.”

tmd3: Thank you for the quick reply. Your explanation was great!

I actually had I.S.R.s but had them commented out. I uncommented them and the program millis() began working again. Sorry for not including everything (like my newt) definition). I was trying to simplify things as to not confuse others but I think I got the opposite result. I will try to be more complete.

My code is actually a bit longer and I’m trying to be modular with it in an attempt to assist in the debugging process. I added parts of my code back in and I’m not getting another problem - one that I get often in fact.

The output to the serial monitor shows that newt is continually progressing - like it should - with the following code.

#define pwmOut 9

int buttonIn=12, potIn=A1, potVal=0, motorRun=0, state,  oldState, count=0; 
double  angularRate, jointAngle=0, oldAngle=1.98, gain=0.01, regA, regB,OrigRegA,OrigRegB, percent, targAngRate;
const double pi=3.1416;
unsigned long newt, oldt=0;


void setup()
{
  Serial.begin(9600);
  
  pinMode(pwmOut, OUTPUT);
  
  // initialize timer1 
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  // Compare B has to be before compare A because the timer TCNT1 
  // resets when it matches OCR1A
  OCR1A   = 64000;
  OCR1B   = 63000;           // compare match register 

  TCCR1B |= (1 << WGM12)|(1 << CS10);

  TIMSK1 |= (1 << OCIE1A)|(1 << OCIE1B);  // enable timer compare interrupt
  
  interrupts();             // enable all interrupts
}

ISR(TIMER1_COMPB_vect)          // timer compare interrupt service routine
{
  digitalWrite(pwmOut, HIGH);
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
  digitalWrite(pwmOut, LOW);
}

void loop()
{
 oldState=state;
  if (digitalRead(buttonIn)==LOW)
  {
    state=0;
  }
  else
  {
    state=1;
  }


  
  if (state!=oldState)
  {
    motorRun=1;
    regA=OrigRegA;
    regB=OrigRegB;
  }

  
  
  //  Reads the voltage from the Goniometer/potentiometer 
  //  and maps 0-5V to 10 bit integer value (0-1023)
  potVal = analogRead(potIn);

  //  Reads the voltage from the from Hall sensors on the  
  //  motor and maps 0-5V to 10 bit integer value (0-1023)
  //  currentVal = analogRead(currentPin);
  jointAngle = (0.3333*potVal-170)*pi/180;
  newt=micros();
  
  Serial.print((newt));
  Serial.print("\t");
}

But when I add the last bit of code after serial.print() (code in full shown below) I only get two values in the serial monitor. Any thoughts?

#define pwmOut 9

int buttonIn=12, potIn=A1, potVal=0, motorRun=0, state,  oldState, count=0; 
double  angularRate, jointAngle=0, oldAngle=1.98, gain=0.01, regA, regB,OrigRegA,OrigRegB, percent, targAngRate;
const double pi=3.1416;
unsigned long newt, oldt=0;


void setup()
{
  Serial.begin(9600);
  
  pinMode(pwmOut, OUTPUT);
  
  // initialize timer1 
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  // Compare B has to be before compare A because the timer TCNT1 
  // resets when it matches OCR1A
  OCR1A   = 64000;
  OCR1B   = 63000;           // compare match register 

  TCCR1B |= (1 << WGM12)|(1 << CS10);

  TIMSK1 |= (1 << OCIE1A)|(1 << OCIE1B);  // enable timer compare interrupt
  
  interrupts();             // enable all interrupts
}

ISR(TIMER1_COMPB_vect)          // timer compare interrupt service routine
{
  digitalWrite(pwmOut, HIGH);
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
  digitalWrite(pwmOut, LOW);
}

void loop()
{
 oldState=state;
  if (digitalRead(buttonIn)==LOW)
  {
    state=0;
  }
  else
  {
    state=1;
  }


  
  if (state!=oldState)
  {
    motorRun=1;
    regA=OrigRegA;
    regB=OrigRegB;
  }

  
  
  //  Reads the voltage from the Goniometer/potentiometer 
  //  and maps 0-5V to 10 bit integer value (0-1023)
  potVal = analogRead(potIn);

  //  Reads the voltage from the from Hall sensors on the  
  //  motor and maps 0-5V to 10 bit integer value (0-1023)
  //  currentVal = analogRead(currentPin);
  jointAngle = (0.3333*potVal-170)*pi/180;
  newt=micros();
  
  Serial.print((newt));
  Serial.print("\t");

  angularRate=abs(jointAngle-oldAngle)/((newt-oldt)/1000000);
  oldAngle=jointAngle;
  oldt=newt;

  
  percent=1-(jointAngle - 0.3)/1.68;
  targAngRate=(-242.2086*pow(percent,3)+172.8958*pow(percent,2)+58.4458*percent+52.1349)*pi/180;
  
  
  //On off transient logic
  if (jointAngle<0.3)
  {
    motorRun = 0;
  }
  
  if (motorRun==1)
  {
    OCR1A=regA;
    OCR1B=regB;
    regB=regB+(angularRate-targAngRate)*gain;
    OCR1B   = regB;
  }
  else
  {
    OCR1A     = 0;
    OCR1B     = 0;
  }
}
 if (motorRun == 1)
  { 
    OCR1A = regA;
    OCR1B = regB;
    regB = regB + (angularRate - targAngRate) * gain;
    OCR1B   = regB;
  }

Your code is entering this section and hanging up, because the interrupts are happening so fast that there is not free time for the Serial print to execute.

Serial.begin(115200);

Increase the speed of Serial.begin and you will see output again.

Works perfectly. Thanks so much Cattledog.