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 start 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



Monday, December 9, 2024

Did Thingiverse shadow ban my models?

As a hobby, I do some 3d modelling generally around small designs I think might be useful. They include things I make to use around the house, or just general interests of mine. 

Recently, I did a couple models in regard to window screens. These models quickly got a lot of attention with views and downloads. For a few months the numbers just kept growing... until suddenly it stopped. 

Download/View Activity

Download/View Activity with Markings

Maybe Thingiverse shadow banned me, making it harder to find my models in their search, but here are a few other possibilities that probably make more sense. 

Weather: For many, going into winter is not the time to be installing window screens. The application of such a thing is generally more of a spring/summer necessity. This could have contributed to a reduction in activity.  

Third-party Referral Sources: There are websites that aggregate models across different platforms for the purpose of comprehensive searches (and monetizing users). These sites may have been contributing to my numbers and have possibly modified their code (i.e. yeggi.com) for reasons only known to them.

Thingiverse Updates: There was a thingiverse update around this time. It is entirely possibly that the update changed things in relation to how models are suggested to site visitors. Another option with this update is that they are actively trying to reduce the number of bots downloading models for the sake of duplicating your work, which may have been part of this update.

At the end of the day I provide these models for free with the hopes that maybe they will help someone else solve a problem or give someone a starting point to make something even better. 

Overall, it is hard to say exactly why the numbers dropped like they did, and we likely will never know. But one thing is for certain. It won't do any good to assume the worst. 





Sunday, September 29, 2024

ESP8266 Captive Portal, Static Serve, and Websockets

While working on a toy for my dog, I wanted to set up an AP with captive portal. This took a little bit because a lot of examples out there were a bit out of date and did not work properly. The main issue was that the CaptiveRequestHandler class was not specifically handling Android and iOS captive handler endpoints. 

I changed the class like this and it worked fine: 

class CaptiveRequestHandler : public AsyncWebHandler {
public:
  CaptiveRequestHandler() {}
  virtual ~CaptiveRequestHandler() {}

  bool canHandle(AsyncWebServerRequest *request){
    String url = request->url();
    return (url == "/generate_204" || url == "/hotspot-detect.html");
  }

    void handleRequest(AsyncWebServerRequest *request) {
        if (!request) {
            Serial.println("Received null request");
            return; // Return early if the request is null
        }

        // Check for specific requests (e.g., Android's `/generate_204`)
        if (request->url() == "/generate_204" || request->url() == "/hotspot-detect.html") {
            // Redirect to the captive portal (ESP8266’s IP)
            request->redirect("http://192.168.4.1/index.html");
        }
    }
};


The canHandle was modified to only handle these methods, otherwise to return false. This is important because later we want to handle requests with other handlers. 

That said, I also added a static serve handler:

WiFi.softAP(SSID);
dnsServer.start(53, "*", WiFi.softAPIP());
server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//only when requested from AP
server.serveStatic("/", LittleFS, "/").setDefaultFile("index.html");

This meant my index.html page would request other assets (images, css, js) and they would be served. One thing to note is that in order for this to work on a platformio project, you need to update your platform.io config with your (filesystemboard_build.filesystem = littlefs)

Finally because we are allowing handlers, we can setup the web sockets. 

// Set up WebSocket
ws.onEvent(onEvent);
server.addHandler(&ws);  // Add WebSocket handler to the server

// Start the server
server.begin();



Friday, September 13, 2024

Slightly Painful - Painless Mesh for ESP32

While working on a mesh networking project, I decided to give Painless Mesh a try. 

I ran into whole bunch of issues in PlatformIO for some reason, so I resorted to using ArduinoIDE 2. 

The first weird thing was that I got a message saying: 

Failed to install library: 'PubSubClient:2.8.0'.

Error: 2 UNKNOWN: destination dir C:\Users\CorrLabs\Documents\Arduino\libraries\PubSubClient already exists, cannot install

The solution to this was just to manually delete the folder and reinstall the library. For some reason there was a library already downloaded, but Arduino IDE could not utilize it.


Then I ran into this one:

wifi.hpp:49:14: error: 'class WiFiClass' has no member named 'setAutoConnect'; did you mean 'setAutoReconnect'?

Fortunately, I found a comment by a person named luckymatt who had the answer to this. Basically the problem is just with compatibility changes between versions. 


At this point, I was able to compile and flash my ESP32-WROOM32 dev board with the Painless Mesh MQTT example.


References:

https://forum.arduino.cc/t/error-with-wifi-hpp-when-compiling-painless-mesh-code/1248608/13

Sunday, June 2, 2024

Visual Studio Installer: ERROR: The system cannot find the file specified - following system restore

Problem: 

A long story short, a bad USB adapter killed motherboard USB headers. The system was old enough that buying a new CPU/motherboard would be as much as buying a used motherboard. I decided to do a new build, and with a fresh install my OS. While installing Visual Studio Community 2022, I found that the installer would download files, but then die when trying to perform the install. I had earlier had a BSOD issue with a PCI card, and ended up running a repair on my system. This messed up a lot of my just installed applications including Visual Studio. Oddly, the installer did not list a specified file, the rest of the error popup was blank.


Solution: 

After researching their cleanup tool (which you can only get if you successfully installed VS) and reading a couple SO posts, I decided to just try something. I renamed my application directories for 

    C:\Program Files (x86)\Microsoft SDKs 

    C:\Program Files (x86)\Microsoft Visual Studio 

and tried the installer again. This time it worked. 

Keep in mind this will likely mess with any settings you have already in place.