CDI tester project

Just to be sure I didn't post a wrong sketch, But what happens is that I get 4 or 5 pulses from D4 when D6 is high. This happens when I reset or do a cold start and looking with scope.

// replaced on 7/22/18 mod on 4/18/2019 changed to go simple transformer control of pos / neg trigger
// update 7/14/2017 added correct math and setting for position of pickup
// revision 10 10/28/2016 adds charging pulse with Timer 2
// lowest RPM = 615 with charge pulse to keep OCR2A <= 255
// CDI Tester Pulse Generator Serial Output Arduino Code
// 8/17 added code for pulse out width

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h> // include i/o class header
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config display for hd44780 chip

int pot1 = A1; // select the input pin for the pot for rpm
int pot2 = A2; // select the input pin for the pot for pickup location in degrees
// int pot3 = A3; // select the input pin for the pot for length of bar on flywheel in degrees
int potValue = 0; // variable to store the value coming from the sensor
int pickupValue = 0; // position of pickup in degrees
int potWidth = 0; // variable to set length of bar on flywheel
int timerTopValue = 12500; // changed from timerTopValue = 0
int outputPin = 4; // select the pin for the output for trigger pulse, changed from 8
int chargePin = 7; // select the pin for the output for charge pulses

volatile boolean trigger = false;
volatile unsigned long delayPeriod;
unsigned long copy_delayPeriod;
volatile unsigned long delayPeriodStart;
float delayDegrees; // changed from int to float for decimal place display
int RPM;
int pickup;
// int barLength;
int pulseWidth;                                            
volatile boolean interruptFlag;
unsigned long analogReadInterval = 500; // read pots and map
unsigned long lastAnalogRead;

// const byte setFallingSwitch = 5;
// char risefall = 'R'; // default rising mode

const byte setChargePulseSwitch = 6;
boolean chargePulse = false ;  // default dc powered mode

volatile byte timeSliceCount = 0; // TDC 0 degrees

void setup() {
// Serial.begin(115200);
// Serial.println("starting...");
  lcd.begin(20, 4); // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.setCursor(1, 0); // lcd display setup of unchanging headings
  lcd.print("RPM:"); // print fixed characters
  lcd.setCursor(12, 0);
  lcd.print("Deg"); 
  lcd.setCursor(1, 1);
  lcd.print("Pos:");
//  lcd.setCursor(12, 1);
//  lcd.print("Bar:");
  lcd.setCursor(1, 2);
  lcd.print("Us Delay:");
  lcd.setCursor(1, 3);
  lcd.print("Deg Advance:");

  pinMode(outputPin, OUTPUT); // declare the outputPin as an OUTPUT
  pinMode(chargePin, OUTPUT); // declare the chargePin as an OUTPUT
// pinMode (setFallingSwitch, INPUT_PULLUP); // check for a LOW input to indicate switch is closed to ground
  pinMode(setChargePulseSwitch, INPUT_PULLUP);

  if (digitalRead(setChargePulseSwitch) == LOW)
    chargePulse = true; // AC CDI

 // Timer1 default set up .5ms trigger pulse every 50 ms
  TCCR1A = 0;
  TCCR1B = (1 << WGM12); // CTC mode to OCR1A
  OCR1A = timerTopValue;
  TIMSK1 |= (1 << OCIE1A); // interrupt enable compareA
  TIMSK1 |= (1 << OCIE1B); // interrupt enable compareB
  OCR1B = 500; // sets trigger pulse width, 500 = 2Ms, 250 = 1Ms, 125 = .5Ms, set to 1250 for 5013 *********************************************
  TCCR1B |= (1 << CS11) | (1 << CS10); // prescaler 64 4us/tick

// Timer2 default setup charge pulse 12 periods 30 degrees each; only 5 get turned on
// charge pulse timing interval = Timer1 trigger period/12 = timerTopValue/96
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = 1 << WGM20; // lsb of mode 7 pwm to OCR2A
  TCCR2B = 1 << WGM22; // msb of mode 7 pwm to OCR2A;
  OCR2A = timerTopValue / 96; // 96 = 12*4*2 (#periods, prescaler difference, up/down timer mode )
  TIMSK2 = 0;
  TIMSK2 = 1 << TOIE2; // enable overflow interrupt
// actually start timer in ISR(TIMER1_COMPA_vect
// to prevent out of sync charge pulse, no prescaler set here

  attachInterrupt(digitalPinToInterrupt(3), delayPeriodTiming, FALLING);

}

void loop()
{
  if (millis() - lastAnalogRead >= analogReadInterval)
  {
    lastAnalogRead += analogReadInterval;
    potValue = analogRead(pot1); // rpm
    pickupValue = analogRead(pot2); // pickup position
    
//  barLength = analogRead(pot3); // length of bar for pickup 
  
// Timer2 OCR2A requires max value 255 => 615 lowest RPM
    if (chargePulse)
    {
      RPM = map(potValue, 0, 1023, 615, 10000);
      pickup = map(pickupValue, 0, 1023, 10, 75); // so advance will read based on delay, 57 for yamaha 350 2 pu, 74 for 1 pu, 72 for tw200, 25 for 5013
      pulseWidth = (60000000/RPM)/360; // time for 1° in uS
//    barSize = map(barLength, 0, 1023, 10, 60);  // 10 for yamaha 350 2 pu, 60 for 1 pu, 60 for tw200
// RPM = 615; // for my serial test purposes 615-3800
    }
    else
    {
      RPM = map(potValue, 0, 1023, 500, 3800);
      pickupValue = map(pickupValue, 0, 1023, 0, 50); // to set position of pickup so advance will read
//    pulseWidth = map(barLength, 0, 1023, 71, 44); // add Width to non charging case
// RPM = 500; // for my serial test purposes 500-3800
    }

    timerTopValue = 15000000UL / RPM;
    OCR1B = pulseWidth;

// if (digitalRead(setFallingSwitch) == LOW) // set Falling
// {
// risefall = 'F';
// }
// else
// {
// risefall = 'R';
// }

    lcd.setCursor(6, 0);
    lcd.print("     "); // print blank spaces to clear old data
    lcd.setCursor(6, 0);
    lcd.print(RPM);  // print rpm

    lcd.setCursor(16, 0);
    lcd.print("  ");
    lcd.setCursor(16, 0);
    lcd.print(pulseWidth, 1); // print us per degree
    
    lcd.setCursor(6, 1);
    lcd.print("   ");
    lcd.setCursor(6, 1);
    lcd.print(pickup); // print pickup coil position

//    lcd.setCursor(16, 1);
//    lcd.print("   ");
//    lcd.setCursor(16, 1);
//    lcd.print(barLength); // length of bar

    lcd.setCursor(11, 2);
    lcd.print("       ");
    lcd.setCursor(11, 2);
    lcd.print(copy_delayPeriod);
   
    lcd.setCursor(14, 3);
    lcd.print("      ");
    lcd.setCursor(14, 3);
    lcd.print(delayDegrees, 1);   // delayDegrees, 1);
  }
 
  if (trigger == true && interruptFlag == true )
  {
    trigger = false;
    interruptFlag = false;
    noInterrupts();
    copy_delayPeriod = delayPeriod;
    interrupts();

    delayDegrees = pickup - (360.0 * (copy_delayPeriod) / (timerTopValue * 4.0)); // for decimal place in deg display.
//    degreesAdvance = pickupValue - delayDegrees; // added
    }
}

ISR(TIMER1_COMPA_vect) {
  OCR1A = (timerTopValue); // value to set delay between pulses to trigger cdi
  digitalWrite(chargePin, LOW); // guarantee off charge pin at trigger
  digitalWrite(outputPin, HIGH); // turn on pin  trigger

// if (risefall == 'R') // switch not set; default Rising trigger
  {
    delayPeriodStart = micros(); // start looking for response as pulse rises
    trigger = true;
  }
// start Timer 2 for charge pulses
  if (chargePulse)
  {
    timeSliceCount = 0;
    TCNT2 = 0;
    OCR2A = timerTopValue/96; // set 12 periods
    TCCR2B |=  1 << CS22 | 1 << CS21; //prescaleer 256 16us/tick
  }
}

ISR(TIMER1_COMPB_vect) {
  digitalWrite(outputPin, LOW);

// if (risefall == 'F') // switch set for Falling trigger
  {
    delayPeriodStart = micros(); // start looking for response as pulse falls
    trigger = true;
  }
}

void delayPeriodTiming()
{
  delayPeriod = micros() - delayPeriodStart;
  interruptFlag = true;
}

ISR(TIMER2_OVF_vect)
// 5 pulses of 30 degrees starting at 60 degrees
// ON at 60,120,180,240,300 = 2,4,6,8,10
// OFF at 90,150,210,270,330 = 3,5,7,9,11
{
  if (timeSliceCount != 0 && timeSliceCount % 2 == 0)
  {
    digitalWrite (chargePin, HIGH);
  }
  else // if (timeSliceCount == 0 || timeSliceCount % 2 == 1)
  {
    digitalWrite(chargePin, LOW);
  }
  timeSliceCount++;

  if (timeSliceCount == 12)
  {
    timeSliceCount = 0;
// stop Timer2 by clearing prescaler bits
    TCCR2B &= ~1<< CS22;
    TCCR2B &= ~1<< CS21;
  }
}

But what happens is that I get 4 or 5 pulses from D4 when D6 is high

Just to be clear. The DC mode is not working properly and all you see are a few trigger pulses on D4 and then they go away.

In AC mode, with the charge pulses, do you see correct trigger pulse output on D4?
Was DC mode working with the original mono pulse code we started with?
Was DC mode working in the Bipolar pulse sketch?

cattledog:
Just to be clear. The DC mode is not working properly and all you see are a few trigger pulses on D4 and then they go away.
Yes that is right

In AC mode, with the charge pulses, do you see correct trigger pulse output on D4?
Yes they are fine then.

Was DC mode working with the original mono pulse code we started with?
Yes

Was DC mode working in the Bipolar pulse sketch?
Sorry, not sure and that test bed is not usable right now.

What I tried to do was go back to the older sketch with the mono pulse output.

Just to be clear. The DC mode is not working properly and all you see are a few trigger pulses on D4 and then they go away.
Yes that is right

I can not confirm what you are seeing. I loaded the code that you posted in #246 and made the RPM fixed at 1500 with this line which I uncommented. The else refers to when there are no charge pulses. That is with pin6 pulled HIGH by its INPUT_PULLUP.

else
    {
      RPM = map(potValue, 0, 1023, 500, 3800);
      pickupValue = map(pickupValue, 0, 1023, 0, 50); // to set position of pickup so advance will read
//    pulseWidth = map(barLength, 0, 1023, 71, 44); // add Width to non charging case
 RPM = 1500; // for my serial test purposes 500-3800

I jumpered the output of pin 4 to a second Arduino (grounds connected) on pin 2 where I ran the following simple interrupt counting code. I saw 25 counts per second which the the 1500 rpm. Pin 4 was outputting when the charge pulses were disabled. I'm not clear about what is going on with the scope or your hardware, but see if you can see what I see with a second Arduino.

volatile unsigned long  count = 0;
unsigned long copyCount = 0;

unsigned long lastRead = 0;
unsigned long interval = 1000;//one second

void setup()
{
  Serial.begin(115200);
  Serial.println("start...");
  
  //interrupt on pin2
  pinMode(2,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2),isrCount,RISING);
}

void loop()
{
  if (millis() - lastRead >= interval) //read interrupt count every second
  {
    lastRead  += interval;
    // disable interrupts,make copy of count,reenable interrupts
    noInterrupts();
    copyCount = count;
    count = 0;
    interrupts();
    //use copyCount for all calulations and actions in loop
    Serial.println(copyCount);
  }
}

void isrCount()
{
  count++;
}

Hi, OK I must have a flaky UNO, I accidentally left it on last night and this morning it was dead, would not drive display so I let it sit disconnected for 30 min and it came back to life but I don't trust it now, more here soon.

Have worked with it anyway and this seems to be a working sketch, it goes back to the one I was using before the DAC idea. I have cleaned up the display items a little and the timing computation works when the AC is on but not when it is off. Also I cannot get it to change from AC to DC without manual reset and don't see why.
Best, Tom

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h> // include i/o class header
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config display for hd44780 chip

int pot1 = A1; // select the input pin for the pot for rpm
int pot2 = A2; // select the input pin for the pot for pickup location in degrees
int pot3 = A3; // select the input pin for the pot for length of bar on flywheel in degrees
int potValue = 0; // variable to store the value coming from the sensor
int pickupValue = 0; // position of pickup in degrees
int potWidth = 0; // variable to set length of bar on flywheel
int timerTopValue = 12500; // changed from timerTopValue = 0
int outputPin = 4; // select the pin for the output for trigger pulse, changed from 8
int chargePin = 7; // select the pin for the output for charge pulses

volatile boolean trigger = false;
volatile unsigned long delayPeriod;
unsigned long copy_delayPeriod;
volatile unsigned long delayPeriodStart;
float delayDegrees; // changed from int to float for decimal place display
int RPM;
int pickup;
// int barLength;
int pulseWidth;                                            
volatile boolean interruptFlag;
// unsigned long analogReadInterval = 500; // read pots and map
unsigned long lastAnalogRead;

// const byte setFallingSwitch = 5;
// char risefall = 'R'; // default rising mode

const byte setChargePulseSwitch = 6;
boolean chargePulse = false ;  // default dc powered mode

volatile byte timeSliceCount = 0; // TDC 0 degrees

void setup() {
// Serial.begin(115200);
// Serial.println("starting...");
  lcd.begin(20, 4); // initialize the lcd for 20 chars 4 lines, turn on backlight
  lcd.setCursor(1, 0); // lcd display setup of unchanging headings
  lcd.print("RPM:"); // print fixed characters
  lcd.setCursor(12, 0);
  lcd.print("Deg"); 
  lcd.setCursor(1, 1);
  lcd.print("Pos:");
//  lcd.setCursor(12, 1);
//  lcd.print("Bar:");
  lcd.setCursor(1, 2);
  lcd.print("Us Delay:");
  lcd.setCursor(1, 3);
  lcd.print("Deg Advance:");

  pinMode(outputPin, OUTPUT); // declare the outputPin as an OUTPUT
  pinMode(chargePin, OUTPUT); // declare the chargePin as an OUTPUT
// pinMode (setFallingSwitch, INPUT_PULLUP); // check for a LOW input to indicate switch is closed to ground
  pinMode(setChargePulseSwitch, INPUT_PULLUP);

  if (digitalRead(setChargePulseSwitch) == LOW)
    chargePulse = true; // AC CDI

 // Timer1 default set up .5ms trigger pulse every 50 ms
  TCCR1A = 0;
  TCCR1B = (1 << WGM12); // CTC mode to OCR1A
  OCR1A = timerTopValue;
  TIMSK1 |= (1 << OCIE1A); // interrupt enable compareA
  TIMSK1 |= (1 << OCIE1B); // interrupt enable compareB
  OCR1B = 500; // sets trigger pulse width, 500 = 2Ms, 250 = 1Ms, 125 = .5Ms, set to 1250 for 5013 *********************************************
  TCCR1B |= (1 << CS11) | (1 << CS10); // prescaler 64 4us/tick

// Timer2 default setup charge pulse 12 periods 30 degrees each; only 5 get turned on
// charge pulse timing interval = Timer1 trigger period/12 = timerTopValue/96
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = 1 << WGM20; // lsb of mode 7 pwm to OCR2A
  TCCR2B = 1 << WGM22; // msb of mode 7 pwm to OCR2A;
  OCR2A = timerTopValue / 96; // 96 = 12*4*2 (#periods, prescaler difference, up/down timer mode )
  TIMSK2 = 0;
  TIMSK2 = 1 << TOIE2; // enable overflow interrupt
// actually start timer in ISR(TIMER1_COMPA_vect
// to prevent out of sync charge pulse, no prescaler set here

  attachInterrupt(digitalPinToInterrupt(3), delayPeriodTiming, FALLING);

}

void loop()
{
  unsigned long analogReadInterval = 500; // read pots and map
  if (millis() - lastAnalogRead >= analogReadInterval)
  {
    
    lastAnalogRead += analogReadInterval;
    potValue = analogRead(pot1); // rpm
    pickupValue = analogRead(pot2); // pickup position
    
//  barLength = analogRead(pot3); // length of bar for pickup 
  
// Timer2 OCR2A requires max value 255 => 615 lowest RPM
    if (chargePulse)
    {
      RPM = map(potValue, 0, 1023, 615, 10000);
      pickup = map(pickupValue, 0, 1023, 10, 75); // so advance will read based on delay, 57 for yamaha 350 2 pu, 74 for 1 pu, 72 for tw200, 25 for 5013
      pulseWidth = (60000000/RPM)/360; // time for 1° in uS
//    barSize = map(barLength, 0, 1023, 10, 60);  // 10 for yamaha 350 2 pu, 60 for 1 pu, 60 for tw200
// RPM = 615; // for my serial test purposes 615-3800
    }
    else
    {
      RPM = map(potValue, 0, 1023, 500, 3800);
      pickupValue = map(pickupValue, 0, 1023, 0, 50); // to set position of pickup so advance will read
//    pulseWidth = map(barLength, 0, 1023, 71, 44); // add Width to non charging case
// RPM = 500; // for my serial test purposes 500-3800
    }

    timerTopValue = 15000000UL / RPM;
    OCR1B = pulseWidth;

// if (digitalRead(setFallingSwitch) == LOW) // set Falling
// {
// risefall = 'F';
// }
// else
// {
// risefall = 'R';
// }

    lcd.setCursor(6, 0);
    lcd.print("     "); // print blank spaces to clear old data
    lcd.setCursor(6, 0);
    lcd.print(RPM);  // print rpm

    lcd.setCursor(16, 0);
    lcd.print("  ");
    lcd.setCursor(16, 0);
    lcd.print(pulseWidth, 1); // print us per degree
    
    lcd.setCursor(6, 1);
    lcd.print("   ");
    lcd.setCursor(6, 1);
    lcd.print(pickup); // print pickup coil position

//    lcd.setCursor(16, 1);
//    lcd.print("   ");
//    lcd.setCursor(16, 1);
//    lcd.print(barLength); // length of bar

    lcd.setCursor(11, 2);
    lcd.print("       ");
    lcd.setCursor(11, 2);
    lcd.print(copy_delayPeriod);
   
    lcd.setCursor(14, 3);
    lcd.print("      ");
    lcd.setCursor(14, 3);
    lcd.print(delayDegrees, 1);   // delayDegrees, 1);
  }
 
  if (trigger == true && interruptFlag == true )
  {
    trigger = false;
    interruptFlag = false;
    noInterrupts();
    copy_delayPeriod = delayPeriod;
    interrupts();

    delayDegrees = pickup - (360.0 * (copy_delayPeriod) / (timerTopValue * 4.0)); // for decimal place in deg display.
//    degreesAdvance = pickupValue - delayDegrees; // added
    }
}

ISR(TIMER1_COMPA_vect) {
  OCR1A = (timerTopValue); // value to set delay between pulses to trigger cdi
  digitalWrite(chargePin, LOW); // guarantee off charge pin at trigger
  digitalWrite(outputPin, HIGH); // turn on pin  trigger

// if (risefall == 'R') // switch not set; default Rising trigger
  {
    delayPeriodStart = micros(); // start looking for response as pulse rises
    trigger = true;
  }
// start Timer 2 for charge pulses
  if (chargePulse)
  {
    timeSliceCount = 0;
    TCNT2 = 0;
    OCR2A = timerTopValue/96; // set 12 periods
    TCCR2B |=  1 << CS22 | 1 << CS21; //prescaleer 256 16us/tick
  }
}

ISR(TIMER1_COMPB_vect) {
  digitalWrite(outputPin, LOW);

// if (risefall == 'F') // switch set for Falling trigger
  {
    delayPeriodStart = micros(); // start looking for response as pulse falls
    trigger = true;
  }
}

void delayPeriodTiming()
{
  delayPeriod = micros() - delayPeriodStart;
  interruptFlag = true;
}

ISR(TIMER2_OVF_vect)
// 5 pulses of 30 degrees starting at 60 degrees
// ON at 60,120,180,240,300 = 2,4,6,8,10
// OFF at 90,150,210,270,330 = 3,5,7,9,11
{
  if (timeSliceCount != 0 && timeSliceCount % 2 == 0)
  {
    digitalWrite (chargePin, HIGH);
  }
  else // if (timeSliceCount == 0 || timeSliceCount % 2 == 1)
  {
    digitalWrite(chargePin, LOW);
  }
  timeSliceCount++;

  if (timeSliceCount == 12)
  {
    timeSliceCount = 0;
// stop Timer2 by clearing prescaler bits
    TCCR2B &= ~1<< CS22;
    TCCR2B &= ~1<< CS21;
  }
}

This code seems very similar to wht you posted in#246.

Have worked with it anyway and this seems to be a working sketch, it goes back to the one I was using before the DAC idea. I have cleaned up the display items a little and the timing computation works when the AC is on but not when it is off

Do you mean that you now see outgoing pulses on pin4 in both modes, but not the timing of the return pulses?

I see trigger output as before with my interrupt counter. I then set up my delayed return pulse sketch for 2000 us delay and I see that reported in the Us Delay: line of the lcd. All looks well with my tool set.

There is certainly clean up to be done, but first, lets work through the issue of sending trigger pulses and reading returns in DC mode.

cattledog:
This code seems very similar to wht you posted in#246.
Do you mean that you now see outgoing pulses on pin4 in both modes, but not the timing of the return pulses?
Yes, the timing computation only works when there are pulses going out on pin 7 for the charge pulse.
Pin 4 has good pulses in both situations, and the relation to the charge pluses is perfect.

I see trigger output as before with my interrupt counter. I then set up my delayed return pulse sketch for 2000 us delay and I see that reported in the Us Delay: line of the lcd. All looks well with my tool set.

There is certainly clean up to be done, but first, lets work through the issue of sending trigger pulses and reading returns in DC mode.
OK, I agree that and the reset should be working first.

Also I cannot get it to change from AC to DC without manual reset and don't see why.

You are only reading the AC/DC setting switch in setup. Leave it ins setup but add the reading to loop here

if (millis() - lastAnalogRead >= analogReadInterval)
  {    
    lastAnalogRead += analogReadInterval;
    potValue = analogRead(pot1); // rpm
    pickupValue = analogRead(pot2); // pickup position

    if (digitalRead(setChargePulseSwitch) == LOW)
    chargePulse = true; // AC CDI
.
.
.

Do you understand what was previously wrong with the pin 4 output?

Yes, the timing computation only works when there are pulses going out on pin 7 for the charge pulse.

Do you know if you are seeing return pulses coming back to pin3?

Yes whether in DC or AC mode there are always pulses at D3, the current to the ign coil is sensed by a clamp on pickup and triggers a small SCR so as long as the coil is making a spark there is a signal at D3

I am not sure what was going on with D4 output, perhaps a conflict in timer? That is why I went back to a known good sketch to modify.
Tom

Tom--
Since I can't confirm your issue, I would like you to try using a second Arduino to issue the response, and see if the calculations occur. Lets try and separate software from hardware issues.

Jumper the cdi tester output on pin 4 to the second Arduino pin 3 and the second Arduino's pin 4 back to pin 3 of the cdi tester. Do you see Us Delay reported in both AC and DC mode?

//pin 3 interrupt as as input
//pin 4 as pulse output
void setup() {
 pinMode(4,OUTPUT);
 attachInterrupt(digitalPinToInterrupt(3),pulse,RISING);//interrupt on pin3
}

void loop() {}

void pulse()
{
  delayMicroseconds(2000);
  //delayMicroseconds(0);
  digitalWrite(4,LOW);//will drive main board interrupt FALLING
  delayMicroseconds(10);
  digitalWrite(4,HIGH);
}

Hi, I may be looking at this wrong, when in DC mode it is pot2 that does not work so it shows position as 0 and therefore degree advance shows as 0 or 0.1 I was thinking that this part of the code was just not working and it may be, just that if pickup position is not set to something real it has nothing to compute. Make sense?
Tom

Make sense?

No.
The math does not require a non zero value

delayDegrees = pickup - (360.0 * (copy_delayPeriod) / (timerTopValue * 4.0)); // for decimal place in deg display.

My test code is showing POS(pickup) at 0. With a 2000 microsecond delay in the response I see Us Delay 2000 and as expected from the math, Deg Advance is negative.

For now, focus on the Us Delay. That's the microsecond value of the delayed response from the cdi unit (or the simulated test code of my previous post.). It shows if there a response read as a reply to the outgoing pulse.

Any time you have a question about values, you can always comment out the code which varies a pot, and just substitute a fixed value.

Hi, re the math, no what I meant was that the pot2 was not being read so the code saw a 0. Once I got the pot for position to read in AC and DC then that problem went away. You will see that I striped a lot away. It seems to work very well, maybe you will see some remnants still lurking in the timer parts, I really don't understand the code for timers!
Thanks for everything.

TESTER.zip (255 KB)

I'm pleased you got the mysteries sorted out. I can't say that I understand what what wrong, but I don't believe it was the code. Given that you have fought your way through so many hardware issues over the long course of this project its time to give you a Karma point.

I noticed on the image of the actual charge pulse output that there are only 4 pulses, and the first one is somewhat low. The pin output is 5 pulses. Do you understand what is going on here?

Nice job cleaning up the code for version_15. There is one issue which needs to be addressed.

You start the timing cycle in two places. This goes back to when we wanted to time from either the rising or falling edge of the trigger pulse which is one degree long. The rising edge timing is in ISR(Timer1_COMPA_vect) and the falling edge timing is in the ISR(TIMER1_COMPB_vect). Either put the R/F back, or decide which start time to use.

ISR(TIMER1_COMPA_vect) {
  OCR1A = (timerTopValue); // value to set delay between pulses to trigger cdi
  digitalWrite(chargePin, LOW); // guarantee off charge pin at trigger
  digitalWrite(outputPin, HIGH); // turn on pin  trigger

  
    delayPeriodStart = micros(); // start looking for response as pulse rises
    trigger = true;
  
  // start Timer 2 for charge pulses
  if (chargePulse)
  {
    timeSliceCount = 0;
    TCNT2 = 0;
    OCR2A = timerTopValue / 96; // set 12 periods
    TCCR2B |=  1 << CS22 | 1 << CS21; //prescaleer 256 16us/tick
  }
}

ISR(TIMER1_COMPB_vect) {
  digitalWrite(outputPin, LOW);
  
    delayPeriodStart = micros(); // start looking for response as pulse falls
    trigger = true;

}

Thanks, re the actual charge pulses, they are charging up a 2.2uf 400v capacitor so the first pulse has a lot of load on it compared to the final one. As for the seemingly only 4 pulses, I think the first one is just too small to show. For this I am only powering the transformer driver circuit with 12v and the working version will likely be driven with a 25v to 35v supply. I also need to work out a pos and neg trigger combined as some Honda CDI need to see both. Most of the Yamaha that I make I need them completely seperate to do testing on the CDI. This will all be done in hardware.
Again, many thanks.

By the way I assume you have a Australian Cattle Dog ? I have a 1 1/2 year old male and he is, well a typical cattle dog but with an attitude.
Tom

I also need to work out a pos and neg trigger combined as some Honda CDI need to see both. Most of the Yamaha that I make I need them completely seperate to do testing on the CDI. This will all be done in hardware.

It's too bad the DAC did not work out for this purpose. Are you certain that with what you know now, you can't get it to work. The code is ready to go :slight_smile:

By the way I assume you have a Australian Cattle Dog ? I have a 1 1/2 year old male and he is, well a typical cattle dog but with an attitude.

Mine is long gone, but I think they all have attitudes. They are very tough breed to have. I never had the patience to properly train mine, and she did what she wanted to do. Totally a mind of it's own.

Mine was a terrible watch dog-- aggressive but not not alert. No alarm barking, but she'd bite when a stranger sneaked up on her.

Cattledog,
Hi, I had an idea I wanted to try. For this I need a second pulse on a second output pin to occur an adjustable time after the first trigger pulse on D4, the time will be 1° so I thought to use pulseWidth.
Of course this code does not work but may give you an idea of what I wanted to do.

ISR(TIMER1_COMPB_vect) {
  digitalWrite(outputPin, LOW);
  time = pulseWidth
  wait(time)
  digitalWrite(output2Pin, HIGH); // turn on 2nd pin trigger D5
  {
    delayPeriodStart = micros(); // start looking for response as pulse rises
    trigger = true;
  }
  digitalWrite(output2Pin, LOW);

Tom

Hi, I had an idea I wanted to try. For this I need a second pulse on a second output pin to occur an adjustable time after the first trigger pulse on D4, the time will be 1° so I thought to use pulseWidth.
Of course this code does not work but may give you an idea of what I wanted to do.

Do you want a second pulse of 1 degree width starting 1 degree after the first pulse is terminated? Does this pulse need to be 1 degree wide, or can it be shorter. Do you want to start the return pulse timing from this second pulse? Is the delay period of 1 degree after the first pulse ends fixed or variable?

Do you still have a working version of the bipolar pulse program. If we make both the first and second pulses positive where bar width is setting the timing between them would that work? We could generate the pulses either with or without the DAC.

I'm trying to decide if we can add a second output pulse to the current unipulse program or if its better to leverage off the two pulse program but make both pulses positive (can be done without DAC).

How certain are you that you will need a two pulse program, and how much is this a quick and dirty experiment?

Hi, well this is just an experiment but it looks likely to be as good or better than what I have now. Remember I once said I did not understand timers? Well that is certainly still true! Today I got a working version going but it has issues. So what I don't know is: where is the width or duration of the existing pulse set? The second pulse, on a different output pin, should likely start right where the first ends but it may need just a tiny amount of time in between. Lets for now assume it won't. But it needs to be as wide as the first.
Thanks, Tom

where is the width or duration of the existing pulse set?

The pulse width is set a fixed one degree, by the OCR1B value. The compare match B turns the pulse off.

The second pulse, on a different output pin, should likely start right where the first ends but it may need just a tiny amount of time in between. Lets for now assume it won't. But it needs to be as wide as the first.

OK. Ill see what I can do. Where does the return pulse delay timing start? With the first or second pulse? Can you explain the function of the second pulse?