hillzofvalp
100 kW
Luke, you would ditch all Leaf systems in doing that right...? Including the bms which I think limits to around 275A? I want to do the same it just sounds like a huge PITA. Please try! :wink:
that's what i'm talk'n about!Soon I will put the more powerfull IGBTs in and crank it up some more!
fechter said:I want to go for a ride!
Amazing what you've gotten that Leaf motor to do.
Arlo1 said:Thanks,
More to come. My brother wants to try the 100$ bill trick again... Lol So I will add 100 phase amps just to be safe.
But I do plan to drive it down the coast in time when I get charging sorted out. I have 8 meanwells on there now but thats only 3kw of charging so I need more charging for longer trips. I am working on my own charger but its quite challenging.
marcexec said:Will you fix the windsceen for the trip?![]()
(obviously just the jealousy talking here)
Can you tell us about your gauges? They look very good.Arlo1 said:Working on some gauges as well.![]()
XLR8 said:Can you tell us about your gauges? They look very good.Arlo1 said:Working on some gauges as well.![]()
#include <Nextion.h>
#include <SoftwareSerial.h>
// Tempreture constants
#define THERMISTORPIN A3 // which analog pin to connect
#define THERMISTORPIN2 A4 // anlog pin for controller temp
#define THERMISTORNOMINAL 15000 // resistance at 25 degrees C
#define THERMISTORNOMINAL2 10000 // resisatance at 25 deg C for controller
#define TEMPERATURENOMINAL 25 // temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL2 25 // temp. for second therminstor resistance
#define BCOEFFICIENT 3950 // The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT2 3950 // Teh bete coefficient for therminstor 2
#define SERIESRESISTOR 9950 // the value of the 'other' resistor
#define SERIESRESISTOR2 9950 // the value for the second other resistor
#define NUMSAMPLES 3 // how many samples to take and average, more takes longer but is more 'smooth'
#define SAMPLEDELAY 10 // how many millis to wait for new sample
// 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
#define HIGHVOLT 480 // Maximum pack voltage
#define LOWVOLT 340 // minimum pack voltage
#define PRECHARGEPERCENT 0.95 // precharge complete percentage
#define PULSEPERROT 4.8 // pulses per rotation of speed sensor
#define WHEELCIRC .1835 // circumference of wheel in meters
// display setup
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
int kmh2 = 0;
int Amp2 = 0;
float PrechargeVolt=0, SystemVolt=0, BatteryAmp=0, PackVolt=0, temp=0, temp2=0, KW=0;
unsigned long timeold;
unsigned long millisecsPerHour = 3600000;
unsigned int wheelcirc = .001835;
/*
* 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, RISING); // 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)
{
// Read voltages and currents
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 = (analogRead(AMPPIN)*1.710655-890); // Bidirectional current sensor 2.5v at middle
KW = (BatteryAmp*PrechargeVolt/1000);
Amp2 = (BatteryAmp+100)/2.8676470;
if(Amp2<66)
Amp2 = 295 + Amp2;
else
Amp2 = Amp2 - 66;
// 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);
}
if (millis() - timeold >= 100)
{
detachInterrupt(0);
kmh = (WHEELCIRC / 1000 * (pulses/PULSEPERROT)) * millisecsPerHour / (millis() - timeold);
timeold = millis();
pulses = 0;
attachInterrupt(0, irspeed, FALLING);
kmh2 = kmh*1.25;
if(kmh2<60)
kmh2 = 300 + kmh2;
else
kmh2 = kmh2 - 60; // get the needle to start at 0 which is 300 deg in nextion
}
//Write it out to serial port
Serial.print("Speed: ");
Serial.println(kmh, DEC);
temp = readThermistor();
temp2 = readThermistor2 ();
Serial.print("Temperature ");
Serial.print(temp);
Serial.println(" *C");
}
/*
* Update the display with all the values
*/
void updateDash(void)
{
int (speed[0]);
myNextion.setComponentValue("n4", temp);
myNextion.setComponentText("t12", String(PrechargeVolt)); // update text using original sensor value
myNextion.setComponentValue("z2", kmh2);
myNextion.setComponentText("t13", String(SystemVolt)); //12v battery gauge
myNextion.setComponentValue("n0", BatteryAmp);
myNextion.setComponentValue("n1", kmh);
myNextion.setComponentValue("n5", temp2);
myNextion.setComponentValue("n6", KW);
myNextion.setComponentValue("z1", Amp2);
}
/*
* Utility function to get the tempreture in degrees C from the thermister
*/
float readThermistor()
{
float reading = 0;
// take N samples in a row, with a slight delay
for (int i=0; i< NUMSAMPLES; i++) {
reading += analogRead(THERMISTORPIN);
delay(10);
}
reading /= NUMSAMPLES;
//Serial.println("Average analog reading ");
//Serial.println(reading);
// convert the value to resistance
reading = 1023 / reading - 1;
reading = SERIESRESISTOR / reading;
//Serial.print("Thermistor resistance ");
//Serial.println(reading);
float steinhart;
steinhart = reading / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
return steinhart;
}
/*
* Utility function to get the tempreture in degrees C from the thermister
*/
float readThermistor2()
{
float reading = 0;
// take N samples in a row, with a slight delay
for (int i=0; i< NUMSAMPLES; i++) {
reading += analogRead(THERMISTORPIN2);
delay(10);
}
reading /= NUMSAMPLES;
//Serial.println("Average analog reading ");
//Serial.println(reading);
// convert the value to resistance
reading = 1023 / reading - 1;
reading = SERIESRESISTOR2 / reading;
//Serial.print("Thermistor2 resistance ");
//Serial.println(reading);
float steinhart;
steinhart = reading / THERMISTORNOMINAL2; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT2; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL2 + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
return steinhart;
}
Lebowski said:You should add some digital filtering to stabilise the readings a bit.
Lets say the signal (or reading) you want to filter is x . Then
filtered_x = filtered_x + alpha * ( x - filtered_x )
here alpha determines how much filtering there is, valid range is between 0 and 1 with 0 being an infinite amount of filtering and 1 being no filtering.
I would start with alpha = 0.1 and then try some different values.
/* digitalSmooth
Paul Badger 2007
A digital smoothing filter for smoothing sensor jitter
This filter accepts one new piece of data each time through a loop, which the
filter inputs into a rolling array, replacing the oldest data with the latest reading.
The array is then transferred to another array, and that array is sorted from low to high.
Then the highest and lowest %15 of samples are thrown out. The remaining data is averaged
and the result is returned.
Every sensor used with the digitalSmooth function needs to have its own array to hold
the raw sensor values. This array is then passed to the function, for it's use.
This is done with the name of the array associated with the particular sensor.
*/
#define SensorPin1 0
#define SensorPin2 0
#define filterSamples 13 // filterSamples should be an odd number, no smaller than 3
int sensSmoothArray1 [filterSamples]; // array for holding raw sensor values for sensor1
int sensSmoothArray2 [filterSamples]; // array for holding raw sensor values for sensor2
int rawData1, smoothData1; // variables for sensor1 data
int rawData2, smoothData2; // variables for sensor2 data
void setup(){
Serial.begin(9600);
}
void loop(){ // test the digitalSmooth function
rawData1 = analogRead(SensorPin1); // read sensor 1
smoothData1 = digitalSmooth(rawData1, sensSmoothArray1); // every sensor you use with digitalSmooth needs its own array
Serial.print(rawData1);
Serial.print(" ");
Serial.println(smoothData1);
rawData2 = analogRead(SensorPin2); // read sensor 2
smoothData2 = digitalSmooth(rawData2, sensSmoothArray2); // every sensor you use with digitalSmooth needs its own array
}
int digitalSmooth(int rawIn, int *sensSmoothArray){ // "int *sensSmoothArray" passes an array to the function - the asterisk indicates the array name is a pointer
int j, k, temp, top, bottom;
long total;
static int i;
// static int raw[filterSamples];
static int sorted[filterSamples];
boolean done;
i = (i + 1) % filterSamples; // increment counter and roll over if necc. - % (modulo operator) rolls over variable
sensSmoothArray[i] = rawIn; // input new data into the oldest slot
// Serial.print("raw = ");
for (j=0; j<filterSamples; j++){ // transfer data array into anther array for sorting and averaging
sorted[j] = sensSmoothArray[j];
}
done = 0; // flag to know when we're done sorting
while(done != 1){ // simple swap sort, sorts numbers from lowest to highest
done = 1;
for (j = 0; j < (filterSamples - 1); j++){
if (sorted[j] > sorted[j + 1]){ // numbers are out of order - swap
temp = sorted[j + 1];
sorted [j+1] = sorted[j] ;
sorted [j] = temp;
done = 0;
}
}
}
/*
for (j = 0; j < (filterSamples); j++){ // print the array to debug
Serial.print(sorted[j]);
Serial.print(" ");
}
Serial.println();
*/
// throw out top and bottom 15% of samples - limit to throw out at least one from top and bottom
bottom = max(((filterSamples * 15) / 100), 1);
top = min((((filterSamples * 85) / 100) + 1 ), (filterSamples - 1)); // the + 1 is to make up for asymmetry caused by integer rounding
k = 0;
total = 0;
for ( j = bottom; j< top; j++){
total += sorted[j]; // total remaining indices
k++;
// Serial.print(sorted[j]);
// Serial.print(" ");
}
// Serial.println();
// Serial.print("average = ");
// Serial.println(total/k);
return total / k; // divide by number of samples
}
Arlo1 said:I found this.
http://playground.arduino.cc/Main/DigitalSmooth
I will try to work it into mine.
I got the Amp gauge and KW gauge working and I would like to add some smoothing. I have 2 caps on the input and its not quite smooth enough.
Its tricky because I am using a 800a current sensor.
I also need to find a way to make sure it Zeros at startup everytime.
Lebowski said:You should add some digital filtering to stabilise the readings a bit.
Lets say the signal (or reading) you want to filter is x . Then
filtered_x = filtered_x + alpha * ( x - filtered_x )
here alpha determines how much filtering there is, valid range is between 0 and 1 with 0 being an infinite amount of filtering and 1 being no filtering.
I would start with alpha = 0.1 and then try some different values.
Arlo1 said:XLR8 said:Can you tell us about your gauges? They look very good.Arlo1 said:Working on some gauges as well.![]()
Thanks. The background is a picture taken here in Nanaimo last summer during a lightning storm. I purchased a Nextion touch screen and programmed it and and arduino to run it.Nextion is a touch screen which comes with a driver built on to the back and you download free software to make your own gauges then you just flash it from a SD card. The code from arduino is simple it just sends the values over the rs232 to the touch screen and the touch screen does the rest. Its actually not hard. I have had some help from Tony as well going over the code as I am not proficient in code yet.
But so far I have the voltage for the 12v battery and the traction pack as well as the temp for the motor and this morning at 1am I added controller temp and now I am making a current sensor so I can know the Amps and watts. Then I will figure out how to work maths for Wh and wh/km!
All in time![]()
https://nextion.itead.cc/
Here is my current code
Edited to add current and KW calculations.
#include <Nextion.h>
#include <SoftwareSerial.h>
// Tempreture constants
#define THERMISTORPIN A3 // which analog pin to connect
#define THERMISTORPIN2 A4 // anlog pin for controller temp
#define THERMISTORNOMINAL 15000 // resistance at 25 degrees C
#define THERMISTORNOMINAL2 10000 // resisatance at 25 deg C for controller
#define TEMPERATURENOMINAL 25 // temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL2 25 // temp. for second therminstor resistance
#define BCOEFFICIENT 3950 // The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT2 3950 // Teh bete coefficient for therminstor 2
#define SERIESRESISTOR 9950 // the value of the 'other' resistor
#define SERIESRESISTOR2 9950 // the value for the second other resistor
#define NUMSAMPLES 3 // how many samples to take and average, more takes longer but is more 'smooth'
#define SAMPLEDELAY 10 // how many millis to wait for new sample
// 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
#define HIGHVOLT 480 // Maximum pack voltage
#define LOWVOLT 340 // minimum pack voltage
#define PRECHARGEPERCENT 0.95 // precharge complete percentage
#define PULSEPERROT 4.8 // pulses per rotation of speed sensor
#define WHEELCIRC .1835 // circumference of wheel in meters
#define FILTER_ALPHA 0.1 // filter co-efficient valid range 0 -> 1 0 = infinite filtering 1 = no filtering
// display setup
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, temp=0, temp2=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 voltages and currents
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_ALPHA*((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);
}
if (millis() - timeold >= 100)
{
detachInterrupt(0);
kmh = (WHEELCIRC / 1000 * (pulses/PULSEPERROT)) * millisecsPerHour / (millis() - timeold); // raw calculation
//kmh = kmh + FILTER_ALPHA*(calc -kmh); // filtered speed
timeold = millis();
pulses = 0;
attachInterrupt(0, irspeed, FALLING);
}
//Write it out to serial port
Serial.print("Speed: ");
Serial.println(kmh, DEC);
temp = temp + FILTER_ALPHA * (readThermistor(THERMISTORPIN) - temp); // filtered read
temp2 = temp2 + FILTER_ALPHA * (readThermistor(THERMISTORPIN2) - temp2); // filtered read
Serial.print("Temperature 1 ");
Serial.print(temp);
Serial.println(" *C");
Serial.print("Temperature 2 ");
Serial.print(temp2);
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", temp);
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", temp2);
myNextion.setComponentValue("n6", KW);
myNextion.setComponentValue("z1", displayAMPS);
}
/*
* Utility function to get the tempreture in degrees C from the thermister
*/
float readThermistor(int thermPin)
{
float reading = 0;
// take N samples in a row, with a slight delay
//for (int i=0; i< NUMSAMPLES; i++) {
// reading += analogRead(thermPin);
// delay(10);
//}
//reading /= NUMSAMPLES;
reading = analogRead(thermPin);
//Serial.println("Average analog reading ");
//Serial.println(reading);
// convert the value to resistance
reading = 1023 / reading - 1;
reading = SERIESRESISTOR / reading;
//Serial.print("Thermistor resistance ");
//Serial.println(reading);
float steinhart;
steinhart = reading / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
return steinhart;
}
SplinterOz said:Hey Arlo I have tidied your code again. The reason for functions is so you don't have to copy and paste code, so I have modified the temperature function.
I have also used Lebowski's filter code on the temperature (rather than average) and the speedo.
Note again I have moved the calculations for the Nextion display into the function to the display function.
Code:#include <Nextion.h> #include <SoftwareSerial.h> // Tempreture constants #define THERMISTORPIN A3 // which analog pin to connect #define THERMISTORPIN2 A4 // anlog pin for controller temp #define THERMISTORNOMINAL 15000 // resistance at 25 degrees C #define THERMISTORNOMINAL2 10000 // resisatance at 25 deg C for controller #define TEMPERATURENOMINAL 25 // temp. for nominal resistance (almost always 25 C) #define TEMPERATURENOMINAL2 25 // temp. for second therminstor resistance #define BCOEFFICIENT 3950 // The beta coefficient of the thermistor (usually 3000-4000) #define BCOEFFICIENT2 3950 // Teh bete coefficient for therminstor 2 #define SERIESRESISTOR 9950 // the value of the 'other' resistor #define SERIESRESISTOR2 9950 // the value for the second other resistor #define NUMSAMPLES 3 // how many samples to take and average, more takes longer but is more 'smooth' #define SAMPLEDELAY 10 // how many millis to wait for new sample // 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 #define HIGHVOLT 480 // Maximum pack voltage #define LOWVOLT 340 // minimum pack voltage #define PRECHARGEPERCENT 0.95 // precharge complete percentage #define PULSEPERROT 4.8 // pulses per rotation of speed sensor #define WHEELCIRC .1835 // circumference of wheel in meters #define FILTER_ALPHA 0.1 // filter co-efficient valid range 0 -> 1 0 = infinite filtering 1 = no filtering // display setup 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, temp=0, temp2=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 voltages and currents 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_ALPHA*((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); } if (millis() - timeold >= 100) { detachInterrupt(0); kmh = (WHEELCIRC / 1000 * (pulses/PULSEPERROT)) * millisecsPerHour / (millis() - timeold); // raw calculation //kmh = kmh + FILTER_ALPHA*(calc -kmh); // filtered speed timeold = millis(); pulses = 0; attachInterrupt(0, irspeed, FALLING); } //Write it out to serial port Serial.print("Speed: "); Serial.println(kmh, DEC); temp = temp + FILTER_ALPHA * (readThermistor(THERMISTORPIN) - temp); // filtered read temp2 = temp2 + FILTER_ALPHA * (readThermistor(THERMISTORPIN2) - temp2); // filtered read Serial.print("Temperature 1 "); Serial.print(temp); Serial.println(" *C"); Serial.print("Temperature 2 "); Serial.print(temp2); 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", temp); 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", temp2); myNextion.setComponentValue("n6", KW); myNextion.setComponentValue("z1", displayAMPS); } /* * Utility function to get the tempreture in degrees C from the thermister */ float readThermistor(int thermPin) { float reading = 0; // take N samples in a row, with a slight delay //for (int i=0; i< NUMSAMPLES; i++) { // reading += analogRead(thermPin); // delay(10); //} //reading /= NUMSAMPLES; reading = analogRead(thermPin); //Serial.println("Average analog reading "); //Serial.println(reading); // convert the value to resistance reading = 1023 / reading - 1; reading = SERIESRESISTOR / reading; //Serial.print("Thermistor resistance "); //Serial.println(reading); float steinhart; steinhart = reading / THERMISTORNOMINAL; // (R/Ro) steinhart = log(steinhart); // ln(R/Ro) steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro) steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To) steinhart = 1.0 / steinhart; // Invert steinhart -= 273.15; // convert to C return steinhart; }
kiwifiat said:SplinterOz said:Hey Arlo I have tidied your code again. The reason for functions is so you don't have to copy and paste code, so I have modified the temperature function.
I have also used Lebowski's filter code on the temperature (rather than average) and the speedo.
Note again I have moved the calculations for the Nextion display into the function to the display function.
I see you also corrected the "attachInterrupt" rising/falling issue and now that you have a single Steinhart–Hart function you can cull the redundant set of identical defines defines BCOEFFICIENT2 3950, TEMPERATURENOMINAL2 25, SERIESRESISTOR2 9950 . Also since you have dropped the averaging function NUMSAMPLES 3 can also be commented out. I expect that the compiler may optimize those away in any case but I'm not certain. Given that the two thermistors have different resistance at 25 degrees you should pass thermistornominal as a parameter to the Steinhart–Hart function or you will get incorrect results when you calculate temperature for thermistor 2. I'm curious as to why both thermistors have identical beta coefficients when they have different nominal resistances at 25C?
I'm doing the similar project but sending the data to an android tablet via bluetooth and rather than interrupt the processor every speed transducer pulse I setup timer0 as a counter that triggers an interrupt every three wheel rotations which reduces the interrupt overhead on the processor. Any how nice work and interesting to see that our approaches are more or less the same.
That Nextion device is cool, I wish I had known about it before I started down the Android path.