Re: Build a New Set of Gauges from Scratch - reading sensors
I found by checking resistance that my old engine temperature sensor was way, way off in resistance, Cold it read 2,000 ohms, and 5,000 ohms hot, instead of the 400 ohms cold down to 9 ohms hot.
I bought a new one from O'Reilly's for 7 bucks. If you have gauge trouble, this is the easiest place to check.
Since a careful check of sensors revealed a problem that would have stopped the train, I think I should go along more carefully in proving out the design of an Arduino reading existing OEM sensors and displaying readings on a liquid crystal display.
To start, I check out the Arduino against the Apple Macbook Air that will be mobile with the Jeep before the final hard-wire install. Using KISS, I run the very most simple software routine there is, to blink a small LED under program control. Looking at the top of an Arduino Uno, you can see a very small resistor just between the GND label and digital pin13. Right below the resistor and showing the letter "L" to the left is and LED.
Over on the right under the UNO word is the power monitor LED. If this goes off, we're in a heap of trouble. To make LED13 blink, we need a SKETCH (remember, that just means "program") like this one:
/*program BLINK.ino
Successful 23 June 2013
*/
#include "Arduino.h";
int ledPin13 = 13; //This is the on-board LED pin but can be used for anything.
void setup() {
// put your setup code here, to run once:
pinMode(ledPin13, OUTPUT); // LEDpin13 now set to OUTPUT
}
// our buddy void tells us he expects nothing back, just an endless loop.
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(ledPin13, HIGH); //setting LEDPin13 HIGH turns it on.
delay(1000); //Arduino counts in milliseconds... this is one second
digitalWrite(ledPin13, LOW); //Set LEDPin13 low
delay(2000); //Leave the LED off for two seconds then loop to the top
}
You can read this sketch like a cookbook recipe. Then you can copy everything between the top /* symbol and the bottom curly brace } and PASTE all into the Arduino IDE. The Left icon showing a check mark checks our sketch for errors. The next icon, a right arrow, UPLOADS the program to an on-board memory region in the Arduino. Once a sketch is successfully checked and loaded, you no longer need the USB cable to a computer. With power on, the Arduino will run this sketch and if turned OFF and back ON will still have this sketch running once power is restored.
In another simple test to help find your way around an Arduino and its sketches, we can plug in an LED like the one pictured.
In this test, plug the short leg or cathode into the GND pin slot, slot #2 in the row along the edge of the Arduino nearest the LEDPin13 blinker. The long leg of the LED, the positive wire or anode, goes to LEDPin13. Now run the Blink sketch again to see the inserted LED blink.
There are hundreds of these trivial yet re-enforcing building-block exercises across the globe of the 'Net.
Using an Arduino to display Jeep gauge data is not much more difficult than the blink demonstration. You know that each gauge is fed by a sensor, a variable resistor that changes its resistance to the passage of electrical current depending on heat, or a fuel wiper level in the fuel tank along wound resistor, or even the pressure exerted by oil pressure. Each sensor has a ground, a variable resistance, and a power source. But Arduino reads voltage, not resistance or current. How to we change the circuit to show a voltage that varies when resistance changes?
That is pie-easy! We use two resistors, not just one, One of these resistors is the sensor resistor in usually our engine or fuel tank. The other we stick into the circuit to make a voltage-splitter.
Here above is a representative voltage-splitter for demonstrating fuel level reading. Five volts from the Arduino 5V power pin plugs to A. Circuit ground plugs to C. We pick off the voltage in the middle of these two resistors at B, and expect the voltage at B to be half the total circuit voltage, since the resistors are identical and share equally the current that flows from A to C.
We've connected the pick-off point at B to Pin A0 on our Arduino. This is an analog pin, and only receives data, doesn't control anything. When we run a sketch to read data from A0 and display it on the Serial Monitor, we see the following:
But 1019 doesn't mean full tank to me; I want to have useful information, not just data from which I can't glean anything useful. If I subtract 1008 from each reading, I get 15, a number equivalent to the full tank I now have in my Jeep. If B to C was the variable wiper resistor in our fuel tanks, as the resistance drops between C and B, the voltage at pickoff point B would drop proportionately, and both our displayed number and the actual fuel remaining in the tank would drop. When we simulate this with a potentiometer, just another fancy name for a variable resistor, here are the numbers we would hope to see:
Fuel Quantity
15
Fuel Quantity
15
Fuel Quantity
15
Fuel Quantity
13
Fuel Quantity
10
Fuel Quantity
8
Fuel Quantity
6
Fuel Quantity
5
Fuel Quantity
4
Fuel Quantity
3
Fuel Quantity
2
Fuel Quantity
1
Fuel Quantity
0
Fuel Quantity
0
Here is the sketch that returned these data points:
/*
Arduino - AnalogInput
*/
int sensorPin = A0; // select the input pin for the potentiometer
int ledPin = 13; // select the pin for the LED
int sensorValue = 0; // variable to store the value coming from the sensor
void setup() {
Serial.begin(9600);
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
// turn the ledPin on
digitalWrite(ledPin, HIGH);
// stop the program for <sensorValue> milliseconds:
delay(sensorValue);
// turn the ledPin off:
digitalWrite(ledPin, LOW);
// stop the program for for <sensorValue> milliseconds:
Serial.println("Fuel Quantity");
Serial.println(sensorValue-1008); //subtract this constant to get the number of gallons in my polyplastic 15Gal,
delay(sensorValue);
}
So far I've been displaying all data on the Serial Monitor. To get the 20X2 LCD to work, I must load the Liquid Crystal library. To do that, I download the liquidcrystal library, usually as a ZIP, from
Arduino Playground Download
I usually download to the Arduino Library and unzip it; On the Arduino IDE use these commands:
Sketch
Import Library
LiquidCrystal
The wiring is a bit tricky the first time, but once any kinks are ironed out, here is what you should see:
And here is the Sketch that produces this display:
//FuelQuan15Gallons
#include <LiquidCrystal.h>
/*
Analog Input
Demonstrates analog input by reading an analog sensor on analog pin 0 and
turning on and off a light emitting diode(LED) connected to digital pin 13.
The amount of time the LED will be on and off depends on
the value obtained by analogRead().
The circuit:
If you've changed the pins, you'll want to make a handy table so you can update the sketch properly.
LCD pin name RS EN DB4 DB5 DB6 DB7
Arduino pin # 7 8 9 10 11 12
The circuit:
* LCD RS pin to digital pin 7
* LCD Enable pin to digital pin 8
* LCD D4 pin to digital pin 9
* LCD D5 pin to digital pin 10
* LCD D6 pin to digital pin 11
* LCD D7 pin to digital pin 12
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
* Note: because most Arduinos have a built-in LED attached
to pin 13 on the board, the LED is optional.
Created by David Cuartielles
modified 30 Aug 2011
By Tom Igoe
This example code is in the public domain.
Arduino - AnalogInput
*/
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
const int sensorPin = A0;
int ledPin = 13; // select the pin for the LED
int sensorValue = 0; // variable to store the value coming from the sensor
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD in the first row.
lcd.print("Fuel Quantity");
Serial.begin(9600);
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
// turn the ledPin on
digitalWrite(ledPin, HIGH);
// stop the program for <sensorValue> milliseconds:
delay(sensorValue);
// turn the ledPin off:
digitalWrite(ledPin, LOW);
// stop the program for for <sensorValue> milliseconds:
Serial.println("Fuel Quantity"); //refresh the text in Row1 of the LCD
Serial.println(sensorValue-1008); //Adjust the sensor value to equal 15 Gallons
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the adjusted value for a full tank
lcd.print(sensorValue-1008);
lcd.println(" Gallons ");
delay(sensorValue);
}
If you've kept your place in the choir book as the pages were turned, you should in reading the above sketch see some old familiar friends.
We've gone from the very most basic function of the Arduino through LED hookup and voltage splitters. We've worked over a voltage splitter as a simulated fuel tank and gotten a sense of how we have to wire up our Arduino into the Jeep circuitry with an extra resistor to enable the Arduino to "see' the data we want. Lastly, the final hurdle of hooking up a 20X2 LCD and displaying lines of text and numbers has been touched on. The next step is to walk the entire shooting match out to my
CJ7 , hook it up, and see what surprises the Real World has in store for us.