The Crazy Clock hardware is pretty well suited to the job - any 1-3 volt power source can be turned into 3.3 volts by the built-in boost converter, and I use LEDs in the test harness, so I know it can successfully drive them.
Getting 120 Hz (since we want the light to blink at 60 Hz, we want to toggle it at 120 Hz) from the 32.768 kHz crystal is simply another exercise in the n/n+1 fractional division machinery that already drives the Crazy Clock firmware. And by toggling them both out of phase, we can ignore the polarity of the LED when we hook it up.
Setting the timer prescaler to 8 yields 4.096 kHz. Divide that by 120 and you get 34 + 2/15. 34 * 13 + 35 * 2 = 512, and 512 divides into 32768 evenly. Some of the light pulses will be 244 µS longer than others, but the 60 Hz average should still be within 10 ppm otherwise, which is the tolerance of the crystal.
Here's a 240 fps slow motion video of the strobe:
/*Phonograph strobe generator for ArduinoCopyright 2015 Nicholas W. SayerThis program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.*//** This is intended to run on an ATTiny45. Connect a 32.768 kHz crystal and fuse it* for the low frequency crystal oscillator, no watchdog or brown-out detector.** Connect PB0 and PB1 to an LED. Either orientation will work. The two pins will* alternate polarity. When this firmware is loaded into a crazy clock, it will* just work - the flyback diodes will serve no purpose and the two series resistors* wil be correct for an LED.**/#include <avr/io.h>#include <avr/sleep.h>#include <avr/power.h>#include <avr/interrupt.h>// 32,768 divided by (8 * 120) yields a divisor of 34 2/15#define CLOCK_CYCLES (15)// Don't forget to decrement the OCR0A value - it's 0 based and inclusive#define CLOCK_BASIC_CYCLE (34 - 1)// a "long" cycle is CLOCK_BASIC_CYCLE + 1#define CLOCK_NUM_LONG_CYCLES (2)// LED pins. So that we don't have to remember which is which, we'll always make one// the opposite of the other.#define P0 0#define P1 1#define P_UNUSED 2ISR(TIMER0_COMPA_vect) {// Do nothing - just wake up}void main() {ADCSRA = 0; // DIE, ADC!!! DIE!!!ACSR = _BV(ACD); // Turn off analog comparator - but was it ever on anyway?power_adc_disable();power_usi_disable();power_timer1_disable();TCCR0A = _BV(WGM01); // mode 2 - CTCTCCR0B = _BV(CS01); // prescale = 8TIMSK = _BV(OCIE0A); // OCR0A interrupt only.set_sleep_mode(SLEEP_MODE_IDLE);DDRB = _BV(P0) | _BV(P1) | _BV(P_UNUSED); // all our pins are output.PORTB = 0; // Initialize all pins low.// Don't forget to turn the interrupts on.sei();unsigned char lastTick = P0;unsigned char cycle_pos = 0xfe;while(1) {// This will alternate the ticks#define TICK_PIN (lastTick == P0?P1:P0)// Toggle the two pins back and forth.PORTB |= _BV(TICK_PIN);lastTick = TICK_PIN;PORTB &= ~ _BV(TICK_PIN);if (++cycle_pos == CLOCK_NUM_LONG_CYCLES)OCR0A = CLOCK_BASIC_CYCLE;if (cycle_pos >= CLOCK_CYCLES) {OCR0A = CLOCK_BASIC_CYCLE + 1;cycle_pos = 0;}sleep_mode();}}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.