Hello all. I'm using an Arduino Uno R3 to try and generate a 1hz timer interrupt with a 20% duty cycle to mimic a GPS 1PPS output. I can produce the 1hz interrupt (and a 2hz interrupt to mimic a 50% duty cycle) but, despite large amounts of reading and googling, my brain will not absorb the necessary information. My code:
The IDE really tries to help you to indent the code..
Use comments... What does "TCCR1A = 0;" actually do? What does the formula without variable do? etc
Why use a 16-bit timer to do it? Why nog 8-bit?
Or more important, why use a interrupt at all? It sooooo slow. Just use millis.
And the hint to fix the problem. You don't want to do something every second (1Hz) but you want to do something after 800ms (turn on) and again after 200ms (turn off)
Which Arduino? If it's an Uno, the best output can be obtained by programming the on board 16U2. It has vastly superior frequency stability because it uses a real quartz crystal for timing.
Perhaps, then, I should rephrase my original question. I am looking for the best (and by best I mean resulting in the most accurate/precise) method of producing a signal or pulse one second in length that is "on" for 20% of its duration and "off" for 80%. Can anyone advise me of the best way to go about this? Thank you.
ncguk:
Perhaps, then, I should rephrase my original question. I am looking for the best (and by best I mean resulting in the most accurate/precise) method of producing a signal or pulse one second in length that is "on" for 20% of its duration and "off" for 80%. Can anyone advise me of the best way to go about this? Thank you.
A timer with output compare method programmed into the 16U2 on the Uno. But you never answered the question of which board you have.
I actually implemented and tested this method. Mine was based on the micros() function, rather than timers, because I was looking for long term accuracy, not low latency.
It can't be explained to a child, sorry. You've chosen a very technical task.
I already gave you a big fat hint (although you skipped it because you didn't liked the rest of my post...). You don't want to do something every second...
I think the accuracy point is way to heavy. Accuracy is a whole world of it's own and "very accurate" and "1Hz" it's just unlikely you need nanosecond accuracy. If you want to have that you need to do more then just use a interrupt...
I think a simple millis thing is fine.
const unsigned int PulseIntervals[] = [800, 200]; //Intervals we want to do stuff
const byte LedPin = 10; //Pin to pulse
void setup(){
pinMode(LedPin, OUTPUT);
}
void loop(){
checkPulse();
}
void checkPulse(){
static unsigned int pulsMillis; //To know when we pulse (ms)
unsigned int millisNow = millis();
//Check if corresponding (to state) interval passed
if(millisNow - pulsMillis >= PulseIntervals[digitalRead(LedPin)]){
pulsMillis = millisNow; //save for next time
digitalWrite(LedPin, !digitalRead(LedPin)); //toggle output
}
}
septillion:
I already gave you a big fat hint (although you skipped it because you didn't liked the rest of my post...). You don't want to do something every second...
I think the accuracy point is way to heavy. Accuracy is a whole world of it's own and "very accurate" and "1Hz" it's just unlikely you need nanosecond accuracy. If you want to have that you need to do more then just use a interrupt...
Actually, accuracy is important. A 2hz timer interrupt works very nicely (and very precisely) as a 1PPS signal with a 50% duty cycle. However, my interest is in being able to produce a 1hz square wave with a 20% duty cycle to mimic a 1PPS pulse. It was my understanding that the most efficient and accurate way of doing that was by using a timer interrupt. If this is not the case and using millis() is the way to go, then I thank you for your answer. In fact, I thank you for your answer either way.
// 2015-11-03 aarg
// PPS generator for 16U2
// works, needs sync input
#define ONE_SEC 1000000UL
#define CAL_CONSTANT 0
#define CYCLE_TIME (ONE_SEC + CAL_CONSTANT)
#define ON_TIME (CYCLE_TIME /5UL)
#define OFF_TIME (CYCLE_TIME - ON_TIME)
unsigned long timeStamp = 0;
unsigned long intervals[] = {ON_TIME, OFF_TIME};
byte states[] = {HIGH, LOW};
const byte NUM_OF_INTERVALS = sizeof(intervals) / sizeof(unsigned long);
byte currentInterval = 0;
void setup()
{
pinMode(MOSI, OUTPUT);
pinMode(LED_BUILTIN_RX, OUTPUT);
pinMode(LED_BUILTIN_TX, OUTPUT);
digitalWrite(LED_BUILTIN_TX, HIGH); //change state of the LED
}
void loop()
{
unsigned long currentTime = micros(); //get current value of millisecond counter
if (currentTime - timeStamp >= intervals[currentInterval]) //if the time interval has elapsed
{
timeStamp += intervals[currentInterval]; //advance to now
currentInterval = currentInterval + 1; // select the next interval in the list
if (currentInterval >= NUM_OF_INTERVALS)
currentInterval = 0;
digitalWrite(MOSI, states[currentInterval]); //change state of the LED
digitalWrite(LED_BUILTIN_RX, states[currentInterval]); //change state of the LED
}
}
"The most accurate" != "the best in a application". People tend to think that. "Oww, I want it to be good so use the best I can get". But then I would need a atomic clock to connect to my watch so I have accurate time.
1ppm is pretty accurate indeed but the resonator on a Arduino isn't that accurate. But I do think a simple millis() sketch is "pretty accurate" in this situation but you didn't tell us what you're really connection to it.
If you really need more accuracy then millis() you can use the timer (and I already gave you all the hints on how to do it really...) but you still have the inaccuracy of the Arduino itself to deal with...
septillion:
1ppm is pretty accurate indeed but the resonator on a Arduino isn't that accurate. But I do think a simple millis() sketch is "pretty accurate" in this situation but you didn't tell us what you're really connection to it.
If you really need more accuracy then millis() you can use the timer (and I already gave you all the hints on how to do it really...) but you still have the inaccuracy of the Arduino itself to deal with...
But this is all why I suggested using the on board 16U2 since it has a separate and superior frequency reference.
aarg:
It's not sacrificed. It still runs a bootloader and USB serial monitor, using Nick Hood's code.
Wasn't aware the USB-Serial part was kept in tact. But still, the hassle for more accuracy while I'm not convinced he needs it.
aarg:
Did I miss something? I don't see a 1ppm anywhere.
My bad, read 1pps as 1ppm all the way. This makes me really think he very very very much overthinks the accuracy. Or at least, he's not gaining any by using a real interrupt because of the Arduino inaccuracy. For something that runs a couple of hours it's probably fine but the Arduino inaccuracy s to big for something like a clock. Then instead of mocking around with calibrating or flashing the 16U2 I would grab a RTC...
ncguk:
Hello all. I'm using an Arduino Uno R3 to try and generate a 1hz timer interrupt with a 20% duty cycle to mimic a GPS 1PPS output. I can produce the 1hz interrupt (and a 2hz interrupt to mimic a 50% duty cycle) but, despite large amounts of reading and googling, my brain will not absorb the necessary information.
You didn't consider using a 5Hz interrupt to generate a 20% duty cycle then?
You probably need a timer mode with a top of OCR1A for the right frequency, while OCR1B defines the duty cycle.
Look for "Modulating 38 kHz signal" here : Gammon Forum : Electronics : Microprocessors : Timers and counters
And you need to enable the interupt.
I'm sorry, but I can't help any further. I have done that kind of things in the past, but it is too long ago