need help with digital input to digital output function

i am trying to take 3 spark outputs from a megasquirt V2.2 and run them into 3 uno inputs.
then have the uno output to the 3 spark IGBT's

so far it almost works but the sparkC does not always come through. not sure if the code is not correct or if the megasquirt is not outputting.

i put in the delay to shorten up the serial monitor info
right now only the input is wired up.
i have one jumper from uno ground to chassis ground of the megasquirt

int sparkA = 2;
int sparkB = 4;
int sparkC = 7;
int copA = 3;
int copB = 5;
int copC = 6;

void setup() { 
 Serial.begin(9600);  
 pinMode(2,    INPUT);       //spark outputs
 pinMode(4,    INPUT);
 pinMode(7,    INPUT);
 pinMode(copA, OUTPUT);      //coil outputs
 pinMode(copB, OUTPUT);
 pinMode(copC, OUTPUT);
}

void loop() {
   while  (digitalRead(sparkA) == HIGH)
   {
    digitalWrite(copA, HIGH);
    Serial.println("  A!");
    delay(1);
   }

   while  (digitalRead(sparkB) == HIGH)
   {
    digitalWrite(copB, HIGH);
    Serial.println("  BBBBBBBB");
    delay(1);
   }

   while  (digitalRead(sparkC) == HIGH)
   {
    digitalWrite(copC, HIGH);
    Serial.println("  CCCCCCCCCCCCCCCCCCCCC");
    delay(1);
   }
    }

and the serial monitor shows..........

  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  CCCCCCCCCCCCCCCCCCCCC
  CCCCCCCCCCCCCCCCCCCCC
  CCCCCCCCCCCCCCCCCCCCC
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  CCCCCCCCCCCCCCCCCCCCC
  CCCCCCCCCCCCCCCCCCCCC
  CCCCCCCCCCCCCCCCCCCCC
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  CCCCCCCCCCCCCCCCCCCCC
  CCCCCCCCCCCCCCCCCCCCC
  CCCCCCCCCCCCCCCCCCCCC
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  A!
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  BBBBBBBB
  A!
  A!
  A!
  A!
  A!
  A!

holy cow got it working perfect at idle!
however it stumbles like a rev limiter with any throttle and the IGBT get hot fast when trying.
something is dwelling the IGBT's too much?
how would i include a fixed dwell value for the digitalWrite(copX, HIGH); ?
i only need about 1-2 millis per (digitalRead(sparkX) == HIGH).

the megasquirt is supposed to output a dwell amount that is set it its software but i have my doubts of it being correct for this

int sparkA = 2;
int sparkB = 4;
int sparkC = 7;
int copA = 3;
int copB = 5;
int copC = 6;

void setup() { 
 Serial.begin(9600);  
 pinMode(2,    INPUT);       //spark signals
 pinMode(4,    INPUT);
 pinMode(7,    INPUT);
 pinMode(copA, OUTPUT);      //coil outputs
 pinMode(copB, OUTPUT);
 pinMode(copC, OUTPUT);
}

void loop() {
        if  (digitalRead(sparkA) == HIGH)
   {
    digitalWrite(copA, HIGH);
    Serial.println("  A");
    delay(1);
   }

   else if  (digitalRead(sparkB) == HIGH)
   {
    digitalWrite(copB, HIGH);
    Serial.println("  BBBBBBBB");
    delay(1);
   }
   else if  (digitalRead(sparkC) == HIGH)
   {
    digitalWrite(copC, HIGH);
    Serial.println("  CCCCCCCCCCCCCCCCCCCCC");
    delay(1);
   }
   else { 
    digitalWrite(copA, LOW);
    digitalWrite(copB, LOW);
    digitalWrite(copC, LOW);
   }
    }

If something gets hot, the circuit diagram should be checked first. Do it yourself, or post it here.

Inputs usually should be enabled with pinMode(pin, INPUT_PULLUP), with HIGH being the default and unconnected value.

the IGBT run cool at idle for minutes on end
only when i apply some throttle does the IGBT get hot.
i will adjust the pinMode(pin, INPUT_PULLUP) tomorrow

Give this a shot (compiles, not tested; monitor temps closely…)

//ref: sketch_oct24b

#define NUM_CYLINDERS       3           //# of cylinders
#define DWELL_TIME          1000ul      //microseconds of dwell time

//pin definitions
const byte sparkA = 2;
const byte sparkB = 4;
const byte sparkC = 7;
const byte copA = 3;
const byte copB = 5;
const byte copC = 6;

//spark control structure
typedef struct structSpkCtl
    {
        byte            pinSpkIn;       //pin number for trigger input
        byte            lastPinSpk;     //used for state change detect logic
        byte            pinCOPOut;      //pin number for COP
        bool            bState;         //COP on (true) or off (false)
        unsigned long   ulDwell;        //in theory allows cylinder specific dwell
        unsigned long   ulTOn;
        
    };

//spark control


structSpkCtl SpkCtl[NUM_CYLINDERS] = 
    {
        {
            .pinSpkIn = sparkA,
            .lastPinSpk = LOW,
            .pinCOPOut = copA,
            .bState = false,
            .ulDwell = DWELL_TIME,
            .ulTOn = 0

        },
        {
            .pinSpkIn = sparkB,
            .lastPinSpk = LOW,
            .pinCOPOut = copB,
            .bState = false,            
            .ulDwell = DWELL_TIME,
            .ulTOn = 0        
        },
        {
            .pinSpkIn = sparkC,
            .lastPinSpk = LOW,
            .pinCOPOut = copC,
            .bState = false,
            .ulDwell = DWELL_TIME,
            .ulTOn = 0
            
        }
    };


void setup() 
{
    Serial.begin(9600); 

    //setup pins and initialize "last" reading of trigger inputs
    for( int i=0; i<NUM_CYLINDERS; i++ )
    {
        pinMode( SpkCtl[i].pinSpkIn, INPUT );
        pinMode( SpkCtl[i].pinCOPOut, OUTPUT );
        //
        SpkCtl[i].lastPinSpk = digitalRead( SpkCtl[i].pinSpkIn );
        
    }//for
                
}//setup

void loop() 
{
    ReadSparkInputs();      //go read a cylinder
    CheckCOPOutputs();      //see if a cylinder's dwell time has ended
        
}//loop

void ReadSparkInputs( void )
{
    byte
        spkState;
    static byte
        idxCylinder = 0;

    //if COP is now on for this cylinder, skip checking trigger
    if( SpkCtl[idxCylinder].bState == false )
    {
        //read trigger input
        spkState = digitalRead( SpkCtl[idxCylinder].pinSpkIn );
        //is pin reading now different from last read?
        if( spkState != SpkCtl[idxCylinder].lastPinSpk )
        {
            //yes...make now-reading "last" reading
            SpkCtl[idxCylinder].lastPinSpk = spkState;
            //if trigger input has gone high...
            if( spkState == HIGH )
            {
                //turn on the COP for that cylinder
                digitalWrite( SpkCtl[idxCylinder].pinCOPOut, HIGH );
                //log the time of turn-on
                SpkCtl[idxCylinder].ulTOn = micros();
                //and set on-flag to true
                SpkCtl[idxCylinder].bState = true;
                
            }//if
            
        }//if
        
    }//if
    
    //check one cylinder each pass
    idxCylinder++;
    if( idxCylinder == NUM_CYLINDERS )
        idxCylinder = 0;
        
}//ReadSparkInputs

void CheckCOPOutputs( void )
{
    static byte
        idxCylinder = 0;

    //is COP for this cylinder currently on?
    if( SpkCtl[idxCylinder].bState )
    {
        //yes...has dwell time expired?
        if( (micros() - SpkCtl[idxCylinder].ulTOn) >= SpkCtl[idxCylinder].ulDwell )
        {
            //yes; set COP output low
            digitalWrite( SpkCtl[idxCylinder].pinCOPOut, LOW );
            //and clear on-flag
            SpkCtl[idxCylinder].bState = false;
            
        }//if
        
    }//if

    //check one COP's dwell time per pass
    idxCylinder++;
    if( idxCylinder == NUM_CYLINDERS )
        idxCylinder = 0;
    
}//CheckCOPOutputs

Hi,
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Have you got a scope to check the waveforms you are reading at input and sending out the outputs?

Thanks.. Tom.. :slight_smile:

coming out of the megasquirt on 3 actual wires not 6
sparkA = 2;
sparkB = 4;
sparkC = 7;

then 3 wires coming out of the uno that are Y to the 330 resistors
so a 330 per ecospark
copA = 3;
copB = 5;
copC = 6;

leg #2 of the IGBT's is the ground of the 2 wire coil on plug

coming out of the megasquirt

Can you see the details on that image because I can't

sorry had a moment trying to use microsoft tools and failed
can you see my literal print/cut/paste image?

i got one of these to monitor

the current to the cop’s

huge thanks to blackfin!
the code seems to be working great and IGBT are cool at all rpm so far
need to bundle this up and go for a drive.

in this area what are the . periods doing????

structSpkCtl SpkCtl[NUM_CYLINDERS] =
{
{
.pinSpkIn = sparkA,
.lastPinSpk = LOW,
.pinCOPOut = copA,
.bState = false,
.ulDwell = DWELL_TIME,
.ulTOn = 0

},
{
.pinSpkIn = sparkB,
.lastPinSpk = LOW,
.pinCOPOut = copB,
.bState = false,
.ulDwell = DWELL_TIME,
.ulTOn = 0
},
{
.pinSpkIn = sparkC,
.lastPinSpk = LOW,
.pinCOPOut = copC,
.bState = false,
.ulDwell = DWELL_TIME,
.ulTOn = 0

}
};

in this area what are the . periods doing

Telling the compiler where to put stuff.

Please remember to use code tags when posting code

turbothis:
huge thanks to blackfin!
the code seems to be working great and IGBT are cool at all rpm so far
need to bundle this up and go for a drive.

in this area what are the . periods doing????

structSpkCtl SpkCtl[NUM_CYLINDERS] =

{
        {
            .pinSpkIn = sparkA, ...

As AWOL noted, it's the syntax required for initializing the elements of a structure (or, in this case, an array of structures.)

Good luck on your drive. Be careful...

TheMemberFormerlyKnownAsAWOL:
Please remember to use code tags when posting code

would be nice to have the quick reply to have the tags too
thanks for the help
i drove around and it did great
i only got some stumbles at idle in gear at a stop light.
not sure what that is from yet

is there an easy arduino example of this array of structure thing?

might also have an injector going bad.......

turbothis:
would be nice to have the quick reply to have the tags too
thanks for the help
i drove around and it did great
i only got some stumbles at idle in gear at a stop light.
not sure what that is from yet

Keep in mind that the plug fires on the trailing edge of the COP drive:

digitalWrite( SpkCtl[idxCylinder].pinCOPOut, LOW );

How is your static timing set? Does the MS perform any spark advance/retard?

Does the trigger signal (e.g. sparkA) take the dwell you're injecting here into account?

Because the spark fires after the dwell period and the dwell period is 1mS right now, that means that at idle the spark occurs ~6-degrees after the trigger; at 7000RPM 1mS to dwell means 42-degrees of crank rotation. In both cases, the result is that the spark event is retarded relative to the trigger.

Unless the static dwell is accounted for in the trigger, the spark timing may be late.

Dwell really should be dynamic; you may not need as much dwell at low manifold vacuum as at WOT when cylinder pressures are higher. Same for coolant and manifold air temperature; colder == higher dwell...

turbothis:
would be nice to have the quick reply to have the tags too

You can turn on the full editor functionality for Quick Reply with a setting in your profile or, of course, you can just type in the tags

MS does the full timing curve
the trigger signal does have dwell on the output. i can set this to zero in the software though. or small....

i was hoping to have the dwell input pass right through the UNO.
so when the MS outputs and dwells this would be the task done by the UNO

turbothis:
MS does the full timing curve
the trigger signal does have dwell on the output. i can set this to zero in the software though. or small....

i was hoping to have the dwell input pass right through the UNO.
so when the MS outputs and dwells this would be the task done by the UNO

The code that I did looks for a rising edge on the trigger (sparkX) input and triggers a high level on the COP output for 1mS.

Would you rather the Uno simply drive its output to be a copy of the input trigger signal? I'm a little confused: why not drive the COPs directly with the MS if you want to have the dwell "dwell input pass right through the UNO"? What is the Uno actually doing?

sorry for the confusion!
the main goal is to drive the COP's with the uno as it function much better at this than the MS. the MS will have massive resets on cranking and while driving when it has the IGBT wired to it.

"Would you rather the Uno simply drive its output to be a copy of the input trigger signal?"
pretty much

If you want the Uno to follow the MS perhaps try this:

//ref: sketch_oct25a

//pin definitions
#define TRGA_MASK   0b00000100  //PD2
#define TRGB_MASK   0b00010000  //PD4
#define TRGC_MASK   0b10000000  //PD7

#define COPA_MASK   0b00001000  //PD3
#define COPB_MASK   0b00100000  //PD5
#define COPC_MASK   0b01000000  //PD6


void setup()
{
    Serial.begin(9600);

    //set triggers as inputs (0), COPs as outputs (1)
    DDRD &= ~(TRGA_MASK | TRGB_MASK | TRGC_MASK);
    DDRD |= (COPA_MASK | COPB_MASK | COPC_MASK);
                   
}//setup

void loop()
{
    byte    
        prt,
        msk;

    //read the port pins
    prt = PIND;
    //COPA follows trigger A
    msk = (prt & TRGA_MASK) ? COPA_MASK:0;
    //COPB follows trigger B
    msk |= (prt & TRGB_MASK) ? COPB_MASK:0;
    //COPC follows trigger C
    msk |= (prt & TRGC_MASK) ? COPC_MASK:0;

    //mask out bits 0 and 1 for OR
    msk &= 0xfc;
    
    //write COPs
    //preserve bits 0 and 1 and OR in msk
    PORTD = (PORTD & 0b00000011) | msk;
           
}//loop

(Note: This could be made simpler if you swapped the function of pins 6 and 7; the logic then becomes a simple shift...)