Vous êtes sur la page 1sur 7

//Transmission controller

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//LCD configuration
#define I2C_ADDR 0x27
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C
lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin,BACKL
IGHT_PIN,POSITIVE);

volatile int active;


//4th gear is safest to start in if all else fails. Engine can't
overrev in 4th
volatile int currentGear = 4;
//Set lockup status to engaged to force unlock at first change
unless later read otherwise, for safety
volatile int lockupStatus = 0;
const int solenoid1 = 5;
const int solenoid2 = 6;
const int LUsolenoid = 7;
const int S1read = 8;
const int S2read = 9;
const int LUread = 4;
const int masterSwitch = 10;
const int upButton = 11;
const int downButton = 12;
int counter = 0;
unsigned long disarmTimer;
unsigned long sensitivity = 500UL;
int buttonsArmed = 0;
int firstRun = 1;
int firstInactiveRun = 1;

void setup()
{
//Prepare screen
lcd.begin(20,4);
lcd.home ();
lcd.setCursor(4,0);
lcd.print("Trans Status");
lcd.setCursor(0,2);
lcd.print("Current Gear:");
lcd.setCursor(0,3);
lcd.print("Lockup clutch:");
//Initialize serial
Serial.begin(9600);
//Initialize relays in OFF position
digitalWrite(solenoid1, HIGH);
digitalWrite(solenoid2, HIGH);
digitalWrite(LUsolenoid, HIGH);
//Set pins to output mode
pinMode(solenoid1, OUTPUT);
pinMode(solenoid2, OUTPUT);
pinMode(LUsolenoid, OUTPUT);
//Pins for switches
pinMode(masterSwitch, INPUT_PULLUP);
pinMode(upButton, INPUT_PULLUP);
pinMode(downButton, INPUT_PULLUP);
//Pins for gear sensing
pinMode(S1read, INPUT);
pinMode(S2read, INPUT);
pinMode(LUread, INPUT);
}

void loop()
{
//Serial counter to watch loop times
Serial.println(counter);
//Master switch goes between auto and manual
if (digitalRead(masterSwitch) == 1) {
active = 1;
}
else{
active = 0;
}

//Active 0 is automatic/factory passthru mode


if (active == 0) {
if (firstInactiveRun == 1) {
//Ensure all relays are off on first loop since arduino
is still connected
digitalWrite(solenoid1, HIGH);
digitalWrite(solenoid2, HIGH);
digitalWrite(LUsolenoid, HIGH);
firstInactiveRun = 0;
//FirstRun set to 1 syncs manual mode to the current gear
when initially switching to manual
firstRun = 1;
}
//Take input and discard to avoid queueing changes
char ser = Serial.read();
//Monitor shift solenoids for gear and lockup clutch
determineGear();
determineLockup();
//Display gear position
lcd.setCursor(1,1);
lcd.print(" OEM in control ");
lcd.setCursor(13,2);
lcd.print(currentGear);
lcd.setCursor(14,3);
lcd.print(lockupStatus);
}

//Active 1 is paddle shift manual mode


if (active == 1) {
if (firstRun == 1) {
//Activate relays to match what automatic/passthru mode was
doing on the previous loop
if (lockupStatus == 1) {
lockupEngage(1);
}
else {
lockupDisengage(1);
}
callGear(currentGear);
//FirstInactiveRun forces all relays off when initally
switched to auto mode
firstInactiveRun = 1;
firstRun = 0;
}
lcd.setCursor(1,1);
lcd.print("Arduino in control");

//This is critical. A normal IF statement will process one


gearchange only, iterate through the loop, then process the next.
//The WHILE loop will parse gearchanges for as many serial
reads are queued up. It's the difference between a fast
//sequence and 'perfect' synchronization.
while (Serial.available()) {
char ser = Serial.read();
//Convert from ASCII to int. Hack, but serial wont normally
be used.
ser = ser - 48;
callGear(ser);
}

//ButtonsArmed is a millis-based debounce system


if (buttonsArmed == 1) {
if (digitalRead(upButton) == 1) {
upShift();
buttonsArmed = 0;
disarmTimer = millis();
}
if (digitalRead(downButton) == 1) {
downShift();
buttonsArmed = 0;
disarmTimer = millis();
}
}
else{
//If not armed, check disarmTimer to re-arm
if ((millis() - disarmTimer) >= sensitivity) {
buttonsArmed = 1;
}
}
lcd.setCursor(13,2);
lcd.print(currentGear);
lcd.setCursor(14,3);
lcd.print(lockupStatus);
}

//Counter only functions as performance metric. Loops at 1000 to


prevent overflow
counter++;
if (counter >= 1000) {
counter = 0;
}
//delay(800);
}

//The following subs activate specific solenoids to shift to the


desired gear. There are 2 shift solenoids and 1 lockup clutch
solenoid
void firstGear()
{
digitalWrite(solenoid1, LOW);
digitalWrite(solenoid2, HIGH);
currentGear = 1;
}
void secondGear()
{
digitalWrite(solenoid1, LOW);
digitalWrite(solenoid2, LOW);
currentGear = 2;
}
void thirdGear()
{
digitalWrite(solenoid1, HIGH);
digitalWrite(solenoid2, LOW);
currentGear = 3;
}
void fourthGear()
{
digitalWrite(solenoid1, HIGH);
digitalWrite(solenoid2, HIGH);
currentGear = 4;
}

//Lockup clutch needed a timer to prevent shifting while the torque


converter is locked (a bad thing).
//If called with NoDelay, it performs just like the gear changes.
//This is useful for FirstRun conditions to sync the relays with
passthru mode for seamless transitions between auto/manual
void lockupEngage(int noDelay)
{
//Delay before continuing in case of pending gear change
if (noDelay != 1) {
delay(750);
}
digitalWrite(LUsolenoid, LOW);
lockupStatus = 1;

}
void lockupDisengage(int noDelay)
{
digitalWrite(LUsolenoid, HIGH);
lockupStatus = 0;
//Delay before continuing in case of pending gear change
if (noDelay != 1) {
delay(750);
}
}
//upShift and downShift are called by the shifter buttons for
sequential gearchanges.
//Handles TC lockup, prevents shifting above 4th or below 1st
void upShift()
{
if (currentGear == 4) {
lockupEngage(0);
}
if (currentGear < 4) {
currentGear++;
if (lockupStatus == 1) {
lockupDisengage(0);
}
}

switch (currentGear) {
{
case 2:
secondGear();
}
break;
{
case 3:
thirdGear();
}
break;
{
case 4:
fourthGear();
}
break;
}
}

void downShift()
{
if ((currentGear == 4) && (lockupStatus == 1)) {
lockupDisengage(0);
}
else {
if (currentGear > 1) {
currentGear--;
if (lockupStatus == 1) {
lockupDisengage(0);
}
}
switch (currentGear) {
{
case 1:
firstGear();
}
break;
{
case 2:
secondGear();
}
break;
{
case 3:
thirdGear();
}
break;
}
}
}

//Code to call specific gear, not necessarily sequentially.


//Currently used for serial testing
void callGear(int option){
switch (option) {
{
case 1:
firstGear();
}
break;
{
case 2:
secondGear();
}
break;
{
case 3:
thirdGear();
}
break;
{
case 4:
fourthGear();
}
break;
{
case 7:
upShift();
}
break;
{
case 8:
downShift();
}
break;
{
case 5:
lockupEngage(0);
}
break;
{
case 6:
lockupDisengage(0);
}
break;
}
}

//Monitor voltage of solenoid 1 and 2 wires to see what the factory


computer is doing
//2 solenoids, 2 states each = 4 gears
void determineGear() {
if (digitalRead(S1read) == 1) {
if (digitalRead(S2read) == 1) {
currentGear = 2;
}
else {
currentGear = 1;
}
}
else {
if (digitalRead(S2read) == 1) {
currentGear = 3;
}
else {
currentGear = 4;
}
}
}

//Monitor voltage of lockup clutch solenoid


void determineLockup() {
if (digitalRead(LUread) == 1) {
lockupStatus = 1;
}
else {
lockupStatus = 0;
}
}

Vous aimerez peut-être aussi