Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 34

Thread: DMX hardware rec for Teensy 3.2?

  1. #1

    DMX hardware rec for Teensy 3.2?

    Hi,

    I'm making a halloween show controller with a Teensy 3.2 at the heart. Currently the Teensy is mounted to a SparkFun board that adapts it to the Arduino hardware format because I needed it to fit a DMX Arduino Shield I had purcahsed. The shield and accompaining library don't work (perhaps looking for an Arduino Uno harware timer that isnt there ??? IDK). I'm scrapping the shield...

    Question? Will someone please recommend a DMX hardware board (Arduino style shield or not) that is proven to work with Teensy 3.2 and DMXSimple which I understand is a PJRC creation that works.

    Thanks in advance.

    Jeff

  2. #2

    TeensyDMX Lib & existing shield

    I’m looking at TeensyDMX and it looks well used/supported so I’m going to concentrate on making that library work.

    I’ll start with the mystery DMX shield and move on with known hardware solutions if any are suggested.

    Thanks.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	2BA4F09C-0C3A-4891-ACBA-7D13678C8516.jpeg 
Views:	16 
Size:	139.5 KB 
ID:	26050  
    Last edited by jparisse; 10-02-2021 at 08:15 PM. Reason: Add Photo

  3. #3
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    695
    Quote Originally Posted by jparisse View Post
    Will someone please recommend a DMX hardware board (Arduino style shield or not) that is proven to work with Teensy 3.2 and DMXSimple
    I have successfully used these Sparkfun boards using the TeensyDMX library:

    Click image for larger version. 

Name:	DMX interface.jpg 
Views:	18 
Size:	62.4 KB 
ID:	26057

    Paul

  4. #4
    Thanks Paul! The key seems to be the TeensyDMX library. I able to get the library to work the hardware. To my DMX instruments to work just required a change from hex to decimal in the “data” string. Thanks again for the referral.

    Jeff

  5. #5
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    345
    Do let me know how the library works for you. Iím very interested in making sure it works well and robustly. (Iím assuming you mean this one: https://github.com/ssilverman/TeensyDMX. Itís also accessible via PlatformIO and the Arduino IDE.)

  6. #6

    Thanks Shawn!

    Quote Originally Posted by shawn View Post
    Do let me know how the library works for you. Iím very interested in making sure it works well and robustly. (Iím assuming you mean this one: https://github.com/ssilverman/TeensyDMX. Itís also accessible via PlatformIO and the Arduino IDE.)
    I canít wait to jump inÖ Iím using very inexpensive fixtures that may not be unit addressable. BUT, your library is the only one (of three) that will communicate with them. I will bring up the DMX ID setting issue with the manufacturer (wish me luck) and in the meantime explore the seven channels of data that the units will accept via TeensyDMX.

    Thanks for your efforts. This is my first foray into DMX lighting and my goal is to entertain the folks that walk by the house on halloween. Iíll keep the thread alive and share my experience.

    Jeff
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	2B55133E-51EC-4F44-9E34-28561565A920.jpeg 
Views:	19 
Size:	142.1 KB 
ID:	26112  

  7. #7
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    345
    I’m glad you got it working! Thanks for sharing the picture. Now I’m curious, what do you think is different or special about those fixtures? I wonder why my library works and not the others? I love this stuff…

  8. #8
    I believe the other libraries made calls to hardware timers that don’t exist on the Teensy (just conjecture). The fixtures have a provision to set the DMX ID but the values either don’t stick or work. I’m waiting for more instruction from the maker.

    Here are some photos of the fixture and the DMX instructions that came with it. I included photos of the project so far and am I’m going to start on the DMX code later today. I will share code as I move along.

    Thanks for being interested, I love this stuff too!

    Jeff
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	4645530C-39F0-47BF-A172-B2694204B25B.jpeg 
Views:	11 
Size:	94.5 KB 
ID:	26119   Click image for larger version. 

Name:	E2918CDE-DF6E-40EB-9FDB-1A7A2132E683.jpeg 
Views:	17 
Size:	129.3 KB 
ID:	26120  

    Click image for larger version. 

Name:	AE39E8D1-9513-472E-994D-1A932904C90E.jpeg 
Views:	12 
Size:	107.1 KB 
ID:	26121   Click image for larger version. 

Name:	E44FBAF8-D50A-4FBE-81B6-7475E598EC0C.jpeg 
Views:	11 
Size:	118.5 KB 
ID:	26122  

    Click image for larger version. 

Name:	52278F87-9085-46A7-867A-91898DCC992B.jpeg 
Views:	15 
Size:	109.4 KB 
ID:	26123   Click image for larger version. 

Name:	A6FB5A03-EAFE-49CE-B6A2-728D7B6119D5.jpeg 
Views:	9 
Size:	131.7 KB 
ID:	26124  


  9. #9

    How to address individual instruments?

    I'm able to send seven channels of information to the first instrument (ID 1) but not to any others. Perhaps this question is too basic for the TeensyDMX documentation; I am a complete DMX newbie. How does one send a dmxTx.set command to other IDs?

    If I set the ID on all instruments to "ID 1" then all lights respond to TeensyDMX commands sent to ID 1 (default ID?).

    I have four instruments (non-moving RGB LED lights) in total, each capable of receiving seven channels of data.

    Thanks in advance.

    Jeff




    Code:
    /*
       A basic toy send example.
    
       This example is part of the TeensyDMX library.
       (c) 2019-2020 Shawn Silverman
    */
    
    #include <TeensyDMX.h>
    
    namespace teensydmx = ::qindesign::teensydmx;
    
    teensydmx::Sender dmxTx{Serial1};
    
    constexpr uint8_t kTXPin = 2;
    uint8_t bright = 255;
    uint8_t red = 128;
    uint8_t green = 128;
    uint8_t blue = 128;
    uint8_t strobe = 0;
    uint8_t mode = 0;
    uint8_t modeModifier = 0;
    uint8_t data[7] {bright, red, green, blue, strobe, mode, modeModifier};
    
    void setup() {
      // Serial.begin(11520);
      pinMode(kTXPin, OUTPUT);
      digitalWrite(kTXPin, HIGH);
    
      // Set channels 1-7 to the 7 values in 'data'
      dmxTx.set(1, data, 7);
    
      dmxTx.begin();
    }
    
    void loop() {
      // Do something, maybe alter channel values.
    }

  10. #10
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    345
    Some questions and comments:
    1. Change "11520" to "115200" in that commented-out Serial.begin(). (For posterity.)
    2. One DMX universe consists of essentially one serial port and 513 slots. (The first slot, slot 0, is the "start code" and there are 512 channels.) The packets are sent approximately 44 times a second.
    3. There's no such thing as "ID" in DMX. I can think of a few possibilities of what they might mean. First, do they mean different universes? (i.e. They all expect channels 1-7, where each device needs different values.) If so, just create more DMX transmitters on more serial ports and connect those separately. Each "universe", however, is still composed of 513 8-bit slots with no further meaning (other than the start code (slot 0) needing to be zero for raw DMX). It's also possible that "ID" means "Starting multiple of 7." For example, ID 1 means channels 1-7, ID 2 means channels 8-14, etc.
    4. Do you need to be setting pin 2 high? It's meant for circuits that require some pin to be set (high or low) to enable or disable TX/RX. For example, the Sparkfun RS-485 breakout boards use such a line. How are you interfacing the serial port to the RS-485 lines? On the other hand, this may be entirely intended. (I’ve received questions about it because I set the pin in the examples and sometimes people just copy it. I believe you know what you’re doing.)
    5. Do you have device docs you can share?
    Last edited by shawn; 10-11-2021 at 03:20 AM.

  11. #11
    shawn,

    Re:
    #1 - burp, how funny that I set that here for debugging.
    #2 - Thanks for that... I understand the universe now! I reason now that the ID is for different universes. I should therefore set all instruments to ID1 (Universe 0).
    #3 - The second possibliity you suggested seems to be correct.
    #4 - Hardware (shown in pic on second post in thread) is poorly documented. Pin #2 is set HIGH to enable transmitting as I am reasoning at this point. I really dont know for sure.
    #5 - I just found this on the web; it pretty much spells out what I reason you're about to tell me. Still a mystery until I start trying out code but I think I get it; I have to send four sets of seven channels to my four instruments (that all live in the same universe).

    I'm laughing only because I thought it was only science fiction superhero movies that employed multiple universes. Thanks for your help and interest in the project. My wife and I hung rigging all day for the animatronic skeletions... I cant wait to add DMX and Im very happy for your help.

    From the web:
    Table 2 – Example channel ranges for 7-channel fixtures in a DMX universe

    Fixture DMX Channel Base Channels Used
    1 1 1-7
    2 8 8-14
    3 15 15-21
    4 22 22-28
    5 29 29-35
    6 36 36-42
    7 43 43-49
    8 50 50-56
    9 57 57-63
    10 64 64-70

    73 505 505-512


    Technical details

    The following tables show the technical specifications of the fixtures, as tested by the Finale support team.



    Table 3 – DMX channels for 7CH personality

    DMX Channel Meaning
    Channel 1 (DMX Channel Base + 0) Dimmer
    Channel 2 (DMX Channel Base + 1) Red
    Channel 3 (DMX Channel Base + 2) Green
    Channel 4 (DMX Channel Base + 3) Blue
    Channel 5 (DMX Channel Base + 4) Strobe (0-7 = no strobe; 8-255 = slow to fast)
    Channel 6 (DMX Channel Base + 5) Set to zero
    Channel 7 (DMX Channel Base + 6) Set to zero

  12. #12
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    345
    Glad you figured it out. Sounds like “ID” is really just “DMX Channel Base”. Side note: that last line, #73, should end in 511.

    This also means you can use the same universe and just set all the fixtures to consecutive numbers and then physically chain them. Then, when addressing each one, just add “(base*7)-6”, assuming the first base is set to “1”.

    How many fixtures in total do you have?

    I’d love to see videos when you have it all working.
    Last edited by shawn; 10-11-2021 at 06:21 AM.

  13. #13
    Senior Member
    Join Date
    Mar 2017
    Location
    Oakland, CA, USA
    Posts
    345
    Here's some code I whipped up. There's lots and lots of ways to tackle this. Hope this is useful.

    Code:
    // C++ includes
    #include <vector>
    
    #include <TeensyDMX.h>
    
    namespace teensydmx = qindesign::teensydmx;
    
    // --------------------------------------------------------------------------
    //  Configuration
    // --------------------------------------------------------------------------
    
    // Enables TX on the connected fixtures.
    constexpr uint8_t kTXPin = 2;
    
    // Number of fixtures.
    constexpr int kFixtureCount = 6;
    
    // --------------------------------------------------------------------------
    //  Fixture interface
    // --------------------------------------------------------------------------
    
    // Provides an easier interface to a fixture.
    class Fixture {
     public:
      Fixture(int id, teensydmx::Sender &dmxTx)
          : base_((id - 1)*7 + 1),
            dmxTx_(dmxTx) {
        // Initialize everything to zero
        dmxTx_.fill(base_, 7, 0);
      }
    
      ~Fixture() = default;
    
      void setDim(uint8_t value) {
        dim_ = value;
        dmxTx_.set(base_ + kDim, value);
      }
      uint8_t getDim() const { return dim_; }
    
      void setRed(uint8_t value) {
        red_ = value;
        dmxTx_.set(base_ + kRed, value);
      }
      uint8_t getRed() const { return red_; }
      
      void setGreen(uint8_t value) {
        green_ = value;
        dmxTx_.set(base_ + kGreen, value);
      }
      uint8_t getGreen() const { return green_; }
    
      void setBlue(uint8_t value) {
        blue_ = value;
        dmxTx_.set(base_ + kBlue, value);
      }
      uint8_t getBlue() const { return blue_; }
    
      // Sets the strobe. 0-7 means "No strobe" and
      // 8-255 means "Slow to fast".
      void setStrobe(uint8_t value) {
        strobe_ = value;
        dmxTx_.set(base_ + kStrobe, value);
      }
      uint8_t getStrobe() const { return strobe_; }
    
     private:
      // Channels
      static constexpr int kDim = 0;
      static constexpr int kRed = 1;
      static constexpr int kGreen = 2;
      static constexpr int kBlue = 3;
      static constexpr int kStrobe = 4;
    
      const int base_;  // Base DMX address
      teensydmx::Sender &dmxTx_;
    
      // Since Sender doesn't currently let you read what's being output,
      // capture the current states here
      uint8_t dim_ = 0;
      uint8_t red_ = 0;
      uint8_t green_ = 0;
      uint8_t blue_ = 0;
      uint8_t strobe_ = 0;
    };
    
    // -------------------------------------------------------------------
    //  Main program
    // -------------------------------------------------------------------
    
    teensydmx::Sender dmxTx{Serial1};  // DMX on Serial1
    
    // All the fixtures, set up in setup().
    std::vector<Fixture> fixtures;
    
    // For "change every second demo"
    elapsedMillis timer;
    
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 4000) {
        // Wait for Serial to initialize for at most 4 seconds
      }
      Serial.println("Starting...");
    
      // Enable DMX output (check if this is needed)
      pinMode(kTXPin, OUTPUT);
      digitalWrite(kTXPin, HIGH);
    
      // Set up all the fixtures
      // Note: There's ways around it, but index 0 has fixture 1,
      //       index 1 has fixture 2, etc.
      for (int i = 0; i < kFixtureCount; i++) {
        fixtures.emplace_back(i + 1, dmxTx);  // Start ID at 1
      }
    
      // I believe the system initializes the sender to be all zero,
      // but clear just in case
      dmxTx.clear();
    
      // Initialize all the fixtures
      Serial.println("Initializing fixtures...");
      for (auto &fixture : fixtures) {
        fixture.setDim(255);
        fixture.setRed(128);
        fixture.setGreen(128);
        fixture.setBlue(128);
        fixture.setStrobe(0);
      }
    
      Serial.println("Starting DMX TX...");
      dmxTx.begin();
    }
    
    void loop() {
      // For demo purposes, change the dimming of all fixtures
      // once every second
      // There's a gazillion other effects you could do here
    
      if (timer < 1000) {
        return;
      }
      timer = 0;
    
      for (auto &fixture : fixtures) {
        fixture.setDim(fixture.getDim() + 128);
      }
    }

  14. #14
    Wow Shawn! Tremendously useful! It may take more time than I have for this Halloween to understand fully but I will look at it very soon.

    I wrote something very simple (luckily for me it is a Roaring Twenties light show so it doesn't need to be sophisticated (like my programming skills). I'd figure that I'd write a bunch of light setting functions and pick them at random as my show progresses.


    /*
    TeensyDMX library (c) 2019-2020 Shawn Silverman
    */

    #include <TeensyDMX.h>

    namespace teensydmx = ::qindesign::teensydmx;

    constexpr uint8_t dmxPin = 2;

    teensydmx::Sender dmxTx{Serial1};

    /*
    Data
    1 [0]brightness 0-255
    2 [1]red 0-255
    3 (2]green 0-255
    4 [3]blue 0-255
    5 [4]strobe 0-255
    6 [5]mode
    0-10 Manual control CH1-CH5
    11-60 Color Selection (controlled by CH7)
    61-110 Color Shade (controlled bt CH7)
    111-160 Color Pulse Transform (speed controlled by CH7)
    161-210 Color Transform (speed controlled by CH7)
    211-255 Sound Control
    7 [6]modifier 0-255
    */

    // Default - All instruments BLUE 50% Brightness
    uint8_t bright = 128;
    uint8_t red = 0;
    uint8_t green = 0;
    uint8_t blue = 255;
    uint8_t strobe = 0;
    uint8_t mode = 0;
    uint8_t modifier = 0;
    uint8_t data[7] {bright, red, green, blue, strobe, mode, modifier}; // All instruments BLUE

    void setup() {
    // Serial.begin(115200);
    pinMode(dmxPin, OUTPUT);
    digitalWriteFast(dmxPin, HIGH);
    dmxTx.set(1, data, 7); // Instrument #1
    dmxTx.set(8, data, 7); // Instrument #2
    dmxTx.set(15, data, 7); // Instrument #3
    dmxTx.set(22, data, 7); // Instrument #4
    dmxTx.begin();
    delay(3000);
    }

    void loop() {
    dmx_allRed();
    dmxTx.begin();
    delay(3000);
    dmx_allGreen();
    dmxTx.begin();
    delay(3000);
    }

    void dmx_allRed() {
    data[0] = 255; // Brightness
    data[1] = 255; // Red
    data[2] = 0; // Green
    data[3] = 0; // Blue
    data[4] = 0; // Strobe
    data[5] = 0; // Mode (see Table)
    data[6] = 0; // Modifier (see Table)
    dmxTx.set(1, data, 7); // Instrument #1
    dmxTx.set(8, data, 7); // Instrument #2
    dmxTx.set(15, data, 7); // Instrument #3
    dmxTx.set(22, data, 7); // Instrument #4
    }

    void dmx_allGreen() {
    data[0] = 255; // Brightness
    data[1] = 0; // Red
    data[2] = 255; // Green
    data[3] = 0; // Blue
    data[4] = 0; // Strobe
    data[5] = 0; // Mode (see Table)
    data[6] = 0; // Modifier (see Table)
    dmxTx.set(1, data, 7); // Instrument #1
    dmxTx.set(8, data, 7); // Instrument #2
    dmxTx.set(15, data, 7); // Instrument #3
    dmxTx.set(22, data, 7); // Instrument #4
    }

  15. #15
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    455
    Do you think in future you could enclose your code between [C ODE] tags. These are the ones produced by pressing the # button above.
    Doing so keeps the format of the code and makes it more readable, so others are more able to help you.
    I am glad you are making progress with your project.
    Code:
    /*
    TeensyDMX library (c) 2019-2020 Shawn Silverman
    */
    
    #include <TeensyDMX.h>
    
    namespace teensydmx = ::qindesign::teensydmx;
    
    constexpr uint8_t dmxPin = 2;
    
    teensydmx::Sender dmxTx{ Serial1 };
    
    /*
    Data
    1 [0]brightness 0-255
    2 [1]red 0-255
    3 (2]green 0-255
    4 [3]blue 0-255
    5 [4]strobe 0-255
    6 [5]mode
    0-10 Manual control CH1-CH5
    11-60 Color Selection (controlled by CH7)
    61-110 Color Shade (controlled bt CH7)
    111-160 Color Pulse Transform (speed controlled by CH7)
    161-210 Color Transform (speed controlled by CH7)
    211-255 Sound Control
    7 [6]modifier 0-255
    */
    
    // Default - All instruments BLUE 50% Brightness
    uint8_t bright = 128;
    uint8_t red = 0;
    uint8_t green = 0;
    uint8_t blue = 255;
    uint8_t strobe = 0;
    uint8_t mode = 0;
    uint8_t modifier = 0;
    uint8_t data[7]{ bright, red, green, blue, strobe, mode, modifier }; // All instruments BLUE
    
    void setup() {
    	// Serial.begin(115200);
    	pinMode(dmxPin, OUTPUT);
    	digitalWriteFast(dmxPin, HIGH);
    	dmxTx.set(1, data, 7); // Instrument #1
    	dmxTx.set(8, data, 7); // Instrument #2
    	dmxTx.set(15, data, 7); // Instrument #3
    	dmxTx.set(22, data, 7); // Instrument #4
    	dmxTx.begin();
    	delay(3000);
    }
    
    void loop() {
    	dmx_allRed();
    	dmxTx.begin();
    	delay(3000);
    	dmx_allGreen();
    	dmxTx.begin();
    	delay(3000);
    }
    
    void dmx_allRed() {
    	data[0] = 255; // Brightness
    	data[1] = 255; // Red
    	data[2] = 0; // Green
    	data[3] = 0; // Blue
    	data[4] = 0; // Strobe
    	data[5] = 0; // Mode (see Table)
    	data[6] = 0; // Modifier (see Table)
    	dmxTx.set(1, data, 7); // Instrument #1
    	dmxTx.set(8, data, 7); // Instrument #2
    	dmxTx.set(15, data, 7); // Instrument #3
    	dmxTx.set(22, data, 7); // Instrument #4
    }
    
    void dmx_allGreen() {
    	data[0] = 255; // Brightness
    	data[1] = 0; // Red
    	data[2] = 255; // Green
    	data[3] = 0; // Blue
    	data[4] = 0; // Strobe
    	data[5] = 0; // Mode (see Table)
    	data[6] = 0; // Modifier (see Table)
    	dmxTx.set(1, data, 7); // Instrument #1
    	dmxTx.set(8, data, 7); // Instrument #2
    	dmxTx.set(15, data, 7); // Instrument #3
    	dmxTx.set(22, data, 7); // Instrument #4
    }

  16. #16
    Senior Member PaulS's Avatar
    Join Date
    Apr 2015
    Location
    Netherlands
    Posts
    695
    @Jeff
    You better delete dmxTx.begin(); from loop().
    You already started the service in your setup(), so no need to (re)start that in loop() again and again. Just apply new values using dmxTx.set(). Like so:
    Code:
    void loop() {
      dmx_allRed();
      delay(3000);
      dmx_allGreen();
      delay(3000);
    }
    Paul

  17. #17
    Quote Originally Posted by BriComp View Post
    Do you think in future you could enclose your code between [C ODE] tags. These are the ones produced by pressing the # button above.
    Doing so keeps the format of the code and makes it more readable, so others are more able to help you.
    I am glad you are making progress with your project.
    Code:
    /*
    TeensyDMX library (c) 2019-2020 Shawn Silverman
    */
    
    #include <TeensyDMX.h>
    
    namespace teensydmx = ::qindesign::teensydmx;
    
    constexpr uint8_t dmxPin = 2;
    
    teensydmx::Sender dmxTx{ Serial1 };
    
    /*
    Data
    1 [0]brightness 0-255
    2 [1]red 0-255
    3 (2]green 0-255
    4 [3]blue 0-255
    5 [4]strobe 0-255
    6 [5]mode
    0-10 Manual control CH1-CH5
    11-60 Color Selection (controlled by CH7)
    61-110 Color Shade (controlled bt CH7)
    111-160 Color Pulse Transform (speed controlled by CH7)
    161-210 Color Transform (speed controlled by CH7)
    211-255 Sound Control
    7 [6]modifier 0-255
    */
    
    // Default - All instruments BLUE 50% Brightness
    uint8_t bright = 128;
    uint8_t red = 0;
    uint8_t green = 0;
    uint8_t blue = 255;
    uint8_t strobe = 0;
    uint8_t mode = 0;
    uint8_t modifier = 0;
    uint8_t data[7]{ bright, red, green, blue, strobe, mode, modifier }; // All instruments BLUE
    
    void setup() {
    	// Serial.begin(115200);
    	pinMode(dmxPin, OUTPUT);
    	digitalWriteFast(dmxPin, HIGH);
    	dmxTx.set(1, data, 7); // Instrument #1
    	dmxTx.set(8, data, 7); // Instrument #2
    	dmxTx.set(15, data, 7); // Instrument #3
    	dmxTx.set(22, data, 7); // Instrument #4
    	dmxTx.begin();
    	delay(3000);
    }
    
    void loop() {
    	dmx_allRed();
    	dmxTx.begin();
    	delay(3000);
    	dmx_allGreen();
    	dmxTx.begin();
    	delay(3000);
    }
    
    void dmx_allRed() {
    	data[0] = 255; // Brightness
    	data[1] = 255; // Red
    	data[2] = 0; // Green
    	data[3] = 0; // Blue
    	data[4] = 0; // Strobe
    	data[5] = 0; // Mode (see Table)
    	data[6] = 0; // Modifier (see Table)
    	dmxTx.set(1, data, 7); // Instrument #1
    	dmxTx.set(8, data, 7); // Instrument #2
    	dmxTx.set(15, data, 7); // Instrument #3
    	dmxTx.set(22, data, 7); // Instrument #4
    }
    
    void dmx_allGreen() {
    	data[0] = 255; // Brightness
    	data[1] = 0; // Red
    	data[2] = 255; // Green
    	data[3] = 0; // Blue
    	data[4] = 0; // Strobe
    	data[5] = 0; // Mode (see Table)
    	data[6] = 0; // Modifier (see Table)
    	dmxTx.set(1, data, 7); // Instrument #1
    	dmxTx.set(8, data, 7); // Instrument #2
    	dmxTx.set(15, data, 7); // Instrument #3
    	dmxTx.set(22, data, 7); // Instrument #4
    }

    Thanks BriComp! I believe I did exactly that and one can reason my intentions from the “encapsulated code” I did publish. I will look more closely at the tiny buttons; none of which say “code”. Thanks for the style tip. I’ll be more careful in my subsequent replies and uses the # button next time.

    Jeff

  18. #18
    Paul,

    Thanks so much for the catch. Iím getting to frantic part of the project and am mired in mechanics and spray paint while attempting to up my coding skills. I bit off more than I can chew this Halloween and I am very grateful for all the help I have been getting in this thread. Teensy rocks and so does the community!

    Jeff

    Click image for larger version. 

Name:	D0C4D7A4-6C56-41CD-BB38-BD235A100A4B.jpeg 
Views:	11 
Size:	105.1 KB 
ID:	26172Click image for larger version. 

Name:	9A1BA3A3-1BB1-45F3-8C17-741D3A392549.jpeg 
Views:	12 
Size:	108.7 KB 
ID:	26171
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	A671F6EF-09D3-4E46-B493-6DE445BAC5EC.jpeg 
Views:	9 
Size:	125.6 KB 
ID:	26170  

  19. #19
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    455
    Thanks BriComp! I believe I did exactly that and one can reason my intentions from the ďencapsulated codeĒ I did publish. I will look more closely at the tiny buttons; none of which say ďcodeĒ. Thanks for the style tip. Iíll be more careful in my subsequent replies and uses the # button next time.

    Jeff
    Yea I couldn't find out how people were encapsulating the code when I first started. Eventually found out how!!
    I have since found that if you hover over the buttons an explanation of it's use pops up.

  20. #20

    Opening Night Friday!

    Here is the basis of what is working for me so far. In the final program, the various light functions will be called at a set time to match the music but a random choice (spot light on dancer #1, all blue, fade to black. etc.). I did something similar with the skeleton dance moves using "switch case" and a random number generator.


    Code:
    /*
       TeensyDMX library (c) 2019-2020 Shawn Silverman
    */
    
    #include <TeensyDMX.h>
    namespace teensydmx = ::qindesign::teensydmx;
    constexpr uint8_t dmxPin = 2;
    teensydmx::Sender dmxTx{Serial1};
    
    /*
       Data
       1 [0]brightness 0-255
       2 [1]red 0-255
       3 (2]green 0-255
       4 [3]blue 0-255
       5 [4]strobe 0-255
       6 [5]mode
              0-10 Manual control CH1-CH5
              11-60 Color Selection (controlled by CH7)
              61-110 Color Shade (controlled bt CH7)
              111-160 Color Pulse Transform (speed controlled by CH7)
              161-210 Color Transform (speed controlled by CH7)
              211-255 Sound Control
       7 [6]modifier 0-255
    */
    
    uint8_t data[7] {128, 0, 0, 255, 0, 0, 0};    // Default: All instruments BLUE @ 50%
    
    void setup() {
      // Serial.begin(115200);
      pinMode(dmxPin, OUTPUT);
      digitalWrite(dmxPin, HIGH);
      for (int x = 1; x <= 23; x = x + 7) {
        dmxTx.set(x, data, 7);
      }
      dmxTx.begin();
      delay(3000);
    }
    
    void loop() {
      dmx_allRed();
      delay(3000);
      for (int fade=255; fade>=0; --fade) {
        dmxTx.set(1, fade);
        delay(10);
      }
      dmx_allGreen();
      delay(3000);
      dmx_allBlue();
      delay(3000);
    }
    
    void dmx_allRed() {
      uint8_t data[7] = {255, 255, 0, 0, 0, 0, 0};
      for (int x = 1; x <= 23; x = x + 7) {
        dmxTx.set(x, data, 7);
      }
    }
    
    void dmx_allGreen() {
      uint8_t data[7] = {255, 0, 255, 0, 0, 0, 0};
      for (int x = 1; x <= 23; x = x + 7) {
        dmxTx.set(x, data, 7);
      }
    }
    
    void dmx_allBlue() {
      uint8_t data[7] = {255, 0, 0, 255, 0, 0, 0};
      for (int x = 1; x <= 23; x = x + 7) {
        dmxTx.set(x, data, 7);
      }
    }

  21. #21

    Stuck for the night.....

    OK... It is 12AM and I have to go to sleep....
    For some reason I can't figure out how an array assignment that works standalone does not work as a function.
    I am getting a error that reads:

    Holiday_Show_Controller: In function 'void playDmx()':

    Holiday_Show_Controller:306: error: cannot convert '<brace-enclosed initializer list>' to 'uint8_t {aka unsigned char}' in assignment

    data[7] = {255, 255, 0, 0, 0, 0, 0}; // Red

    ^
    What am I doing wrong? Thanks in advance....

    Jeff



    Code:
    /***************************************************
      Holiday Show Control - v1.1 10/09/21
      by Jeff W. Parisse - 09/09/2021
      jparisse@me.com
      TeensyDMX library (c) 2019-2020 Shawn Silverman
    
      This program acts as a show controller for holiday show projects. It runs on a Teesy 3.2 and controls servos via
      an Adafruit I2C servo controller, addressable LEDs via a Adafruit M4 Express processor board, sound via an Adafruit
      16Mb Sound F/C Controller and DMX via a CTC-DRA-10-R2 Arduino Shield.
    
      Processor: Teensy 3.2
      PIR Sensor: 5V In, 3.3V Logic HIGH on Detect
      DMX Shield: Generic using TeensyDMX Library
      NEO Processor; Adafruit Itsy Bitsy M4 Express, LOW to trigger
      Sound F/X Board: LOW to trigger
      Servo Driver: I2C Address A1 (despite hardware A0 selected)
      AC Relays: HIGH to turn ON
    
      Pin Outs:
        Pin 0   RX    Serial In
        Pin 1   TX    Serial Out
        Pin 2   DMX   DOUT
        Pin 3   PIR   DIN
        Pin 4   AUX   DIN
        Pin 5   NEO   DOUT
        Pin 6   AC1   DOUT
        Pin 7   AC2   DOUT
        Pin 8   SFX0  DOUT
        Pin 9   SFX1  DOUT
        Pin 10  SFX2  DOUT
        Pin 11  SFX3  DOUT
        Pin 12  SFX4  DOUT
        Pin 13  LED   DOUT
        Pin 14  SFX5  DOUT
        Pin 15  SFX6  DOUT
        Pin 16  SFX7  DOUT
        Pin 17  SFX8  DOUT
        Pin 18  SDA   I2C
        Pin 19  SCL   I2C
        Pin 22  VOL+  DOUT (v1.1 not used)
        Pin 23  VOL-  DOUT (v1.1 not used)
     ****************************************************/
    
    #include <Wire.h>
    #include <Adafruit_PWMServoDriver.h>
    #include <TeensyDMX.h>
    
    #define dmxPin 2
    #define pirPin 3
    #define auxPin 4
    #define neoPin 5
    #define ac1Pin 6
    #define ac2Pin 7
    #define sfx0Pin 8
    #define sfx1Pin 9
    #define sfx2Pin 10
    #define sfx3Pin 11
    #define sfx4Pin 12
    #define ledPin 13
    #define sfx5Pin 14
    #define sfx6Pin 15
    #define sfx7Pin 16
    #define sfx8Pin 17
    #define volupPin 22
    #define voldnPin 23
    #define servoFreq 50                 // ~50 Hz servo updates
    
    Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
    namespace teensydmx = ::qindesign::teensydmx;
    teensydmx::Sender dmxTx{Serial1};
    
    // DMX Variables
    uint8_t data[7] = {0, 128, 128, 128, 0, 0, 0};          // Default: 50% White OFF
    
    // Servo Variables
    uint8_t servo1 = 0;
    uint8_t servo2 = 1;
    uint8_t servo3 = 2;
    uint8_t servo4 = 3;
    uint8_t servo5 = 4;
    uint8_t servo6 = 5;
    uint8_t servo7 = 6;
    uint8_t servo8 = 7;
    uint8_t servo9 = 8;
    uint8_t servo10 = 9;
    uint8_t servo11 = 10;
    uint8_t servo12 = 11;
    uint8_t servo13 = 12;
    uint8_t servo14 = 13;
    uint8_t servo15 = 14;
    uint8_t servo16 = 15;
    
    // Servo Timer
    boolean servoDirection = LOW;
    uint16_t servoMin = 167;                       // 900ms This is the 'minimum' pulse length count (out of 4096)
    uint16_t servoCenter = 279;                    // 900ms This is the 'minimum' pulse length count (out of 4096)
    uint16_t servoMax = 390;                       // 2100ms This is the 'maximum' pulse length count (out of 4096)
    unsigned long servoInterval = 500;             // Default
    unsigned long previousServoMillis = 0;
    
    // Moon Timer
    boolean moonState = LOW;
    uint16_t moonMin = 167;                       // 900ms This is the 'minimum' pulse length count (out of 4096)
    uint16_t moonMax = 390;                       // 2100ms This is the 'maximum' pulse length count (out of 4096)
    unsigned long moonInterval = 10;              // Default Servo Delay
    unsigned long previousMoonMillis = 0;
    
    // Show Timer
    boolean showState = LOW;
    int showMin = 120000;                         // 120,000 ms = 00:02:00 (two minutes)
    int showMax = 180000;                         // 180,000 ms = 00:03:00 (three minutes)
    unsigned long showInterval = 120000;          // 120,000 ms = 00:02:00
    unsigned long previousShowMillis = 0;
    
    // Delay Timer
    boolean delayState = HIGH;
    int delayMin = 30000;                        // 30,000 ms = 00:00:30 (thirty seconds)
    int delayMax = 60000;                        // 60,000 ms = 00:01:00 (one minute)
    unsigned long delayInterval = 15000;         // 15,000 ms = 00:00:15
    unsigned long previousDelayMillis = 0;
    
    int songPick = 6;                            // Start with Song #6
    int dmxPick = 1;                             // Default
    int intervalPick = 2;                        // Default
    int danceStep = 250;                         // Default
    
    void setup() {
      // Serial.begin(115200);
      pwm.begin();
      pwm.setOscillatorFrequency(27000000);
      pwm.setPWMFreq(servoFreq);                 // Analog servos run at ~50 Hz updates
      pinMode(pirPin, INPUT);
      pinMode(auxPin, INPUT_PULLUP);
      pinMode(dmxPin, OUTPUT);
      pinMode(neoPin, OUTPUT);
      pinMode(ac1Pin, OUTPUT);
      pinMode(ac2Pin, OUTPUT);
      pinMode(ledPin, OUTPUT);
      pinMode(sfx0Pin, OUTPUT);
      pinMode(sfx1Pin, OUTPUT);
      pinMode(sfx2Pin, OUTPUT);
      pinMode(sfx3Pin, OUTPUT);
      pinMode(sfx4Pin, OUTPUT);
      pinMode(sfx5Pin, OUTPUT);
      pinMode(sfx6Pin, OUTPUT);
      pinMode(sfx7Pin, OUTPUT);
      pinMode(sfx8Pin, OUTPUT);
      pinMode(volupPin, OUTPUT);
      pinMode(voldnPin, OUTPUT);
    
      // Turn everything OFF
      pwm.setPWM(servo9, 0, moonMin);
      digitalWrite(dmxPin, HIGH);
      for (int x = 1; x <= 23; x = x + 7) {
        dmxTx.set(x, data, 7);
      }
      dmxTx.begin();
      digitalWrite(neoPin, LOW);
      digitalWrite(ac1Pin, LOW);
      digitalWrite(ac2Pin, LOW);
      digitalWrite(ledPin, LOW);
      soundOff();
      delay(4000);                                          // Wait 4 seconds for PIR Module to go LOW
      digitalWrite(sfx0Pin, LOW);                           // Ambient Sound ON
    }
    
    void loop() {
      unsigned long currentMillis = millis();              // Check Time
      boolean pirState = digitalRead(pirPin);              // Check PIR Trigger
      if (pirState == HIGH) {                              // If PIR triggered, change showState to HIGH
        showState = HIGH;
        digitalWrite(ledPin, HIGH);
      }
      else {
        digitalWrite(ledPin, LOW);
      }
      if (showState == HIGH && delayState == HIGH) {
        digitalWrite(sfx0Pin, HIGH);                       // Ambient Sound OFF
        digitalWrite(sfx1Pin, LOW);                        // Play Paper Moon
        digitalWrite(ac1Pin, HIGH);                        // Black Lights ON
        if (moonState == LOW) {
          for (uint16_t moonPos = moonMin; moonPos <= moonMax; ++moonPos) {
            pwm.setPWM(servo9, 0, moonPos); // Test Servo
            delay(10);
          }
    
          // wait for song to end
          delay(5000); //test
    
          digitalWrite(ac1Pin, LOW);                        // Black Lights ON
          for (uint16_t moonPos = moonMax; moonPos <= moonMin; --moonPos) {
            pwm.setPWM(servo9, 0, moonPos); // Test Servo
            delay(10);
          }
          moonState = HIGH;
          digitalWrite(sfx1Pin, HIGH);                     // Paper Moon OFF
        }
    
        // Dance Show Starts Here
        digitalWrite(ac2Pin, HIGH);                       // Mirror Ball ON
        digitalWrite(neoPin, HIGH);                       // Neopixels ON
        playSong();                                       // Start Music
        if (currentMillis - previousServoMillis >= servoInterval) {
          previousServoMillis = currentMillis;
          playDmx();
          for (int x = 1; x <= 23; x = x + 7) {
            dmxTx.set(x, data, 7);
          }
          if (servoDirection == LOW) {
            uint16_t pulseLengthLow1 = random(servoMin, servoCenter);
            uint16_t pulseLengthLow2 = random(servoMin, servoCenter);
            pwm.setPWM(servo1, 0, pulseLengthLow1);
            pwm.setPWM(servo2, 0, pulseLengthLow2);
            pwm.setPWM(servo9, 0, pulseLengthLow2); // Test Servo
            servoInterval = getDanceStep();
            servoDirection = HIGH;
          }
          else {
            uint16_t pulseLengthHigh1 = random(servoCenter, servoMax);
            uint16_t pulseLengthHigh2 = random(servoCenter, servoMax);
            pwm.setPWM(servo1, 0, pulseLengthHigh1);
            pwm.setPWM(servo2, 0, pulseLengthHigh2);
            pwm.setPWM(servo9, 0, pulseLengthHigh2); // Test Servo
            servoInterval = getDanceStep();
            servoDirection = LOW;
          }
        }
    
        // Check for End of Show
        if (currentMillis - previousShowMillis >= showInterval) {
          previousShowMillis = currentMillis;
          previousDelayMillis = currentMillis;
          showState = LOW;                                              // Change STATE to Delay
          delayState = LOW;
          moonState = LOW;
          pwm.setPWM(servo1, 0, servoCenter);
          pwm.setPWM(servo2, 0, servoCenter);
          pwm.setPWM(servo9, 0, servoCenter);                           // Test Servo
          digitalWrite(neoPin, LOW);                                    // NeoPixels Off
          digitalWrite(ac2Pin, LOW);                                    // AC 2 OFF
          soundOff();                                                   // Turn off sound
          digitalWrite(sfx0Pin, LOW);                                   // Sound #0 ON - Scene 0
          ++songPick;                                                   // Advance Song List by 1
          if (songPick >= 9) {                                          // If >8, Rollover Song List
            songPick = 1;
          }
          showInterval = random(showMin, showMax);                      // Pick new show interval.
          delayInterval = random(delayMin, delayMax);                   // Pick new delay interval.
        }
      }
    
      if (currentMillis - previousDelayMillis >= delayInterval) {
        previousDelayMillis = currentMillis;
        delayState = HIGH;
      }
    }
    
    // Functions
    void soundOff() {
      digitalWrite(sfx0Pin, HIGH);
      digitalWrite(sfx1Pin, HIGH);
      digitalWrite(sfx2Pin, HIGH);
      digitalWrite(sfx3Pin, HIGH);
      digitalWrite(sfx4Pin, HIGH);
      digitalWrite(sfx5Pin, HIGH);
      digitalWrite(sfx6Pin, HIGH);
      digitalWrite(sfx7Pin, HIGH);
      digitalWrite(sfx8Pin, HIGH);
      digitalWrite(volupPin, HIGH);
      digitalWrite(voldnPin, HIGH);
    }
    
    void playSong() {
      switch (songPick) {
        case 1:
          digitalWrite(sfx1Pin, LOW);
          break;
        case 2:
          digitalWrite(sfx2Pin, LOW);
          break;
        case 3:
          digitalWrite(sfx3Pin, LOW);
          break;
        case 4:
          digitalWrite(sfx4Pin, LOW);
          break;
        case 5:
          digitalWrite(sfx5Pin, LOW);
          break;
        case 6:
          digitalWrite(sfx6Pin, LOW);
          break;
        case 7:
          digitalWrite(sfx7Pin, LOW);
          break;
        case 8:
          digitalWrite(sfx8Pin, LOW);
          break;
      }
    }
    
    void playDmx() {
      dmxPick = random(1, 11);
      switch (dmxPick) {
        case 1:
          data[7] = {255, 255, 0, 0, 0, 0, 0}; // Red
          break;
        case 2:
          data[7] = {255, 0, 255, 0, 0, 0, 0}; // Green
          break;
        case 3:
          data[7] = {255, 0, 0, 255, 0, 0, 0}; // Blue
          break;
        case 4:
          data[7] = {255, 255, 255, 255, 0, 0, 0}; // White
          break;
        case 5:
          data[7] = {255, 255, 255, 0, 0, 0, 0}; // Yellow
          break;
        case 6:
          data[7] = {255, 255, 0, 255, 0, 0, 0}; // Purple
          break;
        case 7:
          data[7] = {255, 0, 255, 255, 0, 0, 0}; // Cyan
          break;
        case 8:
          uint8_t data[7] = {255, 255, 255, 255, 0, 0, 0};
          break;
        case 9:
          uint8_t data[7] = {255, 255, 255, 255, 0, 0, 0};
          break;
        case 10:
          uint8_t data[7] = {255, 255, 255, 255, 0, 0, 0};
          break;
      }
    //  return data[7];
    }
    
    int getDanceStep() {
      intervalPick = random(1, 5);
      switch (intervalPick) {
        case 1:
          danceStep = 125;
          break;
        case 2:
          danceStep = 250;
          break;
        case 3:
          danceStep = 375;
          break;
        case 4:
          danceStep = 500;
          break;
      }
      return danceStep;
    }

  22. #22
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    9,403
    Quote Originally Posted by jparisse View Post
    OK... It is 12AM and I have to go to sleep....
    For some reason I can't figure out how an array assignment that works standalone does not work as a function.
    I am getting a error that reads:

    Holiday_Show_Controller: In function 'void playDmx()':

    Holiday_Show_Controller:306: error: cannot convert '<brace-enclosed initializer list>' to 'uint8_t {aka unsigned char}' in assignment

    data[7] = {255, 255, 0, 0, 0, 0, 0}; // Red
    You're trying to assign all the values to one single element data[7]
    Last edited by Frank B; 10-14-2021 at 09:02 AM.

  23. #23
    Thanks Frank.
    The same statement works in the setup section:
    [CODE]
    // DMX Variables
    uint8_t data[7] = {0, 128, 128, 128, 0, 0, 0};
    [CODE]
    Any suggestions on how to fix?

  24. #24
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    9,403
    One way is:
    Code:
     const uint8_t xyz[7] = {0, 128, 128, 128, 0, 0, 0};
     memcpy(data, xyz, sizeof(data));
    Or, you can make data a pointer to an array and let it point to the new array (is faster, but i'd not recommend it for beginners) - everything should be const and global, then.

  25. #25
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    9,403
    If your really want to use a pointer (which is better but more difficult)

    Code:
    typedef uint8_t  arr7[7] ;
    
    arr7 white = {0, 128, 128, 128, 0, 0, 0};
    arr7 green = {255, 0, 255, 0, 0, 0, 0};
    
    arr7 *data = &white;
    
    and later just 
    
    data = &green;

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •