Go with custom board with an FRAM for storing the data.
SRAM read/write speeds (so pretty much instantaneous compared to EEPROM), and EEPROM nonvolatility.
Here are 5V parts with SPI interface that would work great.
Would 4Mb of Flash Ram work? Use an ESP8266 board like the Wemos D1 Mini. It comes with 4mB of Flash that you can read and write to like a micro SD card. (It also operates at 80mHz as opposed to the 16mHz of the Uno).
Curious, is your rotary encoder an absolute encoder? or at least does it have a 1/revolution feature?
If not are you saving the position to eeprom to keep track of the absolute position?
Thank you so much, i wasn't aware about this kind of external modules. seems they're approx 0.5 usd at aliexpress which is pretty affordable.
luckily i found the wemos d1 mini in a local electronics shop, i'll try that.
it's not an absolute encoder, the exact part number is: LPD3806-400BM-G5-24C, one complete turn provides 400 pulses. so yes, i'm picking up the last position of mill from eeprom.
If your encoder is not absolute position type, how about a "crankshaft position sensor" (That's what the $500 part in my Jeep is called. I asked for the old part and it turns out to simply be a hall-effect sensor and a magnet imbedded in the flywheel on the motor). This way you don't have to remember anything. One revolution calibrates your encoder position.
yes that part was already exists on stock engine before modding, i removed it. currently quite achieved what i'm trying to do but as stated on title i can't trust to the arduino board in a real world application. one accidental relay hiccup possibly damage to the engine, even might lead to an explosion.
I don't mean to be negative and I may still misunderstand but are you concerned you system might get out of sync if the encoder count pickups a voltage spike and slowly gets out of sync. Automotive electrical systems are terribly noisy. I can't see running a motor for 100's of hours and keeping things in absolute sync by counting the encoder only.
I think you will need a more absolute reference, perhaps a 1/rev signal?
Is your motor particularly slow? The specs I see on this super-cheap encoder say it only encodes up to 2000 RPM and can only physically handle 6000 RPM.
Typically, the encoder looks like a gear with one tooth missing. There is a sensor that pulses as each tooth goes by. The electronics count the teeth going by to measure RPM and looks for the gap in the sequence for its zero mark. The number of teeth is usually in the 30 to 60 range.
Here is a sketch I posted in the forum back in 2018.
It reads a crank position encoder with "12" teeth (actually 11).
volatile unsigned long PulseInterval; // Microseconds between the last two pulses
volatile unsigned long PulseTime; // Time (micros()) of the rising edge of the latest pulse
volatile byte PulseNumber = 0; // Which pulse was the latest pulse
volatile boolean PulseIsNew = false; // Flag set by the ISR
void myPulseIsr()
{
static unsigned long prevPulseTime; // Needed for detecting the new pulse interval
static unsigned long prevPulseInterval; // Needed for detecting the long pulse
PulseTime = micros();
prevPulseInterval = PulseInterval; // save the preceding value
PulseInterval = PulseTime - prevPulseTime;
prevPulseTime = PulseTime;
PulseNumber++;
// A pulse longer than 1.5 times the previous pulse indicates the index pulse (#0).
if (PulseInterval > (prevPulseInterval + (prevPulseInterval >> 1))) // compare to prev * 1.5
{
PulseNumber = 0;
}
PulseIsNew = true; // Let loop() know that new data is available
}
void setup()
{
attachInterrupt(digitalPinToInterrupt(2), myPulseIsr, RISING);
}
void loop()
{
static unsigned long localPulseTime = 0;
static byte localPulseNumber = 0;
static unsigned long microsecondsPerRevolution = 999;
if (PulseIsNew)
{
// Grab the volatile variables.
noInterrupts();
unsigned long localPulseInterval = PulseInterval; // Should work down to 152 RPM
localPulseTime = PulseTime;
byte localPulseNumber = PulseNumber;
PulseIsNew = false;
interrupts();
microsecondsPerRevolution = localPulseInterval * 12;
if (localPulseNumber == 0)
{
microsecondsPerRevolution = localPulseInterval * 6; // Long Pulse
}
}
unsigned long microsecondsSincePulse = micros() - localPulseTime;
long int degreesSinceIndex = 30 * localPulseNumber; // First 11 pulses are at 30° intervals
// Equivalent to (microsecondsPerRevolution / microsecondsSincePulse) * 360 but less subject to truncation
degreesSinceIndex += (microsecondsPerRevolution * 360UL) / microsecondsSincePulse;
// THIS IS WHERE YOU ADJUST 'degreesSinceIndex' FOR OFFSET FROM TDC
// This is where you use the new crank position
}