/*****************************
* Standalone Engine Simulator
* Aaron S. (Detonation) 2023
******************************/
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
// Pins Setup
int sensorPin = A0; // potentiometer
int crankPin = 8; // Crank sensor to ECU
int camPin = 9; // Crank sensor to ECU
const int ledPin = 13; // Nano LED used for Error or "Blink"
/*Rotory Encoder*/
#define CLK 2
#define DT 3
#define SW 4
unsigned long lastButtonPress = 0;
int counter;
int currentStateCLK;
int lastStateCLK;
int pattern; // Store Pattern number here
//String patternName;
/*Used to limit encoders movement outside case values*/
const int encodeMin = 0;
const int encodeMax = 3;
// Crank & Cam output states
int crankState_1 = LOW;
int crankState_2 = HIGH;
int camState_1 = LOW;
int camState_2 = HIGH;
// Storeable values
unsigned long previousMicros; // Store last variable of crankState
unsigned long interval; // Interval at which to trigger stored in milliseconds
unsigned long time; // Store time
unsigned long previousTime; // will store last variable of Time
int rotation; // Store Cam rotation
int i;
int sensorValue; // store value from sensor
// Pot setup for setting RPM
static const long potReadInterval = 100; // How ofter to check is sensorPin has been chnaged
unsigned long previousTime_rpmPot; // will store last variable of Time for rpmPot
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows
void setup(){
Serial.begin(9600);
pinMode(crankPin, OUTPUT); // set the digital pin as output
pinMode(camPin, OUTPUT);
pinMode(ledPin, OUTPUT); // ledPin used for error or no pattern selected
pinMode(CLK, INPUT); // Setup rotory encoder as input
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
lastStateCLK = digitalRead(CLK); // Read the initial state of CLK
// char patternName = 'DetonationEMS'; // Store Pattern Name
}
void loop(){
/* Allows for RPM update to stop for 100ms if potentiometer is at lowest value. */
if (sensorValue < 1){ // Read potentiometer value, if 0 then delay
delay(100);
}
/*Run scripts below when RPM Pot is above 0*/
updateRPM(); //Check RPM Pot
/*Read Rotory Encoder*/
currentStateCLK = digitalRead(CLK); // Read the current state of CLK
char patternName; // Store Pattern Name
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
if (digitalRead(DT) != currentStateCLK) {
pattern --;
Serial.print("Pattern ");
Serial.print(patternName);
} else {
pattern ++;
Serial.print("Pattern ");
Serial.print(patternName);
}
if(pattern > 4) //Limits the encoder from 0-3
pattern = 0;
if(pattern < 0)
pattern = 4;
//Serial.print(pattern); //Display pattern being used
}
lastStateCLK = currentStateCLK;
}
void updateRPM() //Check if CountRefreshed = 0
{
unsigned long millisTime = millis();
if ( millisTime - previousTime_rpmPot >= potReadInterval ){
previousTime_rpmPot = millisTime; // Wait potReadInterval interval to check analogTimer
sensorValue = analogRead(sensorPin);
/*Using values outside maximum removed glitching at highest RPM*/
/*Ardustim POT is mapped (high->low, low->high). Sticking with this for compatibility*/
interval = map(sensorValue, 1060, 0, 0, 4296); // Analog read 0-1024 real/ Digial Write 0 - 4096
/**************************************/
/*rotory options*/
/**************************************/
int range = map(pattern, encodeMin, encodeMax, 0, 3); // Map the range of options
switch (range) {
case 0:
twelve_minus_one_with_cam(); //If we detect LOW signal, button is pressed
patternName = ('12-1');
//Serial.print(" 12-1 ");
break;
case 1:
thirty_six_minus_one(); //If we detect LOW signal, button is pressed
patternName = ('36-1');
break;
case 2:
//blink();
break;
case 3:
//blink();
break;
case 4:
//blink();
break;
}
}
}
/**************************************
* Pattern 12/1 with cam
**************************************/
void twelve_minus_one_with_cam(){
unsigned long currentMicros = micros(); //Math to help lowest RPM resolution
/***************CRANK********************/
time = currentMicros - previousMicros;
if (time > interval) //Change Pin state from HIGH to LOW 23 times
{
previousMicros = currentMicros;
i++;
if (i <= 23)
{
crankState_1 = !crankState_1;
digitalWrite(crankPin, crankState_1);
}
if (i == 24) //On pin state change 24 stay low
{
time = currentMicros - previousTime;
previousTime = currentMicros;
i = 1;
rotation = 1; //Go back to pin state 1 and repeat the proccess
}
/***************CAM********************/
if (rotation >= 1); {
if (i == 22)
{
camState_1 = !camState_1;
digitalWrite(camPin, camState_1);
}
if (i == 23)
{
digitalWrite(camPin, camState_2);
}
rotation = 0;
}
}
}
/**************************************
* Pattern 36/1
**************************************/
void thirty_six_minus_one(){
unsigned long currentMicros = micros(); //Math to help lowest RPM resolution
time = currentMicros - previousMicros;
if (time > interval)
{
previousMicros = currentMicros;
i++;
if (i <= 71) //Change Pin state from HIGH to LOW
{
crankState_1 = !crankState_1;
digitalWrite(crankPin, crankState_1);
}
if (i == 72) //If pin state has changed i times then stay LOW. Dead Spot for trigger.
{
time = currentMicros - previousTime;
previousTime = currentMicros;
i = 1; //Go back to pin state 1 and repeat the proccess
}
}
}