10MHz Rubidium Frequency Standard and Signal Distribution Amp Follow-Up

This is a follow-up to my previous article here. When testing the 1 PPS output I found some strange output which needed further investigation. I also decided to make further use of the micro controller and status LED to indicate the 1 PPS signal to provide a degree of visual confidence that the frequency standard was working.

Various Pictures

IMG_5966.JPG
IMG_5965.JPG
IMG_5964.JPG
IMG_5963.JPG
IMG_5962.JPG
IMG_5961.JPG
IMG_5960.JPG
IMG_5959.JPG
IMG_5958.JPG
IMG_5956.JPG
IMG_5957.JPG
IMG_5954.JPG
IMG_5955.JPG

The 1 PPS Channel
Here is the outline schematic of the digital channel of the video amp that is now used for the 1 PPS signal.

The fast comparator used in this circuit is an LT1016

The Micro-controller
When I first tried to implement this I used (or tried to use) the edge trigger interrupt capability which on the face of it should have been the perfect solution. However, no matter what I tried I could not get it to work, the best I managed to achieve was getting it to work some of the time, but it was very random. I suspect this was down to the way in which the PIC12X handles interrupts and context state saving implemented by the compiler, I read somewhere on the microchip forums that this issue *could* be resolved by upgrading to the PRO version of the compiler…..hmmmmmmm. Anyway, I decided to change tact and poll for the 1PPS signal which meant I also had to construct a really simple pulse stretcher circuit to ensure I was able to catch each pulse. Not as elegant as an interrupt-driven solution but it works. I think the more advanced PIC18Fxxx series micro controllers would have worked using interrupts but those are big chips and I was already committed to the PIC12F675.

Here is the schematic for the micro controller which now also monitors the 1 PPS output of the RBS. The shaded area is what has been added to the circuit since the previous article.

Here is the firmware source code with the 1PPS implementation added. Its implemented as a simple state machine in run mode, I have tried to keep the code simple to read.

#include 

// PIC12F675 Configuration Bit Settings

// CONFIG
#pragma config FOSC  = INTRCIO  // Oscillator Selection bits (Internal oscillator: GPIO on GP4/GP5)
#pragma config WDTE  = OFF      // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP    = OFF      // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD   = OFF      // Data Code Protection bit (Data memory code protection is disabled)

// IMPLEMENTATION STRATEGY
//
// PIN ASSIGNMENTS
//   2 = RFS_RDY signal from Pin 6 (GPIO5)
//   4 - 1PPS signal
//   5 - Front Panel LED
//

// We are running the chip at 4Mhz
#define XTAL_FREQ 4000000

#define CLK_1PPS GPIObits.GPIO4
#define LED_STATUS GPIObits.GPIO2
#define RFS_READY GPIObits.GPIO5

void main(void)
{
    // Used as LED state machine control variable
    char _led_state = 0;

    ADCON0bits.ADON = 0;    // Turn off the ADC
    ANSELbits.ANS = 0;      // Make all inputs digital
    VRCON = 0;              // Turn off the internal voltage reference
    CMCON = 0x7;            // Turn off the comparator

    // Set up our I/O pins
    TRISIObits.TRISIO2 = 0; // Make GPIO2 an output - LED
    TRISIObits.TRISIO4 = 1; // Make GPIO4 an input - 1PPS counter input
    TRISIObits.TRISIO5 = 1; // Make GPIO5 an input - RFS_READY

    while(1)
    {
        if(RFS_READY == 0)
        {
            // This is when we are in run mode.

            // We are polling the 1 PPS signal, if we sense a "1" we set the
            // _led_state variable to the number of 10ms periods you want. In
            // this case I want about 80ms. Once this is set the state machine
            // below will hold the LED on and wait 10ms until ir reaches 2,
            // and then normal state resumes, the end result being an LED thats
            // lit normally, and pulses brightly for about 80ms on each 1pps
            // count.
            if(CLK_1PPS == 1)
                _led_state = 10;

            // This is a simple state machine that will run the LED
            // at one third power by outputting a 33% duty cycle square
            // wave. Each time around the loop the state variable will
            // count 0-1-2-0-1-2...etc LED on for 0, and off 1 & 2.
            // When the 1PPS interrypt is fired, the state machine
            // holds the LED on at full brightness (100% duty)
            switch(_led_state)
            {
            case 0:
                LED_STATUS = 1;
                _led_state = 1;
                break;

            case 1:
                LED_STATUS = 0;
                _led_state = 2;
                break;

            case 2:
                LED_STATUS = 0;
                _led_state = 0;
                break;

            default:
                _led_state--;
                LED_STATUS = 1;
                _delay(10000);
                break;
            }
        }
        else
        {
            // If we get in here we are in warm-up mode. We blink the
            // LED with a short on period (20%) and a long off period (80%)
            // about three blinks a second.
            if(LED_STATUS == 0)
            {
                LED_STATUS = 1;
                _delay(75000);
            }
            else
            {
                LED_STATUS = 0;
                _delay(300000);
            }
        }
    }
}

Catch you next time….

This content is published under the Attribution-Noncommercial-Share Alike 3.0 Unported license.

10 thoughts on “10MHz Rubidium Frequency Standard and Signal Distribution Amp Follow-Up

  1. Hi Gerry
    All 10MHz RS videos are fantastic!
    1. Very professional
    2. Clear and easy to understand
    3. Good examples
    4. Very nice on going problem solving
    And so on . . .
    I learned a lot !
    Keep on the good work!
    Dror

  2. Hello Gerry, on the off-chance that a dozen other people don’t mention it (!) Your non-contact IR temperature meter will ASSUME that it is looking at a less reflective surface than your shiney aluminium front panel. It will woefully under-read the actual thermal temperature, as a result. Google Emissivity Coefficients (if you really must!) OR – just stick a bit of insulating tape on the metal front panel, and point your IR meter at that, instead. I’ll guess at 45 degrees.

    PIC overkill? Nah! I think you should use the spare GPIO ports on that PIC to drive a small LED matrix array back-and-forth, a-la “Night Rider”

    • Hi Laurence,

      Someone else did point this point this out to me, I ended up using black tape as you suggest and it was reading about 36 degrees C instead of the 29 I measured in the video. I should have cross-checked with a thermocouple really :) Thanks for the pointer.

      Night-rider light, hmmm, maybe, always wanted to find a need to make one of those…. :)

      Gerry

  3. newbie question… what’s the intended purpose of the 1pps signal? Can you elaborate on how you plan to make use of this added signal? I must be missing something here…perhaps it’s a radio-enthusiast type of utilization or ?

    • You can use it to drive a clock :) Some gear can synchronise to a 1 pps signal where you have a slow loop time. Imagine feeding a counter with a frequency thats resent and held once a second, thats a basic frequency counter. Gerry

  4. Gerry,

    I noted that in your schematic, the signal from the Rubidium Standard indicating “locked” is called “RBS_RDY” (with a “B”), but in your code it’s being called both “RFS_RDY” (in comments), and “RFS_READY” (in code). I’m presuming the first two of these are typos and all refer to the same signal going into GPIO5.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>