Skip to content

Instantly share code, notes, and snippets.

@EnDagiSaender
Created October 3, 2014 19:09
Show Gist options
  • Save EnDagiSaender/9d333810d5691cf6b386 to your computer and use it in GitHub Desktop.
Save EnDagiSaender/9d333810d5691cf6b386 to your computer and use it in GitHub Desktop.
neopixel in STTNG pinball mod (swedish comments)
/*
Byggt med en arduino Nano v.3
Läser av pin 0-7 (PB0..PB7) som är kopplade till lamporna för alla 7 modes samt finale frontier.
Lyser en lampa jordas pinnen kopplad till den lampan via en optokopplare samt är den släkt
hålls pinnen hög mha en pullup resistorn i mikroprossesorn. Tänds eller släcks en lampa
skapar det en interupt, i interruptrutinen ISR (PCINT2_vect) sparas vilka lampor som tänts i state1,
samt ökar räknaren count, som triggas i main loopen när lamp matrisen gått igenom minst ett varv.
när räknaren gått 2 varv jämförs vilka lampor som varit tända med föregående varv. På så vis får
man reda på vilken lampa som blinkar, dvs vilket mode som är aktivt. Sedan kollas ifall pixlarna
har rätt färg, annars byts det till den färgen. Nackdelen med att jämföra med vilken lampa som
ändrat sig jämt emot föregående varv är ifall man inte startat något mode och bara en lampa blinkar,
då är det ingen lampa som ändrats mellan varven och därför är en räknare (onemodechange) tillagd. Den ökar
för varje varv som enbart en lampa lyser och nollställs ifall fler gör det. Om den inte nollställts
på mer än 2 varv så byter den till den ensama lampans färg. Varför den inte byter direkt är tack vare
senariot då 2 lampor är aktiva (en lyser och en blinkar). då den blinkande är släkt hinner den lysande
leverera fler än 13 interrupts (ett varv) och då skulle isf pixlarna blinka fram och tillbaka mellan
de färgerna.
/Erik Fagerberg (FGR)
*/
#include <Adafruit_NeoPixel.h>
#define PIN 10 // styr alla leds med pinne D10
Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, PIN, NEO_GRB + NEO_KHZ800);
volatile int count = 0; //(varv)Räknare för varje gång någon pinne går hög/låg mer än 13 gånger
int onemode = 0; //räknare för hur många lampor som är tända
int onemodechange = 0; // Räknare för varje varv som enbart 1 lamppa varit tänd
volatile byte state1; // Sparar vilka lampor som varit tända
byte state2, state3; // Sparar nuvarand samt föregående varv av vilka lampor som varit tända
byte chkmode; // Jämför state2,3 för att se vilka lampor som ändrats
int color = 0; //variabeln för att bestämma vilken färg i arrayen som ska användas
//array med de 8 olika RGB färgerna för varje mode
uint32_t mode[8] = {
strip.Color(0, 73, 255), // Blå, Search the galaxy
strip.Color(27, 0, 255), // Lila, Worm hole
strip.Color(255, 0, 255),// Rosa, Time rift
strip.Color(255, 0, 0), // Röd, Finale frontier
strip.Color(255, 95, 0), // Orange, Asteroid threat
strip.Color(255, 255, 0),// Gul, Rescue
strip.Color(0, 255, 69), // Turkos, Battle simulation
strip.Color(0, 255, 0)}; // Grön, Q´s
ISR (PCINT2_vect) //interrupt vektor för när någon av pinnarna 7..0 ändras
{
cli(); // stänger av alla inteupts
// läser av statusen på 7..0 och nollar de bitar för respektive pin där en lampa varit
// tänd och sparar det i state1
state1 &= PIND;
count++; // räknar upp hur många interrupts som varit
sei(); // sätter på interrupts igen
}
void setup()
{
/*
stänger av lite saker i prossesorn som inte programmet använder
så den drar lite mindre ström tex olika seriella komunikationer och analoga
till digitala omvandlare. Ser till att RX,TX (D0,D1) inte tror att den ska
komunicera med usb.
*/
ADCSRA = 0;
PRR = B10010111;
UCSR0B = 0; // stänger av usart. behövs nog inte iom att det görs i
// raden ovanför men vill inte riskera att RX,TX kukar ur
DDRD = 0b00000000; // Sätter pin 7..0 till ingångar
PORTD = 0b11111111; // Ansluter pullup resistor på pin 7..0
state1 = 0b11111111; //sätter lite default startlägen, alla lampor släckta
state2 = 0b11111111;
state3 = 0b11111111;
chkmode = 0b00000000;
PCMSK2 = 0b11111111; // sätter att interrupts ska triggas på alla pinnar 7..0
PCICR |= (1<<PCIE2); // vilken port interrupts ska triggas på, den med pin 7..0 (D)
strip.begin(); // startar igång neopixlarna
strip.setPixelColor(0, mode[0]); //sätter första pixeln för att visa att programmet startat
strip.show(); // tänder upp pixeln blå
}
void loop()
{
if (count > 13){ //efter fler än 13 interrupts, det jag kallar för ett varv
// Stänger så att inte interrupts triggas på pin 7..0 tills alla ändringar i loopen är gjorda
PCICR = 0b00000000;
state2 = state1; // sparar state1 som används i interruptsen som state2
chkmode = (state2 ^ state3); // sparar vilka pinnar som ändrats mellan varven
/*
Går igenom och kollar hur många lampor som varit tända, för att ta reda på ifall det
enbart är en lysande lampa.
*/
onemode = 0;
for(int i=0; i<8; i++){
if (!(bitRead(state2,i))) onemode++; //kollar om en lampa är tänd, isf öka onemode
}
// Om och endast om en lampa varit tänd, öka varvräknaren onemodechange
if (onemode == 1) onemodechange++;
else onemodechange = 0; // Om fler än en lampa varit tänd, nollställ
// Om det gått mer än 2 varv och endast en lampa varit tänd, sätt state2 som senare blir
// state3 som om alla lampor vore släckta samt nolla onemodechange vliket får
// konsekvensen att nästa varv kommer den ensama blinkande lampan se ut som den
// förändrats och pixlarna kan byta färg
if (onemodechange > 2){
state2 = 0b11111111;
onemodechange = 0;
}
/*
kollar ifall och isf vilken lampa som ändrats och då sätter den color till
rätt färg och nollställer räknaren onemodechange.
*/
for(int i=0; i<8; i++){
if (!(chkmode ^ (0b10000000 >> i))) { // samma som att skriva if (chkmode == (0b10000000 >>i))
color = i;
onemodechange = 0;
}
}
// Kollar om pixlarnas nuvarande färg är samma som den valda att byta till, om inte byt till den färgen
if (mode[color] != strip.getPixelColor(0)){
for(int i=0; i<8; i++){ //loop för att sätta de 8 pixlarna till rätt färg
strip.setPixelColor(i, mode[color]);
}
strip.show(); // tänder upp pixlarna
state2 = 0b11111111; // nollställer så att den inte byter fram och tillbaka mellan föregående
} // och nya färgen
state3 = state2; // sparar nuvarande state för att göra jämförelse nästa varv
state1 = 0b11111111; // nollställer variabeln för kollen av vilka lampor som varit tända
count = 0; // nollställer varvräknaren
PCICR = 0b00000100; // sätter på interrupts på pin 7..0 igen
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment