Skip to content

Instantly share code, notes, and snippets.

@mattrude
Last active March 20, 2020 06:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattrude/4fd6fbb814cd7c07e1558050f1e4c7a3 to your computer and use it in GitHub Desktop.
Save mattrude/4fd6fbb814cd7c07e1558050f1e4c7a3 to your computer and use it in GitHub Desktop.
ATtiny85, 74HC959 Traffic Light program written for Atmel Studio 7
/* 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.)
* ______
* PB5 - |° | - VCC - 5v+
* PB3 - | | - PB2 - To DS on 74HC595
* 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.)
* ______
* Red1 - Q1 - |° | - VCC - +5v
* Yellow1 - Q2 - | | - Q0
* Green1 - Q3 - | | - DS - To PB2 on ATtiny85
* Red2 - Q4 - | | - OE - GND
* Yellow2 - Q5 - | | - STCP - To PB1 on ATtiny85
* Green2 - Q6 - | | - SHCP - To PB0 on ATtiny85
* 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 // 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 <util/delay.h> // Include the Delay library
#include <avr/io.h> // Include the IO library
#include <avr/wdt.h> // Include the WatchDog library
// Declare the micros
#define WDTO_2S 7 // Set the watch dog timer to about 2 seconds
#define MCUCSR MCUSR // Source of why an issue 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 functions
void safeMode(uint8_t); // Run safe mode error function
void feedDog(); // Reset the watchdog timer
void delay(uint8_t); // Delay function
void send(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
// Now that everything is setup, starting the main process
int main(void) {
// Check to see if the last ran was finished correctly
if(MCUCSR & (1<<EXTRF)) {
safeMode(10); // External reset!
} else if(MCUCSR & (1<<BORF )) {
safeMode(20); // Brownout reset!
} else if(MCUCSR & (1<<WDRF )) {
safeMode(50); // Watchdog reset!
}
// Set the three shift register pins as outputs
DDRB |= (1 << clockPin) | (1 << latchPin) | (1 << dataPin);
// Before we begin, set the clockPin to LOW
PORTB &= ~(1<<clockPin);
// The primary loop
while (1) {
// Set BOTH directions to Red
send(0b00111111);
delay(changeDelay/8);
// Set the first directions to Green and the second to Red
send(0b10000010);
delay(changeDelay);
// Set the first directions to Yellow and keep the second direction Red
send(0b01000010);
delay(changeDelay/2);
// Set the Both directions to Red
send(0b00100010);
delay(changeDelay/8);
// Set the first directions to Red and the second to Green
send(0b00101000);
delay(changeDelay);
// Set the first directions to Yellow and keep the second direction Red
send(0b00100100);
delay(changeDelay/2);
} // Closing the primary loop
} // Closing the main process
// The error function
void safeMode(uint8_t errorReason) {
send(0b00100010);
delay(10);
errorReason = ((errorReason)*10);
uint8_t i;
for (i = 0; i < errorReason; i++) {
send(0b00100000);
delay(1);
send(0b00000010);
delay(1);
}
} // Closing the safeMode function
// Delay and feed the dog all at the same time
void delay(uint8_t delayTime) {
while (delayTime >= 0) {
feedDog();
_delay_ms(1000);
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 a byte out to the dataPin
void send(uint8_t toSend) {
uint8_t i;
for (i = 0; i < 8; i++) {
sendBit(toSend & 1);
toSend >>= 1;
}
latch(); // Once the Byte has been written, cycle the latch pin to output the data
feedDog(); // Reset the watch dog timer
} // 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);
}
cycleClock(); // Once the bit has been written, cycle the clock
} // 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