non linear compensation

i use my arduino mega 1280 to turn on and off lights on a dashboard of a computer bus simulator, and also to position the needles on the gauges,

The gauges are standard automotive air core motor type gauges, 3 terminals on the back, + 24 volts in, earth and sender connection,
in the vehicle the sender would be a float level sensor for the fuel tank and thermistor type sensor for the water temp. usual range of 0 to 180 ohms (0 being FSD, 180 ohms being needle at the bottom) there is also an oil pressure gauge, the senders range the same but reversed, to 180 - 0 ohms, 0 ohms = FSD.

The sender connection of a gauge is connected to the collector of a NPN transistor, it's emitter connected to earth (and tied between the arduino and 24 volt power supply to the gauges) and the base of the transistor goes via a 1k resistor to an arduino PWM pin,

To move the needle the PWM output is varied,

This all works, BUT the gauges are not linear, and the output from the simulator is, i.e. if the simulators fuel gauge needle is pointing to half way, it sends out 50, if it's at 3/4, 75, and so on.
The arduino gets this data over the serial port, then translates the 0 - 100 inputs to 8 bit PWM output 0-255 steps,

But the real gauge's don't display that properly, as the scale is non linear and hence the needles move different amounts in the lower or upper half of the sweep.

The water temp gauge is the worst, on the dial you can easily see the non linearity,
The distance between the centres of the markings measured from the attached picture, re-sized to the exact real life size of 65mm diameter then measured in a drawing program:
50 to 60 = 3.7mm
60 to 70 = 5.5mm
70 to 80 = 8.3mm
80 to 90 = 9.5mm
90 to 100 = 9.5mm
100 to last marking = 6.2mm

The numbers represent degrees centigrade (they are from a European bus)

So when i run a sweeping PWM script on the arduino just running 0 - 255 - 0 and repeat, running the sweep very slowly you can clearly see the steps the needle moves in in the upper half of the dial, but below 80 the steps get smaller and smaller,
so running the sweep at a faster speed, it takes about 4 to 5 times as long for the needle to travel from 80 down to 50, as it does to travel from the top mark to 80.

The fuel gauge is kind of similar except the other way round, needle moves larger steps in the lower half, smaller steps in the upper half.

Annoyingly the oil pressure gauge is linear, the markings being spaced evenly and the needle making the same size steps throught the needle sweep.

Sorry for the long winded description, wanted to make sure i explained it properly,
so, i need to add some maths type stuff to the arduino script to alter the PWM steps depending on which part of the scale the needle is pointing in,

Maths is my absolute weakest subject, with programming not much stronger :slight_smile: but i can usually get scripts to do what i want eventually with help.

What kinds of things to i need to be looking at to fix my problem?
i imagine the way to do it is to make the PWM signal move multiple steps at the lower range for every one input movement step from the simulator.

Please be simple with me, i can imagine the code to be something along the lines of :
if input less than 15, output xx steps per input step,
if input between 15 and 30, output xx steps per input step, and so on until the largest distance between markings where 1 in = 1 out step,

The fuel gauge only has 5 markings, the distance between 1/2 - 3/4 - full being about equal, and empty to 1/4 being about half the distance as 1/4 to 1/2,

water temp dial.jpg

http://playground.arduino.cc/Main/MultiMap

This might help.

If you have 0-99 steps on "input", then you could use a lookup table to output a value to make the gauge needle point anywhere you want. This could be done with a 100 entry table, but then you have to fill in 100 values. It would be easier to reduce the 0-99 scale to (for example) 0-19. Then a 20 element table might be declared like this:

char output[] = {0, 20, 45, 70, ... ,255}; //20 values total completely up to you

or to make the needle move in the reverse direction:

char output[] = {255, 220, ... , 0};

Divide "input" by 5 to get the table index, a number between 0 and 19.

no, not smoothing the pwm at all, for now, want to get the needles of the real gauges following the simulated gauges first,

I believe the non linearity is built into the gauges, so it makes the important area of the scale more obvious to changes.... with the fuel gauge it moves faster and more visibly at the bottom... where you are likely to run out of fuel, and the water temp gauge, it shows larger steps in the 80 to 100 degree range, as thats the normal operating to overheating range,

I'm looking at the lookup table thing now, as that seems to be the way to sort this,