# Driving an Air Core Speedometer

There are some posts from more than two years ago on this subject, but I’d like to share my experience driving an MX5 air core speedometer using a UNO and an SN754410 H Bridge driver. The attached commented code is self explanatory. I’m using a potentiometer as a potential divider into A1. You don’t need the value of pi, just scale the 1024 bits of the analogRead value to 2 x pi by dividing by 163. In my case, the speedometer only uses three quadrants so I divide by 220 instead to get three quadrants from potentiometer full scale.

Next step, to sniff the speed from a sensor on the propshaft!

Hope someone finds this useful.

Speedo code.txt (2.17 KB)

Just realised, I tried to attach the code as an attachment, but now realise there is a better way!

``````double cosine = 0;  // the value to drive the enable pin for the cosine coil
double sine = 0;    // the value to drive the enable pin for the sine coil
float pot = 0;  // Using a pot to adjust the speed. Needs to be a float variable for angle maths

int sine_plus = 6;
int sine_minus = 10;
int cosine_plus = 4;
int cosine_minus = 2;

// the enable pins for the two coils, driven with PWM signal proportional to sine and cosine respectively
int sine_drive = 5;
int cosine_drive = 3;

double lastmillis = 0;  // Used to check the cycle time
double thismillis = 0;

void setup() {
// put your setup code here, to run once:

Serial.begin(9600);

pinMode(cosine_drive, OUTPUT); // Enable Cosine
pinMode(sine_drive, OUTPUT); // Enable Sine

pinMode(cosine_minus, OUTPUT);
pinMode(cosine_plus, OUTPUT);
pinMode(sine_plus, OUTPUT);
pinMode(sine_minus, OUTPUT);
}

void loop() {

delay(50);  // small delay each cycle to simulate propshaft sensor routine

pot = analogRead(A1);       // centre tap of potentiometer into A1
sine = 255 * sin(pot / 220); // for four quadrants the divisor would be 163 instead of 220
cosine = 255 * cos(pot / 220); // but my meter only uses three quadrants up to 150mph so scaled accordingly

// Just to see what's going on
Serial.print(pot);
Serial.print("\t");
Serial.print(sine);
Serial.print("\t");
Serial.print(cosine);
Serial.print("\t");
thismillis = millis();
Serial.println(thismillis - lastmillis);
lastmillis = thismillis;

if (sine >= 0) {
digitalWrite(sine_minus, LOW); // 1
digitalWrite(sine_plus, HIGH);
analogWrite(sine_drive, sine);
}
else {
// reverse polarity
digitalWrite(sine_plus, LOW); // 1
digitalWrite(sine_minus, HIGH);
analogWrite(sine_drive, -sine);
}

if (cosine >= 0) {
digitalWrite(cosine_minus, LOW); // 1
digitalWrite(cosine_plus, HIGH);
analogWrite(cosine_drive, cosine);
}
else {
// reverse polarity
digitalWrite(cosine_plus, LOW); // 1
digitalWrite(cosine_minus, HIGH);
analogWrite(cosine_drive, -cosine);
}
}
``````

Driving a Air Core Aviation Heading Gauge

Hi,
based on a older solution from https://forum.arduino.cc/index.php/topic,22480.0.html i made my own version for a Collins HDG gauge. It is connected just with 2 resistors. No other hardware is required.
Hope it might be useful for someone.

``````/* Arduino controls AIRCORE Gauge. E.Staebler 0621
* based on:
* https://forum.arduino.cc/index.php/topic,22480.0.html
*
* In this version no floating sine calculation is used.
* A 90 degrees lookuptable in byte-resolution directly to feed the 8Bit PWM/DAC is used instead.
*
* Define the pins the meter is connected to. We need 1 PWM to vary the voltage in
* each coil, and one more to reverse the polarity in that coil. So a total of 4 pins.
*/

#include <avr/pgmspace.h>
___
#define SinDirPin    7         // --|___|-- 560R to Sub-D-5 this controls the polarity to the "sine" coil
___
#define CosDirPin    8         // --|___|-- 560R to Sub-D-1 this controls the polarity to the "cosine" coil

#define SinPin       9         // to Sub-D 2 this controls the voltage to the "sine" coil (PWM)
#define CosPin       10        // to Sub-D-4 this controls the voltage to the "cosine" coil (PWM)

// if scale is 180° shifted, wire:  Arduino  7 to Sub-D 2
Arduino  8 to Sub-D 4
Arduino  9 to Sub-D 5
Arduino 10 to Sub-D 1

int delayTime = 50;                             // milliseconds between each angular step.

// Sinustabelle 1.Quadrant 90 Werte 0-89° in 8 Bit Auflösung
const PROGMEM uint8_t Sine_Lookup[90] =         // DAC/PWM Lookuptable 0-89 degrees Sine in 8 bit resolution
{
0,  4,  9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66,
70, 75, 79, 83, 87, 91, 96,100,104,108,112,116,120,124,127,131,
135,139,143,146,150,153,157,160,164,167,171,174,177,180,183,186,
190,192,195,198,201,204,206,209,211,214,216,219,221,223,225,227,
229,231,233,235,236,238,240,241,243,244,245,246,247,248,249,250,
251,252,253,253,254,254,254,255,255,255
};

void setup(){
Serial.begin(115200);              // for debugging or remote-setting
pinMode(SinPin,       OUTPUT);     // Set the pins to OUTPUT
pinMode(CosPin,       OUTPUT);
pinMode(SinDirPin,    OUTPUT);
pinMode(CosDirPin,    OUTPUT);
digitalWrite(SinDirPin, HIGH);     // Set the initial direction. (forward).
digitalWrite(CosDirPin, HIGH);     // Of course it could be "reverse" depending on which lead you connected :-).

// Vary the PWM-Frequency if noise is annoying   (Pin D9+D10)
// TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to 1 for PWM frequency of 31372.55 Hz
TCCR1B = TCCR1B & B11111000 | B00000010;     // for PWM frequency of 3921.16 Hz
// TCCR1B = TCCR1B & B11111000 | B00000011;    // for PWM frequency of 490.20 Hz (The DEFAULT)
// TCCR1B = TCCR1B & B11111000 | B00000100;    // for PWM frequency of 122.55 Hz
// TCCR1B = TCCR1B & B11111000 | B00000101;    // for PWM frequency of 30.64 Hz
}

void loop() {                                   // Run over and over again
for(int y = 0; y < 360; y++){                  // Rotate 0 through 360 degrees (in degrees!)
setMeterPosition(y);
delay(delayTime);                            // waits for delayTime milliseconds
}
}

void setMeterPosition(int pos){                 // setMeterPosition() - put it at the angle in radians
int  sinCoilValue;
int  cosCoilValue;

*             Sin        Cos
*   0 -  89   + ->       + <-
*  90 - 179   + <-       - ->
* 180 - 269   - ->       - <-
* 270 - 359   - <-       + ->
*/

while (pos>359) pos-=360;                                  // while pos>359 subtract 360. just in case ...

if (pos>=270) {                                            // 4. Quadrant 270-359
digitalWrite(SinDirPin, HIGH);                           // reverse. SinDirPin
digitalWrite(CosDirPin, LOW);                            // neg. CosDirPin
}
else if (pos>=180) {                                       // 3. Quadrant 180-269
digitalWrite(SinDirPin, HIGH);                           // reverse SinDirPin
digitalWrite(CosDirPin, HIGH);                           // reverse CosDirPin
}
else if (pos>=90) {                                        // 2. Quadrant 90-179
digitalWrite(SinDirPin, LOW);                            // neg. SinDirPin
digitalWrite(CosDirPin, HIGH);                           // reverse CosDirPin
}
else {                                                     // 1. Quadrant 0-89
digitalWrite(SinDirPin, LOW);                            // neg. SinDirPin
digitalWrite(CosDirPin, LOW);                            // neg. CosDirPin
}

/*
Serial.print(pos);
Serial.print(":  sinCoilValue: ");                         // Debug
Serial.print(sinCoilValue);
Serial.print("  cosCoilValue: ");
Serial.println(cosCoilValue);
*/

analogWrite(SinPin, sinCoilValue);                         // set the PWM-Values
analogWrite(CosPin, cosCoilValue);
}
``````

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.