Open davepl opened 1 year ago
I will look into this.
@robertlipe Very cool! I just got mine to connect to my home network. I had to do a full reset of my home router to get it to work after hours of reading the code. I really like the UI, however, I think Dave wants IR remote capability too. I will start working on it in the C++ code.
Welcome! IR support is definitely there. I use it frequently. I have some work pending in that code that I'll clean up and submit some day.
It's odd that even the 44 key remote don't really have "obvious" bindings for some of the things I think are obvious. I'm about to put a sticker on mine and rename some of the dedicated color keys to things I need more.
I agree on the key bindings and labels. I'd like to see what you have already done so I don't duplicate your work!
I just don't need a "peach" key. Most of what I was stabbing at was to make more general framework for dealing with remotes that aren't an exact match of those. Even within the 44 key models, I have units with the same codes and different labels and different labels and different (and often conflicting, of course) codes. The labels for brightness and speed are swapped on two of the 44's within reach right now
The most immediately valuable thing is to fix the key44 case to actually build. In the tree I can find right now, I clearly just stabbed at it and fled, but as a hint to get you going, key44 is "just" suffering from neglect.
-#define IR_BPlus 0xFF3AC5 // -#define IR_BMinus 0xFFBA45 // +#define IR_BPLUS 0xFF3AC5 //^M +#define IR_BMINUS 0xFFBA45 //^M
adding some missing definitions, but not mapping them to anything useful:
+#define IR_SMOOTH -1 //^M +#define IR_STROBE -1 //^M +#define IR_FADE -1 //^M
And a note that some 44's do different things with B12-B16:
@@ -145,6 +148,7 @@ RemoteColorCodes[] = { IR_B10, CRGB(255, 255, 000), 64 }, { IR_B11, CRGB(000, 255, 255), 144 }, { IR_B12, CRGB(255, 000, 255), 224 }
I have probably 10-15 dumb little remotes that came with various strings, so when I get motivated, it'll be to make that whole thing a little more flexible and to submit picture of each one and map out the keys ssupported by each. Maybe tables shouldn't be compiled in constants at all, but something where we can interact with the user ("Press brightness down") and learn what the user - sensibly - sees as the buttons, even though the hardware probably all rolled off the same assembly line and they just have different membranes over hte top..
The more intresting side (to me) is what we were discussing above and fleshing out some kind of a common broadcast/listener scheme that ties the remotes AND the network interface (why can't your web browser be the remote?) and delivering those notifications on event changes down to the individual effects.
It's one of sevreal things inside this code that I've poked at and have some ideas on that's just competing for my attention and time. Right now, I'm working on getting a load of new effects stabilized and landed.
It'll be good to have some more C++ folks around. I saw another wave of C++ and Web devs are coming online soon.
On Thu, Aug 10, 2023 at 4:07 PM Andrew Smilie @.***> wrote:
I agree on the key bindings and labels. I'd like to see what you have already done so I don't duplicate your work!
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1673921347, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3Z3BLDYFAL3WNZLC7TXUVEPXANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
Thanks for the great ideas to get me going, and I am glad to help out as much as I can. I love working with embedded systems because I like how you are both designing hardware and software at the same time. I just ordered a 44 key remote to test the code with a 44 key remote. I somehow have been working on an old copy of the git repo. However, this helped me spend some time getting up to speed on this codebase.
Personally, I like flat text files to store settings. they are easy to read in C++ and can be manually modified.
I think we should read key mappings from a IRRemoteSettings.ini text file during boot. This way someone could personalize their remote without having to change and compile the code, and it keeps things as simple as possible.
To expand further, I think it is possible (only if you have a LED matrix panel) to have an effects page that displays the IR code for the last key pressed on the remote. This could be used to help someone map out their remote. I am also sure we could do this mapping process in an automated way using the matrix display and writing the mapping file on the fly. From a procedural point of view, the display would show your current key for 2-5 seconds and then ask the user what key you would like the current key to go, and update the text file to store it.
I think tying the webserver and the IR together could be done, however, what if a user doesn't want a webserver? What if they are installing this in a location which can't broadcast WiFi (hospital)? Personally, I would like to keep these separate for these reasons. I come from a background writing code while working in rooms without outside internet access, so I may bring a different perspective. I have to rely on my memory, books, or the built-in help tools provided with whatever IDE I am using :) The late eighty's never left the building!
I also would like to develop a brightness box which shows up on the mesmerizer to indicate the current brightness level. It would be overlaid on top of the current effect, and would time out after a few seconds of inactivity.
I will spend some time this weekend taking a look at this code.
you are both designing hardware and software at the same time. I just ordered a 44 key remote to test the code with a 44 key remote. I somehow
I have least four different 44 key remotes. They send different codes. :-( I probably have some duplicates of the super generic ones, too.
I think the WLED page lists a bunch of models and includes their IR codes.
Just a few days ago, I got a fancy component tester (not fancy) that includes an IR reader that tells you the code of any key. It doesn't really do anything that a printf in that code doesn't tell me, but it saves me a compile and a peek into the debug log.
I think we should read key mappings from a IRRemoteSettings.ini text file during boot. This way someone could personalize their remote without
Ideally, someone could edit it from the web interface, and that's hard with an .ini
pressed on the remote. This could be used to help someone map out their remote. I am also sure we could do this mapping process in an
Yes, it's clear athat even as many as I have, there are more. Self-serve will be key. It's not out out of the question for someone to take their VCR remote and use that if they're willing to remember that volume up == effect up and channel up == speed up and so on. I don't particularly want to accept a .ini file for that mapping, but I'd like to make it possible for someone to do that.
I think tying the webserver and the IR together could be done, however, what if a user doesn't want a webserver? What if they are installing this in
I think the web interface will be a primary way to administer these for a lot, if not most, people. I could be wrong. The tango between remote, API, and web/mobile interface is one I never got my head really around. In the discussion there's a thread where Rutger had strong opinions on how they should work but I remember getting distracted before really coming back to it.
I also would like to develop a brightness box which shows up on the mesmerizer to indicate the current brightness level. It would be overlaid on top of the current effect, and would time out after a few seconds of inactivity.
Interesting idea. FWIW, I've never needed a 0-32 brightness bar because, well, every pixel is a brightness bar. But I like the idea of an overlay for other things.
I think there's a lot to explore here. Welcome and have fun!
RJL
Message ID: <PlummersSoftwareLLC/NightDriverStrip/issues/284/1684553012@ github.com>
For the two most common remotes (You know, the $.34 ones https://www.aliexpress.us/item/3256805385450409.html on Ali and their 44 pin siblings...) I'd like the user to be able to pick if they have a common 24 or 44 from the web interface, let that write a setting and have an internal table that we search for those models. Sure, the 'overloaded TiVo remote' case is clever, but being easy for the remotes that 90% of the people will actually use counts for a lot, too.
(I've given the remote thing an unhealthy amount of thought to have not actually coded anything for it...it was going to be in my next 2-3 project, though. I've even thought about what a long press might look like in software...)
On Fri, Aug 18, 2023 at 7:01 PM Robert Lipe @.***> wrote:
you are both designing hardware and software at the same time. I just ordered a 44 key remote to test the code with a 44 key remote. I somehow
I have least four different 44 key remotes. They send different codes. :-( I probably have some duplicates of the super generic ones, too.
I think the WLED page lists a bunch of models and includes their IR codes.
Just a few days ago, I got a fancy component tester (not fancy) that includes an IR reader that tells you the code of any key. It doesn't really do anything that a printf in that code doesn't tell me, but it saves me a compile and a peek into the debug log.
I think we should read key mappings from a IRRemoteSettings.ini text file during boot. This way someone could personalize their remote without
Ideally, someone could edit it from the web interface, and that's hard with an .ini
pressed on the remote. This could be used to help someone map out their remote. I am also sure we could do this mapping process in an
Yes, it's clear athat even as many as I have, there are more. Self-serve will be key. It's not out out of the question for someone to take their VCR remote and use that if they're willing to remember that volume up == effect up and channel up == speed up and so on. I don't particularly want to accept a .ini file for that mapping, but I'd like to make it possible for someone to do that.
I think tying the webserver and the IR together could be done, however, what if a user doesn't want a webserver? What if they are installing this in
I think the web interface will be a primary way to administer these for a lot, if not most, people. I could be wrong. The tango between remote, API, and web/mobile interface is one I never got my head really around. In the discussion there's a thread where Rutger had strong opinions on how they should work but I remember getting distracted before really coming back to it.
I also would like to develop a brightness box which shows up on the mesmerizer to indicate the current brightness level. It would be overlaid on top of the current effect, and would time out after a few seconds of inactivity.
Interesting idea. FWIW, I've never needed a 0-32 brightness bar because, well, every pixel is a brightness bar. But I like the idea of an overlay for other things.
I think there's a lot to explore here. Welcome and have fun!
RJL
Message ID: <PlummersSoftwareLLC/NightDriverStrip/issues/284/1684553012@ github.com>
@robertlipe I too have been thinking too much about remotes! The generic 44 key remote I ordered showed up yesterday, so I will look at it this week when I get a chance.
That is a great idea to use the web interface to select and set up the IR remote. I am going to need to study more on how the webserver code and API works. From what I remember browsing through the code and comments, I believe the API uses REST calls. This is way out of my comfort zone writing C and C++ data collection and analysis code and will be a good learning experience!
Right now, the bottom side of src/remotecontrol.cpp mostly sends commands to include/effectmanager.h. That's how it achieves "next effect" and such.
There is a REST_API.md in the root directory that's a good overview of how that works.
Someone once said that learning is like exercising. You should just slightly stretch your limits. Don't tear anything, but a little bit of hurting is OK. :-)
RJL
On Wed, Aug 23, 2023 at 4:26 AM Andrew Smilie @.***> wrote:
@robertlipe https://github.com/robertlipe I too have been thinking too much about remotes! The generic 44 key remote I ordered showed up yesterday, so I will look at it this week when I get a chance.
That is a great idea to use the web interface to select and set up the IR remote. I am going to need to study more on how the webserver code and API works. From what I remember browsing through the code and comments, I believe the API uses REST calls. This is way out of my comfort zone writing C and C++ data collection and analysis code and will be a good learning experience!
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1689608191, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3ZYNVBBFQ237UYFOTDXWXEFRANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
Thanks! I have been playing with the REST API. There are some very interesting things that can be done with this.
I didn't understand school until I realized it is the gymnasium for your brain. I was a junior in high school when I realized this (27 years ago), and it took me to college with a masters degree in electrical and computer engineering. I still take graduate school classes to this day to keep me up to date and keep the brain sharp. The last class I took was on Inertial Navigation and I was introduced formally to rotation matrices, Euler angles and quaternions. It is amazing what the MEMS IMU in your phone can do, especially when combined with a GNSS source using a Kalman filter!
Don’t forget the ESP32 modules like the M5 series have the MPU6886 IMU, so you could play with it right on-chip!
On Aug 27, 2023, at 12:46 PM, Andrew Smilie @.***> wrote:
Thanks! I have been playing with the REST API. There are some very interesting things that can be done with this.
I didn't understand school until I realized it is the gymnasium for your brain. I was a junior in high school when I realized this (27 years ago), and it took me to college with a masters degree in electrical and computer engineering. I still take graduate school classes to this day to keep me up to date and keep the brain sharp. The last class I took was on Inertial Navigation and I was introduced formally to rotation matrices, Euler angles and quaternions. It is amazing what the MEMS IMU in your phone can do, especially when combined with a GNSS source using a Kalman filter!
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1694746045, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4HCF7U4PSGPEPUNMAKGYLXXOPXRANCNFSM6AAAAAAYMW447U. You are receiving this because you were assigned.
I don't think it's on the ESP32 modules or on chip, is it, Dave? I think it's on some dev boards; external to the "Espressif part". (It may sound pedantic until he spends time digging through the Espressif docs trying to find I have a couple of the 6886's and 6050's within reach, in fact. They're plain ole SPI/I2C parts (easy to interface for anyone familiar with electronics; trivial for someone with a master's in EE) and easy to bolt onto anything supporting this code. I'm really loving the ESP32-S3 boards with high exposed pin counts (44 GPIOs or something; almost all of which are attached to a giant multiplexor for easy remapping) for hardware hacking.
Andrew, if you yearn for GNSS + Kalman hacking, I could use a hand with my other hobby project: https://github.com/GPSBabel/gpsbabel/blob/robertlipe-kalman/kalmanfilter.cc
On Sun, Aug 27, 2023 at 3:12 PM David W Plummer @.***> wrote:
Don’t forget the ESP32 modules like the M5 series have the MPU6886 IMU, so you could play with it right on-chip!
- Dave
On Aug 27, 2023, at 12:46 PM, Andrew Smilie @.***> wrote:
Thanks! I have been playing with the REST API. There are some very interesting things that can be done with this.
I didn't understand school until I realized it is the gymnasium for your brain. I was a junior in high school when I realized this (27 years ago), and it took me to college with a masters degree in electrical and computer engineering. I still take graduate school classes to this day to keep me up to date and keep the brain sharp. The last class I took was on Inertial Navigation and I was introduced formally to rotation matrices, Euler angles and quaternions. It is amazing what the MEMS IMU in your phone can do, especially when combined with a GNSS source using a Kalman filter!
— Reply to this email directly, view it on GitHub < https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1694746045>, or unsubscribe < https://github.com/notifications/unsubscribe-auth/AA4HCF7U4PSGPEPUNMAKGYLXXOPXRANCNFSM6AAAAAAYMW447U>.
You are receiving this because you were assigned.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1694751597, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3YNE7UF4QETCHN3PUDXXOS3LANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
It’s inside the orange housing, and listed on the label on the bottom. How or why they do it one way or the other is a hardware problem :-)
The S3 can also act like a flash drive when plugged in, right? That’s a cool feature! I didn’t know there were high pin count versions. I heard somewhere that it doesn’t do DMA, though, which is needed for the HUB75 matrix. Not 100% certain though.
On Aug 27, 2023, at 2:01 PM, Robert Lipe @.***> wrote:
I don't think it's on the ESP32 modules or on chip, is it, Dave? I think it's on some dev boards; external to the "Espressif part". (It may sound pedantic until he spends time digging through the Espressif docs trying to find I have a couple of the 6886's and 6050's within reach, in fact. They're plain ole SPI/I2C parts (easy to interface for anyone familiar with electronics; trivial for someone with a master's in EE) and easy to bolt onto anything supporting this code. I'm really loving the ESP32-S3 boards with high exposed pin counts (44 GPIOs or something; almost all of which are attached to a giant multiplexor for easy remapping) for hardware hacking.
Andrew, if you yearn for GNSS + Kalman hacking, I could use a hand with my other hobby project: https://github.com/GPSBabel/gpsbabel/blob/robertlipe-kalman/kalmanfilter.cc
- I'm secure enough in my programming chops to admit that the math in it makes my head hurt. I "just" needed a way to get rid of the tuned hardcoded constants and make it generally flexible enough to automatically throw out those four consecutive points that zing you from here to Cuba to Null Island and back in four second span.
On Sun, Aug 27, 2023 at 3:12 PM David W Plummer @.***> wrote:
Don’t forget the ESP32 modules like the M5 series have the MPU6886 IMU, so you could play with it right on-chip!
- Dave
On Aug 27, 2023, at 12:46 PM, Andrew Smilie @.***> wrote:
Thanks! I have been playing with the REST API. There are some very interesting things that can be done with this.
I didn't understand school until I realized it is the gymnasium for your brain. I was a junior in high school when I realized this (27 years ago), and it took me to college with a masters degree in electrical and computer engineering. I still take graduate school classes to this day to keep me up to date and keep the brain sharp. The last class I took was on Inertial Navigation and I was introduced formally to rotation matrices, Euler angles and quaternions. It is amazing what the MEMS IMU in your phone can do, especially when combined with a GNSS source using a Kalman filter!
— Reply to this email directly, view it on GitHub < https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1694746045>, or unsubscribe < https://github.com/notifications/unsubscribe-auth/AA4HCF7U4PSGPEPUNMAKGYLXXOPXRANCNFSM6AAAAAAYMW447U>.
You are receiving this because you were assigned.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1694751597, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3YNE7UF4QETCHN3PUDXXOS3LANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1694761026, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4HCF6RVTPMEAP25DQUB6LXXOYRNANCNFSM6AAAAAAYMW447U. You are receiving this because you were assigned.
It's hair-splitting, for sure, but we are in the land of precision. Espressif makes three thingies that appear in our lives. The chips https://www.espressif.com/en/products/socs - the black square things with all the legs, like "ESP32-S3" - the modules https://www.espressif.com/en/products/modules, which are the postage-stamp sized thing with a metal shield on them. These are tiny computers in theri own right, providing the chips with the bare support circuitry they need like crystals and supporting oscillators and - importantly - a highly tuned RF environment that usually includes the antennas for WiFi and BT and is all in a package that can be FCC certified so that a product (like Mesmerizer) probably doesn't have to be. This makes for a nice border fence for the 200+Mhz stuff that requires "real" engineering (RF is HARD) and the kind of glorified breadboarding that makes a product like M5Stick or Mesmerizer. Espressif also makes devkits , which are the modules slapped down onto boards that also bundle accessories ike USB serial bridges, Displays, or other SPI/I2C gizmos, additional serial flash, buttons or like. These products are closer to the M5 Stacks or Arduino Feathers that provide a DIP package or other thing ready to drop onto a breadboard.
So, in terms of integration, the progression might be "ESP32-S3" (chip...I'm leaving off the part numbers of the precise packaging, etc) which goes into a ESP32-S3-WROOM-1 https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf or ESP32-S3-MINI-1 https://www.espressif.com/sites/default/files/documentation/esp32-s3-mini-1_mini-1u_datasheet_en.pdf (module) that can land in a product like a Mesmerizer or a module like full development board like a ESP32-S3-DevKitC-1 https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html
I have this code running on an ESP32S3 with 8MB of SPI and 16 of Flash - that's why I was pushing the bounds of partitioning recently and trying to start conversations about better filesystems.
➜ NightDriverStrip git:(fix_buttons) ✗ grep 8v platformio.ini [env:esp32-s3-devkitc-1-n16r8v-demo] board = esp32-s3-devkitc-1-n16r8v .
The S3 can also act like a flash drive when plugged in, right? That’s a cool feature!
Yes. Because there is a "real" USB controller integrated into the chip, it can pretend to be a USB keyboard, flash drive (e.g. you can be FAT32 and U2F and update firmware by drag and dropping a .bin to the 'drive') or pretend to be a keyboard for simulated test environments or whatever. The other nice thing i that it can be a UART, saving the external cost of a CP2102 or CH340 or whatever, easily offsetting the slightly higher cost of the S3. Oh, that means it also does JTAG over a second interface with no additional hardware, though I've used it only trivially. (I've used the sister function on ESP32-C3 a lot. Works great. Source level single stepping through boot and interrupt handlers is nifty!)
I heard somewhere that it doesn’t do DMA, though, which is needed for the HUB75 matrix. Not 100% certain though.
It has awesome DMA. Like all the Espressif parts, it has goofy rules about being able to DMA from memory that's sitting on an external SPI RAM chip, but even that's possible. It can do a fast copy https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/system/async_memcpy.html (like probably a graphics buffer flip), but can't DMA external memory very well - but that's true on all the ESP32's.
There are several ways to drive the HUB75. It's on my short list to trawl through the code (it's "just" wrapping one of the smartmatrix forks, right?) If using Faptasticks's https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA Smartmatrix, ESP32 S3 is explicitly called out as supported. I think Marc Merlin's smartmatrix https://github.com/marcmerlin/SmartMatrix_GFX fork also does it. I can't recall if Adafruit's https://github.com/adafruit/Adafruit_Protomatter own does - they tend to be very Arduino-centric and like to suffer on 8-bit processors.
I have multiple S3 boards, a bag of I2S level shifters, sockets, and a couple of full-height HUB75 boards in a stack waiting for me to take that dare. Selfishly, I'd like the result to be compatible enough with Mesmerizer AND USE_2812 that I can use the same hardware to drive either form of LED, though perhaps not at the same time. I just haven't taken apart the lower levels of matrixgfx to look at pin numbers, whether I2S, RMT, or bit-banging is used, etc.
I'm very interested in pursuing that. if you'd like to talk about Mesmerizer on ESP32-S3, buzz me. My scope and soldering iron are itching.
Message ID: <PlummersSoftwareLLC/NightDriverStrip/issues/284/1694794270@ github.com>
It’s inside the orange housing, and listed on the label on the bottom. How or why they do it one way or the other is a hardware problem :-) The S3 can also act like a flash drive when plugged in, right? That’s a cool feature! I didn’t know there were high pin count versions. I heard somewhere that it doesn’t do DMA, though, which is needed for the HUB75 matrix. Not 100% certain though. - Dave …
@davepl Dave, I have played around with the IMU a little bit after getting my hands on the M5Stick. The only way I knew it had one is because of the demo code. I didn’t know about the flash drive - that’s really cool.
I was thinking about building a LED light ball with a M5 in the middle that uses the IMU to keep the lights in a fixed position no matter how it spins. It could even display text as you toss it around! The NightDriver library would work well for this. How about an audio spectrum analyzer you can toss around with your friends?
@robertlipe
Andrew, if you yearn for GNSS + Kalman hacking, I could use a hand with my other hobby project: https://github.com/GPSBabel/gpsbabel/blob/robertlipe-kalman/kalmanfilter.cc - I'm secure enough in my programming chops to admit that the math in it makes my head hurt. I "just" needed a way to get rid of the tuned hardcoded constants and make it generally flexible enough to automatically throw out those four consecutive points that zing you from here to Cuba to Null Island and back in four second span.
Robert,
I will definitely check this project out, and see if I can assist you with the Kalman filter. It may require me to write down all of the equations being solved and double check the math. This absolutely can get complicated quickly! If you accidentally rotate out of order, you can get stuck forever. I will have some time this week after work and this weekend to check it out.
Thanks!
Cool thoughts! Maybe it should be Always Blue https://letsplayadrinkinggame.com/blog/always-blue-game-from-silicon-valley/ from a well known show https://www.youtube.com/watch?v=ElJe5M54brI. My own electronics projects are definitely too fragile to be tossed around, so I'd admire this.
GPSes have gotten a lot better in recent years and tend to take out their own garbage points these days instead of just making ^$%$^&*% up. My thinking was that we know time (usually) so we could have some long-running concept of speed via successive points in the polyline of points and see the whacked out "oh, you suddenly accelerated from hiking to supersonic ... and back" and just toss out the zingers while maintaining the overall shape of the polyline. Realistically, futzing with our simplify and and track filters, we can often get most of the bad data. Buzz me offline (or online, but over there) if you're serious about helping out.
On Mon, Aug 28, 2023 at 6:39 PM Andrew Smilie @.***> wrote:
It’s inside the orange housing, and listed on the label on the bottom. How or why they do it one way or the other is a hardware problem :-) The S3 can also act like a flash drive when plugged in, right? That’s a cool feature! I didn’t know there were high pin count versions. I heard somewhere that it doesn’t do DMA, though, which is needed for the HUB75 matrix. Not 100% certain though. - Dave … <#m1299657669412454402>
@davepl https://github.com/davepl Dave, I have played around with the IMU a little bit after getting my hands on the M5Stick. The only way I knew it had one is because of the demo code. I didn’t know about the flash drive - that’s really cool.
I was thinking about building a LED light ball with a M5 in the middle that uses the IMU to keep the lights in a fixed position no matter how it spins. It could even display text as you toss it around! The NightDriver library would work well for this. How about an audio spectrum analyzer you can toss around with your friends?
@robertlipe https://github.com/robertlipe
Andrew, if you yearn for GNSS + Kalman hacking, I could use a hand with my other hobby project: https://github.com/GPSBabel/gpsbabel/blob/robertlipe-kalman/kalmanfilter.cc
- I'm secure enough in my programming chops to admit that the math in it makes my head hurt. I "just" needed a way to get rid of the tuned hardcoded constants and make it generally flexible enough to automatically throw out those four consecutive points that zing you from here to Cuba to Null Island and back in four second span.
Robert,
I will definitely check this project out, and see if I can assist you with the Kalman filter. It may require me to write down all of the equations being solved and double check the math. This absolutely can get complicated quickly! If you accidentally rotate out of order, you can get stuck forever. I will have some time this week after work and this weekend to check it out.
Thanks!
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1696561212, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3Z2CS7YBTHWW2LJEVLXXUT3HANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
I imagine it’s not sensitive enough, but it were, and you could do dead reckoning based on the IMU, then you could put the M5 in a position, press the button to “mark” it, and then move to another spot and have it tell you the measurement between them. That’d be a cool use.
Like I said, I doubt it’s sensitive enough. But if it is, maybe I just invented something cool! :-)
On Aug 28, 2023, at 8:16 PM, Robert Lipe @.***> wrote:
Cool thoughts! Maybe it should be Always Blue https://letsplayadrinkinggame.com/blog/always-blue-game-from-silicon-valley/ from a well known show https://www.youtube.com/watch?v=ElJe5M54brI. My own electronics projects are definitely too fragile to be tossed around, so I'd admire this.
GPSes have gotten a lot better in recent years and tend to take out their own garbage points these days instead of just making ^$%$^&*% up. My thinking was that we know time (usually) so we could have some long-running concept of speed via successive points in the polyline of points and see the whacked out "oh, you suddenly accelerated from hiking to supersonic ... and back" and just toss out the zingers while maintaining the overall shape of the polyline. Realistically, futzing with our simplify and and track filters, we can often get most of the bad data. Buzz me offline (or online, but over there) if you're serious about helping out.
On Mon, Aug 28, 2023 at 6:39 PM Andrew Smilie @.***> wrote:
It’s inside the orange housing, and listed on the label on the bottom. How or why they do it one way or the other is a hardware problem :-) The S3 can also act like a flash drive when plugged in, right? That’s a cool feature! I didn’t know there were high pin count versions. I heard somewhere that it doesn’t do DMA, though, which is needed for the HUB75 matrix. Not 100% certain though. - Dave … <#m1299657669412454402>
@davepl https://github.com/davepl Dave, I have played around with the IMU a little bit after getting my hands on the M5Stick. The only way I knew it had one is because of the demo code. I didn’t know about the flash drive - that’s really cool.
I was thinking about building a LED light ball with a M5 in the middle that uses the IMU to keep the lights in a fixed position no matter how it spins. It could even display text as you toss it around! The NightDriver library would work well for this. How about an audio spectrum analyzer you can toss around with your friends?
@robertlipe https://github.com/robertlipe
Andrew, if you yearn for GNSS + Kalman hacking, I could use a hand with my other hobby project: https://github.com/GPSBabel/gpsbabel/blob/robertlipe-kalman/kalmanfilter.cc
- I'm secure enough in my programming chops to admit that the math in it makes my head hurt. I "just" needed a way to get rid of the tuned hardcoded constants and make it generally flexible enough to automatically throw out those four consecutive points that zing you from here to Cuba to Null Island and back in four second span.
Robert,
I will definitely check this project out, and see if I can assist you with the Kalman filter. It may require me to write down all of the equations being solved and double check the math. This absolutely can get complicated quickly! If you accidentally rotate out of order, you can get stuck forever. I will have some time this week after work and this weekend to check it out.
Thanks!
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1696561212, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3Z2CS7YBTHWW2LJEVLXXUT3HANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1696706228, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4HCFZQ5LHUDAE442DPBTTXXVNHFANCNFSM6AAAAAAYMW447U. You are receiving this because you were mentioned.
I didn’t read all of the comments in this thread but skimmed enough to see the general direction of conversation. Last week I got my first esp32 board (Heltec WiFi kit v3) and some LEDs. Once I got NightDriver running and configured, I wanted to play around with remote functionality. An IR receiver diode was sourced from a dead DVD player. I changed the code for the 44 key remote to “true.” We all know how that didn’t work. Long story: I got all of the key codes for my remote mapped, declared some stuff to make the compiler happy, and defined colors for each button.
This lead me to discover that when a strip should be filled with a single color, it was failing. Turns out an effect was being added instead of the color being drawn. I suggest for general use this be changed. It iterates the color array and passes the value, but calls a different function.
I do have a suggestion that I would gladly try to help with. It’s my opinion that instead of iterating the color array to see if the button pressed matches an entry in the array, each button gets it own dedicated else if section. As inelegant and ugly as that will be, it would allow tinkerers to define whatever action they want. They can comment out the line that would fill the color and make it do whatever they want. It would, however, have a lot of seemingly redundant calls to the color fill method for 12-16 buttons. It makes me sick thinking about it, but would give the greatest flexibility for customization.
I also want to get the functionality of each button working as intended. So brightness would go up or down. The rgb colors could be adjusted on the fly. Fade 3 would loop through three pre-defined effects in a loop with a gentle fade between them. You get the picture.
Would such a contribution to the code be desired? I have 0 experience with C++ besides tinkering with NightDriver in the last week, but think I can manage well enough. It might take me a month or two with my schedule. I suppose I could just fork and do a pull request later and see if it gets accepted.
A major caveat is that whatever remote a person chooses, they will probably need to capture the key codes themselves. That’s easy enough with VS Code and console monitoring. If someone is tinkering at this level they should be able to handle that.
One last thing that’s related: how does one programmatically change the brightness of the LEDs? I’ve tried to make sense of the code to see what I could do to “dim” the LEDs but have come up short. I’ve only seen where the max brightness is calculated based on the max power draw. This is more for eye comfort while coding and getting things to work.
Welcome!
My connectivity from my cabin in the mountsains (boo hoo :-) is too poor to try to hand over a couple of patches I had. It's a good area for someone that's a reasonably meticulous programmer, but not necessarily a C++ whiz. Im on a fone and typing from memory, so please forgive misdirections.
When the 44-key module was copied, it was clearly never tested in this code. I assume the syntax fixes are obvious enough, but we have two mutually exclusive things (use_key_22 and use_key_44 or something) that are each independently defined and that's not going to scale. It should be an enum... or something.
There are many many more remotes than ust "24" and "44". There are many different key caps and code combinations even within those physical configurations. Ideally, some clever internal abstraction to let people make their own mappings would be nifty. Whether that's an easily edited source txt file, a config text file on the device, a JSON thingy edited by WebUI (that we don't have...) or a network configured file or what isn't really clear right now. Going with the theme of simplicity, though, I think we can do better than "24 key that exactly matches Dave's" and "44 key that doesn't even compile".
Without even looking it up, IR receivers are KY-022 and in bulk, cost a fraction of a postage stamp. Repurposing one from a CD player is awesome! I don't know if either of these are materially different than the one in the recommended school supplies list.
There are APIs for changing brightness for both HUB and 281x, but they're annoyingly different. IMO, we can hide that somewhere near the border of effectsmgr.
There are a few effects that take direction (or even hints) for the dozen color buttons, but most of them don't. I'm not sure which end of that rope to pull on. Fix more effects to take color hints or "steal" those extra buttons for something that we might be able to make consistent across remote models?
The data structure I think you want to MAP key codes to actions in C++ is called std::map. You have a table that MAPS key codes into enum values that are internal codes for actions. So code 0x1234 might map to internal code B+/B- which has a numeric value of "5" or something. Take the idea used for color mapping further and up into the actions so it's almost a switch. (It's probably a std::find or something...)
Once I escape remote.h and found remote.cpp and effectsmgr (file names are wrong) some of the more exotic button responses became easier to find and use.
Though we need a bright up and down, IMO, and have buttons labeled bright up and down, those buttons seem to be used for effects prev/next. It seemed weird, IIRC. I hadn't decided whether to fight that or embrace it and look for a different scheme that made more sense when I got distracted/discouraged. It seems like there's some other fundamental button that's mapped, uhm, counterintuitively. Do we need backward compatibility modes for these or can we really not ever change Brt+ to actually mean Brt+ instead of "Next effect"?
Effectsmgr (?) main(?) or something already has code to handle fades between effects. Sadly, many effects (incl. many with my fingerprints) do a clear() in the Init() method which tramples on that. TBF, this "saves" effects from smearing crumbs left from prior effects. It just needs some love to make smooth xsitions work.
IMO, a good web ui dev could help move the "i have a random remote and none of the buggons work" problem ball pretty far. We might even want a special "effect" for HUB75 that displays the received code in hex. Slightly more civilized than requiring a serial termainal and cable, but almost a guarenteed tech support ticket generator because it'll be alien to MOST people. I do think we can go a long way without touching web UI for now.
All opinions/guidance are my own and may or may not reflect those of house management. I've put more than a bit of thought into this area, but never really leaned into "fixing" it once and for all, instead embracing recreating almost (almost!) the same dumb patch every time I touched a fork since most of my remotes are 44's.
I'll be back in the middle of the week. If you and/or Andrew want/need a partner or mentor, I think I'm mostly available.
On Sun, Sep 10, 2023 at 11:15 PM revision29 @.***> wrote:
I didn’t read all of the comments in this thread but skimmed enough to see the general direction of conversation. Last week I got my first esp32 board (Heltec WiFi kit v3) and some LEDs. Once I got NightDriver running and configured, I wanted to play around with remote functionality. An IR receiver diode was sourced from a dead DVD player. I changed the code for the 44 key remote to “true.” We all know how that didn’t work. Long story: I got all of the key codes for my remote mapped, declared some stuff to make the compiler happy, and defined colors for each button.
This lead me to discover that when a strip should be filled with a single color, it was failing. Turns out an effect was being added instead of the color being drawn. I suggest for general use this be changed. It iterates the color array and passes the value, but calls a different function.
I do have a suggestion that I would gladly try to help with. It’s my opinion that instead of iterating the color array to see if the button pressed matches an entry in the array, each button gets it own dedicated else if section. As inelegant and ugly as that will be, it would allow tinkerers to define whatever action they want. They can comment out the line that would fill the color and make it do whatever they want. It would, however, have a lot of seemingly redundant calls to the color fill method for 12-16 buttons. It makes me sick thinking about it, but would give the greatest flexibility for customization.
I also want to get the functionality of each button working as intended. So brightness would go up or down. The rgb colors could be adjusted on the fly. Fade 3 would loop through three pre-defined effects in a loop with a gentle fade between them. You get the picture.
Would such a contribution to the code be desired? I have 0 experience with C++ besides tinkering with NightDriver in the last week, but think I can manage well enough. It might take me a month or two with my schedule. I suppose I could just fork and do a pull request later and see if it gets accepted.
A major caveat is that whatever remote a person chooses, they will probably need to capture the key codes themselves. That’s easy enough with VS Code and console monitoring. If someone is tinkering at this level they should be able to handle that.
One last thing that’s related: how does one programmatically change the brightness of the LEDs? I’ve tried to make sense of the code to see what I could do to “dim” the LEDs but have come up short. I’ve only seen where the max brightness is calculated based on the max power draw. This is more for eye comfort while coding and getting things to work.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1713095116, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3YA2NXB5GCZ5RBFCULXZZ65DANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
@revision29 , I will absolutely be here to bounce ideas and code off of me. And @robertlipe, it would be great to have you as a mentor!
There are a few things about the remote functionality I don’t care for fight now, like the brightness up/down changing effects. I think these buttons should only do brightness things. I also want to have a user definable IR button map that can be modified using the Web interface or a flat text file. We can discuss this further in Dave’s Garage discord server.
Thanks for the feedback and following up. Life has gotten in the way and I have not responded. I had spent a good deal of time writing up a response and the wrong swipe on my trackback triggered my browser to go back in history and it trashed my comment without being so kind as to give me a warning. I will follow up later. The short version is that I have significantly reworked the remote code to have a user remote object with a vector of user define button objects. My underlying thought process is that one day this code will need to be compatible with having a web interface setting / changing these.
Anyway, later today I will retype my comment with code examples in an external markdown editor and then paste in the comment box so that Safari does not eat my comment again. That's what I get for trying to format my code for markdown in a web browser.
Here is a followup to demonstrate what I have done. Keep in mind, this is my first dabbling with C++. I have worked with PHP, JavaScript, SwiftUI, MySQL, and a small amount of perl. I can google and consult stackoverflow like most every other programmer. There are some optimizations to be made once I get more familiar with the language and what can be simplified. Right now my focus is on basic functionality and establishing the main logic.
I have not found to increase brightness, yet. There is a CRGB method to dim a color, but that does math on each of the R, G, and B values of a specific color instance. It gets messy depending on the color. I fell down a couple of rabbit holes late at light trying to figure this out and need to revisit when I have time and a clear mind.
What I have hacked up so far:
New file: userremote.h
enum ButtonActions{
/*
There are / will be definitions for all of the usual actions on 24 and 42 key remotes.
It is understood that this will need to be reworke slightly to be compatible with action assignments being passed through a web interface.
*/
BRIGHTNESSUP,
BRIGHTNESSDOWN,
POWERON,
POWEROFF,
FILLCOLOR,
TRIGGEREFFECT,
CHANGER,
CHANGEG,
CHANGEB,
...
};
/*
This is the class for a user definable remote button.
Of note is the actionArgs property.
It is assumed that at some point a user on a web interface will pass
multiple comma separated arguments through this variable. As of now, I
am just using it to pass a string representing a hex color code.
*/
class RemoteButton
{
public:
String name;
int keyCode;
ButtonActions buttonAction;
String actionArgs;
RemoteButton (String name, int keyCode, ButtonActions buttonAction, String actionArgs) {
this->name = name;
this->keyCode = keyCode;
this->buttonAction = buttonAction;
this->actionArgs = actionArgs;
};
};
This file also contains some declarations for code used to create a CRGB color from a hex string (not hex integer).
The UserRemoteControl class holds all of the button definitions. It also has a property declaring how many buttons this has. That will mostly be useful for when a person is creating a user remote in a web interface.
class UserRemoteControl {
public:
//Eventually, the button type and / or button count will depend on a user setting / config file.
std::vector<RemoteButton> buttons;
void getRemoteButtons();
int buttonCount;
UserRemoteControl (int buttonCount = 0) {
std::vector<RemoteButton> myButons {};
this->buttons = myButons;
getRemoteButtons();
};
};
New file userremote.cpp
Again, will ignore the implementations for the string->hex->CRGB object conversion.
This is the implementation of the UserRemoteControl class getRemoteButtons method. Eventually, this can be retooled to get the arguments from a config file.
void UserRemoteControl::getRemoteButtons() {
//You can also defien each action, color, etc. based on your layout.
//Row 1
this->buttons.push_back(RemoteButton ("Brightness Up",0xFF3AC5,ButtonActions::BRIGHTNESSUP, ""));
this->buttons.push_back(RemoteButton ("Brightness Down",0xFFBA45,ButtonActions::BRIGHTNESSDOWN, ""));
this->buttons.push_back(RemoteButton ("Power On",0xFF827D,ButtonActions::POWERON, ""));
this->buttons.push_back(RemoteButton ("Power Off",0xFF02FD,ButtonActions::POWEROFF, ""));
//Row 2
this->buttons.push_back(RemoteButton ("Full Red",0xFF1AE5,ButtonActions::FILLCOLOR, "FF0000"));
this->buttons.push_back(RemoteButton ("Full Green",0xFF9A65,ButtonActions::FILLCOLOR, "00FF00"));
this->buttons.push_back(RemoteButton ("Full Blue",0xFFA25D,ButtonActions::FILLCOLOR, "0000FF"));
this->buttons.push_back(RemoteButton ("Full White",0xFF22DD,ButtonActions::FILLCOLOR, "999999")); //because we don't want FULL white
//Row 3
this->buttons.push_back(RemoteButton ("Color 1",0xFF2AD5,ButtonActions::FILLCOLOR, "E18E28"));
this->buttons.push_back(RemoteButton ("Color 2",0xFFAA55,ButtonActions::FILLCOLOR, "1B9205"));
this->buttons.push_back(RemoteButton ("Color 3",0xFF926D,ButtonActions::FILLCOLOR, "170C96"));
this->buttons.push_back(RemoteButton ("Color 4",0xFF926D,ButtonActions::FILLCOLOR, "F1BFDC"));
...
//Row 8
this->buttons.push_back(RemoteButton ("Increase Red",0xFF08F7,ButtonActions::CHANGER, "10"));
this->buttons.push_back(RemoteButton ("Increase Green",0xFF8877,ButtonActions::CHANGEG, "10"));
this->buttons.push_back(RemoteButton ("Increase Blue",0xFF48B7,ButtonActions::CHANGEB, "10"));
this->buttons.push_back(RemoteButton ("Quick",0xFFC837,ButtonActions::QUICK, ""));//fade speed is fast
...
}
Changes to remotecontrol.cpp
Added a line above the void RemoteControl::handle() method implementation to create an instance of UserRemoteControl.
UserRemoteControl myRemoteController (44); // My remote has 44 buttons
Removed code handling the button action after the line:
auto &effectManager = g_ptrSystem->EffectManager();
Added in my own button handling code:
auto keyCodeMatch = std::find_if(
myRemoteController.buttons.begin(),
myRemoteController.buttons.end(),
[&result](const RemoteButton& potentialButton) {
return potentialButton.keyCode == result;
}
);
if (keyCodeMatch != myRemoteController.buttons.end())
{
//debugV("We have a matching keycode 0x%08X \n", result);
auto index = std::distance(myRemoteController.buttons.begin(), keyCodeMatch);
RemoteButton thisButton = myRemoteController.buttons[index];
//debugI("We have a matching keycode 0x%08X the button is %s \n", result, thisButton.name);
switch (thisButton.buttonAction){
case ButtonActions::BRIGHTNESSUP:
//To be determined
break;
case ButtonActions::BRIGHTNESSDOWN:
lastManualColor.fadeLightBy(25); // sort of work but is messy and does not work well.
effectManager.SetInterval(0);
effectManager.SetGlobalColor(lastManualColor);
break;
case ButtonActions::POWERON:
effectManager.ClearRemoteColor();
effectManager.SetInterval(0);
effectManager.SetGlobalColor(lastManualColor);
effectManager.StartEffect();
g_Values.Brightness = 200; //we don't want to cause damage or hurt eyes. Margin for going up and down.
break;
case ButtonActions::POWEROFF:
effectManager.SetGlobalColor(CRGB(0,0,0));
g_Values.Brightness = std::max(0, (int) g_Values.Brightness - BRIGHTNESS_STEP);
effectManager.ClearRemoteColor();
break;
case ButtonActions::FILLCOLOR:
lastManualColor = hexToCrgb(thisButton.actionArgs);
effectManager.SetGlobalColor(lastManualColor);
effectManager.SetInterval(0);
break;
case ButtonActions::CHANGER:
if (lastManualColor.red + thisButton.actionArgs.toInt() > 255 ) {
lastManualColor.red = 255;
} else if (lastManualColor.red + thisButton.actionArgs.toInt() < 0) {
lastManualColor.red = 0;
} else {
lastManualColor.red += thisButton.actionArgs.toInt();
}
effectManager.SetGlobalColor(lastManualColor);
effectManager.SetInterval(0);
break;
...
}
}
Yeah, its pretty ugly and does not conform to code formatting standards. But, it does not crash when I press a button that is not defined. To make it so that a user can change button settings via a settings file or web interface, it had to get more complicated. It will crash when running too many LEDs off of a MacBook Air usb port and after setting the global color to white or close enough to white to max out the available amperage. Took me hours to figure out that random crash, but that's another story.
I like them idea.
Can you make this a "real" pull request, please? If you don't mind adding me as a collaborator, I can quickly help you get that past 1990-era C, for example. Commenting on text in email is just error prone.
On Fri, Sep 29, 2023, 10:30 AM Joe Schneider @.***> wrote:
Here is a followup to demonstrate what I have done. Keep in mind, this is my first dabbling with C++. I have worked with PHP, JavaScript, SwiftUI, MySQL, and a small amount of perl. I can google and consult stackoverflow like most every other programmer. There are some optimizations to be made once I get more familiar with the language and what can be simplified. Right now my focus is on basic functionality and establishing the main logic.
I have not found to increase brightness, yet. There is a CRGB method to dim a color, but that does math on each of the R, G, and B values of a specific color instance. It gets messy depending on the color. I fell down a couple of rabbit holes late at light trying to figure this out and need to revisit when I have time and a clear mind.
What I have hacked up so far:
New file: userremote.h
enum ButtonActions{ / There are / will be definitions for all of the usual actions on 24 and 42 key remotes. It is understood that this will need to be reworke slightly to be compatible with action assignments being passed through a web interface. / BRIGHTNESSUP, BRIGHTNESSDOWN, POWERON, POWEROFF, FILLCOLOR, TRIGGEREFFECT, CHANGER, CHANGEG, CHANGEB, ... };
/ This is the class for a user definable remote button. Of note is the actionArgs property. It is assumed that at some point a user on a web interface will pass multiple comma separated arguments through this variable. As of now, I am just using it to pass a string representing a hex color code. / class RemoteButton { public: String name; int keyCode; ButtonActions buttonAction; String actionArgs; RemoteButton (String name, int keyCode, ButtonActions buttonAction, String actionArgs) { this->name = name; this->keyCode = keyCode; this->buttonAction = buttonAction; this->actionArgs = actionArgs; }; };
This file also contains some declarations for code used to create a CRGB color from a hex string (not hex integer).
The UserRemoteControl class holds all of the button definitions. It also has a property declaring how many buttons this has. That will mostly be useful for when a person is creating a user remote in a web interface.
class UserRemoteControl { public: //Eventually, the button type and / or button count will depend on a user setting / config file. std::vector
buttons; void getRemoteButtons(); int buttonCount; UserRemoteControl (int buttonCount = 0) { std::vector myButons {}; this->buttons = myButons; getRemoteButtons(); }; };
New file userremote.cpp
Again, will ignore the implementations for the string->hex->CRGB object conversion.
This is the implementation of the UserRemoteControl class getRemoteButtons method. Eventually, this can be retooled to get the arguments from a config file.
void UserRemoteControl::getRemoteButtons() { //You can also defien each action, color, etc. based on your layout. //Row 1 this->buttons.push_back(RemoteButton ("Brightness Up",0xFF3AC5,ButtonActions::BRIGHTNESSUP, ""));
this->buttons.push_back(RemoteButton ("Brightness Down",0xFFBA45,ButtonActions::BRIGHTNESSDOWN, ""));
this->buttons.push_back(RemoteButton ("Power On",0xFF827D,ButtonActions::POWERON, ""));
this->buttons.push_back(RemoteButton ("Power Off",0xFF02FD,ButtonActions::POWEROFF, ""));
//Row 2 this->buttons.push_back(RemoteButton ("Full Red",0xFF1AE5,ButtonActions::FILLCOLOR, "FF0000"));
this->buttons.push_back(RemoteButton ("Full Green",0xFF9A65,ButtonActions::FILLCOLOR, "00FF00"));
this->buttons.push_back(RemoteButton ("Full Blue",0xFFA25D,ButtonActions::FILLCOLOR, "0000FF"));
this->buttons.push_back(RemoteButton ("Full White",0xFF22DD,ButtonActions::FILLCOLOR, "999999")); //because we don't want FULL white
//Row 3 this->buttons.push_back(RemoteButton ("Color 1",0xFF2AD5,ButtonActions::FILLCOLOR, "E18E28"));
this->buttons.push_back(RemoteButton ("Color 2",0xFFAA55,ButtonActions::FILLCOLOR, "1B9205"));
this->buttons.push_back(RemoteButton ("Color 3",0xFF926D,ButtonActions::FILLCOLOR, "170C96"));
this->buttons.push_back(RemoteButton ("Color 4",0xFF926D,ButtonActions::FILLCOLOR, "F1BFDC"));
...
//Row 8
this->buttons.push_back(RemoteButton ("Increase Red",0xFF08F7,ButtonActions::CHANGER, "10"));
this->buttons.push_back(RemoteButton ("Increase Green",0xFF8877,ButtonActions::CHANGEG, "10"));
this->buttons.push_back(RemoteButton ("Increase Blue",0xFF48B7,ButtonActions::CHANGEB, "10"));
this->buttons.push_back(RemoteButton ("Quick",0xFFC837,ButtonActions::QUICK, ""));//fade speed is fast
... }
Changes to remotecontrol.cpp
Added a line above the void RemoteControl::handle() method implementation to create an instance of UserRemoteControl.
UserRemoteControl myRemoteController (44); // My remote has 44 buttons
Removed code handling the button action after the line:
auto &effectManager = g_ptrSystem->EffectManager();
Added in my own button handling code:
auto keyCodeMatch = std::find_if( myRemoteController.buttons.begin(), myRemoteController.buttons.end(), [&result](const RemoteButton& potentialButton) { return potentialButton.keyCode == result; } );
if (keyCodeMatch != myRemoteController.buttons.end()) { //debugV("We have a matching keycode 0x%08X \n", result); auto index = std::distance(myRemoteController.buttons.begin(), keyCodeMatch); RemoteButton thisButton = myRemoteController.buttons[index];
//debugI("We have a matching keycode 0x%08X the button is %s \n", result, thisButton.name); switch (thisButton.buttonAction){ case ButtonActions::BRIGHTNESSUP: //To be determined break; case ButtonActions::BRIGHTNESSDOWN: lastManualColor.fadeLightBy(25); // sort of work but is messy and does not work well. effectManager.SetInterval(0); effectManager.SetGlobalColor(lastManualColor); break; case ButtonActions::POWERON: effectManager.ClearRemoteColor(); effectManager.SetInterval(0); effectManager.SetGlobalColor(lastManualColor); effectManager.StartEffect(); g_Values.Brightness = 200; //we don't want to cause damage or hurt eyes. Margin for going up and down. break; case ButtonActions::POWEROFF: effectManager.SetGlobalColor(CRGB(0,0,0)); g_Values.Brightness = std::max(0, (int) g_Values.Brightness - BRIGHTNESS_STEP); effectManager.ClearRemoteColor(); break; case ButtonActions::FILLCOLOR: lastManualColor = hexToCrgb(thisButton.actionArgs); effectManager.SetGlobalColor(lastManualColor); effectManager.SetInterval(0); break; case ButtonActions::CHANGER: if (lastManualColor.red + thisButton.actionArgs.toInt() > 255 ) { lastManualColor.red = 255; } else if (lastManualColor.red + thisButton.actionArgs.toInt() < 0) { lastManualColor.red = 0; } else { lastManualColor.red += thisButton.actionArgs.toInt(); } effectManager.SetGlobalColor(lastManualColor); effectManager.SetInterval(0); break; ... } }
Yeah, its pretty ugly and does not conform to code formatting standards. But, it does not crash when I press a button that is not defined. To make it so that a user can change button settings via a settings file or web interface, it had to get more complicated. It will crash when running too many LEDs off of a MacBook Air usb port and after setting the global color to white or close enough to white to max out the available amperage. Took me hours to figure out that random crash, but that's another story.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1741080026, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD33PJH33KPGEMGVUXE3X43SSZANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
I like them idea. Can you make this a "real" pull request, please? If you don't mind adding me as a collaborator, I can quickly help you get that past 1990-era C, for example. Commenting on text in email is just error prone.
@robertlipe To have a "real" pull request I first need to get a proper git setup going. I simply pulled the files to my computer and have been hacking at them locally. Not ideal, especially considering the number of changes that Dave has been committing in GitHub. But, I am not even a contributor to the project (yet). I'm just throwing out some ideas to get the code to work like I want and to hopefully add something of value.
The code needs to be cleaned up significantly before it gets added to the project. For sharing in this thread, I copied the code to a markdown editor to remove a bunch of garbage from debugging and make it readable in the browser. The raw code on my computer is too embarrassing to show. I also want to get the basic functionality of each button working before it's ready. I'm working with a 44 key remote which has more function than Dave's 24 button version in the original code, but there is some overlap. I really want to get the brightness functions working because I need that for real world projects in the works. It is far more a pain in the butt than I originally thought it would be. I also need to figure out some basic effects to add to buttons like Fade3, Fade7, etc. and integrate those without nuking the effects added to effects manager at boot.
I have to laugh at your 1990 era C comment. Nothing says 1990 coding like coordinating programming efforts over email and online chat groups. We've gone from listservs and aim/irc to GitHub managed emails and Discord.
Anyway, once I get the GitHub desktop client setup, fresh copy of the code pulled down I will port over my code to that codebase and move on from there. That will simplify development and feedback.
@revision29 I really appreciate the effort you're putting into going through the learning curve that comes with this project's tech stack (which I appreciate can be very steep), and I think refactoring the setup of the remote control logic/code can be a great step forward concerning the maturity of that particular control interface.
However, as I've mentioned before (in this comment, to be exact) there is one thing I really don't see happening, and that is connecting the web UI to the IR remote control logic. The basic reason is that they are two completely different user interfaces to the same back-end, that largely being the effect manager and the effects it manages.
The IR remote is a "matrix of buttons" without feedback, input fields, sliders, checkboxes, "are you sure?" dialogs, etc. The web UI is everything that I just said the IR remote is not, and more. They're just two completely different beasts that can be used to manage the same back-end. As such, they should be reasoned about separately, considering the specific capabilities and limitations of each.
Reasoning from a different angle, the webserver that publishes the web UI should be able to run on devices without support for the IR remote, and vice versa. We already have quite a few dependencies within this project that one could scratch one's head about, and some efforts are now being made to disentangle those. I really don't think we should introduce a new one.
So again, I'm all for refactoring, modularizing and enriching our IR remote code structure and capability. But let's do that for the merits of the IR remote interface itself. The Web UI has and will have its own development and improvement tract.
If this comes across a bit strong then that's really just because I don't want anyone here to waste brain cycles or lines of code by considering the complexities of something that is and should remain entirely unrelated to the topic at hand.
As always, I'm happy to elaborate if what I just said raises questions or concerns.
@rbergen Thanks for providing direction. I certainly don't want to waste my time on features that won't be used or will cause problems down the line. I don't want to cause collisions between what the IR remote does and the web server. The only reason why I am thinking about the web server is that when a device has a web interface people usually assume some settings can be adjusted from that interface. If the web server were to be expanded to include that functionality, it would be relatively trivial to also allow it to adjust button functionality if the buttons are defined in a user settings file. For the purpose of my current refactoring, it does not matter if the web server is ever involved. I have written my code so that it can be tweaked to interact with a user settings file if that were introduced into the software at a future date.
But, I will more closely read the comment you cited as well as the surrounding context. I have not read many of the discussions outside of this current thread. It's a firehose of information as it is.
Though I just embarrassed myself a bit in another thread, let me say that I've put quite a bit of thought into the remote code, but more in the transformation of keys into actions and not the internal states managed by those actions. So I don't know my approach is "right", but I can try to mentor it back closer to how I would have done it because that is, of course, the One And True Way. :-)
We agree that the remote and the REST API can each modify state of effectmanager that's visible to the other. We don't exactly have a MVP model here and Rutger seems to be against synchronizing them. Maybe someday, BOTH remotecontrol.cpp actually issues a BrightnessChange -10% request down to the REST API and the REST API then sends an OnBrightnessChanged(old: 60, new:50); event to ALL listeners that can modify their representation (move the displayed slider) or not. That's not the world we have today, not a world that any of us are particularly signing up to work on, and I think that's fine. There's plenty we can do to help remotes work better without touching REST, barely touching effectmgr (I'm just leaving that door open - I know in one of my trees I had to "fix" something minor) and without touching the web UI at all. If you want to turn the brightness all the way up on the web and all the way down in your remote, well, knock yourself out.
So Joe's willing to take on actually slinging some bits. I'm willing to help mentor some. I'm a big fan of smart data and dumb code. I love tables. I love dumb code that does table lookups to do easy things. Reacting to a button push should be easy. Good thing, because that's not actually the hard part of the class of remotes we face.
The reality is that these remotes are literally nickels each. They come in many form factors. They may be 24 key or 44 key or any other number. Identical LOOKING remotes may send different codes. Remotes that seem like they were probably manufactured by the same assembly line may have different labels on the "key caps" (domes? pimples?) So you can't really infer anything about the key cap, shape, placement, or action of any key other than by pressing it and seeing what bits come out. This isn't great, but fortunately, most people don't actually WANT 44 unique keys for their Holiday Trees or whatever. Projects bigger than us have tried to unify all the $0.08 remotes in the world and have failed. Partial failure is still success, IMO. (We can probably enumerate < 10 things people REALLY want to do MOST of the time.) There are a ton of remotes out there, but all we really care about are IR, NEC-code remotes.
One constraint of the project is no config files. That wouldn't be my choice, but we have C(++) structs and we have a little bit of wiggle room in the system configuration that's stored in the JSON.
I have probably 15-20 IR colored remotes that I'm willing to photograph and integrate.
Here's what I started to scratch out as a design once or twice.
So we need a table (enum class) that describes Actions: NextEffect PreviousEffect PowerOff PowerOn BrightnessUp BrightnessDown Faster Slower ShowVU HideVU .... anything else we want to ask effectManger (?) to do for us.
We need a table that describes a physical remote, maybe we store key positions or labels or a link to a picture or something. Honestly, the majority of my basket has NO identifying information. That table should also contain the list of 32-bit keycodes that are sent by each key, associating each key with an action
One44KeyRemote: "Crappy 44 key remote", { 0xf700ff, BrightnessUp}, { 0xf7807f, BrightnessDown}, ...
One24KeyRemote "Junky 24 key remote" {0xff3ac5, BrightnessUp} {0xffba45, BrightnessDown}, ... Does each key need a position in x,y and a label? {0xff3ac5, BrightnessUp, "Sun with Arrow above it on a white key", { 0, 0 }
Now, you need a table of remotes Remotes: One44KeyRemote, One24keyRemote,
Now, the Settings needs ONE value: which remote are we using, 0 or 1 for each of those remotes. Based on our recent discussions around permanence and storing stuff forever in JSON, maybe each Remote holds a value like "201704131500" to make them source-reorderable and tolerant of removals and insertions.
auto remote = Remotes[userRemoteIndex]; // or a std::find_if
auto it == std::find_if(remote.begin(), remote.end, [](const remote& r) return { r.keycode == received_keypress } if it! = remote.end() return it->action;
Now, you just make a single call into effectManager.doAction(action).
Now there's still some messiness about colors. This remote has 3 colors. This has 12. That has 16. Do you do RGBA color nearness? Maybe. We should prepare for that to have some fuzziness in the search.
So now, just doing text review without a line-by-line since I can't exactly patch this in...
I think you have some of the same divisions of labor, but in my world, "RemoteButton" is just a struct member. It's data. It does nothing by itself and doesn't seem to make sense as a class. You seem to be very class-happy. :-)
There's code elsewhere in the project for making colors from hex. Who actually calls strtoull isn't very interesting - that's just an overload.
About 30 years ago, C++ got 'implicit this' or 'hidden this' or some such. It was long enough ago that I've forgotten the name. A class can refer to its members without actually saying 'this->'. YOu can probably replace "this->" with "" and it all work the same.
You're calling a ctor on a 5-field thing that .... stores the five fields.
Even if buttons is a std:vector instead of a std::array or a plain ole array, you can still struct init it. buttons[] = { {"UP, 0x1234, BrightnessUp}, {"Down", 0xffba45, BrighnessDown}, ...
The designs aren't that far apart. I'm just thinking to the case of multiple remotes and being able to select them from a Web UI or something.
Your "random" crash isn't random. It's power supply overload. I'm honestly shocked the MBA doesn't have current overload protection. By design (I attended USB design meetings pre-ratification) you were supposed to be able to twist all the wires together and not cause a harmful short.
I have to run, but Let's collab more on it.
On Fri, Sep 29, 2023 at 4:46 PM Rutger van Bergen @.***> wrote:
@revision29 https://github.com/revision29 I really appreciate the effort you're putting into going through the learning curve that comes with this project's tech stack (which I appreciate can be very steep), and I think refactoring the setup of the remote control logic/code can be a great step forward concerning the maturity of that particular control interface.
However, as I've mentioned before (in this comment https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/294#issuecomment-1656697503, to be exact) there is one thing I really don't see happening, and that is connecting the web UI to the IR remote control logic. The basic reason is that they are two completely different user interfaces to the same back-end, that largely being the effect manager and the effects it manages.
The IR remote is a "matrix of buttons" without feedback, input fields, sliders, checkboxes, "are you sure?" dialogs, etc. The web UI is everything that I just said the IR remote is not, and more. They're just two completely different beasts that can be used to manage the same back-end. As such, they should be reasoned about separately, considering the specific capabilities and limitations of each. Reasoning from a different angle, the webserver that publishes the web UI should be able to run on devices without support for the IR remote, and vice versa. We already have quite a few dependencies within this project that one could scratch one's head about, and some efforts are now being made to disentangle those. I really don't think we should introduce a new one.
So again, I'm all for refactoring, modularizing and enriching our IR remote code structure and capability. But let's do that for the merits of the IR remote interface itself. The Web UI has and will have its own development and improvement tract.
If this comes across a bit strong then that's really just because I don't want anyone here to waste brain cycles or lines of code by considering the complexities of something that is and should remain entirely unrelated to the topic at hand.
As always, I'm happy to elaborate if what I just said raises questions or concerns.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1741521898, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD36WBXT2KKYRATRRWATX446SXANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
The only reason why I am thinking about the web server is that when a device has a web interface people usually assume some settings can be adjusted from that interface. If the web server were to be expanded to include that functionality, it would be relatively trivial to also allow it to adjust button functionality if the buttons are defined in a user settings file. For the purpose of my current refactoring, it does not matter if the web server is ever involved. I have written my code so that it can be tweaked to interact with a user settings file if that were introduced into the software at a future date.
@revision29 Thank you for clarifying that, that's very helpful. I'm happy to hear you're not approaching this from the perspective that the web UI should "push IR remote control buttons" in the sense of back-end logic - that in particular is what I'm objecting to.
We can certainly consider making the button assignments configurable "at runtime" from the perspective of the IR remote, and consider how to "logically structure" the storage of this in some sort of flat file - in the end that's how any configuration of this nature would have to "land" on this type of device anyway. We probably should also consider how to make that configuration "externally digestible", acknowledging that the IR remote is probably not the user interface that will be used to change its own configuration.
And as it stands, the web UI may well be the only viable front-end to modify this configuration. I still think we should isolate the two in our thinking, initially. Let's make the configurability setup work from the IR remote perspective first, possibly considering a future "abstract" external source of configuration capability when it comes to structure, naming and internal C++ interface. After that, we can worry about the consumption of and manipulation of this configuration - either via the web UI or, who knows, other channels.
can worry about the consumption of and manipulation of this configuration
- either via the web UI or, who knows, other channels.
Telnet. Like God, Herself, intended. 😁
On Fri, Sep 29, 2023, 7:08 PM Rutger van Bergen @.***> wrote:
The only reason why I am thinking about the web server is that when a device has a web interface people usually assume some settings can be adjusted from that interface. If the web server were to be expanded to include that functionality, it would be relatively trivial to also allow it to adjust button functionality if the buttons are defined in a user settings file. For the purpose of my current refactoring, it does not matter if the web server is ever involved. I have written my code so that it can be tweaked to interact with a user settings file if that were introduced into the software at a future date.
Thank you for clarifying that, that's very helpful. I'm happy to hear you're not approaching this from the perspective that the web UI should "push IR remote control buttons" in the sense of back-end logic - that in particular is what I'm objecting to.
We can certainly consider making the button assignments configurable "at runtime" from the perspective of the IR remote, and consider how to "logically structure" the storage of this in some sort of flat file - in the end that's how any configuration of this nature would have to "land" on this type of device anyway. We probably should also consider how to make that configuration "externally digestible", acknowledging that the IR remote is probably not the user interface that will be used to change its own configuration.
And as it stands, the web UI may well be the only viable front-end to modify this configuration. I still think we should isolate the two in our thinking, initially. Let's make the configurability setup work from the IR remote perspective first, possibly considering a future "abstract" external source of configuration capability when it comes to structure, naming and internal C++ interface. After that, we can worry about the consumption of and manipulation of this configuration - either via the web UI or, who knows, other channels.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1741595417, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3ZFZGDH7ZVEPYCAENTX45PHPANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
Telnet. Like God, Herself, intended. 😁
You know, I actually think that would be pretty darned cool! :)
@robertlipe
I have probably 15-20 IR colored remotes that I'm willing to photograph and integrate.
The problem is not so much the button layout, as we need to compile a list of special buttons they has such as flash, strobe, eject, etc. I want to replicate each of those labels as an entry in the enum to allow decent amount of customization. I am currently using a 44 key remote that came with a less capable LED light set. I also have a DVD remote I intend to re-purpose. It's form the dame DVD player I sourced the IR diode from. My goal is maximum customization to admittedly ridiculous levels.
We need a table that describes a physical remote, maybe we store key positions or labels or a link to a picture or something. Honestly, the majority of my basket has NO identifying information.
My design intention is to hard code as little as possible into the logic. My assumption is that a person will need to take the time to capture the codes for each button and then customize form there. My opinion is that it is needlessly complex to try and pre-populate a table with all of this data. Maybe a future feature would be to simplify the keycode acquisition process. Or we can provide some instruction on how they can capture the keycodes. This project requires a minimum technical capability and capturing keycodes should not be a surmountable task. If the person is soldering and tweaking code, they should be able to follow a guide to get the codes.
Does each key need a position in x,y and a label?
Presently as I have written the end user puts the button definitions in the userremote.cpp file. It's more or less function as the place where they adjust those settings. As I have done, they can layout those definitions in rows to make more visual sense. Coding in remote positions introduces unnecessary complexity. Maybe if there is ever a user settings file we can specify X columns by Y rows, but that would only make sense if you are trying to draw a visual preview in a web interface. The label is not needed for functionality but is more of a convenience to help a person find the button definition as it corresponds to a theoretical label on the remote.
Now, you just make a single call into effectManager.doAction(action).
The remote functionality needs to be distinct from the effects manager code. Things like FADE7, FLASH3, etc. will require building an effect stack and sending that to the effects manager. The reason I have it coded as is, is so that a person can go to the switch in the remotecontrol.cpp and trigger whatever action they want to customize. I do have an arguments string in the button class in case we need to pass arguments to effects manager. We don't want people digging through the effects manager code to try and customize button / enum actions.
"RemoteButton" is just a struct member. It's data. It does nothing by itself and doesn't seem to make sense as a class. You seem to be very class-happy. :-)
Fair point. I much prefer object oriented programming. I'd rather reference button.name instead of button[0]. It's much more readable for someone trying to make sense of the code and makes it so I don't have to remember all of the index numbers when sleep deprived.
There's code elsewhere in the project for making colors from hex.
Yes. It accepts a uint32_t RGB color code. My button definition code is pulling the color code from the arguments property of the button object. That property is a text string to maximize functionality. My solution of converting the text string to 3 separate color values is the best I could come up with. Since I am new to all of this I don't know what functions are more or less optimal. All I know is that it works. I would prefer being able to directly convert the hex text string to uint32_t, but I found no such solution googling. I mean, you can convert the string to an integer but it will not be the kind of integers you are looking for.
YOu can probably replace "this->" with "" and it all work the same.
I spent too much time with ecmascript / php back in the day. Will fix. Thanks for helping me overcome bad noob practices.
Even if buttons is a std:vector instead of a std::array or a plain ole array, you can still struct init it.
I can't remember why I settled on this. I think it has to do with vectors are easier to build on the fly rather than having to declare the whole thing at once. I want the code to be agnostic about the number of buttons a person is utilizing and just build a collection of what buttons they want to define. From my googling it is much easier to add / remove from a vector than it is appending an array.
Your "random" crash isn't random. It's power supply overload. I'm honestly shocked the MBA doesn't have current overload protection. By design (I attended USB design meetings pre-ratification) you were supposed to be able to twist all the wires together and not cause a harmful short.
It seemed random at the time. The problem is I changed how board connected to the computer. In my previous method, the USB hub previously used requested additional power from the USB port (as allowed by the USB-C spec). When I switched to a kludgy cable only solution, the USB port defaulted to a lower allowed wattage, probably whatever USB2 defines. The power negotiation process did not come to mind at all when I switched my connectivity solution. I had erroniosly assumed that when I was plugging in my power adapter it was switching to use that automatically and not drawing power from USB. This situation was compounded by the fact that in my code, I added some debug code in a few places to track when things were triggering. I made some mistakes and was passing the wrong variable types into the debugger. This was when I was trying to figure out the RGB hex string conversion. The code compiled, but when the debugger received the wrong variable type it crashed the board and rebooted just like when it browned out. I had crashes coming from like 3 sources. I got the code problems solved and it was still crashing for "no good reason" . It was at 1:50am when I noticed the brownout error being printed to the console before the board crashed and it clicked what was happening. Then I figured out the proper power connection sequence and all is good. But, part of this is that I had forgotten that I added a color fill effect of pale green after the standard demo rainbow effect. So, at 30 seconds it was guaranteed to crash. But, also I was triggering crashes when I pressed remote buttons before the 30 seconds. It was a bad mix of hardware variables, trying to hack out text conversion functions, frustration, and a late night. I thought it was pretty funny once I figure out what was going on. I had gone through the trouble of disabling all of my code and putting the original code back in place and it was a hardware issue.
TLDR; I got a good laugh over a bad combination of bad code and hardware changes.
I have probably 15-20 IR colored remotes that I'm willing to photograph and integrate.
The problem is not so much the button layout, as we need to compile a list of special buttons they has such as flash, strobe, eject, etc. I want to replicate each of those labels as an
Fair. If you try to actually implement something approximating all the labels on all the remotes, it's going to take a lot of extra work in e.g. effectsmanager. This is why I was focusing more on implementing the most common, unlabeled cases first as they're the ones that'll reasonably already have backing support. I don't think there's a wrong order to tackle it. Just keep it extensible because there will always be another remote with yet one more button that someone will find useful.
I am currently using a 44 key remote that came with a less capable LED light set. I also have a DVD remote I intend to re-purpose. It's form the dame DVD player I sourced the IR diode from. My goal is maximum customization to admittedly ridiculous levels.
IMO, that'll be a common case in reality. Lots of people have arbitrary old remotes from a TV or VCR that will be useful to repurpose.
Lots of random "Arduino beginner" kits include remotes that would be nice to formally capture if we had a way to describe them. For example, the unit pictured in https://www.circuitbasics.com/arduino-ir-remote-receiver-tutorial/
We need a table that describes a physical remote, maybe we store key positions or labels or a link to a picture or something. Honestly, the majority of my basket has NO identifying information.
My design intention is to hard code as little as possible into the logic.
"Smart data. Dumb code." Tables are easy to edit. :-)
The other reason to have these defined in tables instead of code is for a day when a user can add/upload an individual file (maybe it's JSON or CSV or something). Perhaps these could me mechanically generated from one of the many repositories of such things.
Not that we want 49,000 arbitrary remotes...we want an easy way for someone to grab and process one that they want.
Maybe a future feature would be to simplify the keycode acquisition
process.
Just the debug print of "I received unknown code X" isn't bad. When I'm entering them in bulk, my little $10 arbitrary component tester (the kind with the ZIF socket that lets you stab in a chip, transistor, resistor, etc and a tiny display) displays the codes. They're handy for anyone doing lots of work with IR in multiple projects.
Maybe if there is ever a user settings file we can specify X columns by Y rows, but that would only make sense if you are trying to
It'd be handy for doc, too. "Press the second button in the third row" might be easier to express than "press the button that's more green than turquoise". I have remotes with colored labels that are exactly colors on the caps. (No, I'm not color blind - I photographed them and sampled the pixels) Physical locations are cheap and easy to capture by the person contributing support for a new remote, and hard to recreate retroactively.
In a design, please include space for row, column. Even for non-rectangular cases, I think we can make that make sense.
We don't want people digging through the effects manager code to try and
customize button / enum actions.
For specialized cases, it would actually be handy to capture all strokes and pass them through effectsmgr and down into the actual effect. But let's not tackle that initially.
This is why I was going to decouple finding the code and categorizing it (remotecontrol.*) vs acting on it (effectsmgr). If they're eaten at too low of a level, a special effect can't know that "DIY4" was pressed as it gets dropped at too early.
Fair point. I much prefer object oriented programming. I'd rather reference
button.name instead of button[0]. It's much more readable for someone trying to make sense of the code and makes it so I don't have to remember all of the
We also have designated initializers available.
There's code elsewhere in the project for making colors from hex.
Yes. It accepts a uint32_t RGB color code. My button definition code is pulling the color code from the arguments property of the
I'd rather have it all in one place. We shouldn't have remote making a near duplicate of code in color just to work around a missing (needed) constructor or overload.
I would prefer being able to directly convert the hex text string to uint32_t, but I found no such solution googling. I mean, you can convert the string to an integer but it will not be the kind of integers you are looking for.
I was also reluctant to encode 32 bits worth of colors into that layer. We don't need 4bn worth of color resolution and we don't need to fail a match between #f00 and #e00. IMO we can safely decompose that at this layer to something representing "red". Allowing for even 16 colors (does any remote have 32 color buttons?) is probably quite enough. We don't have to go nuts with reduction, but we should remember that these are still embedded systems. Constant, dense data structures in flash are cheaper for us than objects created in core by code.
Via constexpr, we can even do a great amount of type coercion during compilation time.
YOu can probably replace "this->" with "" and it all work the same.
I spent too much time with ecmascript / php back in the day. Will fix. Thanks for helping me overcome bad noob practices.
That's where my (probably harsh sounding - sorry) crack of looking like early 90s' C++ came from. It's a very dated practice.
Even if buttons is a std:vector instead of a std::array or a plain ole array, you can still struct init it.
I can't remember why I settled on this. I think it has to do with vectors are easier to build on the fly rather than having to declare the whole thing at once.
It's still a compile constant. I dont' care if it's a std::vector or a std::array. I'd just much rather it be a structure of some kind with constant initialization instead of created by code to reduce duplication and size. Contrast
this->buttons.push_back(RemoteButton ("Increase Red",0xFF08F7,ButtonActions::CHANGER, "10")); this->buttons.push_back(RemoteButton ("Increase Green",0xFF8877,ButtonActions::CHANGEG, "10")); this->buttons.push_back(RemoteButton ("Increase Blue",0xFF48B7,ButtonActions::CHANGEB, "10"));this->buttons.push_back(RemoteButton ("Quick",0xFFC837,ButtonActions::QUICK, ""));//fade speed is fas
and
{"Increase Red", 0xFF08F7,ButtonActions::CHANGER, "10"}, {"Increase Red", 0xFF8877,ButtonActions::CHANGEG, "10"}, {"Increase Red", 0xFF48B7,ButtonActions::CHANGEB, "10"}, {"Increase Red", 0xFFC837,ButtonActions::QUICK)
Disassemble them. Which do you think takes less code? Hint: one of them takes zero. Whether that table takes the label on the keys or the argument is a string or number or whether the label is derived from the Action is a separate decision.
I want the code to be agnostic about the number of buttons a person is
utilizing and just build a collection of what buttons they want to define. From my googling it is much easier to add / remove from a vector than it is appending an array.
Arrays (or even vectors) can have a varying number of constant members. keys[] = {1, 2, 3} knows to make keys three elements long.
the board and rebooted just like when it browned out. I had crashes coming
from like 3 sources. I got the code problems solved and it was still crashing for "no good reason" . It was at 1:50am when I noticed the brownout error
Ah, it was the board that crashed and not the Mac. Got it. MacOS (and related hardware) is usually really good about not letting you oversubscribe power like that, but it might not be able to gracefully print a message if the power rails are just effectively shorted instead of seeing an actual Device Descriptor that announces power requirement
effect of pale green after the standard demo rainbow effect. So, at 30
seconds it was guaranteed to crash. But, also I was triggering crashes when I pressed remote buttons before the 30 seconds. It was a bad mix of hardware
I've definitely spent time in debugging twilight zone. I feel 'ya.
figure out what was going on. I had gone through the trouble of disabling
all of my code and putting the original code back in place and it was a hardware issue.
https://github.com/PlummersSoftwareLLC/NightDriverStrip/discussions/449
Message ID: <PlummersSoftwareLLC/NightDriverStrip/issues/284/1741760637@
github.com>
Follow up: on a positive note, I got brightness up and down to work with the brightness buttons. I want the brightness level to apply across all effects, not just the ones triggered by the remote. I want a global brightness level that the effects manager reads and applies proportionately to all affects. Partly for the remote functionality, but primarily because in most of my use cases I want to boot at less than full brightness. I can see that will be a nightmare to implement.
Nice. Congrats.
FWIW, I've considered adding a feature to ramp brightness from 20% -> selection on bootup, mostly because I'm a night owl myself and keep scorching my own eyeballs when I boot strip projects. Even a few seconds to look away or let ones own retinas adjust would be helpful, IMO.
It's not really a nightmare, you just have to be accustomed to programming without blocking. (Remember, you're still in a form an an OS and you can't just run around busy-waiting the CPU as the network might be trying to do network stuff or remote stuff or whatever...) Lambdas make that a little less obnoxious to express, but i'm pretty sure that Arduino, FreeRTOS, and ESP-IDF all have ways to express this common idiom as it's used for, say, TCP packet retransmission. You just can't busy-wait the task for 10 seconds on a fade-in or the watchdog timer will byte you. A repeating counter that bumps from 10->100 in steps of 10 (all numbers made up) would do it.
Honestly, doing it once on startup with a global and a timer that rescheduled itself until it didn't wouldn't be the most shameful act one could commit...
Good luck!
...and it's OK if you do that in a future PR.
On Sat, Sep 30, 2023 at 11:17 PM Joe Schneider @.***> wrote:
Follow up: on a positive note, I got brightness up and down to work with the brightness buttons. I want the brightness level to apply across all effects, not just the ones triggered by the remote. I want a global brightness level that the effects manager reads and applies proportionately to all affects. Partly for the remote functionality, but primarily because in most of my use cases I want to boot at less than full brightness. I can see that will be a nightmare to implement.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1741951398, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3YUFIAIOG3VZUIKCB3X5DVEXANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
I got brightness up and down to work with the brightness buttons
Great news, well done!
I can see that will be a nightmare to implement
Why would that be? The setting could be held by the DeviceConfig class, with the benefit it could then also be controlled via the web UI. The only thing we'd have to add is a mechanism to inform EffectManager that the setting changed. I'd probably generalize that by creating and using some sort of event listener interface - or see if the standard library already offers something like that.
It's work, but I'd say quite manageable.
Or maybe I misunderstand your remark?
FWIW, I've considered adding a feature to ramp brightness from 20% -> selection on bootup
Yeah, that's a different animal.
Totally.
...and "I don't think so" on the other point. Observers have been in the std::experimental can (of worms) that's been kicked down the road for a decade or more and never making it to ratification that I know of. I've been sensitive to their progress because in my last two day jobs (one in OSes, one in apps) they were used everywhere.
They're not a terribly difficult design pattern to implement. Without even looking, I'll bet we're already building a couple forms of them for bluetooth or networking or OS scheduling or MQTT or such. I think they've not made it because they're difficult to generalize well for ownership issues. Nieve versions don't scale well. Versions that do scale can hold locks infinitely long, tend to hit priority inversions, have issues with locking reference counters, and such.
There have been a few places in this code I've thought we could use observers and change notifiers and wouldn't let the absence of them being in C++23 be a deal-breaker. There are just a lot of problems we dont' have.
I will concede they can be gnarly to debug. It's crazy hard to set a breakpoint on an event NOT happening. It can be done while keeping nightmares at bay, though.
We have continuations now int he language ('20, I think), but I'm not a fan for reasons that have even less to do with this proposed work. :-)
OTOH, The limits of the current state of the art in applied computer science probably shouldn't be a limiting factor for us to blink LEDs, LOL.
Independent of this work, if I implemented the "power up fade in slowly over N seconds" part, Rutger, would you be interested in handling the UI part of setting N?
Or we just declare that N is 2 or 3 or something and forget the UI, in which case your half could be done now. Do we prever g_values->Brightness (MatrixScaledBrightness?) over LedMatrixGfx:SetBrightness or FastLED::setBrightness or is there yet some other, more authoritative, knob? When I poked at this once before, one of the reasons I turned around was that there seemed to be too many concepts of "brightness".
So let's not distract Joe with this, but it IS something I'd be interested in pursuing for the project if the project wants it.
RJL
On Sun, Oct 1, 2023 at 2:08 AM Rutger van Bergen @.***> wrote:
FWIW, I've considered adding a feature to ramp brightness from 20% -> selection on bootup
Yeah, that's a different animal.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1741985138, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD33GW5BXC3ZLVMK4IX3X5EJGVANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
They're not a terribly difficult design pattern to implement.
Turning that into a prophecy of sorts, I think I'd keep it simple at a conceptual level (read: naive) in this case. I'd create an interface class with one "pure virtual" function that's called something like OnSettingChanged
, which accepts the sender (there is some decision making to be done on how to do this exactly, which might make the pure virtual a template instead) and the changed setting name as its only parameters. That means the interface class can be used for both device and effect settings, and is usable for observers that observe both.
Observer and the observed would have to have a gentleman's agreement that the called functions behave and return quickly, but I think this use case is concrete and simple enough for that to suffice.
Independent of this work, if I implemented the "power up fade in slowly over N seconds" part, Rutger, would you be interested in handling the UI part of setting N? Or we just declare that N is 2 or 3 or something and forget the UI, in which case your half could be done now.
I'd actually choose a sensible N for the user, but make the power-up fade-in a toggle setting; i.e. let the user decide to enable it or not. I'm happy to take care of the DeviceConfig
and CWebServer
changes to add this when the rest is in place.
Do we prever g_values->Brightness (MatrixScaledBrightness?) over LedMatrixGfx:SetBrightness or FastLED::setBrightness or is there yet some other, more authoritative, knob?
Apparently like you, I got lost in the many seemingly similar place there already are to "put something about brightness", and decided to not touch that part until now, in part for that very reason. Taking a few steps back I would say that if we want this to be a device-wide setting then sticking it in DeviceConfig
seems to make sense, but I also note we already have one exception (the effect interval stored in EffectManager
). So, maybe we should figure out what location makes most sense from the perspective of the logic using it, and take it from there.
Sanitizing this part of the project would definitely feel like an improvement to me, although I have to say that my knowledge of that corner of NDS is not enough to be able to say how much we could actually simplify or unify without breaking stuff.
If there is a method to adjust brightness, I have tried it. g_values->Brightness is hard coded to 255 in code and just seems to be used for outputting stats to the console or built in OLED screen. It's more or less a dummy value, currently. FastLED::setBrightness seems obvious, but the current stack for drawing the led pixels completely bypasses whatever this method does. In a normal dataflow you set FastLED.setBrightness() then FastLED.show() or something like that. Bottom line, it does not work with this implementation.
The magic sauce is in a CRGB object. It has a method "maximizeBrightness" which takes a brightness integer. You can maximize between 0 (which effectively sets the color black, making it impossible to bring up the brightness) or 255 which will make the color as bright as possible. In my code I step by 16. The nightmare scenario is changing the brightness on the color sent to each led every time it is sent. For effects where each led might conceivably have a different brightness level (twinkle, fire, etc.), the desired brightness would have to be multiplied by the fractional global brightness. This is the rabbit hole I am heading down currently. I just need to find where in code the color is specified for each pixel and inject some code there to set the brightness based on g_values->Brightness . This is probably similar to what a vanilla implementation of FastLED does behind the scenes. The beauty of this approach is that it will change the brightness on the next frame draw without the need for a watcher since it would just pull the brightness level from g_values->Brightness.
The short version is we need to adjust the color of each pixel using it's maximizeBrightness method just before it is sent out to be drawn.
The other knob that I forgot to list is the power limit.
This is already in place and already is factored in, though only for strip.
On Sun, Oct 1, 2023 at 6:32 PM Joe Schneider @.***> wrote:
If there is a method to adjust brightness, I have tried it. g_values->Brightness is hard coded to 255 in code and just seems to be used for outputting stats to the console or built in OLED screen. It's more or less a dummy value, currently. FastLED::setBrightness seems obvious, but the current stack for drawing the led pixels completely bypasses whatever this method does. In a normal dataflow you set FastLED.setBrightness() then FastLED.show() or something like that. Bottom line, it does not work with this implementation.
The magic sauce is in a CRGB object. It has a method "maximizeBrightness" which takes a brightness integer. You can maximize between 0 (which effectively sets the color black, making it impossible to bring up the brightness) or 255 which will make the color as bright as possible. In my code I step by 16. The nightmare scenario is changing the brightness on the color sent to each led every time it is sent. For effects where each led might conceivably have a different brightness level (twinkle, fire, etc.), the desired brightness would have to be multiplied by the fractional global brightness. This is the rabbit hole I am heading down currently. I just need to find where in code the color is specified for each pixel and inject some code there to set the brightness based on g_values->Brightness . This is probably similar to what a vanilla implementation of FastLED does behind the scenes. The beauty of this approach is that it will change the brightness on the next frame draw without the need for a watcher since it would just pull the brightness level from g_values->Brightness.
The short version is we need to adjust the color of each pixel using it's maximizeBrightness method just before it is sent out to be drawn.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1742238609, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCSD3ZBCQ5MOK3YCUJVL6DX5H4RJANCNFSM6AAAAAAYMW447U . You are receiving this because you were mentioned.Message ID: @.***>
Status update: universal brightness control achievement unlocked. I am utilizing g_Values.Brightness as the universal brightness level. I don't know if this is being stored on device along with the effects manager settings and persists across reboots, but that is something to figure out later. Theoretically a person can just hard code the brightness level to their liking and never touch it again with IR remote or any other mechanism. In other words they can build the code to their specific use case / desired brightness and deploy without ever having to interact with it again. The code to handle all of this is embarrassingly trivial. Most of the work was following the logic and trying to find more detailed FastLED documentation.
In ledstripgfx.cpp
I changed the lines:
for (int i = 0; i < NUM_CHANNELS; i++) FastLED[i].setLeds(effectManager.g(i)->leds, pixelsDrawn);
to
for (int i = 0; i < NUM_CHANNELS; i++) { //changed to the more complex curly brackets format FastLED[i].setLeds(effectManager.g(i)->leds, pixelsDrawn);//Left untouched for (int j = 0; j < FastLED[i].size(); j++){ //Added this for loop to adjust the brightness of the pixel in FastLED. This leaves the original pixel in effectManager untouched. FastLED[i][j].fadeLightBy(255-g_Values.Brightness); // we fade by the inverse of the brightness level. } }
The remote control code just adjusts the global brightness up and down giving about 20 levels of adjustment. I have not looked closely but assume the same tweak will be needed in the ledmatrixgfx.cpp
file.
I ended up going with the fadeLightBy because it fades light proportionately instead of setting to a static brightness level as my previous experimental implementation did on a solid color fill. This means that when a person writes an effect where the LEDs might have different brightness levels (like the fire effect) all LEDs will be dimmed the same percentage. If the brightness is 128 each LED will output at about 50% the luminosity set through the effect. If brightness is 192, the brightness will be at about 75%.
Tip: is first declared in values.h
and is subsequently set to 255 in ledstripgfx.h
. This seems like a redundancy. But changing the value to both of these should set the brightness at boot.
Note: it seems like the matrix code already implements brightness controls. I will build a small test matrix to see if my remote code will also trigger brightness changes in the matrix.
Nice, well done!
I don't know if this is being stored on device along with the effects manager settings and persists across reboots, but that is something to figure out later.
This I can answer straight away: it isn't. In short, for it to be persisted and loaded on boot it would have to somehow end up as a device setting in the DeviceConfig
class.
Note: it seems like the matrix code already implements brightness controls. I will build a small test matrix to see if my remote code will also trigger brightness changes in the matrix.
Please note that LEDMatrixGFX
is only used for HUB75 matrices. WS1812x matrices are driven using the same LEDStripGFX
class that actual strips are.
How is this different from what that matrix already does for brightness when you press the brightness down key (which I think is OFF)? Or did it perhaps only work for matrices and you’ve enabled it for strips?
Rutger, do we persist last brightness? We should!
Thanks! Dave
On Oct 5, 2023, at 11:41 AM, Joe Schneider @.***> wrote:
Status update: universal brightness control achievement unlocked. I am utilizing g_Values.Brightness as the universal brightness level. I don't know if this is being stored on device along with the effects manager settings and persists across reboots, but that is something to figure out later. Theoretically a person can just hard code the brightness level to their liking and never touch it again with IR remote or any other mechanism. In other words they can build the code to their specific use case / desired brightness and deploy without ever having to interact with it again. The code to handle all of this is embarrassingly trivial. Most of the work was following the logic and trying to find more detailed FastLED documentation.
In ledstripgfx.cpp I changed the lines:
for (int i = 0; i < NUM_CHANNELS; i++) FastLED[i].setLeds(effectManager.g(i)->leds, pixelsDrawn);
to
for (int i = 0; i < NUM_CHANNELS; i++) { //changed to the more complex curly brackets format FastLED[i].setLeds(effectManager.g(i)->leds, pixelsDrawn);//Left untouched for (int j = 0; j < FastLED[i].size(); j++){ //Added this for loop to adjust the brightness of the pixel in FastLED. This leaves the original pixel in effectManager untouched. FastLED[i][j].fadeLightBy(255-g_Values.Brightness); // we fade by the inverse of the brightness level. } }
The remote control code just adjusts the global brightness up and down giving about 20 levels of adjustment. I have not looked closely but assume the same tweak will be needed in the ledmatrixgfx.cpp file.
I ended up going with the fadeLightBy because it fades light proportionately instead of setting to a static brightness level as my previous experimental implementation did on a solid color fill. This means that when a person writes an effect where the LEDs might have different brightness levels (like the fire effect) all LEDs will be dimmed the same percentage. If the brightness is 128 each LED will output at about 50% the luminosity set through the effect. If brightness is 192, the brightness will be at about 75%.
Tip: is first declared in values.h and is subsequently set to 255 in ledstripgfx.h. This seems like a redundancy. But changing the value to both of these should set the brightness at boot.
Note: it seems like the matrix code already implements brightness controls. I will build a small test matrix to see if my remote code will also trigger brightness changes in the matrix.
— Reply to this email directly, view it on GitHub https://github.com/PlummersSoftwareLLC/NightDriverStrip/issues/284#issuecomment-1749451402, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4HCF6A2ZXKT2QZWIU475DX535NHAVCNFSM6AAAAAAYMW447WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONBZGQ2TCNBQGI. You are receiving this because you were mentioned.
Rutger, do we persist last brightness? We should!
@davepl No, we don't. As I commented about 15 minutes ago, for that the brightness would have to be "promoted" to a device setting in DeviceConfig. It would have the added benefit that the brightness can also be changed/set using the Web UI. With that brightness device setting in place:
Nothing too complicated overall. I'm sure I can put a PR for this together, this coming weekend.
2 things as a follow up: First: I need to get things ready for making commits to the remote control code. My local repository was way out of sync with the main branch. Getting that straightened out was a pain. I am getting my environment prepared for the eventual task of pushing changes / making pull requests to the remote code. Using the desktop client, I made a pull request for a small, yet important change to effectmanager.h . This is a test to make sure that my setup is setup properly and also correct an annoying bug in the said file. I am still a few weeks out before I will be ready to push the remote code.
Second: Also, I am going to propose putting the main brightness up and down logic into the effect manager instead of the remote. This will allow a person to trigger the adjustment from other interfaces that interact with the effect manger. If a person has a physical push button wired or repurposes a button on the board it can be coded to trigger the brightness change instead of having to interact with the remote control code. I propose three methods: SetBrightness to set a definite level. IncreaseBrightness to increase by 13/255 or about 5%, and DecreaseBrightness to decrease by 13/255. This will be an easy change and will interact with g_Values.Brightness unless / until a different variable is used. (But, to be honest g_Values seems like a decent place to keep it since a person can just set the initial value to be whatever they want at compile time and use their adjustment method to change.) I will issue a pull request soon if this is a good idea. That is assuming my I have everything configured properly to trigger pull requests.
Second: Also, I am going to propose putting the main brightness up and down logic into the effect manager instead of the remote.
@revision29 We will move the main brightness setting (and any logic for changing it around it) not to EffectManager, but to DeviceConfig, as I mentioned in my previous comment. I'll take care of implementing that setting (as well as replicating it to g_Values.Brightness and exposing it to the web UI) this coming weekend. To be honest, I'm not fully convinced that moving the up/down logic away from the remote makes sense, unless and until there really is a second interface that uses the exact same change intervals that the remote does. That said, I don't have that strong an opinion about it either.
@revision29 So the shift of g_Values.Brightness to DeviceConfig is now in the brightness-setting branch in my fork. In the end I decided to remove g_Values.Brightness altogether, because the number of places referencing it was actually rather limited - all of those now read and write brightness in DeviceConfig.
I'll run a final test on PR #451 that I opened a few days ago, and merge that if that still works. I'll then open a new PR for the brightness setting change.
Device Config makes the most sense. I’ve not ventured into that part of the codebase. I erroneously thought the variable for brightness would be stored there and not the logic for making the adjustment. I would suggest using something like the three methods I proposed to make it easier to trigger from other places in the he code. The increase and decrease methods can receive an integer instead of the number being hard coded. For the decrease brightness it is probably important to put a check in place to not allow the value to go below 0 and a similar upper limit of 255 for the increase brightness. Anyway, I’ll try to keep an eye out for your changes and sync down to my codebase so that I can start seriously implementing my code.Out of curiosity, was my pull request regarding the set global color code received? I’m not convinced my GitHub setup is correct or that I know the correct place to initiate a pull request from my fork. On Oct 6, 2023, at 11:38 AM, Rutger van Bergen @.***> wrote:
Second: Also, I am going to propose putting the main brightness up and down logic into the effect manager instead of the remote.
@revision29 We will move the main brightness setting (and any logic for changing it around it) not to EffectManager, but to DeviceConfig, as I mentioned in my previous comment. I'll take care of implementing that setting (as well as replicating it to g_Values.Brightness and exposing it to the web UI) this coming weekend. To be honest, I'm not fully convinced that moving the up/down logic away from the remote makes sense, unless and until there really is a second interface that uses the exact same change intervals that the remote does. That said, I don't have that strong an opinion about it either.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>
@revision29 The PR that will make main brightness a persisted device setting is #454. I did not implement methods to increase or decrease the value (by a value passed or not), but you're free to incorporate that into your future PR. If it's in there I'll consider it again and actually make up my mind about it.
I looked for your global color code PR in this repo, in Dave's fork and in your own fork, but I've been unable to find it in any of those places. I'm sorry to say that means that I can't think of where it went, if anywhere.
At some polnt the "Brightness Down" button, second from the left in the top row of the remote, next to ON) used to dim the brightness. If you hit ON, it would set to max brightness and pin the effect on.
I think the top two buttons should be Brite- and Brite+ and I prefer that Brite+ just goes to max brightness, not steps up. But we need to move the "SET_EFFECT_INTERVAL to MAX" feature to another button, one of the spare buttons in the lower right.