Go Down

Topic: CDI tester project (Read 13959 times) previous topic - next topic

tom_bauer

Cattledog,
I have worked with the code and with the hardware to get a pretty nice result I think. It is mostly a rework of the old version. What I am stumbling on is the DC output. I just want to turn off the HV pulse generator and keep everything else running. When I remove pin 6 from ground the output on pin 5 gets strange, going in cycles. I also want to keeo the reporting of degrees advance in the DC mode.
Thanks, Tom

Code: [Select]
// 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

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

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// set the LCD address to 0x3f for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

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.
    }
}

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;
  }
}

cattledog

#241
Apr 21, 2019, 05:53 pm Last Edit: Apr 21, 2019, 05:53 pm by cattledog
Quote
What I am stumbling on is the DC output. I just want to turn off the HV pulse generator and keep everything else running. When I remove pin 6 from ground the output on pin 5 gets strange, going in cycles.
Code: [Select]

// const byte setFallingSwitch = 5;
// char risefall = 'R'; // default rising mode
//pinMode (setFallingSwitch, INPUT_PULLUP);


You have removed the pinMode for pin5 and it will be floating. I'm somewhat unclear about what you are trying to do with the R/F setting, and you have a conflict here as you are setting the start time for both R and F modes.
Code: [Select]

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;
  }
}


Quote
I also want to keep the reporting of degrees advance in the DC mode.
I see in the last bi-polar pulse code we had
Code: [Select]
degreesAdvance = pickupValue - delayDegrees;

I think you can just add it here, and display it as you do in the bipolar sketch.
Code: [Select]
delayDegrees = pickup - (360.0 * (copy_delayPeriod) / (timerTopValue * 4.0)); // for decimal place in deg display.
degreesAdvance = pickupValue - delayDegrees;



tom_bauer

#242
Apr 21, 2019, 07:03 pm Last Edit: Apr 21, 2019, 07:29 pm by tom_bauer
Hi, I see I misspoke in last message. It should say "What I am stumbling on is the DC output. I just want to turn off the HV pulse generator and keep everything else running. When I remove pin 6 from ground the output on pin 4 gets strange, going in cycles."

OK let me clarify as it may make a difference. I don't think I need a switch to choose between Rise and Fall for the start of the timing operation. It will always be from the Rising edge so I wanted to remove that part of the code and have it operate in that mode only.
Also if it simplifies things there is no need for the code to know when the charge pulses are being used, just a way to turn them on or off by switch. The same switch will turn on the DC when it turns off the charge pulses.
I have had a hardware problem for a long time and did not realize it which is why I thought the DAC may be the answer, but once I found that problem it all became much simpler.

I should also note I am using the pins of the old system, A1 is rpm, A2 is pickup position, D3 is input from sensor for spark, D4 is pulse trigger out, D6 is charge pulse on, D7 is charge pulse out.
Tom

cattledog

Quote
I should also note I am using the pins of the old system, A1 is rpm, A2 is pickup position, D3 is input from sensor for spark, D4 is pulse trigger out, D6 is charge pulse on, D7 is charge pulse out.
Quote
When I remove pin 6 from ground the output on pin 4 gets strange, going in cycles."
I can't see any software interaction between the pulse trigger and the charge pulses or charge pulse selector switch . Can you show the pulse trigger output on a scope? Are you looking at the Arduino output of pin 4, or the HV trigger?

Quote
D6 is charge pulse on, D7 is charge pulse out
Since you moved the switch to D6, are you certain of the wiring, and can confirm that the INPUT_PULLUP is active. Use a simple test with digitalRead() to check the output of the switch.

Once I'm more clear about what is going on, I can simplify the sketch to remove stuff that isn't needed.

I would also recommend that you go back to using the hd44780 library. It really is superior and will make life easy if you have to change a display.

tom_bauer

When I open the switch for D6, it goes to 5v, I have to reset, then output on D7 stops. After reset, the output on D4 runs for several pulses then stops with just a very tiny noise pulse occasionally. I have to reset each time I change D6.
Tom

cattledog

#245
Apr 21, 2019, 09:06 pm Last Edit: Apr 21, 2019, 09:10 pm by cattledog
Quote
I have to reset each time I change D6.
That can be fixed with the changes we made in the Bipolar Pulse Code where the switch checking was moved out of setup and into loop(). It can be added in loop where you do the analogRead() every 500ms or els try and adopt the setSwichPresets function in the last Bipolar code.

Quote
After reset, the output on D4 runs for several pulses then stops with just a very tiny noise pulse occasionally.
I am really confused. After reset with D6 changed, it should just look like a fresh start with D6 set for DC. Do you see normal trigger pulses on D4 in DC mode at all?

tom_bauer

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.

Code: [Select]

// 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;
  }
}

cattledog

Quote
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?

tom_bauer

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.

cattledog

Quote
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.

Code: [Select]

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.

Code: [Select]
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++;
}

tom_bauer

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

Code: [Select]

#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;
  }
}




cattledog

This code seems very similar to wht you posted in#246.
Quote
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.

tom_bauer

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.

cattledog

Quote
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
Code: [Select]

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?

Quote
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?

tom_bauer

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

Go Up