LED matrix control using arrays and state machine?

Well of course you'll need a switched power and a chassis ground :slight_smile:
The point it to not have to mess with the factory turn signal relay / wiring... things that would be more complicated for the average person. My personal car this is going on (1975 Porsche 911) is completely rewired by me with aftermarket engine management and a turbocharger etc so I don't care personally lol

I hope you enjoyed the show!

I'm trying to wrap my head around how to add the functionality you showed to my sketch.

I've tried to insert it here with some naming changes of course.... Sure i'm doing something silly wrong.

Leaving just now for another exciting episode of Real Life, but I can say…

if you read through my code and try it in the wokwi, then carefully examine the ways in which my frame sequencer differs from yours, you may be able to succeed.

In the meantime or if you fail/give up, post the current version and L8R I will try to hook it up in the wokwi and visit the same adjustments to one of your functions.

The main idea is that each function can and should be called every loop, usually doing nothing.

And we let the function finish even if the logic signal that started it going disappears.

This


  if (!turnMachineStep(1) and !digitalRead(3)) {
  	turnMachineStep(0);
  }

might be a little clearer if less compact rendered like

  unsigned char running;

  running =  turnMachineStep(1);       //  step the sequence

  if (!running and !digitalRead(3))    // start/restart the sequence
  	turnMachineStep(0);

a7

Well I got it to verify.

One of these days I'll learn to keep my brackets in place :joy:

I'll be testing this later, thanks again

And your braces… :expressionless:

I remind or tell you that autoformat in the IDE can help show up a mismatch.

a7

1 Like

Okay, it definitely does something different (lol)

Is the serial print part required or just for the way you're testing? I'm assuming this was just for your method of testing.... that they should just be replaced with the RenderFrame commands.

I think I don't know how to properly add your code to mine :expressionless:

//tail lamp dev v3

#include <Adafruit_NeoPixel.h>
#include  "taillightarrays.h"

#define PIN 3

const int sensorPin1 = A0;    // select a input pin for control 1 RUN LAMP
const int sensorPin2 = A1;    // select a input pin for control 2 TURN SIGNAL
const int sensorPin3 = A2;    // select a input pin for control 3 BRAKE LIGHT
const int sensorPin4 = A3;    // select a input pin for control 4 REVERSE
const int sensorPin5 = A4;    // party light

int sensorValue1 = A0;  // variable to store the value coming from the sensor
int sensorValue2 = A1;  // variable to store the value coming from the sensor
int sensorValue3 = A2;  // variable to store the value coming from the sensor
int sensorValue4 = A3;  // variable to store the value coming from the sensor
int sensorValue5 = A4;  // variable to store the value coming from the sensor


const int NUM_PIXELS = 256;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB);


void setup()
{
  strip.begin();
  strip.setBrightness(255);
  strip.show();   // Initialize all pixels to 'off'
  pinMode(A0, INPUT_PULLUP);
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  pinMode(A3, INPUT_PULLUP);




}

void loop()
{


  int state1 = 0; // initialize state1 value to zero
  int state2 = 0; // initialize state2 value to zero
  int state3 = 0; // initialize state3 value to zero
  int state4 = 0; // initialize state4 value to zero
  int state5 = 0; // initialize state4 value to zero

  if (digitalRead(sensorPin1) == LOW) // read the value from the sensor1: //run
    state1 = 1;
  else state1 = 0;


  if (digitalRead(sensorPin2) == LOW) // read the value from the sensor2: //turn
    state2 = 2;
  else state2 = 0;


  if (digitalRead(sensorPin3) == LOW) // read the value from the sensor3: //brake
    state3 = 4;
  else state3 = 0;


  if (digitalRead(sensorPin4) == LOW) // read the value from the sensor4: //reverse
    state4 = 8;
  else state4 = 0;

  if (digitalRead(sensorPin5) == LOW) // read the value from the sensor4: //party lights
    state5 = 20;
  else state5 = 0;


  int totalState = state1 + state2 + state3 + state4 + state5; //total of states to a single int

  //totals of state for which frame to render


  if (totalState == 0) { //off
    delay (200);
    RenderFrame (ledarrayoff);
  }


  if (totalState == 1) { //run
    RenderFrame (ledarrayrun);
  }


  if (totalState == 2 or totalState == 3) { //turn anime turn run anime
  turnAnimeStep();
  }

  if (totalState == 4) { //brake
    RenderFrame (ledarraybrake);
  }


  if (totalState == 5) { //run brake
    RenderFrame (ledarraybrake);
  }


  if (totalState == 6) { //turn brake
    turnbrakeAnimeStep();
  }
    

  if (totalState == 8) { // reverse
    RenderFrame (ledarrayreverse);
  }


  if (totalState == 9) { // run reverse
    RenderFrame (ledarrayrunreverse);
  }


  if (totalState == 10 or totalState == 11) {// turn reverse and run turn reverse
  }


  if (totalState == 12) { // brake reverse
    RenderFrame (ledarraybrakereverse);
  }


  if (totalState == 13) { // run brake reverse
    RenderFrame (ledarraybrakereverse);
  }


  if (totalState == 14 or totalState == 15) { // turn brake reverse
    turnbrakeReverseAnimeStep ();
  }

    if (totalState == 20) { // party lights
    PARTYLIGHTS ();
  }

}



//Anime state machines

//turn anime machine
void turnAnimeStep()
{
      static byte frame = 0;    // reset to replay
      static unsigned long lastTime = 0;
      static unsigned long tween = 0;

      if (millis() - lastTime < tween)
        return;

      lastTime = millis();
      switch (frame) {
        case 0 :
          RenderFrame (ledarrayt1);
          tween = 200;
          frame++;
          break;

        case 1 :
          RenderFrame (ledarrayt2);
          tween = 15;
          frame++;
          break;

        case 2 :
          RenderFrame (ledarrayt3);
          tween = 15;
          frame++;
          break;

        case 3 :
          RenderFrame (ledarrayt4);
          tween = 15;
          frame++;
          break;

        case 4 :
          RenderFrame (ledarrayt5);
          tween = 15;
          frame++;
          break;

        case 5 :
          RenderFrame (ledarrayt6);
          tween = 15;
          frame++;
          break;

        case 6 :
          RenderFrame (ledarrayt7);
          tween = 15;
          frame++;
          break;

        case 7 :
          RenderFrame (ledarrayt8);
          tween = 15;
          frame++;
          break;

        case 8 :
          RenderFrame (ledarrayt9);
          tween = 15;
          frame++;
          break;
          
        case 9 :
          RenderFrame (ledarrayt10);
          tween = 15;
          frame++;
          break;

        case 10 :
          RenderFrame (ledarrayt11);
          tween = 15;
          frame++;
          break;

        case 11 :
          RenderFrame (ledarrayt12);
          tween = 15;
          frame++;
          break;

        case 12 :
          RenderFrame (ledarrayt13);
          tween = 15;
          frame++;
          break;

        case 13 :
          RenderFrame (ledarrayt14);
          tween = 15;
          frame++;
          break;

        case 14 :
          RenderFrame (ledarrayt15);
          tween = 15;
          frame++;
          break;

        case 15 :
          RenderFrame (ledarrayt16);
          tween = 15;
          frame++;
          break;

        case 16 :
          RenderFrame (ledarrayt17);
          tween = 15;
          frame++;
          break;

        case 17 :
          RenderFrame (ledarrayt18);
          tween = 15;
          frame++;
          break;

        case 18 :
          RenderFrame (ledarrayt19);
          tween = 15;
          frame++;
          break;

        case 19 :
          RenderFrame (ledarrayt20);
          tween = 15;
          frame++;
          break;

        case 20 :
          RenderFrame (ledarrayt21);
          tween = 15;
          frame++;
          break;

        case 21 :
          RenderFrame (ledarrayt22);
          tween = 15;
          frame++;
          break;

        case 22 :
          RenderFrame (ledarrayt23);
          tween = 15;
          frame++;
          break;

        case 23 :
          RenderFrame (ledarrayt24);
          tween = 15;
          frame = 0;
          break;
      }
    }

//turn brake anime machine
void turnbrakeAnimeStep()
{
      static byte frame = 0;    // reset to replay
      static unsigned long lastTime = 0;
      static unsigned long tween = 0;

      if (millis() - lastTime < tween)
        return;

      lastTime = millis();
      switch (frame) {
        case 0 :
          RenderFrame (ledarraytb1);
          tween = 200;
          frame++;
          break;

        case 1 :
          RenderFrame (ledarraytb2);
          tween = 15;
          frame++;
          break;

        case 2 :
          RenderFrame (ledarraytb3);
          tween = 15;
          frame++;
          break;

        case 3 :
          RenderFrame (ledarraytb4);
          tween = 15;
          frame++;
          break;

        case 4 :
          RenderFrame (ledarraytb5);
          tween = 15;
          frame++;
          break;

        case 5 :
          RenderFrame (ledarraytb6);
          tween = 15;
          frame++;
          break;

        case 6 :
          RenderFrame (ledarraytb7);
          tween = 15;
          frame++;
          break;

        case 7 :
          RenderFrame (ledarraytb8);
          tween = 15;
          frame++;
          break;

        case 8 :
          RenderFrame (ledarraytb9);
          tween = 15;
          frame++;
          break;
          
        case 9 :
          RenderFrame (ledarraytb10);
          tween = 15;
          frame++;
          break;

        case 10 :
          RenderFrame (ledarraytb11);
          tween = 15;
          frame++;
          break;

        case 11 :
          RenderFrame (ledarraytb12);
          tween = 15;
          frame++;
          break;

        case 12 :
          RenderFrame (ledarraytb13);
          tween = 15;
          frame++;
          break;

        case 13 :
          RenderFrame (ledarraytb14);
          tween = 15;
          frame++;
          break;

        case 14 :
          RenderFrame (ledarraytb15);
          tween = 15;
          frame++;
          break;

        case 15 :
          RenderFrame (ledarraytb16);
          tween = 15;
          frame++;
          break;

        case 16 :
          RenderFrame (ledarraytb17);
          tween = 15;
          frame++;
          break;

        case 17 :
          RenderFrame (ledarraytb18);
          tween = 15;
          frame++;
          break;

        case 18 :
          RenderFrame (ledarraytb19);
          tween = 15;
          frame++;
          break;

        case 19 :
          RenderFrame (ledarraytb20);
          tween = 15;
          frame++;
          break;

        case 20 :
          RenderFrame (ledarraytb21);
          tween = 15;
          frame++;
          break;

        case 21 :
          RenderFrame (ledarraytb22);
          tween = 15;
          frame++;
          break;

        case 22 :
          RenderFrame (ledarraytb23);
          tween = 15;
          frame = 0;
          break;
      }
}

//turn brake reverse anime machine
void turnbrakeReverseAnimeStep()
{
      static byte frame = 0;    // reset to replay
      static unsigned long lastTime = 0;
      static unsigned long tween = 0;

      if (millis() - lastTime < tween)
        return;

      lastTime = millis();
      switch (frame) {
        case 0 :
          RenderFrame (ledarraytbr1);
          tween = 200;
          frame++;
          break;

        case 1 :
          RenderFrame (ledarraytbr2);
          tween = 15;
          frame++;
          break;

        case 2 :
          RenderFrame (ledarraytbr3);
          tween = 15;
          frame++;
          break;

        case 3 :
          RenderFrame (ledarraytbr4);
          tween = 15;
          frame++;
          break;

        case 4 :
          RenderFrame (ledarraytbr5);
          tween = 15;
          frame++;
          break;

        case 5 :
          RenderFrame (ledarraytbr6);
          tween = 15;
          frame++;
          break;

        case 6 :
          RenderFrame (ledarraytbr7);
          tween = 15;
          frame++;
          break;

        case 7 :
          RenderFrame (ledarraytbr8);
          tween = 15;
          frame++;
          break;

        case 8 :
          RenderFrame (ledarraytbr9);
          tween = 15;
          frame++;
          break;
          
        case 9 :
          RenderFrame (ledarraytbr10);
          tween = 15;
          frame++;
          break;

        case 10 :
          RenderFrame (ledarraytbr11);
          tween = 15;
          frame++;
          break;

        case 11 :
          RenderFrame (ledarraytbr12);
          tween = 15;
          frame++;
          break;

        case 12 :
          RenderFrame (ledarraytbr13);
          tween = 15;
          frame++;
          break;

        case 13 :
          RenderFrame (ledarraytbr14);
          tween = 15;
          frame++;
          break;

        case 14 :
          RenderFrame (ledarraytbr15);
          tween = 15;
          frame++;
          break;

        case 15 :
          RenderFrame (ledarraytbr16);
          tween = 15;
          frame++;
          break;

        case 16 :
          RenderFrame (ledarraytbr17);
          tween = 15;
          frame++;
          break;

        case 17 :
          RenderFrame (ledarraytbr18);
          tween = 15;
          frame++;
          break;

        case 18 :
          RenderFrame (ledarraytbr19);
          tween = 15;
          frame++;
          break;

        case 19 :
          RenderFrame (ledarraytbr20);
          tween = 15;
          frame++;
          break;

        case 20 :
          RenderFrame (ledarraytbr21);
          tween = 15;
          frame++;
          break;

        case 21 :
          RenderFrame (ledarraytbr22);
          tween = 15;
          frame++;
          break;

        case 22 :
          RenderFrame (ledarraytbr23);
          tween = 15;
          frame = 0;
          break;
      }
}

//PARTYLIGHTS
void PARTYLIGHTS()
{
      static byte frame = 0;    // reset to replay
      static unsigned long lastTime = 0;
      static unsigned long tween = 0;

      if (millis() - lastTime < tween)
        return;

      lastTime = millis();
      switch (frame) {
        case 0 :          
        RenderFrame (PARTYLIGHT1);
          tween = 200;
          frame++;
          break;


        case 1 :
          RenderFrame (PARTYLIGHT2);
          tween = 200;
          frame = 0;
          break;
      }
    }


void RenderFrame(const uint32_t *arr)
    {
  for (uint16_t t = 0; t < 256; t++)
  {
    strip.setPixelColor(t, arr[t]);
  }
  strip.show();

}

Haha, yes. Neither do I. That is to say there is no good way.

You are correct, the Serial.print stuff is just standing in for the RenderFrame calls. Because of your data-centered approach, I am unable to actually run your code.

So the wokwi above is an attempt to put my idea into your framework. Reread #59 and #65, put your finger on the code in this improved version linked/demo below. It no longer needs a mystery fix, I found two errors that eluded me for I will not tell you how long. One was a typo. Anyway

is as simple as it gets - the animation function has additions, and you call it a little differently.

Just read it and have your animation function nearby and look for the differences.

I cannot recommend that you go to the trouble and retrofit all your animation functions with this idea. It cold work. More likely it will introduce a nasty bunch of unintended consequences and we will curse the day the plan to drain the swamp was hatched.

At this point, I recommend you learn a few new things and write a version 2. With all where it might end up needing to go planned ahead of time… yeah, I do that alla time. :expressionless:

a7