Sunday, May 25, 2025

The formidable Formidable Forms - Which checkboxes are checked?



Helping someone close to me with their WordPress website, and more specifically Formidable Forms, it became apparent that the level of complexity with what they wanted was not as simple as we had hoped. 

Problem:

I needed to be able to determine which checkboxes the user had selected from a question. I didn't want to set up new forms and dynamically link data together (or however that works). I needed to know which product type was selected, and based on features (from checkboxes), compute a modified price for the product. 


Solution:

As I was thinking about the problem, it dawned on me that unique selection from a single number is not a new problem. We use bitwise calculation to determine permissions on file systems, so why wouldn't something like this work here as well?

Here is what I did. 

When you reference the field (group of checkboxes) using their field bracket notation "[123]" it returns the list of selections as a string with commas between each value selected. This is not a problem for JavaScript, but I wanted to solve the problem without writing JavaScript that would have listeners, etc. Also, in the checkboxes field, you can define custom values for each checkbox, and because every value has to be unique to the entire form, you generally preface the value with the option label. When they compute the numbers, they drop off the prefixes unless you specify you want the whole thing. 

In this case, I set up the checkboxes like this:

Option 1 (value: option1 - $1)

Option 2 (value: option1 - $2)

Option 3 (value: option1 - $4)

Option 4 (value: option1 - $8)

with the dollar amounts being base 2. (Ignore them as dollars amounts, that's purely for our logic - you will use the correct values later.) Then, I created an addition hidden field for each checkbox (called HasOption1, etc.) and added the calculation:

([123] % 2 >= 1) ? 1 : 0

To check the first option selection. The modulo 2 cuts off all the base 2 numbers above our target, and the the number "1" after it is checked as greater to or equal to our intended base 2 value (in this case 1) - which would come back as 1 if it is selected and 0 if it is not. 

For example, if we wanted to know if Option 3 was present, we would do this: 

([123] % 8 >= 4) ? 1 : 0

This is because Option 3 has a value of $4, and the value of Option 4 ($8) is too high. 

Later in the code, it was easy enough to reference the new hidden fields like Booleans to determine how to do more advanced calculations. 

If anything though, I realized there is probably a much better way to do forms on WordPress... I just likely won't be the one to build it. (Who knows? Maybe someone already did.) 


Wednesday, February 12, 2025

Why I deleted my Stack Overflow account...



After over 4 years, I finally decided to delete my SO account. Don't get me wrong, there are a lot of great ideas on SO, one of which include the community rating system to bring relevant answers to the top. In addition, they have a whole structure built up to try and help people find answers to their problems. Overall it's a worthy goal. 

The failures come in several ways, however. 

No Answers for Unique Problems

I cannot tell you how many times I have gone in search of answers to specific problems and I just find other people with the same problem. This has felt like it is becoming more common just in the last couple years. Are people still using SO?

Bad Answers

This one is pretty crazy. Sometimes people leave absolutely terrible advice. I've seen comments promoting security by obscurity and outdated password practices (but recently posted answers). 

Outdated Answers

Sometimes the answers are from almost 10 years ago. Makes sense when you consider that SO was released in 2008, but that's not going to help most of us who have tried to keep up with the times and the tech. 

Moderating Disasters

A few times I have been in a hurry but left an answer with links to more resources. Within an hour or so, I would have 5 moderators jumping on me, editing my post, down-voting my answer (all 5 of them), and berating me for linking to websites or blogs and not providing more complete answers. I can understand the desire to keep answers clean and host complete information, but the way this was handled seemed overzealous. One moderator giving feedback would have been plenty. 

Anyway, I'm not going to put up with any of that, so today I decided to delete my SO account. 

So where do we find our answers now?

The Future of Finding Answers

AI comes to the rescue (probably trained in part by SO answers). But these answers (while not always 100% accurate or recent) are getting better and becoming more specific to our situations. The faults of AI are quickly minimizing, and the cost and speed keep improving (i.e. DeepSeek). 

Saturday, February 8, 2025

Full Color Spectrum Color Chart / ColorPicker

For a project I have been working on with ESP32, I wanted to make a simple drawing program. It would be simple enough to add a limited swatch of colors, but I really wanted to provide as many colors as would be supported by the hardware. 

Being that my input controls are limited (it is not a touch screen), I wanted to have all the (spectrum) colors available on one chart. After looking around for a bit, and playing around with DeepSeek, I was able to quickly produce the chart I was looking for, and it's actually pretty simple. 




The answer is that by using two gradients (one horizontal, one vertical) with drawing on a html Canvas element, would produce this result. Here is the HTML if you want to try it yourself. 


     <canvas id="paletteCanvas" width="500" height="300"></canvas>


    <script>
        // Function to initialize the color palette
        function initPalette() {
            const canvas = document.getElementById("paletteCanvas");
            const ctx = canvas.getContext("2d");

            // Create horizontal gradient (hues)
            const horizontalGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
            horizontalGradient.addColorStop(0, "rgb(255, 255, 255)"); // White
            horizontalGradient.addColorStop(0.1, "rgb(255, 0, 0)"); // Red
            horizontalGradient.addColorStop(0.25, "rgb(255, 0, 255)"); // Magenta
            horizontalGradient.addColorStop(0.4, "rgb(0, 0, 255)"); // Blue
            horizontalGradient.addColorStop(0.55, "rgb(0, 255, 255)"); // Cyan
            horizontalGradient.addColorStop(0.7, "rgb(0, 255, 0)"); // Green
            horizontalGradient.addColorStop(0.85, "rgb(255, 255, 0)"); // Yellow
            horizontalGradient.addColorStop(1, "rgb(255, 0, 0)"); // Red

            // Apply horizontal gradient to the canvas
            ctx.fillStyle = horizontalGradient;
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            // Create vertical gradient (brightness)
            const verticalGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
            verticalGradient.addColorStop(0, "rgba(255, 255, 255, 1)"); // White (opaque)
            verticalGradient.addColorStop(0.5, "rgba(255, 255, 255, 0)"); // Transparent
            verticalGradient.addColorStop(0.5, "rgba(0, 0, 0, 0)"); // Transparent
            verticalGradient.addColorStop(1, "rgba(0, 0, 0, 1)"); // Black (opaque)

            // Apply vertical gradient to the canvas
            ctx.fillStyle = verticalGradient;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
        }

        // Initialize the palette when the page loads
        window.onload = initPalette;
    </script>


I also replicated this in Photoshop using 2 gradients stacked, and the result is a bit nicer, having less of that star effect in the middle. 



Monday, January 27, 2025

Lilygo TTGO T-Display ESP32 - 16MB flash troubles with platformio

Problem:

I purchased some t-display compatible boards and wanted to setup them up for some fun projects I have in mind. I generally prefer to use VSCode for my editing over Arduino IDE due to the flexability of control. 

Here is what I needed to figure out:

  • SPI.h was missing
  • Correct Partitions for my board (16MB)
  • How to get pio to understand the board as 16MB and not 4MB (the default lilygo configuration value)
  • Getting my system to use the littlefs filesystem and not spiffs
  • Getting TFT to render following pio upload (worked after arduino IDE upload)

Solutions:

Missing SPI.h, LittleFS.h, FS.h and more
For some reason my build would not find these libraries even though I made sure they existed properly in the esp32 folder. So I included them manually in the platformio.ini file build flags. Once I did this, the system actually healed itself somehow, and I was later able to remove these references. 

build_flags =
    -I"C:\Users\CorrLabs\.platformio\packages\framework-arduinoespressif32\libraries\SPI\src"
    -I"C:\Users\CorrLabs\.platformio\packages\framework-arduinoespressif32\libraries\FS\src"
    -I"C:\Users\CorrLabs\.platformio\packages\framework-arduinoespressif32\libraries\LittleFS\src"

Partitions
The huge_app.csv partition scheme would probably work fine, but I wanted to allocate 4MB for app0 and app1 and then have a large chunk for data, so I created my own partition scheme. 
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x5000,
otadata,  data, ota,     0xe000,  0x2000,
app0,     app,  ota_0,   0x10000, 0x480000,
app1,     app,  ota_1,   0x490000,0x480000,
spiffs,   data, spiffs,  0x910000,0x6E0000,
coredump, data, coredump,0xFF0000,0x10000,

16MB not 4MB!
Despite having specified that my build.flash_size was 16MB in my platformio.ini file, the system insisted that my board was only 4MB and therefore would complain when trying to upload my filesystem image. I could not find any settings I could set from the ini that would solve this problem. I ended up creating my own board definition by copying lilygo t-display and making one called lilygo-t-display16mb and updated the values inside the file to be for 16MB. I also created the variant folder of the same name with the pins_arduino.h so it would be able to find those by default. 

C:\Users\CorrLabs\.platformio\platforms\espressif32\boards\lilygo-t-display.json
C:\Users\CorrLabs\.platformio\platforms\espressif32\boards\lilygo-t-display16mb.json

"build": {
    ...
    "variant": "lilygo_t_display16mb"
},
...
"upload": {
    "flash_size": "16MB",
    "maximum_ram_size": 327680,
    "maximum_size": 16777216,
    ...
  },

C:\Users\CorrLabs\.platformio\packages\framework-arduinoespressif32\variants

LittleFS
PlatformIO really wanted to make my filesystem SPIFFS, but on certain projects I prefer the safety of littlefs. This seemed to do the trick. 
board_build.filesystem = littlefs

TFT Display Issues
I have the display working fine in my Arduino IDE, but for some reason it does not display anything when trying to load a bmp from my LittleFS filesystem. It also would not display a red screen using only the TFT_eSPI library, so I knew it had to be something with the configuration for the TDT display. Oddly, the User_Setup.h file was identical to my Arduino IDE one - and that one worked. The versions of TFT were the same, so I did a Full Clean and reinstalled the one in pio just to be sure. Still no dice.

I was also able to eliminate that something was incorrect with my spiffs partition, as a partition flashed from my PIO project will work fine when connected to firmware flashed by Arduino IDE without flashing the spiffs partition again. This means the problem is exclusively related to the firmware code. 

Turns out if you have the right build flags, in your ini - it will work just fine, no User_Setup.h needed and no modifying dependency code:
build_flags =
    -D USER_SETUP_LOADED
    -D ST7789_DRIVER
    -D TFT_WIDTH=135
    -D TFT_HEIGHT=240
    -D CGRAM_OFFSET
    -D TFT_MOSI=19
    -D TFT_SCLK=18
    -D TFT_CS=5
    -D TFT_DC=16
    -D TFT_RST=23
    -D TFT_BL=4
    -D TFT_BACKLIGHT_ON=1
    -D SPI_FREQUENCY=40000000