Greetings from Germany!
Firstof thers some pretty bad englisch involved in this post hope we can get along anyway.
So lets go!
Im building a Capacitor discharge ignition module for my scooter as is want to change the ignition curve
and have a build in speed/rev limiter.
It is an AC CDI.
basic principle:
Coils on the scooter generator charge a capacitor which is rapitly discharged with a thyristor
causing a high Voltage at the ignition coil which is transformed to a even higher voltage causing a spark
at the spark plug.
the scooter has a vr sensor to determine top dead center (TDC) and revolution time.
the signal is fet into the CDI module which calculates the ingnition time and when to trigger the Thyristor.
to work out everything i got a experimental setup
i conectet the flywheel (with one tooth for vr sensor) an the vr sensor to an electric motor to simulate the engine running.
the vr signal is fet into a zero crossing circut for conditioning into a digital signal
which is fet in to an Teensy 4.0. (for now TDC is as the tooth passes the sensor in reality its some degrees before TDC)
for bluetooth comunication i use a HC06 module.
the following things work just fine:
- caculating the time for a revolution and sending it to the phone or pc
- setting the ignitiontime by sending the amount of degrees befor TDC over the phone with the app bluetooth terminal
the speed/rev limiter and the ignition curve can be set aside for now
i only want to have a stable ignitiontiming.
and thats the problem
while mesuring the input signal and the trigger signal with the oscilloscope i noticed the ignition point
jumping around about 100us back and forth which (at this engine speed) translated in to about 3 degrees angular position – target is to get under 1 degree!
i thought maybe it is just the revolution time that jumping around but the percentige or degrees stay stable so i checkt the rev times over the serial monitor-
Exsample times measured:
Serial Monitor
20673.00
20672.00
20662.00
20667.00
20663.00
20665.00
they are stable enough
as the triggersignal is like a pwm signal set HIGH on the trigger point set LOW (pretty acurate 1-3us after TDC) at TDC
i measured the degress before TDC with a little arduino scetch:
float ONCycle;Â Â Â Â Â Â Â
float OFFCycle;Â Â Â Â Â Â
float T;
float z;Â Â Â Â Â Â Â Â Â
int F;Â
const int PulseIN = 7;Â Â Â
void setup() {
 Serial.begin(9600);
 pinMode(PulseIN, INPUT);
}
void loop() {
 ONCycle = pulseIn(PulseIN, HIGH);
 OFFCycle = pulseIn(PulseIN, LOW);
 T = ONCycle + OFFCycle;
 z = ONCycle / T;
 z = z *360;
 Serial.print(z);
 Serial.println();
 }
as you see the degrees jump around quite a lot:
Serial Monitor
3.59
4.17
4.44
3.72
3.96
5.27
here is the code for the teensy maybe you see an error
#define HWSERIAL Serial1 // Serialport used to comunicate with a HC06 bluetoth moduale
unsigned long starttime; // startime for counting time of a revolution
unsigned long sendezeit; // for sending revolution time in some intervall on the serial
const int vrsens = 7; // Variable reluctance sonsor imput fet thrue a circut as i need a digital signal
const int transistor = 4; // transistor that is triggert to discharge the capacitor which leads to a spark
float umdrehungszeit; // time for a revolution
float zuendzeitpunkt; // time till the next triggerpoint
float zuendwinkel = 0.973; // coefficent which multiplies with the time for a revolution given in percent set by defalt to 10 deegres before TDC
int logiclevel; // for saving the logiclevel of the inputsignal used to determin TDC and revolution time
int lastlogiclevel; // for compering to logiclevel
int counter; // for counting the edges of the vr inputsignal --> 2 edges per revolution
int motorstatus; // counter to determin if the engine is rumming
const byte numChars = 32; // used for Serial comunication Arduino Forum --> Robin2 Serial Input Basics thanks a lot by the way
char receivedChars[numChars]; // used for Serial comunication Arduino Forum --> Robin2 Serial Input Basics
boolean newData = false; // used for Serial comunication Arduino Forum --> Robin2 Serial Input Basics
void setup() {
 Serial.begin(9600);
 HWSERIAL.begin(9600);
 pinMode(vrsens, INPUT);
 pinMode(transistor, OUTPUT);
}
void loop() {
 recvWithStartEndMarkers(); // comunication with bluethoth module Arduino Forum --> Robin2 Serial Input Basics
 if (newData == true) { // if i send the ignitionpoint in degrees before TDC over bluethoth checks if data arivet caculates the coefficent and echos it
   float rxzw = atof(receivedChars); // translation from char array to float
   rxzw = rxzw * 0.00278; // 0.278 is one degree in percent
   rxzw = 1 - rxzw;
   zuendwinkel = rxzw;
   HWSERIAL.println(zuendwinkel); //echo for checking
   Serial.println(zuendwinkel);
   newData = false;
 }
/*Â if (motorstatus >= 2){ // if engine is running send revolution time per intervall set by sendezeit
  if (sendezeit<millis()){
   Serial.print(umdrehungszeit);
   Serial.println();
   sendezeit = 1000 + millis();
  }
 } */
 logiclevel = digitalRead(vrsens); // saving curent logiclevel
 if (logiclevel != lastlogiclevel){ // locking for an edge
  if (motorstatus == 0){ // if i hookup the circut there will be one edge detectet but the engine is still not running
   motorstatus = 1;
   } else if (motorstatus == 1){ // after too edges the engine is running
    motorstatus = 2;
    HWSERIAL.print("Motor an"); // feedback german for "engine running"
    HWSERIAL.println();
    Serial.print("Motor an");
    Serial.println();
    }
  if (counter == 0){ // after first edge start counting revolutiontime and edges
   starttime = micros();
   counter = counter + 1;
   }else if (counter == 1){ // if theres bin an edge allredy add one
    counter = counter + 1;
    }else{ // if theres bin too one revolution happend --> caculate the revolution time reset counter
     counter = 0;
     umdrehungszeit = micros() - starttime;
     Serial.print(umdrehungszeit);
     Serial.println();
     }
  if (logiclevel == HIGH){ // if there is an edge and the logiclevel is high now it is TDC therefor caculate the next trigger point
   zuendzeitpunkt = umdrehungszeit * zuendwinkel; // triggerpoint is revolutiontime times coefficent therefor a fraction of a revolution
   zuendzeitpunkt = zuendzeitpunkt + micros(); // add this time to the current time
   }
  }
 if (zuendzeitpunkt < micros()){ // if the triggertime is smaler than current time trigger transistor
  digitalWrite(transistor, HIGH);
  }else{
   digitalWrite(transistor, LOW); // writes LOW if theres a new trigger point --> shortly after TDC usaly 1-3 microseconds mesured with the ossiloscope
   }
 lastlogiclevel = logiclevel; // saving last logiclevel for edgedetection
}
void recvWithStartEndMarkers() { // // comunication with bluethoth module Arduino Forum --> Robin2 Serial Input Basics
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  while (HWSERIAL.available() > 0 && newData == false) {
    rc = HWSERIAL.read();
    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      } else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
       }
    } else if (rc == startMarker) {
      recvInProgress = true;
     }
  }
}