Using Freertos and Neopixels

Home Forums Projects Using Freertos and Neopixels

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #1381
    Smartwar
    Participant

    Here s an example of using FreeRtos in a small processor (ATmega328p) to flash a couple of strings of neopixels. This is about the smallest capability processor that FreeRtos will run on so it has limited capability, but is a useful simple example of using it, to schedule two independent tasks. Here it is just pasted in. There doesn’t seem a way of adding attachments.
    Happy New Year
    Martin
    /*
    Name: FlashyNew.ino
    Created: 2020-05-10 13:19:53
    Author: DESKTOP-NG83FJ4\marti
    */

    #include <Arduino_FreeRTOS.h>
    #include <Adafruit_NeoPixel.h>

    // Which pin for NeoPixels?

    #define NEOPIN1 5
    #define NEOPIN2 4

    // How many NeoPixels are attached to the Arduino?
    #define NUMPIXELS 10 //medium band
    #define PIXCOLEN 11 //medium band

    // When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
    // Note that for older NeoPixel strips you might need to change the third parameter–see the strandtest
    // example for more information on possible values.
    // here we are using two separate strings, so 2 instances of the library object are created.

    Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, NEOPIN1, NEO_GRB + NEO_KHZ800);
    Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS, NEOPIN2, NEO_GRB + NEO_KHZ800);
    // put in array so you can be easier manipulated.
    Adafruit_NeoPixel neoarray[2] = { pixels1,pixels2 };

    uint8_t Pixcol[PIXCOLEN][3];
    uint8_t Setcol[8][3] =
    {
    {0, 0,80},
    {0,80, 0},
    {80,0, 0},
    {0,60,60},
    {60,0,60},
    {60,60,0},
    {0, 0, 0},
    {50,50,50}
    };

    uint8_t Set2col[8][3] =
    {
    { 0, 0,70 },
    { 0,70, 0 },
    { 70,0, 0 },
    { 0,50,50 },
    { 50,0,50 },
    { 50,50,0 },
    { 20, 10, 20 },
    { 40,40,40 }
    };

    int lcnt;
    bool led1on = true;
    bool led2on = false;
    int mode = 0;
    long sttime;
    bool enabledis = true;
    void setup()
    {
    Serial.begin(38400);

    mode = 0;

    for (int ix = 0; ix < 2; ix++)
    {
    neoarray[ix].begin();

    neoarray[ix].setPixelColor(0, neoarray[ix].Color(0, 0, 100));
    neoarray[ix].setPixelColor(1, neoarray[ix].Color(0, 100, 0));
    neoarray[ix].setPixelColor(2, neoarray[ix].Color(100, 0, 0));
    neoarray[ix].setPixelColor(3, neoarray[ix].Color(0, 100, 100));
    neoarray[ix].setPixelColor(4, neoarray[ix].Color(100, 100, 0));
    neoarray[ix].setPixelColor(5, neoarray[ix].Color(100, 0, 100));
    neoarray[ix].setPixelColor(6, neoarray[ix].Color(180, 100, 50));
    neoarray[ix].setPixelColor(7, neoarray[ix].Color(50, 180, 100));
    neoarray[ix].setPixelColor(8, neoarray[ix].Color(100, 50, 180));
    neoarray[ix].setPixelColor(9, neoarray[ix].Color(100, 100, 100));
    neoarray[ix].show();

    }
    /*
    here all the stuff for freertos. Note that the small stack size means only simple routines can be run in the task. If you use
    another processor with more memory then increase the stack size and it can then support more neopixels and more of the routines.
    There could be an interaction between the two tasks using a common resource, but I haven’t noticed it so far, If with bigger
    number of pixels it needs it then you could use a mutex to prevent tasks interfering.
    This example is just about on the limit for freertos in a small processor like the Atmega328p.
    Have fun.
    */

    Serial.println(“Starting Flashy”);

    delay(1000);

    xTaskCreate(
    taskOne, /* Task function. */
    “NeopixRun”, /* String with name of task. */
    100, /* Stack size in bytes. */
    NULL, /* Parameter passed as input of the task */
    3, /* Priority of the task. */
    NULL); /* Task handle. */

    xTaskCreate(
    taskTwo, /* Task function. */
    “LEDFlash1”, /* String with name of task. */
    100, /* Stack size in bytes. */
    NULL, /* Parameter passed as input of the task */
    1, /* Priority of the task. */
    NULL); /* Task handle. */

    Serial.println(“Starting Scheduler”);
    vTaskStartScheduler();
    }

    void colorSet(uint8_t neos, uint32_t c, uint16_t wait)
    {
    // TickType_t xDelay = pdMS_TO_TICKS(wait);
    for (uint16_t i = 0; i < neoarray[neos].numPixels(); i++)
    {
    neoarray[neos].setPixelColor(i, c);
    }
    neoarray[neos].show();
    delay(wait);
    }

    void colorWipe(uint8_t neos, uint32_t c, uint16_t wait)
    {

    for (uint16_t i = 0; i < neoarray[neos].numPixels(); i++)
    {
    neoarray[neos].setPixelColor(i, c);
    neoarray[neos].show();
    delay(wait);
    }
    }

    void shiftpixcol()
    {
    uint8_t abyte;
    // get bit 152 which is byte 19 in pixcol[6][0]
    uint8_t fbyte = Pixcol[6][0];
    // next bit 153 first in byte 20 in pixcol[6][1]
    uint8_t sbyte = Pixcol[6][1];
    fbyte = fbyte & 0x80;
    sbyte = sbyte & 0x01;
    // now shift fbyte so it is in low bit to match sbyte
    fbyte = fbyte >> 7;
    fbyte = fbyte ^ sbyte; // Xord to lsb
    // now rotate the PixCol

    for (int ix = 0; ix < NUMPIXELS; ix++)
    {
    for (int iy = 0; iy < 3; iy++)
    {
    abyte = Pixcol[ix][iy];
    abyte = abyte >> 7;
    Pixcol[ix][iy] = Pixcol[ix][iy] << 1; // shift up 1
    Pixcol[ix][iy] = Pixcol[ix][iy] | fbyte; //last times high bit
    fbyte = abyte;
    }

    }
    }

    void supershifter(uint8_t neos, uint16_t wait, uint16_t reps)
    {
    unsigned int z;
    TickType_t xDelay = pdMS_TO_TICKS(wait);
    for (z = 0; z < reps; z++)
    {

    for (int x = 0; x < NUMPIXELS; x++)
    {
    neoarray[neos].setPixelColor(x, neoarray[neos].Color(Pixcol[x][0], Pixcol[x][1], Pixcol[x][2]));

    }
    neoarray[neos].show();
    vTaskDelay(xDelay);
    for (int y = 0; y < 8; y++)
    {
    shiftpixcol();
    }

    }
    }

    void shiftseg(uint8_t neos, uint16_t wait, uint8_t nosegs, uint16_t reps, uint16_t celll)
    {
    uint8_t seglen = NUMPIXELS / nosegs;
    uint16_t acelll = 0;
    int pixfix;
    int scol;
    unsigned int z;
    TickType_t xDelay = pdMS_TO_TICKS(wait);
    // Serial.print(“seglen:”);
    // Serial.println(seglen);
    for (z = 0; z < reps; z++)
    {

    scol = random(8);
    // show all
    for (int x = 0; x < NUMPIXELS; x++)
    {
    neoarray[neos].setPixelColor(x, neoarray[neos].Color(Pixcol[x][0], Pixcol[x][1], Pixcol[x][2]));
    }
    neoarray[neos].show();
    vTaskDelay(xDelay);
    // calc next
    for (int segs = 0; segs < nosegs; segs++)
    {
    if ((segs & 0x01) == 1)
    {
    pixfix = seglen * segs;
    for (int y = seglen * (segs + 1); y > pixfix; y–)
    {
    Pixcol[y][0] = Pixcol[y – 1][0];
    Pixcol[y][1] = Pixcol[y – 1][1];
    Pixcol[y][2] = Pixcol[y – 1][2];
    }
    if (acelll == 0)
    {
    for (int y = 0; y < 3; y++)
    {
    Pixcol[pixfix][y] = Setcol[scol][y];
    }
    }
    }
    else
    {
    pixfix = seglen * (segs + 1);
    // scol = random(8);
    for (int y = seglen * segs; y < pixfix; y++)
    {
    Pixcol[y][0] = Pixcol[y + 1][0];
    Pixcol[y][1] = Pixcol[y + 1][1];
    Pixcol[y][2] = Pixcol[y + 1][2];
    }
    if (acelll == 0)
    {
    for (int y = 0; y < 3; y++)
    {
    Pixcol[pixfix][y] = Setcol[scol][y];
    }

    }
    }

    }
    acelll++;
    if (acelll >= celll)
    acelll = 0;
    }
    }

    void comet(uint8_t neos, uint16_t wait, uint16_t reps, uint16_t celll)
    {
    unsigned int cpos = 0;
    unsigned int whlof = 0;
    unsigned int z;
    unsigned int y;
    unsigned int pn;
    uint32_t clr;
    uint32_t aclr;
    uint8_t whlr;
    TickType_t xDelay = pdMS_TO_TICKS(wait);
    for (z = 0; z < reps; z++)
    {

    whlr = ((cpos * 4) + whlof) & 0xff;
    clr = Wheel(neos,whlr);
    for (uint16_t i = 0; i < neoarray[neos].numPixels(); i++)
    {
    neoarray[neos].setPixelColor(i, 0);
    }
    if (cpos > 0)
    {
    pn = 0;
    for (y = (cpos – celll); y < cpos; y++)
    {
    if (y >= 0)
    {
    aclr = setbright(neos,pn, clr, celll);
    neoarray[neos].setPixelColor(y, aclr);

    }
    pn++;

    }
    }
    neoarray[neos].show();
    vTaskDelay(xDelay);

    cpos++;
    if (cpos > NUMPIXELS)
    {
    cpos = 0;
    whlof = whlof + 8;
    }
    }

    }

    void shifter(uint8_t neos, uint16_t wait, uint16_t reps, uint16_t celll)
    {
    TickType_t xDelay = pdMS_TO_TICKS(wait);
    uint16_t acelll = celll;
    unsigned int z;
    for (z = 0; z < reps; z++)
    {

    for (int x = 0; x < NUMPIXELS; x++)
    {
    neoarray[neos].setPixelColor(x, neoarray[neos].Color(Pixcol[x][0], Pixcol[x][1], Pixcol[x][2]));

    }
    neoarray[neos].show();
    vTaskDelay(xDelay);
    for (int y = NUMPIXELS – 1; y > 0; y–)
    {
    Pixcol[y][0] = Pixcol[y – 1][0];
    Pixcol[y][1] = Pixcol[y – 1][1];
    Pixcol[y][2] = Pixcol[y – 1][2];
    }
    acelll–;
    if (acelll == 0)
    {

    // first pick a random colour of 6
    int scol = random(8);

    for (int y = 0; y < 3; y++)
    {
    Pixcol[0][y] = Setcol[scol][y] + random(15);
    }
    acelll = celll;
    }
    }
    }

    uint32_t setbright(uint8_t neos, int psn, uint32_t clr, uint16_t celll)
    {
    uint8_t r;
    uint8_t g;
    uint8_t b;
    b = clr & 0x0f;
    g = (clr >> 8) & 0x0f;
    r = (clr >> 16) & 0x0f;

    b = (psn * b) / celll;
    g = (psn * g) / celll;
    r = (psn * r) / celll;
    uint32_t ires = neoarray[neos].Color(r, g, b);
    return ires;

    }

    void rainbow(uint8_t neos,uint16_t wait)
    {
    TickType_t xDelay = pdMS_TO_TICKS(wait);
    uint16_t i, j;

    for (j = 0; j < 256 * 5; j++) {
    for (i = 0; i < neoarray[neos].numPixels(); i++)
    {
    neoarray[neos].setPixelColor(i, Wheel(neos,(i + j) & 255));
    }
    neoarray[neos].show();
    vTaskDelay(xDelay);
    }
    }

    // Slightly different, this makes the rainbow equally distributed throughout
    void rainbowCycle(uint8_t neos,uint16_t wait)
    {
    TickType_t xDelay = pdMS_TO_TICKS(wait);
    uint16_t i, j;

    for (j = 0; j < 256 * 5; j++)
    { // 5 cycles of all colors on wheel
    for (i = 0; i < neoarray[neos].numPixels(); i++)
    {
    neoarray[neos].setPixelColor(i, Wheel(neos,((i * 256 / neoarray[neos].numPixels()) + j) & 255));
    }
    neoarray[neos].show();
    vTaskDelay(xDelay);
    }
    }

    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r – g – b – back to r.
    uint32_t Wheel(uint8_t neos, uint16_t WheelPos) {
    WheelPos = 255 – WheelPos;
    if (WheelPos < 85) {
    return neoarray[neos].Color(255 – WheelPos * 3, 0, WheelPos * 3);
    }
    else if (WheelPos < 170) {
    WheelPos -= 85;
    return neoarray[neos].Color(0, WheelPos * 3, 255 – WheelPos * 3);
    }
    else {
    WheelPos -= 170;
    return neoarray[neos].Color(WheelPos * 3, 255 – WheelPos * 3, 0);
    }
    }

    void taskOne(void* pvParameters)
    {
    const TickType_t xDelay50ms = pdMS_TO_TICKS(50UL);
    const TickType_t xDelay100ms = pdMS_TO_TICKS(100UL);
    const TickType_t xDelay500ms = pdMS_TO_TICKS(500UL);

    for (;;)
    {
    rainbow(0,30);
    vTaskDelay(xDelay50ms);
    }
    }
    void taskTwo(void* pvParameters)
    {
    const TickType_t xDelay50ms = pdMS_TO_TICKS(50UL);
    const TickType_t xDelay100ms = pdMS_TO_TICKS(100UL);
    const TickType_t xDelay500ms = pdMS_TO_TICKS(500UL);

    for (;;)
    {
    rainbowCycle(1,30);
    vTaskDelay(xDelay500ms);
    comet(1,50, 600, 8);
    }
    }

    void loop()
    {
    // Serial.println(“Main Loop”);
    // delay(3000);
    }

Viewing 1 post (of 1 total)
  • You must be logged in to reply to this topic.