#include <Nextion.h>
#include <SoftwareSerial.h>
// Tempreture constants
// Motor Temp ???
#define THERMISTORPIN A3 // which analog pin to connect
#define THERMISTORNOMINAL 15000 // resistance at 25 degrees C
#define TEMPERATURENOMINAL 25 // temp. for nominal resistance (almost always 25 C)
#define BCOEFFICIENT 3950 // The beta coefficient of the thermistor (usually 3000-4000)
#define SERIESRESISTOR 9950 // the value of the 'other' resistor
// Controller Temp
#define THERMISTORPIN2 A4 // anlog pin for controller temp
#define THERMISTORNOMINAL2 10000 // resisatance at 25 deg C for controller
#define TEMPERATURENOMINAL2 25 // temp. for second therminstor resistance
#define BCOEFFICIENT2 3950 // Teh bete coefficient for therminstor 2
#define SERIESRESISTOR2 9950 // the value for the second other resistor
// Pin constants
#define PACKVOLTPIN A0 // pack voltage sensor
#define PREVOLTPIN A1 // system voltage sensor
#define SYSVOLTPIN A2 // precharge voltage sensor
#define AMPPIN A5 // current sensor
#define SPEEDPIN 2 // The pin the encoder is connected
#define CONTACTORPIN 12 // control the contactor
// Vehicle Constants
//Battery
#define HIGHVOLT 480 // Maximum pack voltage
#define LOWVOLT 340 // minimum pack voltage
#define PRECHARGEPERCENT 0.95 // precharge complete percentage
//Speed
#define PULSEPERROT 4.8 // pulses per rotation of speed sensor
#define WHEELCIRC .1835 // circumference of wheel in meters
// Smoothing Constants // filter co-efficient valid range 0 -> 1 0 = infinite filtering 1 = no filtering
#define FILTER_BATTERY 0.1
#define FILTER_SPEED 0.4
#define FILTER_TEMP 0.1
// display variables
SoftwareSerial nextion(10, 11); // Nextion TX to pin 2 and RX to pin 3 of Arduino
Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps
// Interrupt variables
volatile byte pulses = 0;
// normal variables
int kmh = 0; // speed reading
float PrechargeVolt=0, SystemVolt=0, BatteryAmp=0, PackVolt=0, tempMotor=0, tempController=0, KW=0;
unsigned long timeold;
unsigned long millisecsPerHour = 3600000;
/*
* Setup function...
* start serial devices and dash
* set pinmodes
* attach interrupts
* set start timer
*/
void setup() {
Serial.begin(9600); // initialize serial communication at 9600 bits per second:
myNextion.init();
pinMode(CONTACTORPIN, OUTPUT); //
digitalWrite(CONTACTORPIN, LOW); //Makes contactor outout LOW initially (zero)
//Use statusPin to flash along with interrupts
pinMode(SPEEDPIN, INPUT_PULLUP); // using INPUT_PULLUP means no need for a external pullup resisitor.
//Interrupt 0 is digital pin 2, so that is where the IR detector is connected
attachInterrupt(0, irspeed, FALLING); // change to falling as standard state is high
timeold = millis();
}
/*
* Interrupt handling
*/
void irspeed()
{
//Update count
pulses++;
}
/*
* Main loop really simple and easy to follow
*/
void loop()
{
readVehicle();
updateDash();
}
/*
* Get the values from all the sensors and calculate the "real" values
*/
void readVehicle(void)
{
int calc = 0;
// Read battery information
PackVolt = (analogRead(PACKVOLTPIN)/2.048); //Outputs values from 0-1023, so 2.048 will make the maximum voltage 500V. Set appropriate voltage divider!
PrechargeVolt = (analogRead(PREVOLTPIN)/2.048); //Outputs values from 0-1023, so 2.048 will make the maximum voltage 500V. Set appropriate voltage divider!
SystemVolt = (analogRead(SYSVOLTPIN)/47.34); //Outputs values from 0-1023 so 63.94 is 16v with a 5v input
BatteryAmp = BatteryAmp + FILTER_BATTERY*((analogRead(AMPPIN)*1.710655-890) - BatteryAmp); // Bidirectional current sensor 2.5v at middle
KW = (BatteryAmp*PrechargeVolt/1000);
// Enable the contactor if the pack and precharge are ok
if (PackVolt > LOWVOLT && PackVolt < HIGHVOLT // pack voltage within correct parameters
&& PackVolt * PRECHARGEPERCENT <= PrechargeVolt) // 95% precharge, change 0.95 to whatever to get you want your precharge to be
{
digitalWrite(CONTACTORPIN, HIGH);
}
// calculate speed
if (millis() - timeold >= 100)
{
detachInterrupt(0);
kmh = (WHEELCIRC / 1000 * (pulses/PULSEPERROT)) * millisecsPerHour / (millis() - timeold); // raw calculation
kmh = kmh + FILTER_SPEED*(calc -kmh); // filtered speed
timeold = millis();
pulses = 0;
attachInterrupt(0, irspeed, FALLING);
}
// read and calculate tempretures
tempMotor = tempMotor + FILTER_TEMP * (readThermistor(THERMISTORPIN, THERMISTORNOMINAL, TEMPERATURENOMINAL,
BCOEFFICIENT, SERIESRESISTOR) - tempMotor); // filtered read
tempController = tempController + FILTER_TEMP * (readThermistor(THERMISTORPIN2, THERMISTORNOMINAL2,TEMPERATURENOMINAL2,
BCOEFFICIENT2, SERIESRESISTOR2) - tempController); // filtered read
//Write it out to serial port
Serial.print("Speed: ");
Serial.println(kmh, DEC);
Serial.print("Temperature 1 ");
Serial.print(tempMotor);
Serial.println(" *C");
Serial.print("Temperature 2 ");
Serial.print(tempController);
Serial.println(" *C");
}
/*
* Update the display with all the values
* ALL logic around display including calculations are here
*/
void updateDash(void)
{
int displayKMH, displayAMPS;
displayKMH = kmh*1.25;
if(displayKMH<60) displayKMH += 300 ;
else displayKMH -= 60; // get the needle to start at 0 which is 300 deg in nextion
displayAMPS = (BatteryAmp+100)/2.8676470;
if(displayAMPS<66) displayAMPS = 295 + displayAMPS;
else displayAMPS = displayAMPS - 66;
myNextion.setComponentValue("n4", tempMotor);
myNextion.setComponentText("t12", String(PrechargeVolt)); // update text using original sensor value
myNextion.setComponentValue("z2", displayKMH);
myNextion.setComponentText("t13", String(SystemVolt)); //12v battery gauge
myNextion.setComponentValue("n0", BatteryAmp);
myNextion.setComponentValue("n1", kmh);
myNextion.setComponentValue("n5", tempController);
myNextion.setComponentValue("n6", KW);
myNextion.setComponentValue("z1", displayAMPS);
}
/*
* Utility function to get the tempreture in degrees C from the thermister
*/
float readThermistor(int thermPin, int nomResistance, int nomTemp, int seriesRes, int bCoefficient)
{
float reading = 0;
reading = analogRead(thermPin);
// convert the value to resistance
reading = 1023 / reading - 1;
reading = seriesRes / reading;
float steinhart;
steinhart = reading / nomResistance; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= bCoefficient; // 1/B * ln(R/Ro)
steinhart += 1.0 / (nomTemp + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
return steinhart;
}