Arduino Projekten

Mon 21-Jan-19
15:48:40




Random Figuren

Datum: Sat 01 March 2014
Samenvatting: Random figuren op de panelen, echter nog zonder interupt.


Tijd om wat zaken te versnellen en om er meteen iets leuks van te maken.

Vanuit het vorige deel (de Schuine Lijnen) zijn er wat figuur-funkties bij geprogrammeerd. Elk figuur moet op een bepaalde (x;y) plek en in een bepaalde kleur (k) worden gezet. De figuur selectie zelf gebeurt in een eenvoudige [switch-case]-statement:

  1. Vierkant
  2. VierkantOpen
  3. Cirkel
  4. CirkelOpen
  5. Kruis
  6. Fourdots
  7. Smilie

Ik wilde 3 analoge ingangen vrij hebben, die zijn hier benut voor 3 potmeters. Want niets is vervelender om elke keer in het programma een klein dingetje te veranderen en weer te Uploaden naar de Arduino:

  • (nr 6) De snelheid van het wisselen van de patronen - Helemaal rechts: wisselt wel de patronen, maar positie blijft ongewijzigd.
  • (nr 5) De kleur - Helemaal links: geeft een random kleur.
  • (nr 4) Het patroon - Helemaal links: geeft een random patroon.
Voordat een nieuw figuur neergezet wordt, moeten er gegevens van het oude figuur worden bewaard (xx_old, yy_old, figuur_old). Eerst wordt hetzelfde patroon weer getekend, maar dan in het zwart (de RGB zijn uit). Daarna komt op de nieuwe positie een nieuw figuur. Deze truuk werd vroeger al toegepast op een home-computer en in DOS-programma's.

En tijdens dit alles moet de LedPaneel routine [IntOneRow()] blijven doorlopen. Daar komt de gehele [del = del + 1;] telling bij kijken (del = delay). In feite telt deze hoeveel keren de Paneel Routine doorlopen is en laat dan de Figuur-routine doorlopen (de gehele IF-statement).

Het belangrijkste is de Paneel-routine [IntOneRow]. De overige routines hebben ondersteunende funkties. Om de Paneel-routine goed te laten funktioneren, zijn er eerst duidelijke afspraken nodig van aansluitingen, Led-posities en kleuren. Één en ander is bepaald door de aansluitingen op de Arduino en door de uitvoer-snelheden. Tijdens de ontwikkeling zijn definities ook op details gewijzigd, maar de hoofdindeling is blijven bestaan. Het wordt een taai verhaal met veel theorie en overdenkingen.

  • Noot vooraf: "%" geeft binaire notatie aan (In Arduino C++ is dat "B"); "$" geeft hexa-decimale notatie aan (in C++ is dat "0x").

    Led definities.

    Allereerst moet duidelijk zijn welk nummer de Led's krijgen. Aangezien 2D-objecten meestal met een (x;y)-stelsel werken, zijn ze op deze manier ook makkelijk te nummeren. X gaat horizontaal en bedient de kolommen, Y gaat vertikaal en bedient de regels. (X;Y) = (Kolom;Regel) = (Col;Row). Dan hou ik de (Col;Row) als interne benamingen en de (X;Y) de externe benamingen voor gebruik in het globale programma. Dit geheel is in een plaatje als volg samen te vatten.

    Paneel co-ordinaten

    Om zo'n paneel snel aan te kunnen sturen zijn array-constructies reuze geschikt, zowel in logische nummeringen als in snelheid. Elke Led heeft een nummer gekregen, elke array-element heeft ook een nummer. De Led's zijn 2D-genummerd, dus het array wordt (in ieder geval) twee-dimensionaal.

    Het kleinste array element is een byte. En er gaan 8 bits in zo'n byte-element. Een paneel heeft 512 RGB-Led's (16x32 Led's) en elke Led heeft 3 "aansluitingen". Voor elke aansluiting is een bitje nodig, totaal dus 1536 bits.

    De panelen zijn opgebouwd in twee helften, met elke helft zijn eigen RGB-aansluitingen. Om informatie voor regel 0 (de bovenste regel) naar het paneel te sturen, wordt tegelijk informatie voor regel 8 gestuurd (de bovenste regel van de onderste helft). Of te wel, deze twee regels moeten tegelijk van informatie worden voorzien voor een efficient en snel gebruik. Deze twee regels moeten hun informatie vanuit 1 byte krijgen.

    En nu komt de eerste geheugen verspilling al om de hoek kijken. Van de poort van de Arduino, waar de RGB-aansluitingen op zitten, worden 6 pinnen gebruikt, elke helft van het paneel heeft 3 aansluitingen. Pin 0 en Pin 1 zijn gereserveerd (voor seriele communicatie met de PC), die zijn (zeg maar) niet te gebruiken. Deze worden niet voorzien van data, maar worden wel verspild in de RGB-bytes.

    In het kort: Een paneel heeft 1536 bitjes aan informatie nodig, maar er worden 2048 bitjes voor gebruikt. Voor 1 paneel zijn dan 256 bytes nodig. 32 bytes voor elke regel MAAL 16 regels DELEN DOOR 2 helften. Resultaat: een kwart deel wordt verspild, maar uitlezen en wegsturen wordt er makkelijk en snel door gemaakt.

    Zoals eerder genoemd, worden de RGB-aansluitingen op 1 poort verbonden en wel op de D2 .. D7 (D0 en D1 zijn voor de seriele aansluitingen). Bij de oorspronkelijke AdaFruit 16x32-paneel Tutorial denkt men graag in de volgorde van BGR. Ik denk graag in de volgorde RGB, dit is net andersom (kwam ik ook op de harde manier achter). Of te wel, de Rood krijgt een hoger bitje dan de Blauw. Zo kom ik op dat elke byte de volgende bit-definitie krijgt:

    bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
    Rood OnderGroen OnderBlauw Onder Rood BovenGroen BovenBlauw BovenSeriele ComSeriele Com
    R 2 G 2 B 2 R 1 G 1 B 1 x x

    Zo is elke byte (= Array Element) compatibel gemaakt met de aansluitingen ... want deze informatie moet echt in een snel tempo gebeuren, voor een knipper vrij beeld.

    Wat er nu nodig is, is een groot aantal elementen, een groot aantal bytes. Bij 32 Led's op een regel, worden hier 32 elementen in 1 dimensie gebruikt. Met 8 regels worden dit 8 elementen in de tweede dimensie. Grafisch is dit als volg voor te stellen.

    Array co-ordinaten

    In programma-code wordt dit:
    volatile byte PanelData [MaxCol][MaxRow]; // = [00..31],[0..7] of (% Rl Gl Bl Ru Gu Bu 0 0)

    Helderheid regelen gaat met Binaire Code Modulatie

    Het is mogelijk om een vorm van helderheid toe te passen. Van de Arduino zijn er projektjes die hiervoor gebruik maken van PWM, Puls Wijdte Modulatie. Dit werkt goed bij enkele Leds en wanneer elke Led zijn eigen aansturing heeft. Bij de Led-Panelen zou dit een ingewikkelde en tijdrovende routine opleveren (is onderzocht). Een alternatieve methode is BCM, wat staat voor Binaire Code Modulatie.

    BCM komt neer op het volgende idee. Elke Led krijgt meerdere elementen-bitjes, te nummeren als LSB (Laagst Significant Bitje) tot en met MSB (Meest Significant Bitje). Het idee bij BCM is: Verstuur de data van de laagste bits 1 keer. Verstuur de data van de tweede bits 2 keer. Van de derde bits 4 keer, Vierde bits 8 keer, tot de gewenste helderheid-bits "op" zijn en begin dan weer bij de laagste bits. Bij mijn project heb ik 3 helderheid-bitjes aangebracht, maar, als de micro-controler snel genoeg is, zijn meer bits mogelijk. In een plaatje komt BCM op het volgende neer:

    BCM definities

    Elke helderheid-bit moet ook in het paneel-array worden opgeslagen. Dit levert een stapel elementen-bytes op van 3 hoog. Of te wel, het eerdere gegeven paneel-array wordt 3 hoog gemaakt.

    In programma-code wordt dit:
    volatile byte PanelData [MaxCol][MaxRow][MaxBright]; // = [00..31],[0..7],[0..2] of (% Rl Gl Bl Ru Gu Bu 0 0)

    Ik heb echter twee panelen achter elkaar gekoppeld, tot een paneel van 64 Led's naast elkaar. Ik heb dus OF twee van deze array's nodig, OF een dubbel zo lange array. Dat laatste biedt echter meer snelheid.

    In programma-code wordt dit:
    volatile byte PanelData [MaxCol][MaxRow][MaxBright]; // = [00..63],[0..7],[0..2] of (% Rl Gl Bl Ru Gu Bu 0 0)

    Verder zijn enkele gegevens hard gecodeerd, zoals de [MaxRow = 8;] en de [MaxBright = 3;].

    In programma-code wordt dit:
    volatile byte PanelData [MaxCol][8][3]; // = [00..63],[0..7],[0..2] of (% Rl Gl Bl Ru Gu Bu 0 0)

    Kleur definities

    Door deze aparte manier van Paneel-data moet er een eenduidige afspraak komen om kleuren te gebruiken. Als eerste is er heel simpel gebruikt: [kleur = % 0000 0RGB]. Een ondersteunende routine moet dan zorgen dat deze 1-bits kleurtjes op de juiste manier in het Paneel-array wordt gestopt ... dit is inclusief in de juiste bits van een array-element (bits 765 of bits 432).

    Bij het uitbreiden van de helderheid tot 2-bits per kleur, werd dit [kleur = % 00RG BRGB]. Het blijft in een byte passen. Het blijkt echter dat er weinig helderheids verschil te zien is in 2 bits per kleur.

    Er kwam een derde bit per kleur bij. En er kwam een moeilijkheid bij. Een byte heeft niet genoeg ruimte om 3-bits * 3 kleuren (= 9 bits) op te slaan. Een byte voor een kleur werd gauw een word (= 16-bits) voor een kleur. En de kleur definitie is geworden: [kleur = % 0000 0RRR 0GGG 0BBB = $0RGB].

    De volgorde van Rood-Groen-Blauw is behouden en er is eenvoud om de kleuren te gebruiken ... bij gebruik van hexadecimale notatie.

    De [IntOneRow]-routine.

    Dit is de aller belangrijkste routine en heeft 1 hoofdtaak. Namelijk zo snel mogelijk alle data uit het Paneel-array naar het Led-Paneel brengen. En deze zou door een timer-interupt gestart moeten worden. In deze projekt-fase wordt deze routine nog door de [void Loop()] aangeroepen om het verder te kunnen fine-tunen tot een goed werkend geheel.

    Hoe moet deze routine zijn taak doen? Bij elke regel moet hij een regel byte voor byte op de pinnen D2 .. D7 van de Arduino zetten en dan een Clock-puls geven aan het paneel. Zoals eerder geschreven, worden dan twee Led-regels van data voorzien, voor elke helft van het paneel een regel.

    Is er een hele regel weggestuurd, dan moet deze routine een puls op de Latch zetten om alle data tegelijk zichtbaar te maken.

    Voor de helderheid moet er nog een teller worden opgehoogd, namelijk [BrightCount].

    Eerst werd de data opgesplitst in losse bitjes en elk bitje werd via een [digitalWrite(,)] naar een poort-bitje gebracht. Dit leverde 6 tijdrovende akties op, zoals ook gebruikt is bij de Schuine Lijnen.

    //----------------------------------------------
    byte rgb = PaneelData[rc][RowCount] >>2;
    //----------------------------------------------
    digitalWrite(r2 , rgb & 1); rgb = rgb>>1;
    digitalWrite(g2 , rgb & 1); rgb = rgb>>1;
    digitalWrite(b2 , rgb & 1); rgb = rgb>>1;
    //----------------------------------------------
    digitalWrite(r1 , rgb & 1); rgb = rgb>>1;
    digitalWrite(g1 , rgb & 1); rgb = rgb>>1;
    digitalWrite(b1 , rgb & 1); rgb = rgb>>1;
    //----------------------------------------------

    6 regels (eigenlijk 12, want twee instructies op 1 regel) kunnen vervangen worden door slechts 1 snelle regel. Er werd al vroeg rekening gehouden met het feit dat dit ook daadwerkelijk mogelijk is.

    // Send the RGB to the RGB-lines
    byte rgb = PanelData[rc][RowCount];
    PORTD = ( PORTD & B00000011 ) | rgb;

    Hierbij is rekening gehouden dat de oorspronkelijke bits 0 en 1 van deze port voor andere zaken wordt gebruikt (de [& B00000011]) en dus niet verstoord mogen worden.

    Zowel de Clock als de Latch werden eerst door Arduino routines [digitalWrite(,)] gedaan. Bij het toevoegen van Helderheid blijkt het beeld irritant te knipperen. Na het uitzoeken hoe dit via direkte poort-aansturing [PORTB = PORTB and/or iets] gedaan moest worden, is de snelheid een stuk hoger geworden. In het programma zijn deze stukjes duidelijk te herkennen, inclusief het Arduino-alternatief erachter als commentaar. Direkte Poort-programmering is echt een stuk sneller ... maar brengt ook een risico met zich mee.

    Voor het Latchen moet eerst het rijnummer nog naar het paneel worden gestuurd, ook om figuur-geesten te voorkomen. Ook het versturen van het rij-nummer wordt gedaan door direkte-poort programmering.

    // Select the Row on the panels.
    PORTC = ( PORTC & B11111000 ) | RowCount;

    Voor de helderheid aansturing in BCM is een extra array gebruikt, die moet aangeven wanneer welke laag (met helderheid-bitjes) naar het display moet worden gestuurd. Zoals ik al schreef, array's zijn heel makkelijk en tevens heel snel in het gebruik.

    const byte BrightRow [7] = {0,1,1,2,2,2,2}; // Counter Conversion for Binairy Code Modulation.
  • C++ begint array's te tellen vanaf element 0. Bij BCM is dit element in principe niet nodig en kan dus tellen van 1 t/m 7. Hier wordt wel vanaf 0 geteld t/m 6.
  • Het complete pakket van data uitlezen wordt dan:

    byte BrightLayer = BrightRow[BrightCount]; // Buiten de Data-Uitschuif Lus
    byte rgb = PanelData[rc][RowCount][BrightLayer];
    met:
  • rc => ReadColumn.
  • RowCount => Regel teller, loopt van 0..7.
  • BrightCount => Helderheids teller, loopt van 0..6.
  • Brightlayer = BrightRow[BrightCount] => Welke laag moet naar het paneel worden gestuurd ... En wanneer.
  • Aan het eind van deze routine wordt eerst de [RowCount} verhoogd, tot alle rijen [0..7] aan de beurt geweest zijn. Daarna wordt de [BrightCount] pas verhoogd [0..6].

    Betere Helderheid.

    Omdat ik bij het BCM een eigen array gebruik, is het mogelijk om hiermee het verschil in helderheid te vergroten (groter contrast, c.q. een soort van gamma-correctie) door elke rij niet dubbel zo vaak naar de panelen ter sturen, maar bijvoorbeeld 3 keer zo vaak. Er moeten dan twee regels worden aangepast:

    const byte MaxBrightCount = 13; // Count 0..MaxBrightCount
    const byte BrightRow [13] = {0,1,1,1,2,2,2,2,2,2,2,2,2}; // Counter Conversion for Binairy Code Modulation.

    Nadeel hiervan is weer wel dat het beeld weer irritant gaat knipperen, vooral bij lagere helderheden. Op de foto is dit echter niet te zien ("Duty Cycle 1:13") vanwege de sluitertijd (1/6sec).

    Ondersteunende funkties.

    Nu is er een routine die alle data naar het paneel stuurt. Maar het Paneel-array moet ook nog worden voorzien van data. En wel op een makkelijke manier. Routines die rekening houden met de eerder vastgelegde definities voor Paneel co-ordinaten en kleuren (inclusief helderheid). Hieronder een korte beschrijving van de ondersteunende routines.

    Arduino Pin definities.

    Alle Pin definities zijn hard-coded. Het maakt het programma stug met veranderingen en moeilijker om te lezen. Maar het verhoogd de snelheid.

    Desondanks zijn alle pinnen hier genoteerd als commentaar.

    [void InitPan()]

    Deze zet de benodigde Arduino pinnen op uitgang. Hier wordt direkte-poort programmering [DDRC DDRD DDRB] gebruikt om snelheids redenen.

    Hierin moet nog komen de voorbereidingen om timer-interupts te genereren.

    [void ClrPan()]

    In het kort: Deze routine wist het paneel. De kleur wordt gehaald uit een variabele [BGCOLOR] (van BackGroundCOLOR), zodat ook een andere kleur als achtergrond kan worden gebruikt.

    Op dit moment is het niet aan te raden om een andere achtergrond kleur te gebruiken, omdat de figuren dan, door de lichtuitstraling, moeilijk zichtbaar worden. Maar het is wel mogelijk.

    De werking is standaard. Twee geneste [FOR(;;)]-loops gaan alle array-bytes af.

    [void SetPoint (byte _x, byte _y, word _k)]

    Deze zet een Led aan op de gewenste positie (_x;_y) in de kleur _k. Met _k = 0 wordt de Led uitgezet.

    [byte LowColor (word _k)]

    Pakt de laagste bits van alle kleuren. Nodig voor in laag [0] van het Paneel-array.

  • Er is gebruik gemaakt van logische bewerkingen (AND OR Shift), in plaats van rekenkundige bewerkingen (+ - * /). Logische bewerkingen hebben geen last van overflow in de resultaten en logische bewerkingen zijn sneller.

    [byte MidColor (word _k)]

    Pakt de middelste bits van alle kleuren. Nodig voor in laag [1] van het Paneel-array.

  • Zie LowColor over logische bewerkingen.

    [byte HighColor (word _k)]

    Pakt de hoogste bits van alle kleuren. Nodig voor in laag [2] van het Paneel-array.

  • Zie LowColor over logische bewerkingen.

    [word Dec2RGB (word _k)]

    Zet een 9-bits decimale kleur (= % 0000 000R RRGG GBBB) om in een 9-bits hexadecimale kleur (= % 0000 0RRR 0GGG 0BBB).

  • Zie LowColor over logische bewerkingen.

    Character projekties?

    In het kort: deze zijn er (nog) niet.

    Ze kunnen nu wel gemaakt kunnen worden met de [void SetPoint (byte _x, byte _y, word _k)]-routine, maar dan moet men wel zelf alle losse puntjes van een character naar de Paneel-array sturen.

    Hoe snel is het eigenlijk?

    Er is nog een lichte knippering waar te nemen, vooral wanneer alle Led's branden (bij het instellen van een [bgcolor] is dat met dit programma waar te nemen.

    Wanneer de snelheid van de figuur-wisselingen omhoog gedraaid wordt, is de knippering ook gauw waar te nemen. De 8 groene Led's op het printje (dat op de Ardino geplaatst wordt), laat ook zien dat er een snelheids probleem is. 1 Ledje brandt iets feller dan de andere 7 ("Te Snel -Too Fast"). Tevens komen er kleur-verschillen in de figuren op het Paneel. Een figuur dat 1 kleur hoort te hebben, krijgt opeens meer kleuren.

    Misschien is dit kleur-effect ook het gevolg van een juiste combinatie van figuur-wisseling en [IntOneRow]-aanroep ... een soort interferentie tussen beide "loop"s.

    Wellicht dat de timer-interupt deze interferentie oplost.


    Broncode: [1: Random Figuren]

    1: De broncode van Random Figuren

    (Sat 01 March 2014)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    //     ---------------------------------------------------------
    //     |  Experimentation Kit for Arduino Example Code         |
    //     |  RGBMatrix : RGB Matrix - Random Shapes               |
    //     ---------------------------------------------------------

    // BackGround-Color (format: 0x0RGB = B 0000 RRRR GGGG BBBB)
    const word bgcolor = 0x0000;

    // Delay-var
    int del = 0;

    // (x;y) of Shape
    byte xx     = 0;
    byte xx_old = 0;
    byte yy     = 0;
    byte yy_old = 0;
    // Color of Shape
    word kk     = 0;
    // Some Pot-vars
    word pot_del    = 0;
    word pot_kleur  = 0;
    word pot_figuur = 0;
    word figuur_old = 0;

    void setup()
    { InitPan();
      Serial.begin(115200);
      randomSeed(analogRead(0));
    }

    void loop()
    {
      IntOneRow();
      pot_del = analogRead(5);
      del = del + 1;
      if ( del > (pot_del + 7 ) )
         { del = 0;
           if ( pot_del <1010 )
              { // Kies een (xx,yy) random
                xx = random( 0,61);
                yy = random( 0,13);
              }
           // Kies een kleur (potmeter of random)
           pot_kleur = analogRead(4) / 2;
           if ( pot_kleur == 0 )
              { pot_kleur = random( 1, 512);
              }
           kk = Dec2RGB(pot_kleur);

           // Kies een figuur (potmeter)
           pot_figuur = analogRead(3)/4;
           if ( pot_figuur == 0 )     { pot_figuur = random( 0, 255)}
           figuur( figuur_old , xx_old , yy_old , bgcolor   );
           figuur( pot_figuur , xx     , yy     , kk        );
           // Sla oude figuur op
           figuur_old = pot_figuur;
           // Sla oude (xx,yy) op
           xx_old = xx;
           yy_old = yy;
         }
    }

    void figuur (byte figuur_nummer, byte x, byte y, word k)
    { figuur_nummer = map ( figuur_nummer, 1, 255, 1, 7 );
      switch (figuur_nummer)
        { case 1 : Cirkel (x,y,k);
                   break;
          case 2 : CirkelOpen (x,y,k);
                   break;
          case 3 : Vierkant (x,y,k);
                   break;
          case 4 : VierkantOpen (x,y,k);
                   break;
          case 5 : Kruis (x,y,k);
                   break;
          case 6 : Fourdots (x,y,k);
                   break;
          case 7 : Smilie (x,y,k);
                   break;
        }
    }

    void Vierkant (byte x, byte y, word k)
    { SetPoint (x+0, y+0, k );
      SetPoint (x+0, y+1, k );
      SetPoint (x+0, y+2, k );
      SetPoint (x+0, y+3, k );
      SetPoint (x+1, y+0, k );
      SetPoint (x+1, y+1, k );
      SetPoint (x+1, y+2, k );
      SetPoint (x+1, y+3, k );
      SetPoint (x+2, y+0, k );
      SetPoint (x+2, y+1, k );
      SetPoint (x+2, y+2, k );
      SetPoint (x+2, y+3, k );
      SetPoint (x+3, y+0, k );
      SetPoint (x+3, y+1, k );
      SetPoint (x+3, y+2, k );
      SetPoint (x+3, y+3, k );
    }

    void VierkantOpen (byte x, byte y, word k)
    { SetPoint (x+0, y+0, k );
      SetPoint (x+0, y+1, k );
      SetPoint (x+0, y+2, k );
      SetPoint (x+0, y+3, k );
      SetPoint (x+1, y+0, k );
      SetPoint (x+1, y+3, k );
      SetPoint (x+2, y+0, k );
      SetPoint (x+2, y+3, k );
      SetPoint (x+3, y+0, k );
      SetPoint (x+3, y+1, k );
      SetPoint (x+3, y+2, k );
      SetPoint (x+3, y+3, k );
    }

    void Cirkel (byte x, byte y, word k )
    { SetPoint (x+0, y+1, k );
      SetPoint (x+0, y+2, k );
      SetPoint (x+1, y+0, k );
      SetPoint (x+1, y+1, k );
      SetPoint (x+1, y+2, k );
      SetPoint (x+1, y+3, k );
      SetPoint (x+2, y+0, k );
      SetPoint (x+2, y+1, k );
      SetPoint (x+2, y+2, k );
      SetPoint (x+2, y+3, k );
      SetPoint (x+3, y+1, k );
      SetPoint (x+3, y+2, k );
    }

    void CirkelOpen (byte x, byte y, word k )
    { SetPoint (x+0, y+1, k );
      SetPoint (x+0, y+2, k );
      SetPoint (x+1, y+0, k );
      SetPoint (x+1, y+3, k );
      SetPoint (x+2, y+0, k );
      SetPoint (x+2, y+3, k );
      SetPoint (x+3, y+1, k );
      SetPoint (x+3, y+2, k );
    }

    void Kruis (byte x, byte y, word k)
    { SetPoint (x+0, y+0, k );
      SetPoint (x+1, y+1, k );
      SetPoint (x+2, y+2, k );
      SetPoint (x+3, y+3, k );
      SetPoint (x+0, y+3, k );
      SetPoint (x+1, y+2, k );
      SetPoint (x+2, y+1, k );
      SetPoint (x+3, y+0, k );
    }

    void Fourdots (byte x, byte y, word k)
    { SetPoint (x+0, y+0, k );
      SetPoint (x+0, y+3, k );
      SetPoint (x+3, y+3, k );
      SetPoint (x+3, y+0, k );
    }

    void Smilie (byte x, byte y, word k )
    { SetPoint (x+0, y+0, k );
      SetPoint (x+3, y+0, k );
      SetPoint (x+0, y+2, k );
      SetPoint (x+1, y+3, k );
      SetPoint (x+2, y+3, k );
      SetPoint (x+3, y+2, k );
    }

    //==============================================================================
    // Paneel Vars.
    const byte MaxCol = 64;
    volatile byte PanelData [MaxCol][8][3];   // = [00..63],[0..7],[0..2] of (Rl Gl Bl Ru Gu Bu 0 0)
    volatile byte RowCount = 0;
    // Brightness Vars.
    const byte MaxBrightCount = 7;    // Count 1..MaxBrightCount
    volatile byte BrightCount = 0;
    const byte BrightRow [7]  = {0,1,1,2,2,2,2}; // Counter Conversion for Binairy Code Modulation.

    // RGB Pin Definitions - All Pins are hardcoded to speed things up.
    // const int a   = A0;  // Address A (A0)
    // const int b   = A1;  // Address B (A1)
    // const int c   = A2;  // Address C (A2)
    // const int b1  =  2;  // Blue 1
    // const int g1  =  3;  // Green 1
    // const int r1  =  4;  // Red 1
    // const int b2  =  5;  // Blue 2
    // const int g2  =  6;  // Green 2
    // const int r2  =  7;  // Red 2
    // const int clk =  8;  // Clock
    // const int oe  =  9;  // outEnable
    // const int lat = 10;  // Latch

    void InitPan()
    // Initializing the Panel
    { // Put Pins to Output (A0 A1 A2 - D2 D3 D4 - D5 D6 D7 - D8 D9 D10)
      DDRC = DDRC | B00000111;    // pinMode(a  , OUTPUT); pinMode(b  , OUTPUT); pinMode(c  , OUTPUT);
      DDRD = DDRD | B11111100;    // pinMode(r1 , OUTPUT); pinMode(g1 , OUTPUT); pinMode(b1 , OUTPUT);
                                  // pinMode(r2 , OUTPUT); pinMode(g2 , OUTPUT); pinMode(b2 , OUTPUT);
      DDRB = DDRB | B00000111;    // pinMode(clk, OUTPUT); pinMode(oe , OUTPUT); pinMode(lat, OUTPUT);
      ClrPan();
      // Assign the display-function to an Interupt on Timer 1
      //
      // ... Yet To Explore,
      //                     Yet To Fill In ...
      //
      // TCCR1A = 0;                                    // Normal operation
      // TCCR1B = bit(WGM12) | bit(CS10) | bit (CS12);  // CTC, scale to clock / 1024
      // OCR1A =  999;                                  // Compare A register value (1000 * clock speed)
      // TIMSK1 = bit (OCIE1A);                         // Interrupt on Compare A Match
      //  // Now Attach the function ...
      // attachInterrupt ( int_number , IntOneRow() , interupt_mode );
      
    }

    void ClrPan()     
    // Clear the Panel with bgcolor
    { byte _lc = (  LowColor(bgcolor) * 9 ) << 2;
      byte _mc = (  MidColor(bgcolor) * 9 ) << 2;
      byte _hc = ( HighColor(bgcolor) * 9 ) << 2;
      for (byte ww=0; ww<8; ww=ww+1)
      { for (byte qq=0; qq<MaxCol; qq=qq+1)
        { PanelData [qq][ww][0] = _lc;
          PanelData [qq][ww][1] = _mc;
          PanelData [qq][ww][2] = _hc;
        }
      }
    }

    byte LowColor (word _k)
    // Get the LowColor rgb from 0000 0RRR 0GGG 0BBB
    { return (( _k & 0x0100 ) >> 6 ) + (( _k & 0x0010 ) >> 3 ) + (( _k & 0x0001 )      );
    }

    byte MidColor (word _k)
    // Get the MidColor RGB from 0000 0RRR 0GGG 0BBB
    { return (( _k & 0x0200 ) >> 7 ) + (( _k & 0x0020 ) >> 4 ) + (( _k & 0x0002 ) >> 1 );
    }

    byte HighColor (word _k)
    // Get the HighColor RGB from 0000 0RRR 0GGG 0BBB
    { return (( _k & 0x0400 ) >> 8 ) + (( _k & 0x0040 ) >> 5 ) + (( _k & 0x0004 ) >> 2 );
    }

    word Dec2RGB (word _k)
    // Convert a decimal color into a hex RGB-color 0000 0RRR 0GGG 0BBB
    { return (( _k & 0x01C0 ) << 2 ) + (( _k & 0x0038 ) << 1 ) + ( _k & 0x0007 );
    }

    void SetPoint (byte _x, byte _y, word _k)
    // Let one Led lit at the (x;y) position
    { _x = ( _x & 0x3F );
      _y = ( _y & 0x0F ) ^ 0x0F;  // y = ( y and $0F ) xor $0F
      byte _y7 = _y & 0x07;
      _k = _k & 0x0777;
      byte _lc =  LowColor(_k);
      byte _mc =  MidColor(_k);
      byte _hc = HighColor(_k);
      // Put The Pixel On The Right Spot.
      if (( _y & 0x08 ) == 0 )
         { // This is the Upper-half
           PanelData[_x][_y7][0] = ( PanelData[_x][_y7][0] & B11100000 ) | ( _lc << 2 );
           PanelData[_x][_y7][1] = ( PanelData[_x][_y7][1] & B11100000 ) | ( _mc << 2 );
           PanelData[_x][_y7][2] = ( PanelData[_x][_y7][2] & B11100000 ) | ( _hc << 2 );
         }
      else
         { // This is the Lower half.
           PanelData[_x][_y7][0] = ( PanelData[_x][_y7][0] & B00011100 ) | ( _lc << 5 );
           PanelData[_x][_y7][1] = ( PanelData[_x][_y7][1] & B00011100 ) | ( _mc << 5 );
           PanelData[_x][_y7][2] = ( PanelData[_x][_y7][2] & B00011100 ) | ( _hc << 5 );
         }
    }

    void IntOneRow()
    // The main interupt-routine. Do One Row (at each Interupt)
    { byte rc=MaxCol;
      byte BrightLayer = BrightRow[BrightCount];
      do { rc=rc-1;
           // Send the RGB to the RGB-lines
           byte rgb = PanelData[rc][RowCount][BrightLayer];
           PORTD = ( PORTD & B00000011 ) |  rgb;
           // Clock the RGB
           PORTB = PORTB | B00000001;        // digitalWrite(clk, HIGH);
           PORTB = PORTB & B11111110;        // digitalWrite(clk, LOW );
         } while (rc>0);     
      // Make it Invisible
      PORTB = PORTB | B00000010;             // digitalWrite(oe , HIGH);
      // Select the Row on the panels.
      PORTC = ( PORTC & B11111000 ) | RowCount;
      // Latch the Data
      PORTB = PORTB | B00000100;             // digitalWrite(lat, HIGH);
      PORTB = PORTB & B11111011;             // digitalWrite(lat, LOW );
      // Make it Visible again
      PORTB = PORTB & B11111101;             // digitalWrite(oe , LOW );
      // Next Row
      RowCount = RowCount + 1;     // Count the Row
      if ( RowCount >= 8 )
         { RowCount = 0;
           BrightCount = BrightCount + 1;    // Inc the Brightness counter
           if ( BrightCount >= MaxBrightCount )      
              { BrightCount = 0; 
              }
         }
    }



    Broncode: [1: Random Figuren]
  • Afbeeldingen

    rndfiguur_1.jpg
    1/11: rndfiguur_1.jpg.
    rndfiguur_2.jpg
    2/11: rndfiguur_2.jpg.
    rndfiguur_3.jpg
    3/11: rndfiguur_3.jpg.
    rndfiguur_4.jpg
    4/11: rndfiguur_4.jpg.
    rndfiguur_5.jpg
    5/11: rndfiguur_5.jpg.
    rndfiguur_6.jpg
    6/11: rndfiguur_6.jpg.
    rndfiguur_7.jpg
    7/11: rndfiguur_7.jpg.
    rndfiguur_8.jpg
    8/11: rndfiguur_8.jpg.
    rndfiguur_9.jpg
    9/11: rndfiguur_9.jpg.
    rndfiguur_a.jpg
    10/11: rndfiguur_a.jpg.
    rndfiguur_b.jpg
    11/11: rndfiguur_b.jpg.

    De aansluitingen van Paneel aansluitingen.

    De RGB is net andersom dan van de Library.

    Arduino Uno

    Pwr USB ?
     
    ?
    aref
    gnd Gnd's (4x)
    ? d13
    ioreff d12
    reset d11
    +3.3v d10 Latch
    +5v d9 Oe
    Gnd's (4x) gnd d8 Clock
    Gnd's (4x) gnd
    Vin d7 R2
    d6 G2
    A  (A0) a0 d5 B2
    B  (A1) a1 d4 R1
    C  (A2) a2 d3 G1
    Figuurpot (4) a3 d2 B1
    Kleurpot (5) a4 d1
    Snelheidpot (6) a5 d0