Stap 5: Schrijf de code
Eerst, moet u de TLC5940 Aduino bibliotheek. De installatie-aanwijzingen zijn verouderd. Download de bibliotheek en unzip in een tijdelijke map. Dan open de Arduino editor en ga naar de schets -> bibliotheek importeren en toevoegen van de bibliotheek. De editor doet de rest.
Bewerk het tlc_config.h bestand te wijzigen van het aantal TLC5940 van u gebruikt. Dit project loopt u TLCs zodat de lijn leest
#define NUM_TLCS 3
De code is vrij eenvoudig van hier en is toegelicht. Ik heb enkele opmerkingen aan het einde ook.
LEDController.ino
#include "Arduino.h" #include <Tlc5940.h> #include <tlc_config.h> #include "LedController.h" // Root List for all LEDs List *lightList = NULL; // various values for iterating through the RGBs int rgbIndex = 0; int rgbLastStart = 0; boolean firstRGBIndex; int maxRGB = 252; // Handy for steping through all the LEDs // Each LED will flash, which helps find missing or incorrect connections void diag() { for(uint8_t x= 0; x < 40; x++) { if ( x > 0) { Tlc.set(x-1,0); } Tlc.set(x,1000); while(Tlc.update()); delay(500); } } /* Pause for 5 seconds so that you can pull up any diagnostic you may need. Initialize the TLC chain. Create the complete light list */ void setup() { delay(5000); Tlc.init(); Tlc.clear(); lightList = createList(); addNode(lightList, createRGBCluster1()); addNode(lightList, createLEDCluster1a()); addNode(lightList, createLEDCluster2()); } /* Increment the RGB value so it slowly moves through the list of color transitions. Keep the current time so you know when to turn on and off lights. Run through the list. */ void loop() { //diag(); rgbIndex = rgbLastStart + 1; firstRGBIndex = true; long time = millis(); iterateList(time,lightList); /* The update finishes asynchronously on the TLC's. You must wait till everything updates or your lights will display incorrect values. */ while(Tlc.update()); } /* Single link list. Most of the following functions create a node of some type and attach it to the end of a list. This system creates lists of lists for each LED array. This exposed some memory challenges as the list is using some statically allocated values and shares some of those values. Pointers would have been a wiser choice. */ List* createList(void) { List *list = (List*)malloc(sizeof(List)); list->head = NULL; list->tail = NULL; return list; } List* addNode(List* list, Node* node) { if (list != NULL && node != NULL) { if (list->head == NULL) { list->head = node; list->tail = list->head; } else { list->tail->next = node; list->tail = node; } } } Node* createNode(NodeType type, uint8_t pin) { Node *result = (Node*)malloc(sizeof(Node)); result->next = NULL; result->type = type; switch(type) { case LIST: result->value = createList(); break; case LED_RGB: result->value = createRGB(pin); break; case LED_NORMAL: result->value = createLED(pin); break; } return result; } Node* createRGBNode(List* list, uint8_t pin, Runtimes runtimes, RGB *useSettings) { Node *results = createNode(LED_RGB, pin); RGB* rgb = (RGB*)results->value; configureRGB(rgb, runtimes, useSettings); addNode(list, results); return results; } void configureRGB(RGB* rgb, Runtimes runtimes, RGB *useSettings) { if ( useSettings != NULL) { rgb->useSettings = useSettings; rgb->color = useSettings->color; rgb->runtimes = useSettings->runtimes; } else { rgb->runtimes = runtimes; } } RGB* createRGB(uint8_t pin) { RGB *result = (RGB*)malloc(sizeof(RGB)); result->pin = pin; result->color.r = 0; result->color.g = 0; result->color.b = 0; result->useSettings = NULL; return result; } Node* createLEDNode(List* list, uint8_t pin, Runtimes runtimes, uint8_t level) { Node *results = createNode(LED_NORMAL, pin); LED* led = (LED*)results->value; led->level = level; led->runtimes = runtimes; addNode(list, results); return results; } LED* createLED(uint8_t pin) { LED *result = (LED*)malloc(sizeof(LED)); result->pin = pin; result->level=0; result->runtimes.startTime=0; result->runtimes.runTime=0; result->runtimes.on=false; return result; } void setRGBLed(RGB *led) { Tlc.set(led->pin,led->color.r); Tlc.set(led->pin+1,led->color.g); Tlc.set(led->pin+2,led->color.b); } /* iterate through the list and determine the correct way to execute each node. */ void iterateList(long time, List* list) { if(list != NULL) { Node* node = list->head; while(node != NULL) { executeNode(time, node); node = node->next; } } } void executeNode(long time, Node* node) { if(node != NULL) { switch(node->type) { case LIST: iterateList(time, (List*)node->value); break; case LED_RGB: setRGB(time,(RGB*)node->value); break; case LED_NORMAL: setLED(time,(LED*)node->value); break; default: Tlc.set(1,200); Tlc.update(); break; } } else { } } /* Horrible cheating going on here. There is only one RGB list so we're going to keep some extra state and apply it to just this rgb list. blech. However, this array runs much faster by iterating through precalculated values than trying to calculate and display those values. */ void setRGB(long time, RGB* rgb) { if (rgb != NULL) { boolean cycle = time > rgb->runtimes.startTime + rgb->runtimes.wait; if ( cycle ) { if ( rgb->useSettings != NULL ) { rgb->color = rgb->useSettings->color; rgb->runtimes = rgb->useSettings->runtimes; } else { if ( firstRGBIndex ) { firstRGBIndex = false; rgbLastStart++; if ( rgbLastStart > maxRGB) { rgbLastStart = 0; } rgbIndex = rgbLastStart; } rgb->color = rgbPattern[rgbIndex++]; if ( rgbIndex > maxRGB) { rgbIndex = 0; } } rgb->runtimes.startTime = time; } setRGBLed(rgb); } } void setLED(long time, LED* led) { if (led != NULL) { long execWindow = led->runtimes.startTime + led->runtimes.runTime; if(led->runtimes.runTime == -1 || (time > led->runtimes.startTime && time < execWindow)) { led->runtimes.on = true; Tlc.set(led->pin, led->level); } else if ( time > execWindow && led->runtimes.on == true ) { led->runtimes.startTime = time + led->runtimes.wait; led->runtimes.on = false; Tlc.set(led->pin, 0); } } } /* The various LED array factory methods */ Node* createRGBCluster1(void) { int i = 0; int wait = 50; Runtimes rt = (Runtimes) { 0, 0, wait, false }; Node* rgbList = createNode(LIST, 0); List* rgbCluster1 = (List*)rgbList->value; Node* a = createRGBNode( rgbCluster1, i, rt, NULL); Node* b = createRGBNode( rgbCluster1, i+=3, rt, NULL); Node* c = createRGBNode( rgbCluster1, i+=3, rt, NULL); Node* d = createRGBNode( rgbCluster1, i+=3, rt, NULL); Node* e = createRGBNode( rgbCluster1, i+=3, rt, NULL); // Let them share values which creates a kind of cool looking // fountain effect. createRGBNode( rgbCluster1, i+=3, rt, (RGB*)e->value); createRGBNode( rgbCluster1, i+=3, rt, (RGB*)d->value); createRGBNode( rgbCluster1, i+=3, rt, (RGB*)c->value); createRGBNode( rgbCluster1, i+=3, rt, (RGB*)b->value); createRGBNode( rgbCluster1, i+=3, rt, (RGB*)a->value); return rgbList; } Node* createLEDCluster1a(void) { int i = 30; Node* ledList = createNode(LIST, 0); List* ledCluster = (List*)ledList->value; createLEDNode( ledCluster, i++, (Runtimes) { -1, -1, -1, true }, 300); createLEDNode( ledCluster, i++, (Runtimes) { -1, -1, -1, true }, 300); createLEDNode( ledCluster, i++, (Runtimes) { -1, -1, -1, true }, 300); createLEDNode( ledCluster, i++, (Runtimes) { -1, -1, -1, true }, 300); createLEDNode( ledCluster, i++, (Runtimes) { -1, -1, -1, true }, 300); createLEDNode( ledCluster, i++, (Runtimes) { -1, -1, -1, true }, 300); return ledList; } Node* createLEDCluster2(void) { int i = 36; Node* ledList = createNode(LIST, 0); List* ledCluster = (List*)ledList->value; createLEDNode( ledCluster, i++, (Runtimes) { 10000, 30000, 25000, true }, 3000); createLEDNode( ledCluster, i++, (Runtimes) { 10000, 30000, 25000, true }, 3000); createLEDNode( ledCluster, i++, (Runtimes) { 3000, 90000, 45000, true }, 3000); createLEDNode( ledCluster, i++, (Runtimes) { 3000, 90000, 45000, true }, 3000); return ledList; } /* This is some old code that did the sine wave calculation. It works but is very slow. I wrote some code to capture the values and write them out the serial console instead and then copied the values into the header void setRGBFreq(RGB *led, uint8_t i, uint8_t max) { float frequency = .3; led->r = sin(frequency*(i) + 0) * 127 + 128; led->g = sin(frequency*(i) + 2) * 127 + 128; led->b = sin(frequency*(i) + 4) * 127 + 128; uint8_t total = led->r + led->g + led->b; if ( total > max ) { led->r -= led->r/total * 100.0; led->g -= led->g/total * 100.0; led->b -= led->b/total * 100.0; } //printList(led); }*/
LEDController.h
<code> #ifndef LEDController #define LEDController #define RGB_LEDS 10 typedef enum { LIST, LED_RGB, LED_NORMAL } NodeType; typedef struct { long startTime; long runTime; long wait; boolean on; } Runtimes; typedef struct { uint8_t r; uint8_t g; uint8_t b; } Colors; typedef struct rgb { Colors color; uint8_t pin; Runtimes runtimes; struct rgb *useSettings; } RGB; typedef struct { uint8_t pin; uint8_t level; Runtimes runtimes; } LED; typedef struct node { NodeType type; void* value; struct node* next; } Node; typedef struct { Node* head; Node* tail; } List; static Colors rgbPattern[] = { {128, 243, 31},{165, 222, 11},{199, 193, 1},{227, 158, 3}, {246, 120, 15},{254, 83, 38},{251, 50, 68},{237, 24, 104}, {213, 7, 142},{182, 1, 179},{145, 6, 211},{107, 22, 236}, {71, 47, 250},{40, 80, 254},{17, 117, 247},{3, 155, 229}, {1, 190, 202},{10, 220, 168},{29, 242, 131},{58, 253, 93}, {92, 253, 58},{130, 242, 30},{167, 221, 10},{201, 191, 1}, {228, 156, 3},{247, 118, 16},{254, 81, 39},{251, 48, 70}, {236, 22, 106},{212, 6, 144},{180, 1, 181},{143, 6, 213}, {105, 23, 237},{69, 49, 251},{39, 82, 254},{16, 119, 246}, {3, 157, 228},{1, 192, 200},{11, 222, 166},{31, 243, 129}, {59, 253, 91},{94, 253, 57},{132, 241, 29},{169, 219, 10}, {203, 189, 1},{230, 154, 4},{247, 116, 17},{254, 79, 41}, {250, 46, 72},{235, 21, 109},{210, 5, 147},{178, 1, 183}, {141, 7, 214},{103, 24, 238},{68, 51, 251},{37, 84, 254}, {15, 121, 245},{3, 159, 226},{1, 194, 198},{12, 223, 164}, {32, 243, 126},{61, 254, 89},{96, 252, 55},{134, 240, 27}, {171, 218, 9},{204, 187, 1},{231, 152, 4},{248, 114, 18}, {254, 77, 43},{250, 45, 74},{234, 20, 111},{208, 5, 149}, {176, 1, 185},{139, 8, 216},{101, 25, 239},{66, 52, 252}, {36, 86, 254},{14, 123, 245},{2, 161, 225},{2, 196, 196}, {12, 224, 162},{34, 244, 124},{63, 254, 87},{98, 252, 53}, {136, 239, 26},{173, 216, 8},{206, 186, 1},{232, 150, 5}, {249, 112, 20},{254, 75, 44},{249, 43, 76},{233, 19, 113}, {207, 4, 151},{174, 1, 187},{137, 8, 217},{99, 27, 240}, {64, 54, 252},{34, 88, 254},{13, 125, 244},{2, 163, 224}, {2, 198, 195},{13, 226, 160},{35, 245, 122},{65, 254, 85}, {100, 252, 51},{138, 238, 25},{175, 215, 7},{208, 184, 1}, {233, 147, 5},{249, 109, 21},{254, 73, 46},{248, 42, 78}, {231, 18, 115},{205, 4, 153},{172, 1, 188},{135, 9, 219}, {97, 28, 241},{62, 56, 253},{33, 90, 253},{12, 128, 243}, {2, 165, 222},{2, 199, 193},{14, 227, 158},{36, 246, 120}, {67, 254, 83},{102, 251, 50},{140, 237, 24},{177, 213, 7}, {128, 243, 31},{165, 222, 11},{199, 193, 1},{227, 158, 3}, {246, 120, 15},{254, 83, 38},{251, 50, 68},{237, 24, 104}, {213, 7, 142},{182, 1, 179},{145, 6, 211},{107, 22, 236}, {71, 47, 250},{40, 80, 254},{17, 117, 247},{3, 155, 229}, {1, 190, 202},{10, 220, 168},{29, 242, 131},{58, 253, 93}, {92, 253, 58},{130, 242, 30},{167, 221, 10},{201, 191, 1}, {228, 156, 3},{247, 118, 16},{254, 81, 39},{251, 48, 70}, {236, 22, 106},{212, 6, 144},{180, 1, 181},{143, 6, 213}, {105, 23, 237},{69, 49, 251},{39, 82, 254},{16, 119, 246}, {3, 157, 228},{1, 192, 200},{11, 222, 166},{31, 243, 129}, {59, 253, 91},{94, 253, 57},{132, 241, 29},{169, 219, 10}, {203, 189, 1},{230, 154, 4},{247, 116, 17},{254, 79, 41}, {250, 46, 72},{235, 21, 109},{210, 5, 147},{178, 1, 183}, {141, 7, 214},{103, 24, 238},{68, 51, 251},{37, 84, 254}, {15, 121, 245},{3, 159, 226},{1, 194, 198},{12, 223, 164}, {32, 243, 126},{61, 254, 89},{96, 252, 55},{134, 240, 27}, {171, 218, 9},{204, 187, 1},{231, 152, 4},{248, 114, 18}, {254, 77, 43},{250, 45, 74},{234, 20, 111},{208, 5, 149}, {176, 1, 185},{139, 8, 216},{101, 25, 239},{66, 52, 252}, {36, 86, 254},{14, 123, 245},{2, 161, 225},{2, 196, 196}, {12, 224, 162},{34, 244, 124},{63, 254, 87},{98, 252, 53}, {136, 239, 26},{173, 216, 8},{206, 186, 1},{232, 150, 5}, {249, 112, 20},{254, 75, 44},{249, 43, 76},{233, 19, 113}, {207, 4, 151},{174, 1, 187},{137, 8, 217},{99, 27, 240}, {64, 54, 252},{34, 88, 254},{13, 125, 244},{2, 163, 224}, {2, 198, 195},{13, 226, 160},{35, 245, 122},{65, 254, 85}, {100, 252, 51},{138, 238, 25},{175, 215, 7},{208, 184, 1}, {233, 147, 5},{249, 109, 21},{254, 73, 46},{248, 42, 78}, {231, 18, 115},{205, 4, 153},{172, 1, 188},{135, 9, 219}, {97, 28, 241},{62, 56, 253},{33, 90, 253},{12, 128, 243}, {2, 165, 222},{2, 199, 193},{14, 227, 158},{36, 246, 120}, {67, 254, 83},{102, 251, 50},{140, 237, 24},{177, 213, 7} }; // Basic Double Linked-List functions for LEDs List* createList(void); List* addNode(List* list, Node* node); Node* createNode(NodeType type, uint8_t pin); RGB* createRGB(uint8_t pin); LED* createLED(uint8_t pin); Node* createRGB(List* list, uint8_t pin, Runtimes runtimes, RGB *useSettings); Node* createLEDNode(uint8_t pin, Runtimes runTimes, uint8_t level); void iterateList(long time, List* list); void setRGBLED(long time, RGB *led); void setLED(long time, LED* led); //Cluster factories Node* createRGBCluster1(void); Node* createRGBCluster1a(void); Node* createLEDCluster2(void); void configureRGB(RGB* rgb, Runtimes runtimes, RGB *useSettings); #endif
De code gebruikt een verschillende één gekoppelde lijsten voor het beheren van alle de LED's, de kleuren, helderheid, duur en andere instellingen. Met behulp van een gekoppelde lijst was een vergissing, en ik zou geheugen beheren op een andere manier. Waarom? De statisch toegewezen rgbPattern gebruikt veel geheugen, maar al het geheugen is aaneengesloten. De gekoppelde lijsten zijn niet aaneengesloten door intentie, eerder bij toeval. Het resultaat is dat je kunt kleine blokken van het geheugen wordt toegewezen voor elk knooppunt in de lijst. De allocator zal het eerste blok van het geheugen waarin het knooppunt kan passen in grijpen. Dit resulteert in de allocator verlaten van kleine geheugen hiaten tussen lijsten en knooppunten. Deze verschillen zijn vaak niet bruikbaar en de toepassing niet langer de maximale hoeveelheid geheugen kan toewijzen.
Hardlopen onvoldoende geheugen is een beetje vreemd: de Arduino opnieuw wordt opgestart. U wacht enkele seconden en dan kijken naar het reboot opnieuw, en opnieuw, en je krijgt het idee. Ik schreef een snelfunctie, niet opgenomen in de code, die een aantal bits met een stel interval zou schrijven op een pin me een idee te geven hoe ver de toepassing kreeg. Ik aangesloten op een oscilloscoop aan de pin en keek naar de bits. Wetende dat ik was opnieuw op te starten, was de eerste truc. De pin-schrijver schreef zes bits binnen de Setup-functie en vervolgens vijf bits zou schrijven in de loop-functie. De vijf bits werden nooit getoond. Slechts de zes bits per seconden 15 of zo.
Het was toen slechts een kwestie van het spelen rond met een paar dingen. Ik ontdekte dat commentaar uit van een gebouw ter waarde van LEDs de voortgang van de toepassing aan de loop laten en actief blijven. Ik verminderde het aantal kleuren de rgbPattern fietste door en vervolgens uncommented het gebouw. De toepassing ran weer normaal.
Elk object kleur is slechts 24 bytes, maar er zijn 64 lijnen met 4 kleurobjecten elke. Iets meer dan 6k bracht op kleur rotatie.
Het volgende ding zou zijn geweest een eenvoudige matrix toewijzen voor alle knooppunten. Dan het zou zijn een ingepakte geheugenblok voor alle de LEDs en vrijgelatene opwaarts veel meer geheugen voor de rest van de app.
De oplossing die waarschijnlijk om te werken voor een groter netwerk van LED's is echter een groter bord met meer geheugen. Een Mega zou gemakkelijk behandelen een groot aantal gebouwen.