#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // Create a new LiquidCrystal_I2C display object with the correct I2C address and display size
// Define the pins
const int currentPin = A0; //information about current
const int voltagePin = A2; //information about voltage
const int motorPin = 7; //motor running pin, HIGH = motor running, TEST purpose LOW
const int pwmPin = 9; //PWM output pin
const int relayPin = 3; //Relay control pin
float voltageFactor = 5.00 / 1023.00; //Factor to convert ADC reading to voltage
// OLD: float currentFactor = 80.00 / (4.15 - 2.02); // Adjusted for 2.02 volts = 0 amps and 4.15 volts = 80 amps
// NEW: Define the points for current calculation / the line equation
float x1 = 2.02; // volts
float y1 = 0; // amps
float x2 = 4.1538; // volts
float y2 = 80; // amps
// Calculate the slope and intercept
float m = (y2 - y1) / (x2 - x1);
float b = y1 - m * x1;
float currentCal = 1; // Variable to shift th whole current level
float sensVfactor = 20.00 / 4.9248; //4.9248 volts = 20 volts, factor to convert high voltage to 0-5 V
float current; //store current value
float sensVoltage; //store sensed voltage
const int N = 25; //number of current readings to average
const int Y = 25; //number of sensed voltage readings to average
int readings[N]; //array to store the current readings
int readingsV[Y]; //array to store the sensed voltage readings
int motorStatus; //0=stopped, 1=starting, 2=running, 3=stopped but did run, on status 3, just switch off and on again to go back 0
int lcdStep; //0=current display, 1=voltage display
unsigned long lastTime = 0; //timer to measure engine sensor input time for starting
void setup() {
Serial.begin(9600); // Start the serial communication
// Initialize the LCD here
// Give the screen time to boot
delay(50);
lcd.begin(16, 2);
lcd.backlight();
lcd.clear();
// Change timers on pins to change PWM freq to 122 Hz
// Pins D9 and D10 - 122 Hz
TCCR1A = 0b00000001; // 8bit
TCCR1B = 0b00000100; // x256 phase correct
// Make pins output/input
pinMode(currentPin, INPUT); //Information on charging current
pinMode(voltagePin, INPUT); //information on voltage, for real use, delete _PULLUP
pinMode(motorPin, INPUT_PULLUP); //Vibration sensor in, for motor running detect, for real use, delete _PULLUP (it is for test purpose, pullup resistor)
pinMode(pwmPin, OUTPUT); //Alternator pwm output
pinMode(relayPin, OUTPUT); //Ignition relay pin
// Start Duty Cycle at 100 %, alternator electromagnet off
analogWrite(pwmPin, 255);
}
void motorRunning() { //engine running function
if (digitalRead(motorPin) == HIGH && motorStatus == 0) {
if (millis() - lastTime >= 6000) { //wait at least 6 seconds before ramping up pwn and so start charging
motorStatus = 1;
}
} else if (motorStatus == 0) {
lastTime = millis();
lcd.setCursor(0, 0); //On lcd print Finnish to start the engine
lcd.print("K");
lcd.print((char)0xe1);
lcd.print("ynnist");
lcd.print((char)0xe1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("moottori");
}
}
void rampUp() { //rampup pwm
// Ramp pwm up
if (motorStatus == 1) {
analogWrite(pwmPin, 48);
delay(1000);
analogWrite(pwmPin, 83);
delay(1000);
analogWrite(pwmPin, 118);
delay(1000);
analogWrite(pwmPin, 153); //Duty Cycle at 60 percent
motorStatus = 2;
}
}
//void shutDown() { //engine shutdown, execute relay
// If the charging current drops below five amperes
// start the shutdown function and turn off the relay for 15 seconds
// if (current < 5 && motorStatus == 2) {
// digitalWrite(relayPin, LOW);
// Stop Duty Cycle at 100 %, alternator electromagnet off
// analogWrite(pwmPin, 255);
//lcd.clear();
//lcd.setCursor(0, 0);
//lcd.print("Sammutus");
//motorStatus = 3;
// } else {
// digitalWrite(relayPin, HIGH); //else, keep relay on
//}
//}
void showCurrent() { //show current and voltage on lcd only when normal running state
if (motorStatus == 2) {
lcd.setCursor(0, 0);
lcd.print("Virta:");
lcd.setCursor(0, 1);
lcd.print((float)current);
lcd.print(" ");
lcd.setCursor(5, 1);
lcd.print(" A");
lcd.setCursor(8, 0);
lcd.print("J");
lcd.print((char)0xe1);
lcd.print("nnite:");
lcd.setCursor(8, 1);
lcd.print((float)sensVoltage);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.print(" V");
}
}
void loop() {
//calculate current from shunt reading
// Calculate the charging current from the average and display it on the LCD screen.
// take N readings and store them in the array
for (int i = 0; i < N; i++) {
readings[i] = analogRead(currentPin);
delay(10); // wait for 10 milliseconds between readings
}
// calculate the average of the N readings
float sum = 0;
for (int i = 0; i < N; i++) {
sum += readings[i];
}
float average = sum / N;
float voltage = average * voltageFactor; // Convert ADC reading to voltage
//OLD
//current = voltage * currentFactor; // Convert voltage to current
//NEW
current = (m * voltage + b) * currentCal; // Convert voltage to current using the new linear equation
//calculate high voltage from voltage divider input
// Calculate the charging voltage from the average and display it on the LCD screen.
// take Y readings and store them in the array
for (int j = 0; j < Y; j++) {
readingsV[j] = analogRead(voltagePin);
delay(10); // wait for 10 milliseconds between readings
}
// calculate the average of the N readings
float sumV = 0;
for (int j = 0; j < Y; j++) {
sumV += readingsV[j];
}
float averageV = sumV / Y;
float voltageV = averageV * voltageFactor; // Convert ADC reading to voltage
sensVoltage = voltageV * sensVfactor; // Convert voltage to real voltage
motorRunning();
rampUp();
//shutDown();
showCurrent();
Serial.print("Lcdstep: ");
Serial.print((int)lcdStep);
Serial.println();
Serial.print("Jannite: ");
Serial.print((float)sensVoltage);
Serial.println();
Serial.print("Virta: ");
Serial.print((float)current);
Serial.println();
}