I am using the Eleego UNO R3 for it and sloeber Eclipse IDE. I've downloaded the timer1.zip and stored the TimerOne.h and TimerOne.cpp in E:\ard-eclipse\sloeber\arduinoPlugin\libraries\timer_one\version1. Then I've created a new sketch and did "add a library to the selected project". I chose "timer_one".
After I clicked "Upload Sketch" I got following errors:
Description:
make: *** [sloeber.ino.cpp.o] Error 1
previous definition of 'class TimerOne'
recipe for target 'sloeber.ino.cpp.o' failed
redefinition of 'class TimerOne'
Resource Qualified Name:
/pwm_timer1
/pwm_timer1/libraries/timer_one/TimerOne.h
/pwm_timer1/Release/subdir.mk
/pwm_timer1/libraries/timer_one/TimerOne.h
What have I done wrong here? I do not have anything doubled or so. Why would that be a redefine?
My code pwm_timer1.ino:
#include "Arduino.h"
#include "TimerOne.h"
unsigned long pwm_high = 0;
unsigned long current_t = 0;
void setup()
{
pinMode(10, OUTPUT);
Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 512); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback);
}
void loop()
{
//Add your repeated code here
}
void callback()
{
digitalWrite(10, digitalRead(10)^1);
Serial.println(millis());
}
And sloeber.ino.cpp:
#ifdef __IN_ECLIPSE__
//This is a automatic generated file
//Please do not modify this file
//If you touch this file your change will be overwritten during the next build
//This file has been generated on 2018-12-25 19:13:08
void setup() ;
void loop() ;
void callback() ;
#include "pwm_timer1.ino"
#endif
Why wouldn't you use the Arduino IDE? Try it in the Arduino IDE and run it without the file/piece of code within the #ifdef. If it still gives an error, post the entire printout here.
I use it, because I am used to the Eclipse IDE and it is has a good file overview on the left side. Luckily I've found the error. I've edited sloeber.ino.cpp to:
#ifdef __IN_ECLIPSE__
//This is a automatic generated file
//Please do not modify this file
//If you touch this file your change will be overwritten during the next build
//This file has been generated on 2018-12-25 19:13:08
void callback() ;
#include "pwm_timer1.ino"
#endif
Now I have no error anymore. But I do not get any Serial output. It seems the Timer1 would never go into overflow. But I set it to 1/2 second so it should really call the ISR callback(), which should print me the millis() in an unsigned long.
Also, you should not use Serial.print() within a ISR. It is not guaranteed to work. It will probably work some of the time, but not always.. Better to just set a flag and deal with the flag inside loop().
//#include "Arduino.h"
#include "TimerOne.h"
unsigned long pwm_high = 0;
unsigned long current_t = 0;
byte flag = LOW;
void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 512); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback);
}
void loop()
{
if(flag == HIGH)
{
//Serial.print(millis());
//Serial.println(digitalRead(9));
flag = LOW;
}
Serial.println(digitalRead(9));
}
void callback()
{
digitalWrite(10, digitalRead(10)^1);
flag = HIGH;
}
For this I tried to see the actual PWM signal, which I created on digital pwm pin 9. But somehow I only get zeros at my Serial monitor. What is my mistake here?
Thank you. I do not really understand. I want to print a 0001100011000 pattern read from pwm pin 9 so I can see the pwm the timer1 producing is actually there. But if I declare pin 9 as output, input or nothing it always gives me following pattern on the serial monitor:
0
0
0
0
what you are missing is that you set the interval for calling the ISR reading the pin to the same as the time for a pwm cycle of the pin. Hence the pin will always have the same state (though it is either just about to change or has just changed (i think the latter but .. ah well) connect a LED to pin 9 as well and see.
If you print the results of reading pin 9 every time through loop(), you will get thousands of readings before you toggle the pin with your 500msec cycle time. Since your frequency is 500msec, I'd suggest putting a delay inside loop()
void loop()
{
delay(50); // should get enough readings to see pin
Serial.print(millis());
Serial.print(": " );
Serial.println(digitalRead(9));
}
Thank you for the answers! Unfortunately, I couldn't change anything to the better here. I did add a delay and changed the ISR time and pwm duty cycle.
Updated Code:
#include "TimerOne.h"
unsigned long pwm_high = 0;
unsigned long current_t = 0;
volatile byte flag = LOW;
void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
Timer1.initialize(50000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 128); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback);
}
void loop()
{
if(flag == HIGH)
{
//Serial.print(millis());
//Serial.print(digitalRead(10));
flag = LOW;
}
delay(50);
Serial.print(millis());
Serial.print(": ");
Serial.println(digitalRead(9));
}
void callback()
{
digitalWrite(10, digitalRead(10)^1);
flag = HIGH;
}
A class can be defined only once per translation unit, and has to have the same definition across translation units.
This error is typically caused by including the header that defines the class multiple times (directly or indirectly) and should be fixed by using include guards.
#include "TimerOne.h"
unsigned long pwm_high = 0;
unsigned long current_t = 0;
volatile byte flag = LOW;
void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
Timer1.initialize(50000); // initialize timer1, and set a 1/2 second period
Timer1.pwm(9, 128); // setup pwm on pin 9, 50% duty cycle
Timer1.attachInterrupt(callback);
sei();
}
void loop()
{
if(flag == HIGH)
{
Serial.print(millis());
flag = LOW;
}
}
void callback()
{
flag = HIGH;
}
At no point does the author of the TimerOne library enable the global interrupt flag. Thus the callback is never called and you only print out the pin state. Adding it in the setup function should enable the interrupts.
Modified Oct 2011 by Andrew Richards to avoid certain problems:
[...]
Remove global enable of interrupts (sei())- could be running within an interrupt routine)
LightuC:
At no point does the author of the TimerOne library enable the global interrupt flag. Thus the callback is never called and you only print out the pin state. Adding it in the setup function should enable the interrupts.
interrupts are on by default.
If you change pin 9 to pin 13 and toggle it in the ISR callback, the onboard LED will blink quite nicely