#define DEBUG
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <neotimer.h>
Neotimer motorTime = Neotimer(10000);
Neotimer stepTime = Neotimer(1000);
Neotimer shutTime = Neotimer(10000);
Neotimer crankTime = Neotimer(4000);
Neotimer crankWait = Neotimer(5000);
Neotimer voltageWait = Neotimer(2000);
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int currentPin = A0;
const int voltagePin = A2;
const int motorPin = 2;
const int pwmPin = 9;
const int relayPin = 4;
const int rpmPin = 11;
const int starterPin = 3;
float voltageFactor = 5.00 / 1023.00;
float x1 = 0.500;
float y1 = 0;
float x2 = 4.005;
float y2 = 150;
float m = (y2 - y1) / (x2 - x1);
float b = y1 - m * x1;
float currentCal = 1;
float sensVfactor = 20.00 / 4.9248;
float current;
float sensVoltage;
const int N = 25;
const int Y = 25;
int readings[N];
int readingsV[Y];
int pwmValues[] = { 24, 41, 58, 77 };
int currentPwmStep = 0;
int motorStatus;
int startTry;
float startVoltage = 11.9;
float shutCurrent = 5;
float upVoltage = 15;
float rpmTH = 300;
float rpmRun = 1800;
unsigned long rpm = 0;
unsigned long duration;
void setup() {
Serial.begin(250000);
#ifdef DEBUG
Serial.println("Setup...");
#endif
Wire.begin();
Wire.beginTransmission(0x27);
if (Wire.endTransmission() == 0) {
delay(50);
lcd.begin(16, 2);
lcd.backlight();
lcd.clear();
} else {
#ifdef DEBUG
Serial.println("Ei LCD:ta. Ohitus.");
#endif
}
TCCR1A = 0b00000001;
TCCR1B = 0b00000100;
pinMode(currentPin, INPUT);
pinMode(voltagePin, INPUT);
pinMode(motorPin, INPUT_PULLUP);
pinMode(pwmPin, OUTPUT);
pinMode(relayPin, OUTPUT);
pinMode(rpmPin, INPUT_PULLUP);
pinMode(starterPin, OUTPUT);
analogWrite(pwmPin, 255);
#ifdef DEBUG
Serial.println("Setup ok.");
#endif
}
void motorCrankState() {
if (motorStatus == 0 && sensVoltage < startVoltage) {
#ifdef DEBUG
Serial.println("Jannitekynnys kaynnistykseen!");
#endif
if (!voltageWait.started()) {
voltageWait.start();
}
if (voltageWait.done()) {
motorStatus = 1;
voltageWait.reset();
}
} else if (motorStatus == 0) {
voltageWait.stop();
voltageWait.reset();
}
}
void Crank1() {
if (motorStatus == 1 && startTry == 0 && rpm == 0) {
if (rpm <= rpmTH) {
digitalWrite(starterPin, LOW);
if (!crankTime.started()) {
crankTime.start();
}
if (crankTime.done()) {
digitalWrite(starterPin, HIGH);
crankTime.reset();
if (!crankWait.started()) {
crankWait.start();
}
if (crankWait.done()) {
startTry = 1;
crankWait.reset();
}
} else if (startTry == 0) {
crankWait.stop();
}
} else if (rpm > rpmTH) {
digitalWrite(starterPin, HIGH);
crankTime.stop();
startTry = 1;
motorStatus = 2;
crankTime.reset();
}
}
}
void Crank2() {
if (motorStatus == 1 && startTry == 1 && rpm == 0) {
if (rpm <= rpmTH) {
digitalWrite(starterPin, LOW);
if (!crankTime.started()) {
crankTime.start();
}
if (crankTime.done()) {
digitalWrite(starterPin, HIGH);
crankTime.reset();
if (!crankWait.started()) {
crankWait.start();
}
if (crankWait.done()) {
startTry = 2;
crankWait.reset();
}
} else if (startTry == 1) {
crankWait.stop();
}
} else if (rpm > rpmTH) {
digitalWrite(starterPin, HIGH);
crankTime.stop();
startTry = 2;
motorStatus = 2;
crankTime.reset();
}
}
}
void Crank3() {
if (motorStatus == 1 && startTry == 2 && rpm == 0) {
if (rpm <= rpmTH) {
digitalWrite(starterPin, LOW);
if (!crankTime.started()) {
crankTime.start();
}
if (crankTime.done()) {
digitalWrite(starterPin, HIGH);
crankTime.reset();
if (!crankWait.started()) {
crankWait.start();
}
if (crankWait.done()) {
startTry = 3;
crankWait.reset();
}
} else if (startTry == 2) {
crankWait.stop();
}
} else if (rpm > rpmTH) {
digitalWrite(starterPin, HIGH);
crankTime.stop();
startTry = 3;
motorStatus = 2;
crankTime.reset();
}
}
}
void Crank4() {
if (motorStatus == 1 && startTry == 3 && rpm == 0) {
if (rpm <= rpmTH) {
digitalWrite(starterPin, LOW);
if (!crankTime.started()) {
crankTime.start();
}
if (crankTime.done()) {
digitalWrite(starterPin, HIGH);
crankTime.reset();
if (!crankWait.started()) {
crankWait.start();
}
if (crankWait.done()) {
startTry = 4;
crankWait.reset();
}
} else if (startTry == 3) {
crankWait.stop();
}
} else if (rpm > rpmTH) {
digitalWrite(starterPin, HIGH);
crankTime.stop();
startTry = 4;
motorStatus = 2;
crankTime.reset();
}
}
}
void Crank5() {
if (motorStatus == 1 && startTry == 4 && rpm == 0) {
if (rpm <= rpmTH) {
digitalWrite(starterPin, LOW);
if (!crankTime.started()) {
crankTime.start();
}
if (crankTime.done()) {
digitalWrite(starterPin, HIGH);
motorStatus = 5;
crankTime.reset();
if (!crankWait.started()) {
crankWait.start();
}
if (crankWait.done()) {
startTry = 5;
crankWait.reset();
}
} else if (startTry == 4) {
crankWait.stop();
}
} else if (rpm > rpmTH) {
digitalWrite(starterPin, HIGH);
crankTime.stop();
startTry = 5;
motorStatus = 2;
crankTime.reset();
}
}
}
void motorRunning() {
if ((motorStatus == 2) && digitalRead(motorPin) == HIGH || rpm > rpmRun) {
motorTime.reset();
#ifdef DEBUG
Serial.println("Kayntitieto!");
#endif
if (!motorTime.started()) {
motorTime.start();
}
if (motorTime.done()) {
motorStatus = 3;
#ifdef DEBUG
Serial.println("Kay.");
#endif
}
} else if (motorStatus == 0 || motorStatus == 1) {
motorTime.stop();
#ifdef DEBUG
Serial.println();
Serial.println("Kaynnistys...");
#endif
lcd.setCursor(0, 0);
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() {
if (motorStatus == 3) {
stepTime.reset();
if (stepTime.repeat()) {
analogWrite(pwmPin, pwmValues[currentPwmStep]);
currentPwmStep++;
#ifdef DEBUG
Serial.println("Ramp up...");
#endif
if (currentPwmStep >= sizeof(pwmValues) / sizeof(pwmValues[0])) {
motorStatus = 4;
}
}
}
}
void shutDown() {
if (current >= 0 && current < shutCurrent && sensVoltage < upVoltage && digitalRead(motorPin) == HIGH && motorStatus == 4) {
shutTime.reset();
digitalWrite(relayPin, LOW);
analogWrite(pwmPin, 15);
if (!shutTime.started()) {
shutTime.start();
}
if (shutTime.done()) {
analogWrite(pwmPin, 255);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sammutus");
motorStatus = 0;
#ifdef DEBUG
Serial.println("Sammutettu.");
#endif
}
} else if (motorStatus == 4) {
motorTime.stop();
digitalWrite(relayPin, HIGH);
#ifdef DEBUG
Serial.println("Kaynnissa.");
#endif
}
}
void showCurrent() {
if (motorStatus == 4) {
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");
#ifdef DEBUG
Serial.println("Virta LCD.");
#endif
}
}
void loop() {
for (int i = 0; i < N; i++) {
readings[i] = analogRead(currentPin);
delay(5);
}
float sum = 0;
for (int i = 0; i < N; i++) {
sum += readings[i];
}
float average = sum / N;
float voltage = average * voltageFactor;
current = (m * voltage + b) * currentCal;
for (int j = 0; j < Y; j++) {
readingsV[j] = analogRead(voltagePin);
delay(5);
}
float sumV = 0;
for (int j = 0; j < Y; j++) {
sumV += readingsV[j];
}
float averageV = sumV / Y;
float voltageV = averageV * voltageFactor;
sensVoltage = voltageV * sensVfactor;
{
duration = pulseIn(rpmPin, FALLING, 500000);
rpm = 60000.0 / duration * 1000;
}
motorCrankState();
Crank1();
Crank2();
Crank3();
Crank4();
Crank5();
motorRunning();
rampUp();
shutDown();
showCurrent();
#ifdef DEBUG
Serial.print("Jannite: ");
Serial.print((float)sensVoltage);
Serial.println();
Serial.print("Virta: ");
Serial.print((float)current);
Serial.println();
Serial.print("Tila: ");
Serial.print(motorStatus);
Serial.println();
Serial.print("Start tila: ");
Serial.print(startTry);
Serial.println();
#endif
}