Arduino 4L80e controller

Steel Soldiers is supported by:

patracy

Administrator
Administrator
Steel Soldiers Supporter
13,585
603
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

New member
27
11
3
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

Active member
2,895
6
38
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.
 
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