Advertisement
grist

ATtiny Pulse Receiver

Nov 14th, 2014
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.38 KB | None | 0 0
  1. /*
  2.  * ATtiny85_PulseReceiver.c
  3.  *
  4.  * Created: 10/16/2014 12:48:10 PM
  5.  *  Author: grist.carrigafoyl
  6.  
  7.  A receiver for signals from a fibre optic connector for use with a Micro-brute
  8.  Tesla Coil. Will respond to pin changes on PCINT0 (PB0, pin 5), but will not
  9.  allow a pulse greater than a preset width to occur. Using an external crystal
  10.  oscillator for the clock.
  11.  
  12.  Also incorporating a guard timer to prevent pulses ocurring too often.
  13.  
  14.  
  15.  Input is on PB0, pin5
  16.  Output is on PB1, pin 6.
  17.  
  18.  v1.00 First working version. Trips up on pulses less than 5us
  19.  v1.01 Trying to fix trip. Moved max width timer to first instruction after interrupt triggered
  20.  v1.02 Still trips up and latency seemed high. Moved max width timer to last instruction in PCINT0_vect
  21.  v1.03 Fixed trip up. Even feeding a 2MHz signal with nanosecond pulses doesn't phase it.
  22.  */
  23.  
  24. #define F_CPU 8000000UL // 8Mhz
  25. #define MAX_PULSE_WIDTH 190 // microseconds
  26. #define MIN_GUARD_TIMER 60 // min microseconds between pulses
  27. #define INPUT_PIN PB0
  28. #define OUTPUT_PIN PB1
  29.  
  30.  
  31. #include <avr/io.h>
  32. #include <avr/interrupt.h>
  33.  
  34. // Used to control the behaviour of COMPB_vect
  35. volatile uint8_t long_timer_active = 0;
  36.  
  37.  
  38. int main(void)
  39. {
  40.     // Set Output pin as output
  41.     DDRB |= _BV(OUTPUT_PIN);
  42.    
  43.     // Set up the interrupt on pin 5
  44.     GIMSK |= _BV(PCIE); // pin change interrupt enable
  45.     PCMSK |= _BV(PCINT0); // only react to changes on PCINT0, ie PB0, pin 5
  46.    
  47.     // Timer0 interrupt settings to limit the pulse width
  48.     TCCR0A = _BV(WGM01); // ctc mode
  49.     TIMSK |= _BV(OCIE0A) | _BV(OCIE0B); // Enable Timer 0 COMP A & B interrupt vectors on match
  50.     // Not setting this here as it starts the timer. That will be done by the timer 1 interrupt.
  51.     //TCCR0B|= _BV(CS01); // prescaler 8, so OCR0A is in ยตs @ 8MHz
  52.     OCR0A = MAX_PULSE_WIDTH; // should be close to microseconds with prescalar 8 and 8MHz clock
  53.     OCR0B = MIN_GUARD_TIMER; // minimum time between pulses
  54.  
  55.     sei(); // enable global interrupts 
  56.    
  57.     while(1)
  58.     {
  59.         //TODO:: Nothing to see here.
  60.     }
  61. }
  62.  
  63.  
  64. ISR(PCINT0_vect) {
  65. // React to changes on pin 5. Logic is reversed as the fibre optic receiver
  66. // holds the pin high until it receives a signal.
  67.     if ((PINB & _BV(INPUT_PIN)) == 0) { // pin is now low, so rising edge of original pulse
  68.         PORTB |= _BV(OUTPUT_PIN); // turn the output pin on
  69.         TCNT0 = 0; // reset the counter
  70.         long_timer_active = 1;
  71.     } else { // pin now high, so falling edge of original pulse
  72.         PORTB &= ~_BV(OUTPUT_PIN); // output pin off
  73.         TCNT0 = 0;
  74.         PCMSK = 0; // disable pin change interrupts until the guard timer has expired
  75.         long_timer_active = 0;
  76.     }
  77.     TCCR0B|= _BV(CS01); // start the max pulse width timer with prescaler 8
  78. }
  79.  
  80.  
  81. ISR(TIMER0_COMPA_vect)
  82. // Max pulse width timer. If we get to here then a pulse was received that exceeded the max
  83. // allowable. This could cause an over-current condition and damage to the IGBTs.
  84. {
  85.     // Turn off the pin.
  86.     PORTB &= ~_BV(OUTPUT_PIN);
  87.     PCMSK = 0; // disable pin change interrupt
  88.     // set the prescalar to 1024 to really delay the next possible pulse.
  89.     TCCR0B = _BV(CS00) | _BV(CS02);
  90.     long_timer_active = 0;
  91. }
  92.  
  93. ISR(TIMER0_COMPB_vect)
  94. // Guard timer. No pin change interrupts are allowed until this has expired.
  95. {
  96.     if (long_timer_active == 0) {
  97.         // Turn the timer off, we're done with it for now
  98.         TCCR0B = 0;
  99.     }
  100.     // Reenable pin change interrupts on the input pin
  101.     PCMSK |= _BV(PCINT0);
  102. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement