• Steel Soldiers now has a few new forums, read more about it at: New Munitions Forums!

  • Microsoft MSN, Live, Hotmail, Outlook email users may not be receiving emails. We are working to resolve this issue. Please add support@steelsoldiers.com to your trusted contacts.

Arduino 4L80e controller

patracy

Administrator
Staff member
Administrator
14,639
4,820
113
Location
Buchanan, GA
Another update. Tow/Haul mode.

https://www.youtube.com/watch?v=sy-IBEU7eOg

This code still does not contain any safety for the downshifting. I'm going to get a LCD screen next and start outputting some of the actions to the screen. Also I'll start pulling in RPM inputs once I build out that interface. (I'm just going to cheat to simulate that, I'll use my signal generator and frequency/4 = rpm) I can just use a pot for the TPS. No need to build another arudino code just to simulate that.

Code:
#define NUM_FWD_GEARS               4       //#     number of forward speeds

#define BUTTON_READ_INTERVAL        50ul    //mS    time between up/down button reads

#define NO_PRESS                    0x00    //mask  bit mask for no buttons pressed
#define BUTTON_UP_PRESSED           0x01    //mask  bit mask for up button pressed
#define BUTTON_DOWN_PRESSED         0x02    //mask  bit mask for down button pressed

#define TCC_DELAY                   1000ul  //mS    after TCC is enabled, time delay before activation

const byte buttonUP = 2;                    //pin   Push Button for UP shift
const byte buttonDOWN = 4;                  //pin   Push Button for Down shift
const byte switchTOWMODE = 7;               //pin   Switch for tow/haul mode
const byte solA = 3;                        //pin   Solenoid A output
const byte solB = 5;                        //pin   Solenoid B output
const byte TCC  = 6;                        //pin   TCC output

byte
    gearSelection,
    lastGearSelection,
    lastUp,
    lastDn,
    lastTM;
bool
    bTCCStatus;

typedef struct structGearSolenoidProfiles
**
    byte    solenoid_A;
    byte    solenoid_B;
    bool    bTCCGearEnable;
   
}sGearSolenoidProfiles;

//
// How does Arduino know reverse, park or drive?
//
const sGearSolenoidProfiles GearSolenoidProfiles[NUM_FWD_GEARS] =
**
    **
        //1st
        .solenoid_A = HIGH,
        .solenoid_B = LOW,
        .bTCCGearEnable = false
    },
    **
        //2nd
        .solenoid_A = LOW,
        .solenoid_B = LOW,
        .bTCCGearEnable = false
    },
    **
        //3rd
        .solenoid_A = LOW,
        .solenoid_B = HIGH,
        .bTCCGearEnable = true
    },
    **
        //4th
        .solenoid_A = HIGH,
        .solenoid_B = HIGH,
        .bTCCGearEnable = true
    }
   
};//GearSolenoidProfiles[]

void setup()
**
    Serial.begin(115200); //debug
   
    pinMode( buttonUP, INPUT_PULLUP );
    lastUp = digitalRead( buttonUP );       //set initial button state
    pinMode( buttonDOWN, INPUT_PULLUP );
    lastDn = digitalRead( buttonDOWN );     //set initial button state
    pinMode( switchTOWMODE, INPUT_PULLUP );
       
    pinMode( solA, OUTPUT );                //Solenoid A set as output
    pinMode( solB, OUTPUT );                //Solenoid B set as output
    pinMode( TCC, OUTPUT );                 //TCC set as output

    digitalWrite( solA, LOW );             //set intital state as off
    digitalWrite( solB, LOW );
    digitalWrite( TCC, LOW );

    //internal flag for TCC status
    bTCCStatus = false;
    gearSelection = 0;          //start in "1st" gear for this test
    lastGearSelection = 0xff;   //ensure we change into correct gear first pass by making last != current
   
}//setup

void loop() 
**
    Gear_Selection_Control();
    Gear_Solenoid_Control();
    TCC_Control();
   
}//loop

void Gear_Selection_Control( void )
**
    byte
        btnState;
       
    btnState = ReadButtons();
    switch( btnState )
    **
        case    NO_PRESS:
            //nothing pressed or not read (interval not elapsed); no action
        break;

        case    BUTTON_UP_PRESSED:
            if( gearSelection < (NUM_FWD_GEARS-1) )
            **
                Serial.println( "GSelC: Gear++" );
                gearSelection++;
            }//if
           
        break;

        case    BUTTON_DOWN_PRESSED:
            if( gearSelection > 0 )
            **
                Serial.println( "GSelC: Gear--" );
                gearSelection--;
            }//if               
        break;

        default:
            //only remaining possibility is both pressed; ignore with no action
        break;
       
    }//switch
   
}//void
   
void Gear_Solenoid_Control( void )
**
    if( gearSelection != lastGearSelection )
    **
        Serial.print( "GSolC: Gear Selected - Old: " );
        Serial.print( lastGearSelection );
        Serial.print( " New: " );
        Serial.println( gearSelection );
       
        lastGearSelection = gearSelection;
        digitalWrite( solA, GearSolenoidProfiles[gearSelection].solenoid_A );
        digitalWrite( solB, GearSolenoidProfiles[gearSelection].solenoid_B );
       
    }//if
       
}//Gear_Control

// TCC state machine names
#define ST_TCC_OFF      0
#define ST_TCC_DELAY    1
#define ST_TCC_ON       2
//
void TCC_Control( void )
**
    static unsigned long
        timeTCCSolenoid;
    static byte
        stateTCC = ST_TCC_OFF;
    unsigned long
        tNow;
    bool
        bTCCEnabled;

    if( gearSelection == 3 )
        bTCCEnabled = true;
    else if( gearSelection == 2 && digitalRead( switchTOWMODE ) == HIGH )
        bTCCEnabled = true;
    else
        bTCCEnabled = false;
               
    tNow = millis();

    switch( stateTCC )
    **
        case    ST_TCC_OFF:
            if( bTCCEnabled == true )
            **
                Serial.println( "TCCC: TCC_OFF -> ON" );
                timeTCCSolenoid = tNow;               
                stateTCC = ST_TCC_DELAY;
               
            }//if
           
        break;

        case    ST_TCC_DELAY:
            if( bTCCEnabled == true )
            **               
                if( (tNow - timeTCCSolenoid) >= TCC_DELAY )
                **
                    Serial.println( "TCCC: TCC ON" );
                    digitalWrite( TCC, HIGH );
                    bTCCStatus = true;
                    stateTCC = ST_TCC_ON;
                   
                }//if
               
            }//if
            else
            **
                Serial.println( "TCCC: TCC_DELAY -> OFF" );
                stateTCC = ST_TCC_OFF;
               
            }//else
           
        break;

        case    ST_TCC_ON:
            if( bTCCEnabled == false )
            **
                Serial.println( "TCCC: TCC_ON -> OFF" );
                digitalWrite( TCC, LOW );
                bTCCStatus = false;
                stateTCC = ST_TCC_OFF;
               
            }//if
           
        break;
       
    }//switch
       
}//TCC_Control

//returns a mask:
//0b00000000 - no buttons pressed
//0b00000001 - up pressed
//0b00000010 - down pressed
//0b00000011 - both pressed
//
byte ReadButtons( void )
**
    static unsigned long
        timeButton = 0;
    unsigned long
        tNow;
    byte
        retval,
        nowButton;

    retval = NO_PRESS;
   
    tNow = millis();
    if( (tNow - timeButton) >= BUTTON_READ_INTERVAL )
    **
        //set up for next read interval
        timeButton = tNow;

        //read the button and set the flags
        nowButton = digitalRead( buttonUP );
        if( nowButton != lastUp )
        **
            lastUp = nowButton;
            if( nowButton == LOW )
            **
                Serial.println( "RB: UP BTN" );
                retval |= BUTTON_UP_PRESSED;
            }
               
        }//if
       
        nowButton = digitalRead( buttonDOWN );
        if( nowButton != lastDn )
        **
            lastDn = nowButton;
            if( nowButton == LOW )
            **
                Serial.println( "RB: DN BTN" );
                retval |= BUTTON_DOWN_PRESSED;
            }
               
        }//if
       
    }//if
   
    return retval;
   
}//ReadButtons
 

jnissen

Member
42
28
18
Location
Austin/TX
Hardware interrupts will be your friend for all the pulse inputs and such. Avoid blocking code by trying to sample the inputs. Ideally put everything off a timer interrupt and service the various inputs/ outputs, if any, within the time period you allocate. Not sure how many embedded projects you have done till now. Having a timer based routine to set or service various inputs and outputs ensures the controller will be at least as responsive as your timer setting. If it takes 10K cycles per timer to service all your inputs and outputs, at 8MHz then you have at least a 8M/10K or 800Hz update rate. That’s roughly 12.5mS response time guaranteed. If you can service all your I/O in less than 10K cycles then you can reduce the timer service interrupt.

You haven’t mentioned how you structured your code so you may already be all over this.

Update - just looked at your code. You can still benefit from a timer interrupt architecture. Up to you but I’ve regretted not doing it on mission critical tasks in the past.

BTW the timer routine is nice because if your unable to complete all your I/O servicing within your allocated time then you can have error recovery built in.

I’ve built many controller projects over the years and this type of architecture works very well.


Sent from my iPad using Tapatalk
 
Last edited:

Keith_J

Well-known member
3,657
1,323
113
Location
Schertz TX
Interesting. I'm doing the similar but using a TCI 6X package which has the controller. I have a NIB GM throttle position sensor and a Dakota Digital alternator W term converter for TPS and RPM respectively. I have the Advanced Adapter 0410 for transmission to NP 205.

Yes, this is a 7000 dollar conversion. Plus there are twin GT1544V turbos in the future. They will also use the TPS and RPM sensors for the VNT control. Shooting for 10 PSI boost at 1500 RPM . Looking for 350 ft lbs of torque down low. This should keep BSFC under 0.39 lbs/HP*hour at 2000 RPM.
 

DblTrbl

New member
3
0
1
Location
NJ
Patracy, you had a thread on arduino forums that I was going to comment on, but it's locked.

Hope you made some progress.

I've built an arduino 4l80e controller and enhanced it over the last 6 years. Mine is feature rich and has been working flawlessly for years and thousands of miles.

If you're still working on this, I have some input for you, especially related to line pressure.
 

Skinny

Well-known member
2,130
488
83
Location
Portsmouth, NH
With the cost of an off the shelf 4L80 controller, I would consider a 6L80 instead. Sure itnis more money but why not have a 4:1 first gear and dual overdrives?

I am really trying ti convince myself to stick with an NV4500 but that 6 speed sure would make the 6.2 more tolerable in every regard.

Sent from my SM-T380 using Tapatalk
 

Keith_J

Well-known member
3,657
1,323
113
Location
Schertz TX
6L80 is a totally different beast. Its reliability is from integration of the engine and transmission to work together by reducing torque during shifts.
The 4L80 is much tougher because it has to shift under full engine torque. The 6L80 might survive with a stock 6.2 but any mods..

If 6 speed is your goal, look at the TCI 6X. It is a 4L80 with a modified valve body allowing the overdrive to split 1st and 2nd as well as 3rd. Plus modified 1st and second for a 2.97 ratio (stock is 2.48).
 
Last edited:

Skinny

Well-known member
2,130
488
83
Location
Portsmouth, NH
Not sure what you are referencing but the 6L80 was meant to work with all the high output V8s. It's good for like 600hp stock.

Sent from my Moto G (5) Plus using Tapatalk
 

Keith_J

Well-known member
3,657
1,323
113
Location
Schertz TX
Not sure what you are referencing but the 6L80 was meant to work with all the high output V8s. It's good for like 600hp stock.

Sent from my Moto G (5) Plus using Tapatalk
The transmission and engine work together. Since the 6l80 shifts clutch to clutch without overrunning sprags, engine power is reduced between shifts. The transmission control module requires input from the engine control module AND the TCM requests reduced torque during the handoff. Just a fraction of a second and the driver does not sense the loss of torque.
 

Skinny

Well-known member
2,130
488
83
Location
Portsmouth, NH
I am sure it does, that type of shift strategy was pretty much the standard even back in the day with the single step shifting 4 speeds.

I remember doing superchargers on the Toyotas and it had so much bog during shifts, it was the only way to keep the aw4 from exploding with all that power.

I guess is that really a deal-breaker? I wonder if any of that is changeable. I know there is a lot of settings just with the 4L80. A lot of the torque management is removable.

I mean with 50% more gears and closer steps between them, would you be at much of a disadvantage?



Sent from my Moto G (5) Plus using Tapatalk
 

Skinny

Well-known member
2,130
488
83
Location
Portsmouth, NH
While I am sitting on tech support hold to fix junk Briggs and Stratton generators...I'm snooping around in this 6L80.


So it appears you can change spark timing adjustment during all shifts, factory appears to kill 20 degrees which you can adjust on each shift strategy. It also has a bunch of torque management changes for shifting which can lower the transition between gears. Of course all of this is not stock and will change transmission longevity. But of course so does adding twin turbos so it is what it is.

So I guess as long as you want to spend big money all of this can be changed. I have an HP Tuner ($400 something) and 2 credits ($100) to work on my 8.1 4L80 Suburban swap. That is probably the ballpark for working on a 6L80 controller. I guess the big question is how long can a 4L80 vs 6L80 hold up to full power shifts?

The more I read the more I like an NV4500 and just accept the fact I won't be cruising at 80mph any time soon.
 

Keith_J

Well-known member
3,657
1,323
113
Location
Schertz TX
Just go with a 6X if six speed is a must. It is a bit closer range but is better suited for the torque of a 6.2 diesel. 2650 RPM at 70 MPH is all I feel comfortable in a 35 year old vehicle. Yes, that is on the high side of torque peak but it's far better than stock in the brake specific fuel consumption curve (that is the inverse curve of torque).
 

Skinny

Well-known member
2,130
488
83
Location
Portsmouth, NH
The 6L80 has way better ratios. First is way lower and the 2nd overdrive is taller.

So Im looking at $3k for a reman NV4500 with the whole install kit from AA. Add clutch pieces and a pedal bracket, that puts another $600 in the mix. Bonus for not having to refit driveshafts.

I think the only downside is the overdrive is really set up for the cruise speed you mentioned. Which isnt too bad. I can deal with 75mph as an optimal cruise.

6L80 is probably going for what $1500 at least. Controller adds a grand. Driveshaft refit is around $500. Tcase adapter is $700. So $3700 plus figuring out a shifter setup and smashing your head tuning it.

Money wise if you can get an inexpensive auto they are pretty close and the 6L80 is just about the greatest thing ever made from a gearing perspective. Im still really hung up on the complexity. Is it worth eaking out the little bit more in acceleration and cruise speed by giving up what essentially is a cockroach next to a mushroom cloud? A diesel and NV4500 needs nothing but one wire and fuel to run. Well that and some fancy synchromesh fluid

Sent from my SM-T380 using Tapatalk
 

als804

Member
89
66
18
Location
kimcheon, ROK
how is your project going? i am considering to do this. at D shift i wanna shift automatically with adruino. it's so interesting. i have some experience with arduino. wanna know ur job
 

als804

Member
89
66
18
Location
kimcheon, ROK
NOW i got 4L80E from surplus VAN for my CUCV and wanna make simple controller referencing the code you suggests.
my goal is FULL-MANUAL SHIFT with automatically PWM controlled PCS on basis of RPM.
Getting RPM is challenging. 4l80E has two VSS making sine waved outputs which frequecy have to be read for calculating RPM.
but it could not be read directly in arduino. i should convert VSS digtal output into analog output.
now i am trying to find how to do it.
 

DblTrbl

New member
3
0
1
Location
NJ
I know this may be an old thread, but thought I'd comment anyway.

Actually, RPM is pretty easy to get. Just use the LS coil signal as input instead of a VSS sensor. It's a 5V square wave.

But RPM is not a good driver for Line pressure. Instead, consider using the MAP sensor or the Pedal sensor.
 

DblTrbl

New member
3
0
1
Location
NJ
On the other hand, RPM is very important for a transmission controller. You never want to allow a downshift if your RPM is high and the downshift will cause the engine to over rev (aka "Money Shift").
 

patracy

Administrator
Staff member
Administrator
14,639
4,820
113
Location
Buchanan, GA
There's nothing that would provide a tach signal in the CUCV. Nor is there a MAP or pedal sensor.
 
Top
AdBlock Detected

We get it, advertisements are annoying!

Sure, ad-blocking software does a great job at blocking ads, but it also blocks useful features of our website like our supporting vendors. Their ads help keep Steel Soldiers going. Please consider disabling your ad blockers for the site. Thanks!

I've Disabled AdBlock
No Thanks