Arduino kontrollerad RGB LED Dot Matrix styrelse (4 / 4 steg)
Steg 4: programmering
Som vi sa i steg 3, rekommenderar vi att titta på denna video: http://www.youtube.com/watch?v=FehBLNHMlfo. Det visar hur du faktiskt ansluter Arduino till TLCs i första hand, så det är ett bra ställe att börja. När det gäller programmering, vi dela upp arbetet bland två Arduinos och fick dem att kommunicera. Följande program är bara ram för en slutprodukt. LED Driver Arduino är klar, även om registeransvarige är helt enkelt ett skal för vad du vill programmera styrelsen att göra:LED Driver Arduino:
Texas Instruments TLC 5940 med Arduino
Med hjälp av www.kevindarrah.com
#include < SPI.h > //Serial perifera Interface Library
Inkludera den lätt flytt-Lib
#include < EasyTransfer.h >
EasyTransfer ET;
Detta måste vara exakt samma på andra Arduino
struct RECEIVE_DATA_STRUCTURE {
int LEDGrid [18].
};
int LEDData [18].
RECEIVE_DATA_STRUCTURE matrix;
byte ch = 0, chbit = 0, spibit = 0, spibyte = 0; / / variabler används av tlc sub rutin
int SINData; //variable används för att flytta data till TLC
byte transferbyte [48] ;// byte som skickas till tlc5940 via SPI
48 eftersom 16 kanaler @ 12bits ger 384bits, 384/8 = 48 byte, 12 bitar till 8-bitars omvandling
byte DCvalue [32]; / / 0-63, 6 bitars DOT korrigering byte
int i, j, k, l, m, n; misc variabler
int count = 0;
//*******************************************************************************************
//*******************************************************************************************
void setup() {/ / MAIN SETUP MAIN SETUP MAIN SETUP MAIN SETUP MAIN SETUP
ET.begin(details(matrix), & följetong);
pinMode (7, OUTPUT); //XLAT
pinMode (3, OUTPUT); //OSC2B GSCLK
pinMode (4, OUTPUT); //VPRG
pinMode (11, OUTPUT); //MOSI DATA
pinMode (13, OUTPUT); //SPI klocka
Stift 5 är tomt
Ställ in SPI
SPI.setBitOrder (MSBFIRST); //Most signifikanta biten första
SPI.setDataMode(SPI_MODE0); / / läge 0 stigande kanten av data, hålla klockan låg
SPI.setClockDivider (SPI_CLOCK_DIV4), //Run data i på 16MHz/4-4MHz
för (jag = 0; jag < 48; i ++) //clear ut grå skala Data
transferbyte [i] = 0;
för (jag = 0; jag < 32; i ++) //set Dot korrigering data till max (63 decimal för 6 bitars)
DCvalue [i] = 63.
Serial.BEGIN (9600); //debugging?
Ställ in DOT korrigering
DotCorrection(); / / sub rutin hjälper
noInterrupts(); / / ställa upp räknare, så gå inte in avbryter
TCCR2A = B00010010; //Timer 2 inställd Jämför läge växla stift 5 @ 8MHz, Arduino Digital 3
TIMER 2 ÄR GSCLCK
Timer 2 prescaler satt till 1, 16/1 = 16 MHz, men växlar pin 5 varje andra cykel, 8MHz
TCCR2B = B00000001;
TCCR1A = B00000000; //Timer 1 inte växla något, används för att räkna
Timer 1 prescaler inställd Fclk/256
Varför? Vi behöver räkna 4096 pulser av Timer 2 - stift 5
8 MHz = 1 puls varje 125ns - 4096 pulser skulle behöva 512us
Timer 1 körs på 16MHz/256 = 62,5 kHz, behöver vi en match på varje 512us
Jag kan i princip få ett avbrott att bli synad varje 512us, så...
Jag måste köra Timer 2 @ 8MHz för 512us att få 4096 pulser
Jag kan inte räkna dessa pulser egenskapslistan (för fort), så
Jag ska räkna med Timer 1, vilket gör en räknas varje 16us
Disken börjar på 0, så vi ska ställa till 31 att få ett avbrott efter 512us
TCCR1B = B00001100; //Mode=CTC med OSCR1A = topp och 256 som prescaler
Maskera uppsättning upp, kommer att kräva ISR (Inerrupt Service rutin) jämför matcha på A
TIMSK1 = B00000010;
Detta är de match värdena för räknare
0 här betyder det kommer att matcha på en cykel av klocka/prescaler
OCR1A = 31; //to få våra 512us avbrott
interrupts(); / / kick off timers!
attachInterrupt (0, uppdatering, RISING);
48
för (jag = 0; jag < 48; i ++) //wipe data i tlc
TLC i, 0. / / det här är hur du uppdaterar lysdioderna, tlc är en subrutin med två ingångar
TLC(Channel, Value) kanalen i detta fall är 0-32 och värdet är 0-4095 intermittens
4095 är 100% på
pinMode (5, OUTPUT); //BLANK vi inrättat detta stift här, så det är fortfarande i en hög impedans
Ange under hela installationen, annars lysdioderna galen! även om du skriver denna hög
för (int jag = 0; jag < 22; i ++) {
TLC((i*3),4095);
}
Delay(100);
för (int jag = 0; jag < 22; i ++) {
TLC((i*3),0);
}
för (int jag = 0; jag < 22; i ++) {
TLC((i*3)+1,4095);
}
Delay(100);
för (int jag = 0; jag < 22; i ++) {
TLC((i*3)+1,0);
}
för (int jag = 0; jag < 22; i ++) {
TLC((i*3)+2,4095);
}
Delay(100);
för (int jag = 0; jag < 22; i ++) {
TLC((i*3)+2,0);
}
}
void loop() {/ / MAIN LOOP MAIN LOOP MAIN LOOP MAIN SLINGA MAIN LOOP MAIN LOOP
updateLED();
Detta skulle vara ett bra ställe att lägga animationer på grund av att du kan använda alla
av färg combos, inte bara 10 eller så.
}
ISR(TIMER1_OVF_vect) {
} / / Över gränsen flagga avbryta du behöver detta även om du inte använder det
ISR(TIMER1_COMPB_vect) {
} / / Jämföra B - inte används
ISR(TIMER1_COMPA_vect) {/ / avbryta om du vill räkna 4096 pulser på GSLCK
PORTD | = 1 << 5; / / Skriv tom hög om du vill återställa 4096 räknaren i TLC
PORTD | = 1 << 7; / / Skriv XLAT hög att spärren i data från den senaste datan strömmen
PORTD & = ~ (1 << 7), //XLAT kan gå låg nu
PORTD & = ~ (1 << 5), //Blank går låg att starta nästa cykel
SPI.end (); //end SPI så vi kan skriva till klockan stift
PORTB | = 1 << 5; / / SPI klocka pin-för att ge det extra räkningen
PORTB & = ~ (1 << 5); / / databladet säger du behöver detta av någon anledning?
SPI.begin(); / / starta om SPI
för (SINData = 95. SINData > = 0; SINData--) {/ / skicka data!
SPI.transfer(transferbyte[SINData]); / / The SPI port bara förstår byte-8 bitar bred
TLC behöver 12 bitar för varje kanal, så 12 bitar gånger 64 kanaler ger 768 bitar
768/8 = 96 bytes, 0-95
}
greve ++;
}
void updateLED() {
ET.receiveData();
för (int jag = 0; jag < 18; i ++) {
Skriva ut vad som händer
Serial.Print (matrix. LEDGrid[i]);
Serial.Print(",");
Switch som tar emot 0-10 data och omvandlar det till färger.
Switch (matrix. LEDGrid[i]) {
fall 0: / / OFF
TLC(((3*i)),0);
TLC(((3*i)+1),0);
TLC(((3*i)+2),0);
bryta;
fall 1: / / röd
TLC(((3*i)),4095);
TLC(((3*i)+1),0);
TLC(((3*i)+2),0);
bryta;
fall 2: / / grön
TLC(((3*i)),0);
TLC(((3*i)+1),0);
TLC(((3*i)+2),4095);
bryta;
fall 3: / / blå
TLC(((3*i)),0);
TLC(((3*i)+1),4095);
TLC(((3*i)+2),0);
bryta;
fall 4: / / lila
TLC(((3*i)),2000);
TLC(((3*i)+1),4095);
TLC(((3*i)+2),0);
bryta;
fall 5: / / TEAL
TLC(((3*i)),0);
TLC(((3*i)+1),4095);
TLC(((3*i)+2),4095);
bryta;
mål 6: / / gul
TLC(((3*i)),3000);
TLC(((3*i)+1),0);
TLC(((3*i)+2),4095);
bryta;
fall 7: / / rosa
TLC(((3*i)),4095);
TLC(((3*i)+1),3500);
TLC(((3*i)+2),3500);
bryta;
mål 8: / / ORANGE
TLC(((3*i)),2232);
TLC(((3*i)+1),0);
TLC(((3*i)+2),1108);
bryta;
mål 9: / / ljus blå
TLC(((3*i)),1000);
TLC(((3*i)+1),4095);
TLC(((3*i)+2),2000);
bryta;
mål 10: / / vit
TLC(((3*i)),1500);
TLC(((3*i)+1),4095);
TLC(((3*i)+2),4095);
bryta;
standard:
TLC(((3*i)),100);
TLC(((3*i)+1),200);
TLC(((3*i)+2),200);
}
}
Serial.println("");
}
Annullera tlc (int kanal, int värde) {/ / TLC att uppdateringen TLC att uppdateringen TLC att uppdatera TLC Update
Denna rutin måste ske så snabbt som möjligt!
IF(Value>4095)
värde = 4095;
IF(Value<0)
värde = 0;
Vi måste omvandla värdet 12 bitar till en 8-bitars BYTE, kan inte SPI skriva 12bits
Vi räkna ut där i alla byte att skriva till, så vi inte behöver slösa tid
uppdatera allt
12 bitar i byte, en start på 12 bitar kommer antingen 0 eller 4 i en byte
spibit = 0;
om (bitRead (kanal, 0)) //if Läs om värdet är udda, är i början på en 4
spibit = 4;
Detta är en förenkling av kanal * 12 bitar/8 bitar
spibyte = int (kanal * 3/2), //this assignes som byte 12 bit värdet börjar i
för (chbit = 0; chbit < 12, chbit ++, spibit ++) {/ / börja precis vid där uppdateringen kommer att gå
IF(spibit==8) {//during 12 bitar cykeln, gränsen för byte infaller
spibyte ++; //roll in i den nästa byten
spibit = 0; //reset lite räkna i byten
}
om (bitRead (värde, chbit)) //check värdet 1 och 0 är
bitSet (transferbyte [spibyte], spibit), //transferbyte är vad som skrivs till TLC
annat
bitClear (transferbyte [spibyte], spibit);
} //0-12 bit loop
}
void DotCorrection() {
PORTD | = 1 << 4; //VPRG till DC läge hög
spibyte = 0; //reset våra variabler
spibit = 0;
för (ch = 0; ch < 32; ch ++) {/ / 6 bitar en bit x 32 utgångar
för (chbit = 0; chbit < 6; chbit ++) {
IF(spibit==8) {
spibyte ++;
spibit = 0;
}
om (bitRead (DCvalue [ch], chbit)) //all 6 bitar
bitSet (transferbyte [spibyte], spibit); //setting bit 7 för överföring byte
annat
bitClear (transferbyte [spibyte], spibit);
spibit ++;
}
}
SPI.begin();
för (j = spibyte; j > = 0; j--) {
SPI.transfer(transferbyte[j]);
}
PORTD | = 1 << 7;
PORTD & = ~ (1 << 7);
PORTD & = ~ (1 << 4), //VPRG är bra att gå in i normal sätt låg
}
Controller Arduino:
/*
Data läses:
0: OFF VERKLIGEN NU
1: RÖD IDK
2: GRÖN SPELAR
3: BLUE NOTE
4: LILA BAR
5: KRICKA -
6: GUL -
7: ROSA -
8: ORANGE -
9: L-BLÅ -
10: VIT -
DEF:TEST-
*/
De ovanstående uppgifter som motsvarar den färginformation enligt LED Driver Arduino
Inkludera den lätt flytt-Lib
#include < EasyTransfer.h >
EasyTransfer ET;
Detta måste vara exakt samma på andra Arduino
struct SEND_DATA_STRUCTURE {
int LEDGrid [18].
};
SEND_DATA_STRUCTURE matrix;
//----------------------------Variables-------------------------
int buttonRaw [6] [3].
int LEDData [6] [3].
//--------------------------------------------------------------
void setup() {
Börja följetong på 9600 - felsökning
Serial.BEGIN(9600);
EasyTransfer börjar
ET.begin(details(matrix), & följetong);
Stift 7-9 används för knappen trådarna
pinMode (7, OUTPUT);
pinMode (8, OUTPUT);
pinMode (9, OUTPUT);
Definiera speaker port - inte faktiskt används i denna skalprogram
pinMode (2, utgång);
buttonCheck();
}
//------------------------------Setup---------------------------
void loop() {
buttonCheck();
Update();
Lägg till faktiskt program i detta utrymme. Läsa värdena som knappen, Ställ in den
lampor, och spela upp ljud. Dess allt upp till dig. Detta är ramen
för vad du vill.
}
//-----------------------------Programs--------------------------
Updater: lägga till faktiska ljus skicka mekanik. Enkelt sätta LEDData [x] [y]
array-koordinat som motsvarar lämplig ljuset till ett antal
från 0 till 10 enligt definitionen på toppen av detta program.
void update() {
för (int y = 0; y < 3; y ++) {
för (int x = 0, x < 6, x ++) {
Matrix. LEDGrid [gridCount] = LEDData [x] [y];
gridCount ++;
}
Delay(5);
}
gridCount = 0;
ET.sendData();
}
//-------------------
Knappen kontroll: kontrollerar knappen värden och sparar det rådata till en matris.
Ordern går från (0,0)-(6,0), sedan (0,1)-(6,1), etc. Dessa data kan
används för att växla värden, etc.
void buttonCheck() {
för (int y = 0; y < 3; y ++) {
digitalWrite(7+y,HIGH);
för (int x = 0; x < 6; x ++) {
buttonRaw [x] [y] = analogRead (x);
}
digitalWrite(7+y,LOW);
}
}