Hey all! I have a project I would like to do for a car I'm restoring. I want to use an ATtiny85 (if it's powerful enough) to make the dome and courtesy lights (converted to LEDs) fade on and off when the door opens and closes. I also want to add a pushbutton somewhere on the drivers side that, after it's pressed, will roll the window down when the door opens, and back up when it closes.
If I wire it up the way I have it in the schematic, then when the regular window switch (not shown in the schematic, but it just reverses polarity to the motor) is pressed, it'll create a direct short. That's obviously not good. My best idea so far is to make the regular window switch an input for the microcontroller, then just control the windows directly from the microcontroller. Other than that, I can't think of any way to isolate my circuit from the factory circuit. That's why I've come here. Here is a link to a schematic of the factory wiring, the window circuit is in the middle of the picture.
Here is my sketch (I received help from some great people on the Programing Questions sub-forum). The pushbutton inputs are coded for pulldown resistors, but the build will use the internal pull-up resistors.
/* This sketch has two purposes and is designed for use in a car. The first
purpose of this sketch is to fade a set of LEDs on when the car door is opened,
then fade them back off when the car door is closed. The second purpose of
this sketch is to make a push button that when pressed, the door window will
roll down when the door is opened, then roll back up when the door is clossed.*/
// Define the pins the pushbutton and door switches are on
const int buttonPin[] = {
2, 4, 6};
// Define the pins that will ultimately control the window rolling up or down
const int windowPin[] = {
7, 8};
// Define the pin the LEDs to fade are on
const int ledPin = 3;
// Define the amount of time the fade delay will be
const int fadeDelay = 15;
// Define the brightness increase interval
const int fadeAmount = 3;
// Define the delay for button debounce
const int debounceDelay = 15;
// Define the amount of time the windows will spend rolling up and down.
//rollUpDelay will be longer to ensure window rolls all the way up.
const int rollUpDelay = 3000;
const int rollDownDelay = 2000;
//Variables that will change
// Variable to track the current state of the push button, in an array the size
//of buttonPin.
boolean currentButtonVal[sizeof(buttonPin)/sizeof(buttonPin[0])];
// Initialize variables to define and store the debounced switch values. doorSwitch
//is in an array the size of buttonPin
byte doorSwitch[2];
byte windowButton;
// Define the inital brightness of the LED. Starts off, or 0
int brightness = 0;
// Define the inital "previous time" variable for comparison with millis().
//Will start at 0 and be redifned every time fadeDelay has passed.
unsigned long previousTime = 0;
// Define the inital comparison time for the debounce function. Has the same
//purpose as in "previousTime."
unsigned long lastDebounceTime = 0;
// Initialize a variable that is set to millis() every time a button state is
//toggled. In an array the size of buttonPin[], and is unique to each button.
unsigned long toggleTime[sizeof(buttonPin)/sizeof(buttonPin[0])];
// Define the inital state for a button toggle. This value will be reversed
//when a button is pressed. In an array the size of buttonPin[], and is unique
//to each button.
boolean buttonToggle[sizeof(buttonPin)/sizeof(buttonPin[0])] = {};
// Initialize a variable to track if the rollWindow function should be active
boolean rollWindowToggle;
// Initialize a variable to detect if the rollWindow button should finish
boolean continueFunction;
void setup () {
for (int i = 0; i < sizeof(buttonPin)/sizeof(buttonPin[0]); i++) {
pinMode (buttonPin[i], INPUT);
}
for (int i = 0; i < sizeof(windowPin)/sizeof(windowPin[0]); i++) {
pinMode (windowPin[i], OUTPUT);
}
pinMode (ledPin, OUTPUT);
}
void loop () {
// Create a variable to store the millis() value this time through the loop
unsigned long currentTime = millis();
// Define variables to debounce and keep track of the different switches
doorSwitch[0] = debounce(0);
doorSwitch[1] = debounce(1);
windowButton = debounce(2);
// If either car door is open, then fade the LEDs. If both car doors are
//closed, then fade the LEDs off.
if (doorSwitch[0] == HIGH || doorSwitch[1] == HIGH) {
if (currentTime - previousTime > fadeDelay) {
previousTime = currentTime;
brightness = brightness + fadeAmount;
// Limit the fade amount from going above 255
brightness = min(brightness, 255);
analogWrite (ledPin, brightness);
}
}
else {
if (currentTime - previousTime > fadeDelay) {
previousTime = currentTime;
brightness = brightness - fadeAmount;
// Limit the fade amount from going bellow 0
brightness = max(brightness, 0);
analogWrite (ledPin, brightness);
}
}
// If windowButton has been toggled to true (on) and the door switch is HIGH,
//then make rollWindowToggle true. This allows the rollWindow function to
//begin. If buttonToggle is not true (on), then make rollWindowToggle false.
if (buttonToggle[2]) { //Start function when buttonToggle is true
if (doorSwitch[0] == HIGH) { //If the door is open
rollWindowToggle = true; //Let the rollWindow function execute
}
}
else rollWindowToggle = false;
// Test to see if rollWindowToggle was toggled on while the door was open,
//if it was, then reset toggleTime so the window will still roll the correct
//amount of time. continueFunction must not equal true so toggleTime does not
//continuously reset if rollWindowToggle gets toggled while the function is
//in progress.
if (!rollWindowToggle && doorSwitch[0] == HIGH && !continueFunction) {
toggleTime[0] = millis();
}
// Iniate rollWindow function if either requirment is meant. continueFunction
//tracks if the function should continue, even if rollWindowToggle is
//toggled to false.
if (rollWindowToggle || continueFunction) {
// Iniate rollWindow function, doorSwitch and toggleTime indicate which
//switch will activate the function. currentTime passes the variable assigned
//to millis().
rollWindow(0, currentTime);
}
}
void rollWindow (int thisSwitch, unsigned long currentTime) {
// If statements checks if door is open or closed and performs apropriate function
// If the door is open
if (doorSwitch[thisSwitch] == HIGH) {
// Define the state of continueFunction to indicate that the function is
//in progress and should continue until it is complete
continueFunction = true;
// If the rollDownDelay time has passed, stop rolling the window. If not,
//roll the window down. Make windowPin[1] LOW to ensure the window will
//not try to roll down and up at the same time.
if (currentTime - toggleTime[thisSwitch] > rollDownDelay) { //If roll up time has passed:
digitalWrite (windowPin[0], LOW); //Stop rolling the window down
}
else {
digitalWrite (windowPin[1], LOW); //Make sure the window is not rolling up
digitalWrite (windowPin[0], HIGH); //Make the window roll down
}
}
// If the door is closed:
else {
// If the rollUpDelay time has passed, stop rolling the window, reset
//buttonToggle[2] to false, and make continueFunction false to indicate
//the function is complete. If rollUpDelay time has not passed, then
//roll the window up and make windowPin[0] LOW to ensure the window will
//not try to roll up and down at the same time.
if (currentTime - toggleTime[thisSwitch] > rollUpDelay) {
digitalWrite (windowPin[1], LOW);
buttonToggle[2] = false;
continueFunction = false;
}
else {
digitalWrite (windowPin[0], LOW);
digitalWrite (windowPin[1], HIGH);
}
}
}
// Create a debounce function to debounce the switches, start the toggleTime
//timer, and toggle the buttonToggle variable. Return the value current.
byte debounce(int thisButton) {
// Take a reading of the switch pin and store it in a local variable.
byte current = digitalRead(buttonPin[thisButton]);
// If the reading does not equal the current recorded state of the button,
//wait the debounceDelay, then take another reading of the currenet value and
//begin the toggle timer. If the state of the switch is high, then toggle
//buttonToggle.
if (currentButtonVal[thisButton] != current) {
if (millis() - lastDebounceTime > debounceDelay) {
current = digitalRead(buttonPin[thisButton]);
toggleTime[thisButton] = millis();
if (current == HIGH) {
buttonToggle[thisButton] = !buttonToggle[thisButton];
}
}
}
// Record the curent button value and return current
currentButtonVal[thisButton] = current;
return current;
}
Here is the schematic. This is my first real schematic, so I'm open to suggestions on how I can improve it.


