Timer1 amateur help

Hey guys,

Im just trying to use timer1 to call a function.

Here is my code:

#include <TimerOne.h>

void setup() {
  pinMode(9, OUTPUT);
  Timer1.initialize();
  Timer1.attachInterrupt(pwm, 5000000);
  
}

void loop(){
  digitalWrite(13,HIGH);
}

void pwm(){
 digitalWrite(9, HIGH);
 delay(250);
 digitalWrite(9,LOW);
 delay(250);
 digitalWrite(9, HIGH);
 delay(250);
 digitalWrite(9,LOW);
 delay(250);digitalWrite(9, HIGH);
 delay(250);
 digitalWrite(9,LOW);
 delay(250);
}

Basically I am trying to blink an LED at 1/4 second intervals, 3 times, every 5 seconds. I am doing this to try and work out how to use Timer1. At the moment my LED will blink every 5 seconds (as hoped), but will only turn on once and only for a very short period of time. When I change the sketch so that the LED should only blink once and stay on for one second, the LED does not do this and blinks for that same short period of time.
What’s wrong with my code?

Thanks for your help!

void pwm(){
 digitalWrite(9, HIGH);
 delay(250);
 digitalWrite(9,LOW);
 delay(250);
 digitalWrite(9, HIGH);
 delay(250);
 digitalWrite(9,LOW);
 delay(250);digitalWrite(9, HIGH);
 delay(250);
 digitalWrite(9,LOW);
 delay(250);
}

delay() does not work in an interrupt handler, because interrupts are disabled while the ISR is running, and delay() relies on interrupts.

ISRs should be very, very fast. delay() is absolutely not to be used in an ISR.

If you want to blink the LED, change the interval for the interrupt to 1/4 of a second, and determine, in the ISR whether to turn the LED on, off, or do nothing.

Using a timer for this is overkill.

Think about how you would perform the required actions using just a watch and a pad of paper.

Alright. So I am very inexperienced with programming, but I know what I want my sketch to do and I know the logic of it. If I write it in english maybe you, or someone else, could help me with the C language?

Ok so:

if Timer1 period is up { begin PWM function; stop Timer1; start a new timer which will be used to stop the PWM function; { if the new timer's period is up { stop PWM function; restart Timer1;} } }

This would have to be in my void loop() I'd imagine. And i'd also have to do some defining and stuff at the beginning of my sketch, but I don't know how to do that...

Any help would be greatly appreciated! :):)

Reread the last line of my reply.

How would you do this without a stopwatch?

if Timer1 period is up

This means that the difference between "now" and "then" is equal to, or greater than, some defined interval.

begin PWM function;

analogWrite(somePWMPin, someValue);

stop Timer1;

We don't have a stopwatch, so there is nothing to stop.

start a new timer which will be used to stop the PWM function;

Save "now" as "then".

So, "now" can be obtained from millis().

unsigned long then;

And, now we have "then".

unsigned long now;
unsigned long then = 0;
unsigned long interval = 1000; // Whatever interval appeals to you

void loop()
{
   now = millis();
   if(now - then > interval)
   {
      analogWrite(somePin, someValue);
      then = now;
   }
}

All that is left for you to do is define the pin and value to use.

Hello Paul,

i’m just browsing the whole forum, and reading your answer makes pop a question in my head. i read that in ISR, calling delay is useless because delay itself relies on interrupts which are disabled in an ISR. So wouldn’t it be possible to:

  • Calculate the time in nano second that it takes for the chip to make one operation (Let’s pretend it’s ins).
  • Based on that, if a delay of 50 is required, make a loop like for (unsigned int isz=0; isz<65535, isz++) {} (10000 is temporary)
  • And then look at the assembly generated by this loop, count the number of instructions (Let’s pretend it’s 4).
  • Substitute 65535 by the required delay taking into account the operation delay generated by the loop (50ms = 50000ns, so 50000 / 5 / 4 = 2500).
  • Then re-code the dummy loop like that: for (unsigned int isz=0; isz<10000, isz++) {}
  • Once the operation time constant is known, and the count of instructions by the loop too, having a delay would be a matter of writing the same loop and just changing the required amount of operations done by this loop?

Or am i dreaming about something very silly?
Pierre.

http://www.arduino.cc/playground/Code/Timer1

Look at the PWM example. I think the answer is there.

i read that in ISR, calling delay is useless because delay itself relies on interrupts which are disabled in an ISR.

True.

Calculate the time in nano second that it takes for the chip to make one operation

Sure. It's the inverse of the frequency that the chip operates at. 16Mz --> 62.5 nanoseconds.

Based on that, if a delay of 50 is required

A delay of 50 what? nanoseconds, microseconds, milliseconds, seconds, days, years?

Once the operation time constant is known, and the count of instructions by the loop too, having a delay would be a matter of writing the same loop and just changing the required amount of operations done by this loop?

True. But there are two things you need to be concerned with. First, if the body of the loop does nothing, the compiler will probably optimize away the whole loop. Oops, there goes the delay.

You can prevent this from happening by making the loop do something to a variable and marking that variable volatile.

That will change your loop time, so you need to adjust the number of iterations.

Second, the loop you describe allows you to do nothing while the loop is running. If you add something to the loop, it changes the timing which changes the number of iterations, outside of your control.

If you need a delayNanoseconds() function, this is the way to do it, though.

PaulS:

Based on that, if a delay of 50 is required

A delay of 50 what? nanoseconds, microseconds, milliseconds, seconds, days, years?

i'm not sure of anything anymore. 50 nano quantic-intricated peer apples?[edit]Ah no sorry, i just re-read the whole thing, and i figured we need a delay of 2.21GW Giga-What??? Yeah! A delay in Watts exists in 4 dimensions, and the flux capacitor would then convert it to 42, which is the answer to everything.[/edit]

PaulS:

Once the operation time constant is known, and the count of instructions by the loop too, having a delay would be a matter of writing the same loop and just changing the required amount of operations done by this loop?

True. But there are two things you need to be concerned with. First, if the body of the loop does nothing, the compiler will probably optimize away the whole loop. Oops, there goes the delay. You can prevent this from happening by making the loop do something to a variable and marking that variable volatile.

Or declaring the incremented variable before the loop's scope, in that specific case the loop will not be optimized because the compiler knows that the value of the increment once the loop has finished may be critical for your purpose.

PaulS: Second, the loop you describe allows you to do nothing while the loop is running. If you add something to the loop, it changes the timing which changes the number of iterations, outside of your control.

But wasn't the initial topic about that? Having a reliable pseudo-delay function accessible from within an ISR? Or do i miss something else here? [edit]Ah no i see why it would be stupid to do that. The ISR would consume almost all the processing power. Duh'![/edit]

Or declaring the incremented variable before the loop’s scope, in that specific case the loop will not be optimized because the compiler knows that the value of the increment once the loop has finished may be critical for your purpose.

No, that won’t work. Compilers are smarter than that. If you increment the variable n times in an otherwise useless loop, the compiler will simply increment the variable by n, and dump the loop.

But wasn’t the initial topic about that? Having a reliable pseudo-delay function accessible from within an ISR? Or do i miss something else here?

Maybe it was, but the initial premise (that interrupts were needed) was flawed, so the rest is immaterial.

Hey Paul,

Thanks a lot mate! Here is what I’m using now:

#include <TimerOne.h>

unsigned long now;
unsigned long then = 0;
unsigned long interval = 2500000;

void setup(){
  pinMode(9, OUTPUT);
  Timer1.initialize();
  digitalWrite(13,HIGH);

}

void loop(){
  now = micros(); //variable to store the read value
  if (now - then > interval){
    Timer1.pwm(9,512,100000);
    then = now;}

I am still using the Timer1.pwm because I need my PWM to be at 38Khz (I realise that this sketch is making it go at 10Hz), and the analogueWrite() has a fixed frequency of 490Hz.

How would I then get my Timer1.pwm to stop? With my sketch, as it is. ledPin 13 lights up, 2.5 seconds pass, then the pwm starts. I want the pwm to stop after x microseconds, then restart after x microseconds.

Cheers mate!

This is what I’ve come up with now:

#include <TimerOne.h>

unsigned long now;
unsigned long then = 0;
unsigned long interval = 2500000;
unsigned long pwminterval = 5000000;

void setup(){
  pinMode(9, OUTPUT);
  Timer1.initialize();
  digitalWrite(13,HIGH);

}

void loop(){
  now = micros(); //variable to store the read value
  if (now - then > interval){
    Timer1.pwm(9,512,100000);}
  if (now - then > pwminterval){
      digitalWrite(9,LOW);

      now = then;}
    
}

It doesn’t work :(:frowning: It should: turn pin13 on HIGH, wait 2.5seconds, start pwm, stop pwm after 2.5s, wait 2.5 seconds, start pwm, stop pwm after 2.5s… etc. But instead it: turns on pin13 HIGH, waits 2.5 seconds, starts pwm, stops pwm for a little bit (less than 2.5s) and then erratically blinks on and off randomly.

What is the problem with the sketch?
I have a feeling that Timer1. is screwing with the timing of it all. Because when I take out the ‘now = then’ (on the last line of my sketch) pwm still continues even though the Timer1.'s pin is meant to be LOW.

Cheers!

LiamLambChop:
This is what I’ve come up with now:

#include <TimerOne.h>

unsigned long now;
unsigned long then = 0;
unsigned long interval = 2500000;
unsigned long pwminterval = 5000000;

void setup(){
  pinMode(9, OUTPUT);
  Timer1.initialize();
  digitalWrite(13,HIGH);

}

void loop(){
  now = micros(); //variable to store the read value
  if (now - then > interval){
    Timer1.pwm(9,512,100000);}
  if (now - then > pwminterval){
      digitalWrite(9,LOW);

now = then;}
   
}




It doesn't work :(:( It should: turn pin13 on HIGH, wait 2.5seconds, start pwm, stop pwm after 2.5s, wait 2.5 seconds, start pwm, stop pwm after 2.5s...... etc. But instead it: turns on pin13 HIGH, waits 2.5 seconds, starts pwm, stops pwm for a little bit (less than 2.5s) and then erratically blinks on and off randomly.

What is the problem with the sketch?
I have a feeling that Timer1. is screwing with the timing of it all. Because when I take out the 'now = then' (on the last line of my sketch) pwm still continues even though the Timer1.'s pin is meant to be LOW.

Cheers!

I think you should use this function before setting the pin on HIGH or LOW.

disablePwm(pin)
Turns PWM off for the specified pin so you can use that pin for something else.

I am still using the Timer1.pwm because I need my PWM to be at 38Khz (I realise that this sketch is making it go at 10Hz), and the analogueWrite() has a fixed frequency of 490Hz.

Had you mentioned this in your first post, you might have been steered in a completely different direction, using TimerOne exclusively.

Sorry about that Paul.

hickscorp: i'm not sure of anything anymore. 50 nano quantic-intricated peer apples?[edit]Ah no sorry, i just re-read the whole thing, and i figured we need a delay of 2.21GW Giga-What??? Yeah! A delay in Watts exists in 4 dimensions, and the flux capacitor would then convert it to 42, which is the answer to everything.[/edit]

That post made my day.

PaulS: A delay of 50 what? nanoseconds, microseconds, milliseconds, seconds, days, years?

Goats?

hahaha I agree Nick!

Guys!! I have written a sketch which works :D:D:D I’m so happy.

Here it is. Let me know if you think it won’t work (I need it to blink an LED at 38kHz (so on for 13 microseconds and off for 13 microseconds) for 60 cycles/blinks, pause for 520 microseconds (this is equivalent to 20 blinks), then repeat).

/* People counter sketch baby!
 */

// constants won't change. Used here to 
// set pin numbers:
const int ledPin =  9;      // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMicros = 0;        // will store last time LED was updated
long then = 0; //stores value of now when it was last updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 13 ;           // interval at which to blink (microseconds)
long pause = 520; // pause between pulsing
long pausepulse = 2080; //time from beginning of pause till end of pulsing

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the 
  // difference between the current time and last time you blinked 
  // the LED is bigger than the interval at which you want to 
  // blink the LED.
  long now = micros();
  
  if (now - then >= pause && now - then <= pausepulse){
    unsigned long currentMicros = micros();
 
    if(currentMicros - previousMicros > interval) {
    // save the last time you blinked the LED 
    previousMicros = currentMicros;   

    // 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(ledPin, ledState);
    }}
  if (now - then >= pausepulse){
    then = now;}
  
  }