turning a collins Aerospace RMI-36 VOR/compass display into a clock

Status
Not open for further replies.
There is only a single DAC output on the Teensy's. But your VOR probably doesn't really need a sine wave -- likely a square wave will do, and you can generate those from PWM signals -- to get your phase shift of 360 deg/minute, he 2nd channel would run at (400 + 1/60) Hz.

Note that the VORs require 7.9 VAC -- with a Teensy 3.2, the most you could get is about 3.3VAC, and the drive strength would be a little marginal with the VOR 5 kΩ loading. You might be able to use a low cost audio stereo amplifier chip (with an output DC-blocking capacitor) to drive the VOR.
 
Cool. The T_3.5 and T_3.6 have twin DAC's.

But as Jp3141 notes I saw this on the item page: VOR 1/2 POSITIONING ACCURACY: Less than +-2.0 degrees (w/ synchro input); Less than +-2.1 degrees (w/ square wave input)
 
so here is the fun thing, I have 8 old engineering units without ID plates to play with. I am going to gut the inside and install the driver teencys with a RTC. I have all the drawing and schematics ( I am an engineering tech). so I need to figure out how to make 4 400Hz (square?) waves, reference, second sweep, Minutes sweep, Hours sweep. the compass card rotates once per minute and the yellow / green hands rotate with the compass card for minutes/ hours.
 
if I need 4 tones where I can change the relative phase between 4 continuous 400Hz tones, I need to use at a minimum, a teency 3.5 as it has 4 timers. correct?
 
Before diving into timers, I would create a simple-as-possible software prototype using only elapsedMicros and digitalWriteFast. Just have code in your loop() check if enough time as elapsed and change the pins as needed.

These software created waveforms won't be as perfect as it created directly from the channels of a FTM timer, but there's a good chance the imperfections won't be significant. Even if they are a problem, you can at least get it mostly working the easy way and do quite a bit of experimenting on what waveforms you truly need. That is likely to be a much less frustrating experience than doing experimentation while also dealing with how to use hardware timers. When (if) you do end up moving to a timer-based approach, having a working prototype and all the details of the waveforms you need well tested will let you focus on just the timers.
 
+1

Such an instrument has a certain inertia, so an abrupt phase shift per second will make the indcator overshoot or oscillate, as this abrupt phase shift would not normally be encountered in flight.

So it will be necessary to make a continous phase sweep of 6° over a second.
It is too late now and my head is already sleepng... So as a result it could be two frequencies, the base 400 Hz and the phase 406.6666 Hz, or something....math after wine.... but you get the idea?
 
[video]C:\Users\pjporham\Downloads\NavClock.mp4[/video]
NavClock1a.jpg

I am having problems uploading a 5 second video of a LabView version of what I a looking to build. I need 4 stable square waves, I can do a write at 400Hz*60= 24000KHz. that would give me the resolution, but can I read a SPI bus to read a RTC?. with out a jitter in the wave forms?
 
838 and 58 seconds.jpg

so the compass card rotates at once per minute, the time is 8:38 and 58 seconds. its funny watching engineers try and figure out how read the time. I would like to update the phase of the Square waves at 2Hz. what do you think, can I do fast writes at 24000KHz, or use the 4 timers for 4 PWM's and shnge the phase at 2Hz.
 
Here is code that show how simple it can be to create two waveforms. Note that if you have two waveforms of the same frequency and continuously shift phase, then one can't be a 50% duty cycle waveform.

Code:
// program to demonstrate two square waves
// use with the Arduino serial plotter

// change these
const unsigned period = 5000000;          // how fast for first waveform in usec
const unsigned period2 = period * 1.2;    // how fast for second in usec

// don't change
unsigned next1, next2, next3, next4;
unsigned state1 = 0, state2 = 0;
unsigned count = 0;



void setup() {
  Serial.begin(19200);
  while (!Serial) {}
  Serial.printf("first second\n");
  Serial.printf("3.5 3.5\n");   // start marker on plot

  // start timers - non 50% duty cycle is possible
  unsigned thetime = micros();
  next1 = thetime + .5 * period;
  next2 = next1 + .5 * period;
  next3 = thetime + .5 * period;
  next4 = next3 + .5 * period2;
}

void loop() {

  // alternatively, this code could be in a timer interrupt service routine
  unsigned thetime = micros();

  // first wave rising edge
  if ((next1 - thetime) > period) { // relies on unsigned wrap around
    state1 = 1;
    next1 += period;
  }

  // first wave falling edge
  if ((next2 - thetime) > period) {
    state1 = 0;
    next2 += period;
  }

  // second wave rising edge
  if ((next3 - thetime) > period2) {
    state2 = 1;
    next3 += period2;
  }

  // second wave falling edge
  if ((next4 - thetime) > period2) {
    state2 = 0;
    next4 += period2;
  }

  delay(100);
  Serial.printf("%u %u\n", state1 * 3, state2 * 3 + 4);

  if (count++ > 500) for (;;) {}    // stop after 500 points

} // loop()
 
Hmmmm
Tone 1 is a 400Hz it is the trigger on an oscope displayed on ch1
tone 2 is a 400Hz tone on channel 2. It will change phase of 6 degrees at a one second rate. (Phase is relative to Tone 1).
tone 3 is a 400Hz tone on channel 3 it will change phase of 6 degrees at a once per minute rate
tone 4 is a 400Hz tone on channel 4 it will change phase 360 degrees over 12 hours.
at a once per minute rate the Teency shall read the current time from a RTC (SPI)

so I really need minutes (tone 3) and hours (tone 4) to be rolling with the second hands phase offset but thats later...
Tones 2,3,4 will do a phase jump, but shall not be interrupted. phase jumps can be at 1 to 4Hz. phase jumps are like the ticking of a clocks hands.
 
You could use the RTC that's built into Teensy 3.2. All that's needed it adding a 32.768 kHz crystal, and a 3V coin cell if you want it to keep time while main power is off.
 
I've made the experiment. Two frequencies, 400.0 Hz and 400.0166 Hz, the phase relation needs 60 seconds to turn 360°, smoothly without jumps, which would make a beautiful seconds hand.
View attachment 21369
Last night's calculation was offset by wine... :eek: sorry
 
Two frequencies, 400.0 Hz and 400.0166 Hz

Wow, those are really close. The difference in waveform period is only 100ns! Using elapsedMicros won't work.

So I tried an experiment with the cycle counter. Here's the code.

Code:
const uint32_t cycles_per_toggle1 = (double)(F_CPU / 2) / 400.000L + 0.49L;
const uint32_t cycles_per_toggle2 = (double)(F_CPU / 2) / 400.016L + 0.49L;
uint32_t last_toggle1 = 0;
uint32_t last_toggle2 = 0;

void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  while (!Serial && millis() < 2500) ; //wait
  Serial.println("400.000 and 400.016 Hz Test");
  Serial.println("---------------------------");
  Serial.printf("  400.000 Hz needs %u cycles per toggle\n", cycles_per_toggle1);
  Serial.printf("  400.016 Hz needs %u cycles per toggle\n", cycles_per_toggle2);
  // start both pins LOW
  digitalWriteFast(2, LOW);
  digitalWriteFast(3, LOW);
  ARM_DEMCR |= ARM_DEMCR_TRCENA;
  ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
  last_toggle1 = ARM_DWT_CYCCNT;
  last_toggle2 = last_toggle1;
}

void loop() {
  uint32_t counter = ARM_DWT_CYCCNT;
  if (counter - last_toggle1 > cycles_per_toggle1) {
    last_toggle1 += cycles_per_toggle1;
    digitalToggleFast(2);
  }
  if (counter - last_toggle2 > cycles_per_toggle2) {
    last_toggle2 += cycles_per_toggle2;
    digitalToggleFast(3);
  }
  //Serial.println(counter);
}
 
On Teensy 3.2 the time difference to toggle the pin is only 5 CPU cycles.

Code:
400.000 and 400.016 Hz Test
---------------------------
  400.000 Hz needs 120000 cycles per toggle
  400.016 Hz needs 119995 cycles per toggle

The results aren't wonderful. Here's what my frequency counter measures on the 2 pins.

DSC_0992_web.jpg

DSC_0993_web.jpg
 
Teensy 4.0 does much better. But even at 600 MHz, the difference in time to toggle the pins is only 30 cycles.

Code:
400.000 and 400.016 Hz Test
---------------------------
  400.000 Hz needs 750000 cycles per toggle
  400.016 Hz needs 749970 cycles per toggle

DSC_0991_web.jpg

DSC_0990_web.jpg
 
Given that it is driving a mechanical system, the requirement to have the phase change smoothly by 'x' ns every single cycle isn't real -- it just requires that the average does this.

It still does require that the 2nd frequency cycle through 360 deg every minute -- so the frequency is (400Hz*60+1)/60 = 400 + 1/60 = 400.01667 Hz -- or (as Paul says) 100 ns step AVERAGE per cycle.

So, you could do a step of 1 us every 10 cycles, or 100 us every 100 cycles etc. There is no harm in trying to achieve 100ns/cycle, but as long as errors don't accumulate, the average is all that really matters in a mechanical system like this.I think Paul's code will correctly deliver the phase shift on average -- which is all that is required.

p.s. the code above doesn't work on a Teensy_LC; perhaps some of the ARM constants are not defined.
 
Last edited:
Teensy LC (actually Cortex M0+) lacks the cycle counter hardware.

You could try to get something system from the SysTick timer. But it's currently used for millis(), so reprogramming it with a longer count duration will break most of the Arduino timing functions.
 
Where did digitalToggleFast() come from ? I can't even find it on Google. What other useful functions am I missing ?
 
Where did digitalToggleFast() come from ? I can't even find it on Google. What other useful functions am I missing ?

It was just added. Processor has native support for doing that - it was just formalized in last release of two of TeensyDuino - see I saw it exists on some other boards as well. But if it is standard - it is very new.
 
No, the change of phase does not have to be exact every cycle of the frequency. If generating constant frequencies, this just happens automatically.
The more stable the frequency, the more silent the instrument, more exact the display, the less stress on mechanics, the less power consumption.

Also, the mechanical system can oscillate, can be stressed by repetitive abrupt actions. So in my humble opinion it would be much better to just go the frequency way.
For simplicity, I'd just phase sync every 30 seconds or 180°, because this is more easily accomplished. With stable frequencies, originating from the same master clock, like they do here, the nonlinearity errors would not be noticable and it would have built-in time sync ability with whatever source, be it GPS, etc.
 
One could use a double or a "long long bin 32" fixed point for the period and counter - but this only reduces, not eliminates error accumulation.

So +1 on resetting the counters to be in perfect sync with each other and the real-time clock every 30 seconds.
 
Status
Not open for further replies.
Back
Top