Understanding TimerOne

Hi,
I´m new to programming and trying to understand some functions. I have successfully "read" voltage to make a led blink at different speed according to voltage input on A0. Now i´m trying to do the same but using TimerOne instead of "delay" but i cant get it to work the way i want. Now the input value (get_voltage) to adjust the blinking is in the setup but i want it in the loop. Is that possible and what code shall i use? maybe "bool"?

regards
Joakim

const unsigned int POT_READ=0;
  const float SUPPLY_VOLTAGE=5.0;
  const unsigned int BAUD_RATE=9600;
  #include "TimerOne.h"

void setup() {
 Serial.begin(BAUD_RATE);
 pinMode(9, OUTPUT);
Timer1.initialize(get_voltage()*50000);      
Timer1.pwm(9,512);              
Timer1.attachInterrupt(callback);  

}

void callback()
{
digitalWrite(10, digitalRead(10) ^ 1);
}
 
 void loop() {
 Serial.print(get_voltage());
Serial.println(" Volt");
delay(1000);


}

const float get_voltage(){
const int out_voltage=analogRead(POT_READ);
const float voltage=out_voltage*SUPPLY_VOLTAGE/1024;
return (voltage);
}

I am not familiar with the Timer1 library.

If you are not especially interested in using the library you can probably achieve what you want by using millis() as illustrated in Several Things at a Time

...R

People will find it easier to help you if you post your code using the code tags. You can do that by hitting the “Code” icon above the posting area. It is the first icon, with the symbol: </>

const unsigned int POT_READ=0;
  const float SUPPLY_VOLTAGE=5.0;
  const unsigned int BAUD_RATE=9600;
  #include "TimerOne.h"

void setup() {
 Serial.begin(BAUD_RATE);
 pinMode(9, OUTPUT);
Timer1.initialize(get_voltage()*50000);         // initialize timer1, and set a 1/2 second period
Timer1.pwm(9,512);                // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt

}

void callback()
{
digitalWrite(10, digitalRead(10) ^ 1);
}
 
 void loop() {
 Serial.print(get_voltage());
Serial.println(" Volt");
delay(1000);


}

const float get_voltage(){
const int out_voltage=analogRead(POT_READ);
const float voltage=out_voltage*SUPPLY_VOLTAGE/1024;
return (voltage);
}

To change the frequency within the loop add the following line

void loop() {
ICR1 = (get_voltage()*50000); //add this line 
Serial.print(get_voltage());
Serial.println(" Volt");
delay(1000);
}

If you read the documentation (TimerOne.h) for the TimerOne library you will see how the frequency is set by Timer1.initialize().

You can also just use the analogRead to adjust the duty cycle on pin 9
Not tested:
Timer1.setPwmDuty(9,analogRead(A0));

.

DS21:
Hi,
I´m new to programming and trying to understand some functions. I have successfully “read” voltage to make a led blink at different speed according to voltage input on A0. Now i´m trying to do the same but using TimerOne instead of “delay” but i cant get it to work the way i want. Now the input value (get_voltage) to adjust the blinking is in the setup but i want it in the loop. Is that possible and what code shall i use? maybe “bool”?

You don’t need a timer library to do what you are doing. Try this:

#define DIV_1024 (_BV(CS12)|_BV(CS10))

#define LED_PIN 13 // any pin number you like

volatile uint8_t state = 0;
volatile uint16_t divider;
uint16_t analog;
uint16_t frequency;

ISR (TIMER1_COMPA_vect)
{
	digitalWrite (LED_PIN, state ? HIGH : LOW);
	state ? state = 0 : state = 1;
	OCR1A = divider; // set divider (i.e. frequency)
}

void setup (void)
{
	// setup pin as an output
	pinMode (LED_PIN, OUTPUT);

	// set timer 1 to Mode 4
	TCCR1A = 0;
	TCCR1B = _BV (WGM12);
	// set clock prescaler to F_CPU/1024
	TCCR1B |= DIV_1024;
	// enable interrupt on OCR1A match
	TIMSK1 = _BV (OCIE1A);
}

void loop (void)
{
	analog = analogRead (A0); // any analog port you want
	// map analog 0..1023 to 100...500 (whatever you want)
	frequency = map (analog, 0, 1023, 100, 500);
	// calculate divider needed
	divider = ((F_CPU / 1024) / ((frequency * 2) + 1));
	delay (500); // wait 1/2 sec between changes
}

This demo maps analog 0…1023 to 100…500 hertz, but you can change it to whatever you wish (as you can change which pin to use for the output signal and which pin as the analog input).

Note: We set the divider INSIDE the ISR to avoid confusing it by asynchronously setting it at random and “pulling the rug out from under it” if we set it inside the loop.

Hope this helps.

LarryD:
You can also just use the analogRead to adjust the duty cycle on pin 9
Not tested:
Timer1.setPwmDuty(9,analogRead(A0));

.

That would change the BRIGHTNESS of the LED depending on the analog reading, but not it's blink rate. I assumed the OP wanted a different blink rate.... maybe I'm wrong?

Anyway, now he's got two options! :slight_smile:

#define DIV_1024 (_BV(CS02)|_BV(CS00))
TCCR1B |= DIV_1024;

Your # define is setting up the prescaler on Timer0. For Timer1

#define DIV_1024 (_BV(CS12)|_BV(CS10))

cattledog:

#define DIV_1024 (_BV(CS02)|_BV(CS00))
TCCR1B |= DIV_1024;

Your # define is setting up the prescaler on Timer0. For Timer1

#define DIV_1024 (_BV(CS12)|_BV(CS10))

Yeah, it’s a typo, but the bits are the same so it works anyway! :slight_smile:

Thank you all!! this is really an amazing forum! I´ll try it and come back with report

Regards
Joakim