winstonusmc Posted September 20, 2015 Share Posted September 20, 2015 Been working on some arduino integration into my Z for a little while. I have come with the idea of using an Arduino micro controller to give me a level of calibration to the gauges and give the ability to have warning lights that more modern cars have. I also want to broadcast the values on a sort of CANBUS to interact with other systems. I purchased a oil and temp gauge on eBay to mess with. I was going to try to repurpose it as a boost and afr gauge, but the bi-metal strips are not near fast enough to keep up with a boost or afr signal. starting out I have coded warning lights on both the oil and temp gauge. I havent designed a circuit yet for either sensors though. Still just playing around with it for now. I have ordered a few Arduino Pro Minis to mount on custom printed boards that will run the gauges. Quote Link to comment Share on other sites More sharing options...
winstonusmc Posted September 20, 2015 Author Share Posted September 20, 2015 const int tempPin = A0; const int batteryPin = A1; const int oilPin = A2; const int tempOutput = 9; const int oilOutput = 10; const int tempLed = 12; const int oilLed = 13; int oilPressure = 0; int coolantTemp = 0; float sourceVoltage = 0.00; void setup() { Serial.begin(9600); pinMode(tempLed, OUTPUT); pinMode(oilLed, OUTPUT); } void loop() { batteryVoltage(); tempGauge(); //oilGauge(); // print the results to the serial monitor: Serial.print(" "); Serial.print(sourceVoltage); Serial.print("V"); Serial.print(" "); Serial.print(coolantTemp); Serial.print("*F"); Serial.print(" "); Serial.print(oilPressure); Serial.println("psi"); delay(100); } void batteryVoltage() { sourceVoltage = analogRead(batteryPin) * 0.0198817038; } void tempGauge() { // gauge variables const int sensorCalMin = 0; //minimum sensor value const int sensorCalMax = 1023; //maximum sensor value const int valueMin = 15; //gauge value at 120* const int valueMax = 88; //gauge value at 250* const int warning = 220; // warning level value int tempSensor = 0; int outputValue = 0; tempSensor = analogRead(tempPin); // read the analog in value: coolantTemp = map(tempSensor, sensorCalMin, sensorCalMax, 0.00, 300.00); //calibration of temp sensor outputValue = map(coolantTemp, 120, 250, valueMin, valueMax); //calibration of temp gauge outputValue = constrain(outputValue, 0, 100); //Gauge limits analogWrite(tempOutput, outputValue); if (coolantTemp >= (warning)) // Low warning light { digitalWrite(tempLed, HIGH); } if (coolantTemp <= (warning - 5)) //Hysteresis for light off { digitalWrite(tempLed, LOW); } //Serial for DeBug //Serial.print(" Temp Sensor Value = "); //Serial.print(tempSensor); //Serial.print(" output = "); //Serial.print(outputValue); } void oilGauge() { // gauge variables const int sensorCalMin = 0; //minimum sensor value const int sensorCalMax = 1023; //maximum sensor value const int valueMin = 41; //gauge value at 0psi const int valueMax = 115; //gauge value at 90psi const int warning = 15; // warning level value int oilSensor = 0; int outputValue = 0; // read the analog in value: oilSensor = analogRead(oilPin); // map it to the range of the analog out: oilPressure = map(oilSensor, sensorCalMin, sensorCalMax, 0, 90); outputValue = map(oilPressure, 0, 90, valueMin, valueMin); outputValue = constrain(outputValue, 0, 120); //Gauge limits analogWrite(oilOutput, outputValue); if (oilPressure <= (warning)) // Low warning light { digitalWrite(oilLed, HIGH); } if (oilPressure >= (warning + 3)) //Hysteresis for light off { digitalWrite(oilLed, LOW); } } The code, feel free to critique. I am very new to coding, so I am open to suggestions. Quote Link to comment Share on other sites More sharing options...
BLOZ UP Posted September 22, 2015 Share Posted September 22, 2015 Looks good to me. Did you consider replacing the needle moving mechanism with a stepper? Or is this to retain stock gauges without any modifications? Logic looks fine to me. Only things I would do are just some convenience and code reducing changes: Move and rename const ints out of methods into global namespace (or whatever it is in processing), eg. oilPressureMax, etc. Generalize the hysteresis idiom into a function (could also use an 'else' clause in front of the second if statement, but that's minor) Generalize the gauge setting into a function, eg. 'setGauge(oilOutput, sensorData, gaugeData)' or something like that. Quote Link to comment Share on other sites More sharing options...
Midri Posted September 23, 2015 Share Posted September 23, 2015 (edited) DON'T RUN 12V TO ANY OF YOUR PINS! If you're using one of the older Arduinos you can run up to 5v to those pins or 3.3v on the new Dues. You're going to fry that board if you're not using a voltage ladder to step the cars 0v-14v (yes 14v whilst running) down to 0v-5v You're also going to need to use a voltage doubler to get 0v-10v out of the 5v outputs on an older arduino or 2 doublers to get 13.2v out of the new boards outputs. One last thing, remember the amperage constraints of the Arduino, you've only got like 200mAh on all output pins combined with a 20mAh (they're rated for a max of 40mAh, but getting that much has been inconsistent for me) limit per pin. Those older gauges are going to suck that up like a sponge. You're not going to be able to work more than 2 or 3 gauges at once without building a more complex driver system (multi channel led driver would work) and many gauges might not work at all. Example: https://www.youtube.com/watch?v=uDFOjg54TyM -- His 6 modern gauges require about 600mAh to run all of them, that's about 100mAh per gauge... or 5x what is rated for the Arduino per pin and 3x the amount of total current the Arduino can output. Edited September 23, 2015 by Midri Quote Link to comment Share on other sites More sharing options...
winstonusmc Posted September 23, 2015 Author Share Posted September 23, 2015 Well if you look close, you will see a NPN transistor that has 12v on it and arduino is hooked into that. Those gauges wouldn't even move on 5v. Tried it with just the potentiometer on 5v. These gauges are crazy slow, so I am looking into alternatives for the third gauge hole, like a oled display. Quote Link to comment Share on other sites More sharing options...
Midri Posted September 23, 2015 Share Posted September 23, 2015 (edited) A transistor (I personally would use a MOSFET) will work for outputs I suppose if you use PWM drive them with 12v and gate them with 5v/3.3v, but your inputs to actually read the sensors from the engine are all going to be 12v so be careful. Edited September 23, 2015 by Midri Quote Link to comment Share on other sites More sharing options...
winstonusmc Posted September 23, 2015 Author Share Posted September 23, 2015 (edited) Working with megasquirt has shown me that a normal variable resistor type sensor like a temp sensor uses a 5v signal from the ECU in a voltage divider circuit the same way the Arduino would work. as long as I supply the voltage from the Arduino. In the Datsun gauges it is 12v, but the way I am going to tap into them will be similar to how an ECU does it. Edited September 23, 2015 by winstonusmc Quote Link to comment Share on other sites More sharing options...
winstonusmc Posted October 25, 2015 Author Share Posted October 25, 2015 (edited) More progress on the gauge setup. I have connected an Arduino to the CANBUS on my Megasquirt 3 to display things that the ECU knows. The whole idea is to run any gauges off of CAN that the ECU provides, like coolant temp, AFR, boost, even oil pressure. This way I simplify wiring and remove extra sensors on the engine. I have ordered an OLED display to insert into the gauge body and may upgrade to a high def color later. I have been working on coding to display the info from the CanBus on the Megasquirt this weekend and have setup a simple LCD displaying MAP and AFR to demonstrate the concept. Also the code is hosted on Github: https://github.com/winstonusmc/arduino/blob/master/arduino_megasquirt_afr_map_gauge #include <SPI.h> #include "mcp_can.h" #include <LiquidCrystal.h> LiquidCrystal lcd(9, 8, 7, 6, 5, 4); //raw readings int seconds = 0; int pw1 = 0; int pw2 = 0; int rpm = 0; int adv = 0; float afrtgt1 = 0.0; float baro = 0; float MAP = 0; float mat = 0; float clt = 0; int tps = 0; float bat = 1; float afr1 = 1; int cel_status = 0; unsigned long previousMillis = 0; unsigned char Flag_Recv = 0; unsigned char len = 0; unsigned char buf[8]; INT32U canId = 0x000; char str[20]; MCP_CAN CAN(10); // Set CS to pin 10 void setup() { Serial.begin(115200); lcd.begin(16, 2); lcd.setCursor(0,0); lcd.print("MAP "); lcd.setCursor(6,0); lcd.print("AFR"); CAN.begin(CAN_500KBPS); // init can bus : baudrate = 500k CAN.init_Mask(0,0,0x7ff); CAN.init_Mask(1,0,0x7ff); //CAN.init_Filt(0,0,0x5f0); //CAN.init_Filt(1,0,0x5f2); //CAN.init_Filt(2,0,0x5f3); //CAN.init_Filt(3,0,0x0); //CAN.init_Filt(4,0,0x0); //CAN.init_Filt(5,0,0x0); } void loop() { canRead(); //rpmSmoothing(); canDisplay(); } void canRead() { if(CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf switch (CAN.getCanId()) { case 0x5f0: seconds = word(buf[0] , buf[1]); pw1 = word(buf[2] , buf[3]); pw2 = word(buf[4] , buf[5]); rpm = word(buf[6] , buf[7]); break; case 0x5f1: // Group 1 adv = word(buf[0] , buf[1]); afrtgt1 = buf[4]; //mat = word(buf[4] , buf[5]); //clt = word(buf[6] , buf[7]); break; case 0x5f2: // Group 2 baro = word(buf[0] , buf[1]); MAP = word(buf[2] , buf[3]); mat = word(buf[4] , buf[5]); clt = word(buf[6] , buf[7]); break; case 0x5f3: // Group 3 tps = ((buf[0] * 256) + buf[1]); bat = ((buf[2] * 256) + buf[3]); afr1 = ((buf[4] * 256) + buf[5]); //afr2 = (((buf[6] *256) + buf[7]); break; } } } void canDisplay() { const int interval = 50; unsigned long currentMillis = millis(); //refresh rate if (currentMillis - previousMillis >= interval) { //if time elapsed is greater than the signal interval previousMillis = currentMillis; //then reset time // Display to LCD and Serial lcd.setCursor (0,1); lcd.print((MAP/10), 1); lcd.setCursor (6,1); lcd.print(afr1/10, 1); lcd.setCursor (10,1); lcd.print("/1"); Serial.print(" Snds "); Serial.print(seconds); Serial.print(" RPM "); Serial.print(rpm); Serial.print(" PW1 "); Serial.print(pw1/1000, 2); Serial.print(" ADV "); Serial.print(adv/10, 1); Serial.print(" AFRtgt "); Serial.print(afrtgt1/10, 1); Serial.print(" AFR "); Serial.print(afr1/10, 1); Serial.print(" MAP "); Serial.print(MAP/10, 1); Serial.print(" CLT "); Serial.print(clt/10, 1); Serial.print(" TPS "); Serial.print(tps/10); Serial.println(" "); } } Edited October 25, 2015 by winstonusmc Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.