Created
October 10, 2012 19:58
-
-
Save robotjoosen/3868021 to your computer and use it in GitHub Desktop.
Veins 74HC595 PWM code
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
/* ------------------------------------------------------------------------------------------------ | |
* Cynaptic Collective - Veins Basic v1.0 | |
* | |
* Project : Veins | |
* Client : Melkweg Amsterdam / OffCentre 2012 / Deframe Collective | |
* Author : Roald Joosen | |
* Start date : 21 aug 2012 | |
* End date : 16 sept 2012 | |
* | |
* ------------------------------------------------------------------------------------------------ */ | |
// Include Libraries | |
#include <TimerOne.h> | |
// 74HC595 Settings | |
#define shiftRegisters 4 // Shift Register Amount | |
byte setRegisterPin[shiftRegisters * 8]; // Pin total | |
int __74HC595_DS = 11; // Serial Data Input | |
int __74HC595_SH_CP = 13; // Shift Register Clock pin | |
int __74HC595_ST_CP = 10; // Storage Register Clock pin (latch pin) | |
int __74HC595_ST_CP_PORTB = __74HC595_ST_CP - 8; // Faster Latch | |
// Segment Mask | |
int layout_cols = 19; | |
int layout_rows = 3; | |
int layout[3][19] = | |
{ | |
{ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 } | |
}; | |
// Pin Assignment | |
int register_pin_total = 29; | |
int register_pins [3][19] = | |
{ | |
{ 0, 1, 2, 3, 6, 9, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 4, 7, 10, 13, 15, 16, 17, 18, 19, 20, 22, 24, 0, 0, 0, 0 }, | |
{ 0, 0, 0, 5, 8, 11, 14, 0, 0, 0, 0, 0, 21, 23, 25, 26, 0, 0, 0 } | |
}; | |
int register_pin_value[3][3][19]; // [ target value, current value, direction ][ row 1 ~ 3 ][ Segment 0 ~ 19 ] | |
int max_brightness = 255; | |
// Timers | |
unsigned long next_update; | |
int update_rate; | |
unsigned long next_segment; | |
int segment_rate; | |
int current_segment; | |
/* ------------------------------------------------------------------------------------------------ */ | |
// | |
// iProcess && setup SPI | |
// Original by : Joseph Francis | |
// | |
/* ------------------------------------------------------------------------------------------------ */ | |
#define TICKER_PWM_LEVELS 32 // Brightness levels | |
#define TICKER_STEP 256/TICKER_PWM_LEVELS // Full Step size | |
#define TICKER_HALFSTEP 256/(TICKER_PWM_LEVELS/2) // Half Step size | |
#define TICKER_QUADSTEP 256/(TICKER_PWM_LEVELS/4) // Quad Step size | |
#define TIMER_DELAY 280 // Higher is slower | |
int ticker; | |
void iProcess() | |
{ | |
byte registerValue[shiftRegisters]; | |
ticker = ( ticker > TICKER_PWM_LEVELS ) ? 0 : ticker + 1; | |
int myPos = ticker * TICKER_STEP; | |
for (int i = 0 ; i < 8; i++ ) | |
{ | |
int myLev = 0; | |
for (int iSR = 0 ; iSR < shiftRegisters ; iSR++) | |
{ | |
myLev = (setRegisterPin[i+(iSR*8)] > myPos) ? 1 : 0; | |
bitWrite( registerValue[iSR], i, myLev ); | |
} | |
} | |
latchOff(); | |
for (int iSR = shiftRegisters-1 ; iSR >= 0 ; iSR--) | |
{ | |
spi_transfer(registerValue[iSR]); | |
} | |
latchOn(); | |
} | |
void latchOn() | |
{ | |
bitSet(PORTB,__74HC595_ST_CP_PORTB); | |
} | |
void latchOff() | |
{ | |
bitClear(PORTB,__74HC595_ST_CP_PORTB); | |
} | |
void setupSPI() | |
{ | |
byte clr; | |
SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master | |
SPCR &= ~( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits | |
clr=SPSR; // clear SPI status reg | |
clr=SPDR; // clear SPI data reg | |
SPSR |= (1<<SPI2X); // set prescaler bits | |
delay(10); | |
} | |
byte spi_transfer(byte data) | |
{ | |
SPDR = data; // Start the transmission | |
loop_until_bit_is_set(SPSR, SPIF); | |
return SPDR; // return the received byte, we don't need that | |
} | |
/* ------------------------------------------------------------------------------------------------ */ | |
// | |
// Loop & Setup | |
// | |
/* ------------------------------------------------------------------------------------------------ */ | |
void setup() | |
{ | |
pinMode(__74HC595_DS, OUTPUT); | |
pinMode(__74HC595_ST_CP, OUTPUT); | |
pinMode(__74HC595_SH_CP, OUTPUT); | |
digitalWrite(__74HC595_DS,LOW); | |
digitalWrite(__74HC595_ST_CP,LOW); | |
digitalWrite(__74HC595_SH_CP,LOW); | |
Serial.begin(9600); | |
setupSPI(); | |
Timer1.initialize(TIMER_DELAY); | |
Timer1.attachInterrupt(iProcess); | |
// Set var values | |
segment_rate = 200; | |
update_rate = 20; | |
} | |
void loop() | |
{ | |
if( millis() > next_update ) | |
{ | |
for( int c=0;c<layout_cols; c++ ) | |
{ | |
for( int r=0; r<layout_rows; r++) | |
{ | |
if(layout[r][c] > 0 && register_pin_value[0][r][c] != register_pin_value[1][r][c]) | |
{ | |
setRegisterPin[register_pins[r][c]] = register_pin_value[1][r][c]; | |
if(register_pin_value[2][r][c] == 0) | |
{ | |
if(register_pin_value[1][r][c] < register_pin_value[0][r][c]-TICKER_HALFSTEP) | |
register_pin_value[1][r][c] += TICKER_HALFSTEP; | |
else | |
register_pin_value[2][r][c] = 1; | |
} | |
else | |
{ | |
if(register_pin_value[1][r][c] > 0) | |
{ | |
register_pin_value[1][r][c] -= TICKER_STEP; | |
} | |
else | |
{ | |
register_pin_value[0][r][c] = 0; | |
register_pin_value[1][r][c] = 0; | |
register_pin_value[2][r][c] = 0; | |
} | |
} | |
} | |
} | |
} | |
next_update = millis() + update_rate; | |
} | |
if( millis() > next_segment ) | |
{ | |
for( int r=0; r < layout_rows; r++ ) | |
{ | |
if( layout[r][current_segment] > 0 ) | |
{ | |
register_pin_value[0][r][current_segment] = max_brightness; | |
} | |
} | |
current_segment = ( current_segment < layout_cols ) ? current_segment + 1 : 0 ; | |
next_segment = millis() + segment_rate; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment