Last active
August 26, 2021 01:27
-
-
Save mattrude/05e26efc310f657d7a4e65c267c1e7ce to your computer and use it in GitHub Desktop.
This is a Advanced Traffic Stop Light program written for an ATtiny85 & 74HC595, using Atmel Studio 7.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ATtiny85 - Advanced Traffic Stop Light - Version 0.1.1 - 2020-03-20 | |
* Copyright (c) 2020 Matt Rude <matt@mattrude.com> | |
* | |
* ********************************************************************************* | |
* | |
* This is the Advanced Traffic Stop Light program written for an ATtiny85 using | |
* Atmel Studio 7: https://www.microchip.com/mplab/avr-support/atmel-studio-7 | |
* | |
* For more on the ATtiny85, see: https://www.microchip.com/wwwproducts/en/ATtiny85 | |
* | |
* The ATtiny85 was programed with the Tiny AVR programmer PGM-11801 by SparkFun | |
* Electronics: https://www.sparkfun.com/products/11801 | |
* | |
* The circuit is powered by an external DC buck converter running at +5v. | |
* | |
* ********************************************************************************* | |
* | |
* Required Hardware: | |
* | |
* - 1x ATtiny85 Micro Controller | |
* - 1x 74HC959 Shift Register | |
* - 2x Red LED | |
* - 2x Yellow LED | |
* - 2x Green LED | |
* - 6x 220 ohm Resistors | |
* - 1x Large Breadboard | |
* - 20x Jumper Wires of various colors | |
* | |
* Required Tools: | |
* | |
* - Generic Windows 7+ Computer with a free USB port | |
* - Atmel Studio 7 software | |
* - Tiny AVR programmer - PGM-11801 | |
* - DC Power Supply | |
* | |
* ********************************************************************************* | |
* | |
* ATtiny85 pin-out: | |
* (Note: the dot next to the PB5 pin represents the dot on the chip.) | |
* ______ | |
* (not used) - PB5 - |° | - VCC - 5v+ | |
* (not used) - PB3 - | | - PB2 - To DS on 74HC595 | |
* (not used) - PB4 - | | - PB1 - To STCP on 74HC595 | |
* GND - GND - |______| - PB0 - To SHCP on 74HC595 | |
* | |
* 74HC959 Shift Register pin-out: | |
* (Note: the dot next to the Q1 pin represents the dot on the chip.) | |
* ______ | |
* Red Light - Q1 - |° | - VCC - +5v | |
* Yellow Light - Q2 - | | - Q0 - Red Walk Sign | |
* Green Light - Q3 - | | - DS - To PB2 on ATtiny85 | |
* Red turn Arrow - Q4 - | | - OE - GND | |
* Yellow turn Arrow - Q5 - | | - STCP - To PB1 on ATtiny85 | |
* Green turn Arrow - Q6 - | | - SHCP - To PB0 on ATtiny85 | |
* Green Walk Sign - Q7 - | | - MR - +5v | |
* GND - GND - |______| - Q7S | |
* | |
* ********************************************************************************* | |
* | |
* Changelog: | |
* | |
* 2020-03-20 - 0.1.1 - Correct WDT function to load at start correctly. | |
* - Minor comment updates | |
* 2020-03-07 - 0.1.0 - Initial Release | |
* | |
* ********************************************************************************* | |
* | |
* MIT License: | |
* | |
* Copyright (c) 2020 Matt Rude <matt@mattrude.com> | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in all | |
* copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
* SOFTWARE. | |
* | |
* ********************************************************************************* | |
*/ | |
// Set the default amount of time, in seconds, to wait between light changes. | |
#define changeDelay 30 // Amount of time to delay light changes in seconds | |
// Declare the shift register pins | |
#define clockPin PB0 // Connected to SHCP (pin 11) on the 74HC595. | |
#define latchPin PB1 // Connected to STCP (pin 12) on the 74HC595. | |
#define dataPin PB2 // Connected to DS (pin 14) on the 74HC595. | |
// Set required variables | |
#define F_CPU 1000000UL // Set the CPU clock frequency to 1MHz | |
// Include the required libraries for the program | |
#include <avr/io.h> // Include the IO library | |
#include <util/delay.h> // Include the Delay library | |
#include <avr/sleep.h> | |
#include <avr/interrupt.h> | |
#include <avr/wdt.h> // Include the WatchDog library | |
// Declare the micros | |
#define WDTO_1S 6 // Set the watch dog timer to about one second | |
#define MCUCSR MCUSR // Source of why the last reset happened | |
#define setHigh(pn) PORTB |= (1<<pn) // Write digital HIGH to pin <pn> on PORTB | |
#define setLow(pn) PORTB &= ~(1<<pn) // Write digital LOW to pin <pn> on PORTB | |
// Declare the different light configurations | |
#define redLight 0b100 // Red (Stop) Light | |
#define yellowLight 0b010 // Yellow (Slow Down) Light | |
#define greenLight 0b001 // Green (Go) Light | |
#define dWalkLight 0b10 // Red Don't Walk Sign | |
#define walkLight 0b01 // Walk Sign | |
// Declare the functions | |
void safeMode(uint8_t); // Run safe mode error function | |
void feedDog(); // Reset the watchdog timer | |
void runDelay(uint16_t); // Delay function | |
void send(uint8_t,uint8_t,uint8_t); // Send a Byte to the Shift Register | |
void sendBit(uint8_t); // Send a Bit to the Shift Register | |
void latch(); // Latch the Shift Register | |
void cycleClock(); // Cycle the Shift Register clock | |
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // Disable ADC | |
// Now that everything is setup, starting the main process | |
int main(void) { | |
// Set the three shift register pins as outputs | |
DDRB |= (1 << clockPin) | (1 << latchPin) | (1 << dataPin); | |
// Before we start, set the clockPin to LOW | |
PORTB &= ~(1 << clockPin); | |
// Check to see if the last ran was finished correctly | |
if(MCUCSR & (1<<EXTRF)) { | |
safeMode(2); // External reset! | |
} else if(MCUCSR & (1<<BORF )) { | |
safeMode(10); // Brownout reset! | |
} else if(MCUCSR & (1<<WDRF )) { | |
safeMode(60); // Watchdog reset! | |
} | |
// The start the primary loop | |
while (1) { | |
// Set BOTH directions to Red | |
send(redLight, redLight, dWalkLight); | |
send(redLight, redLight, dWalkLight); | |
latch(); | |
runDelay((changeDelay * 1000) / 6); | |
// Set the first directions to Green and the second to Red | |
send(greenLight, greenLight, walkLight); | |
send(redLight, redLight, dWalkLight); | |
latch(); | |
runDelay(changeDelay); | |
// Set the first directions to Yellow and keep the second directions Red | |
send(yellowLight, yellowLight, dWalkLight); | |
send(redLight, redLight, dWalkLight); | |
latch(); | |
runDelay((changeDelay * 1000) / 4); | |
// Set Both directions to Red | |
send(redLight, redLight, dWalkLight); | |
send(greenLight, greenLight, walkLight); | |
latch(); | |
runDelay(changeDelay); | |
// Set the first directions to Red and the second to Green | |
send(redLight, greenLight, walkLight); | |
latch(); | |
runDelay(changeDelay * 1000); | |
// Set the first directions to Yellow and the second to Red | |
send(redLight, yellowLight, dWalkLight); | |
latch(); | |
runDelay((changeDelay * 1000) / 4); | |
} // Closing the primary loop | |
} // Closing the main process | |
// The error function | |
void safeMode(uint8_t errorReason) { | |
send(redLight, redLight, dWalkLight); | |
send(redLight, redLight, dWalkLight); | |
latch(); | |
_delay_ms(500); | |
errorReason = ((errorReason)*10); | |
uint8_t i; | |
for (i = 0; i < errorReason; i++) { | |
send(redLight, redLight, dWalkLight); | |
send(000, 000, 00); | |
latch(); | |
_delay_ms(500); | |
send(000, 000, 00); | |
send(redLight, redLight, dWalkLight); | |
latch(); | |
_delay_ms(500); | |
} | |
} // Closing the safeMode function | |
// Delay and feed the dog all at the same time | |
void runDelay(uint16_t delayTime) { | |
while (delayTime >= 0) { | |
feedDog(); | |
_delay_ms(500); | |
feedDog(); | |
_delay_ms(500); | |
delayTime = (delayTime-1); | |
} | |
feedDog(); | |
} // Closing the delay function | |
// Reset the watch dog timer | |
void feedDog() { | |
#define wdt_reset( ) __asm__ __volatile__ ("wdr") | |
} // Closing the feedDog function | |
// Writes data to the dataPin | |
void send(uint8_t toSendMain,uint8_t toSendTurn, uint8_t toSendWalk) { | |
for (uint8_t a = 0; a < 3; a++) { | |
sendBit(toSendMain & 1); | |
toSendMain >>= 1; | |
} | |
for (uint8_t b = 0; b < 3; b++) { | |
sendBit(toSendTurn & 1); | |
toSendTurn >>= 1; | |
} | |
for (uint8_t c = 0; c < 2; c++) { | |
sendBit(toSendWalk & 1); | |
toSendWalk >>= 1; | |
} | |
} // Closing the send function | |
// Writes a single bit to the dataPin, then cycles the clock | |
void sendBit(uint8_t bit) { | |
if (bit == 0) { | |
setLow(dataPin); | |
} else { | |
setHigh(dataPin); | |
} | |
// Once the bit has been written, cycle the clock | |
cycleClock(); | |
} // Closing the sendBit function | |
// Tells the shift register to output all the bits it has | |
void latch() { | |
setHigh(latchPin); | |
setLow(latchPin); | |
} // Closing the latch function | |
// Tells the shift register to read a bit by ticking the clock forward | |
void cycleClock() { | |
setHigh(clockPin); | |
setLow(clockPin); | |
} // Closing the cycleClock function |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment