Hit and miss engine controller

hello
I am trying to use a attiny85 as a simple controller to turn any engine that uses the rcexl system into a hit and miss engine

so I got far enough that I can read the rpm from the hall sensor
and I can control a led with the rpm
but I have problems with the outputting of the signal

the incomming signal should go out to another pin
but somehow the signal it sends is not a pulse
its on or off

can somone here help me fix it?

int Pin = 2; // Hall sensor at pin 2
int Pout = 13;// cdi at pin 13
int PoutState = HIGH; //setting startup state
int Miss = 500; //setting the miss rpm (more then this means no spark)

unsigned long rpm = 0;
unsigned long duration;

void setup() {
  pinMode(Pin, INPUT); //Sets sensor as input
  pinMode(Pout, OUTPUT); //Sets pin as output to cdi 

}
void loop()
{
  PoutState = digitalRead(Pin); //I try to set the output
//PoutState = !digitalRead(Pin); //Inverted in case the cdi wants a negative signal
  
  duration = pulseIn(Pin, FALLING, 500000); //times the amount of microseconds the motor is not timing IR, Times out after 100000 uS. Raise the timeout for slower RPM readings. .5 second
  rpm = 60000.0/duration*1000; //See above
  
  if (rpm >= Miss){ //read rpm and compair it to the set variable
    digitalWrite(Pout, HIGH); //Setting the cdi in a standby state
  //digitalWrite(Pout, LOW); //Inverted in case the cdi wants a negative signal
    }
  else{
    digitalWrite(Pout, PoutState); //Send the saved input to the output
  }
}

I'm not convinced you are calculating the RPM correctly, shouldn't you be finding the time between Hall sensor pulses?

Regardless, to create a pulse out you need to do something like:

unsigned long pulseDelay = 5; // substitute required pulse time (us)

digitalWrite(Pout, HIGH);
delayMicroseconds (pulseDelay);
digitalWrite(Pout, LOW);

I don't know what the pulseDelay should be; presumably it should be similar to the pulse width of the Hall sensor.

Should be ok for the ignition to fire all the time, a hit and miss engine usually has the exhaust valve held open to prevent drawing in the fuel/air mixture.

For reference, I believe the "rcexl cdi" system the OP refers to are those here:

A Hall sensor provides a pulse every revolution. The RCEXL controller detects the falling edge of the pulse and fires the spark plug. The Hall sensor should be positioned 28-30 degrees before TDC.

the puls must be the same as the input
so if the rpm treshold isnt reached the incomming puls also is the outgoeing one

so this would not work because it would make it a one shot

You haven't really specified what you want, nor do any of the data sheets specify the waveform exactly, so I am basically guessing. I don't have the hardware to test.

Based on what I think should happen, I would rewrite the sketch. Perhaps we should start by defining exactly what is required...

sorry I am bad at describing what I am mean
lets try again

there is a engine that uses a hall sensor to trigger the rpm
and I want the engine to behave as a hit and miss

so I tried using a script that can read the sensor and give me a rpm output
and I added a bit of code to put in a limit
and above that limit there is no output
and under the limit the sensor signal should be copied to the output pin

is this clearer?

Not really, I understand the overall view. Still need more to write the code.

Does this diagram accurately explain it?

that looks about right

this script can read the sensor its a 3144 type|

float revolutions=0;
int rpm=0; // max value 32,767 16 bit
long  startTime=0;
long  elapsedTime;
 
void setup() 
{
    Serial.begin(9600);
    pinMode(2, INPUT_PULLUP);           // set pin to input
}
 
void loop() {
revolutions=0; rpm=0;
startTime=millis();         
attachInterrupt(digitalPinToInterrupt(2),interruptFunction,RISING);
delay(1000);
detachInterrupt(2);                

//now let's see how many counts we've had from the hall effect sensor and calc the RPM
elapsedTime=millis()-startTime;     //finds the time, should be very close to 1 sec

if(revolutions>0)
{
  rpm=(max(1, revolutions) * 60000) / elapsedTime;        //calculates rpm
}
String outMsg = String("RPM :") + rpm;
Serial.println(outMsg);
}

void interruptFunction() //interrupt service routine
{  
  revolutions++;
}

I went back to the original code
and I added a serial monitor
it shows the rpm perfectly
with a hall sensor and a hall sensor emulator

so if I get a way to output the pulse I am good

You need to use either an external logic gate, or an interrupt, nothing else is fast enough or consistent enough.

This is unlikely to work. If you do not hold the exhaust valve open while the ignition is cut off, there will be a lot of work being done on the compression strike, slowing the engine rapidly. If you do not at least cut off the fuel intake, you will be pumping a very combustible fuel/air mixture through the engine and into the exhaust, likely causing a backfire whenever you re-enable the ignition.
The flywheel is also likely to be must too small to maintain speed for any length of time.

yea I dont realy care about pumping fuel in the exhaust
and as somone who rebuild a cox 049 to run on all the fuel types
I just like to experiment
and yes I want to have a hit and miss cox 049

Try this, I tested with a pulse generator, and it seems to generate a reasonable output (as seen on oscilloscope).

It could be optimised a little more if necessary. However, I suspect it might need more sophisticated control techniques than a "bang-bang" approach (pun intended :slight_smile: )

int Pin = 2; // Hall sensor at pin 2
int Pout = 13;// cdi at pin 13


unsigned long target_rpm = 3000;

unsigned long last_pulse;       // in microseconds
unsigned long target_time = 0;  // in microseconds

void setup() 
{
  pinMode(Pin, INPUT); // Sets sensor as input
  pinMode(Pout, OUTPUT); // Sets pin as output to cdi 

  //calculate time of 1 revolution at target RPM (in microseconds)
  target_time = 60000000UL / target_rpm;

  Serial.begin(115200);
}

void loop() 
{
  while (1)
  {
    // wait for leading edge
    while (digitalRead (Pin) == LOW)
    {};

    unsigned long now = micros();

    if (now - last_pulse > target_time)
    {
      // slower than target RPM, output pulse
      digitalWrite (Pout, HIGH);
    }

    // wait for trailing edge
    while (digitalRead (Pin) == HIGH)
    {};

    // end output pulse
    digitalWrite (Pout, LOW);

    last_pulse = now;

  }
}

I did a full test with a cdi
and it looks to work
It also doesnt look like there is to much delay
now to test it on a engine

i found some sort of bug
on low rpm the pulse doesnt get outputted correctly

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.