Ok, maybe not stupid, but I did miss something pretty fundamental and I missed it early enough to waste a couple of days of development time. Also, there was a side quest through the quicksand that is Windows USB drivers.
As mentioned earlier, ESP-NOW is expected to fulfill a number of needs for my project. To recap, I have built a reliable target activating system applicable to several shooting sports I am involved in. It is reliable because it is electrically pretty simple, with some switches and relay providing the limited logic needed, a control box with said relays and switches and a battery and finally the connectors and cabling to hook it all up.
Removing those cables can be done with a wireless system that essentially doubles the built cost for the system. It would also be plenty reliable, but the cost is prohibitive, especially as I do intend to sell this system and I can’t make the price attractive and make a little money on it if I have to spend that much on the wireless technology.
The hardware for ESP-NOW is built in to microcontrollers that already support WiFi and are incredibly cheap. Furthermore, adding a microcontroller will let me replace a couple of other expensive parts while added even more features.
Of course, ya gotta get it working first.
I had easily set up two devices where one could messages to the other. I found an easy to follow YouTube tutorial for two way communication between two devices and chose that one to implement for the next step. The tutorial had a lot of symetry to it. Two ESP32 devices, each with an environmental sensor (temperature, humidity and pressure) and a tiny OLED display. The environmental data from each device was displayed on the other. The sketches are identical on both devices other than the manual entry of each devices peer MAC address, the device it is sending data to. While some of the ESP-NOW tutorials included facilities to scan for peers and automatically record their MAC addresses, this one assumes you know the MAC address for each of your devices and even includes a super simple sketch to extract the mac of the board it runs on. I ran this sketch and recorded these MAC addresses in a notepad text file for later reference. The sketch requires the MAC address to be stored in an array variable and in the declarations area of the sketch, this array variable was created in this form…
… where you would substitute the MAC address octets of the peer device for 0xFF in each position. If you leave it all FF’s, it will work by broadcasting the data to all devices on the network and the ESP-NOW devices will actually listen. However, the receiving devices do not acknowledge receipt of the message, where as unicasting to a specific MAC address does. There are situations where broadcast is appropriate, but for my purposes, I’d rather have the acknowledgement.
In my notepad, I created this string of hex notation digits so that I could just copy and paste the MAC into any script I was working on.
I modified the sketch, simplified it, removing all the code to support the display and environmental sensor because I didn’t have those to connect to it. My sketch sent two bytes to each other. Eventually, my messages between units will also be just two bytes, on as a unit identifier, the other as a command or status. I could probably make that two nybbles and just send a single byte.
The trouble is that my devices would only send one way. I had intended one to be the Activator and one to be the Control Box. Under normal circumstances, the Control Box will send a command to the Activator to instruct it to trip immediately. The Activator will either periodically send a status or it will respond to a poll for status from the Control Box. In my case, however, communication was also only one direction. The sending unit did not have an acknowledgement and the receiving unit never received any messages. I did a few minor troubleshooting steps to ensure that my sketches were indeed identical other than the peer MAC addresses.
The next step was to swap out equipment. I was using one ESP32 for the Control Box, assuming I would want to add more features to that one eventually and they have more I/O pins. The Activator was a very inexpensive ESP8266 board and there was always a chance one might have a bad transmitter. When I started swapping boards and sketches around, the laptop would occasionally not drop the virtual comm port when a board was unplugged. It would sometimes take a reboot to clear this issue. I had two instances of the Arduino IDE running. Juggling two IDEs and two of about four available cards when sometimes the USB subsystem would basically stop responding and require a reboot to fix quickly grew tedious as hell. I reached a stopping point on the first day and had to drop it at least overnight.
The next day, I decided that, since I was fighting some weird issues, I would work with some ESP32 boards instead of the 8266’s. The libraries for ESP-NOW and WiFi are different between the two MCUs. It was just a variable wanted to eliminate. The situation was largely unchanged, including the USB virtual comm port issues. I had a new sympton there. Now sometimes, I could get two of the same virtual comm port number. A bit of research revealed that sometimes, the USB to serial chips on these boards will have the same serial number, at least as far as Windows Device Manager can tell, so it give them the same comm port. I could manually edit one of them to an unused port number and make them work, but the more I unplugged boards, the more often the entire subsystem would lock up. Reboots would take several minutes, then time out with an error “DRIVER POWER STATE FAILURE” and it would then reboot itself from the reboot process. It happened several times and took 5-10 minutes EACH TIME to complete a reboot. That was the clue I finally latched onto and worked on replacing the driver for the USB to serial chip on these boards, the Silicon Labs C210X series.
That is an easy download, but of course by now, things weren’t going to go easy. Eventually, I discovered that there were three separate sets of Silicon Labs drivers installed on my laptop. I presume there was some subtle difference between some of the ESP boards I have plugged into this laptop and each installed it’s own ‘most recent’ drivers. I deleted them all and installed the fresh download from Silicon Labs, dated in 2023. This seemed to settle down the USB traumas.
Of course, they would still only communicate in one direction.
Now that I felt like I could trust the USB stuff, I added some code to print the device’s MAC address and peer MAC address during the setup() function. It never printed. I added other tag prints to show where in setup execution was. Those never printed. It was like it was skipping the setup() function. Google again.
Eventually, I found some references to the serial port/driver being slow to come up at boot timer or after an upload. One solution was to use a while loop to wait until the serial system was active. That didn’t help, either. Finally, one suggestion was to literally wait for 5 seconds before executing the Serial.begin() function and that finally worked! It was kludgy and needed only for sanity checking while developing, but it worked. The two MAC addresses printed out.
Since I copied and pasted the information into my notepad file, I have no idea how one of those MAC addresses was wrong and more importantly, how a C got changed to a D. They are adjacent keys, but good grief.
It can easily be argued that fixing the USB driver thing definitely needed to be done, but because of that distraction and the slow start on the USB serial port connected to it, troubleshooting a friggin’ TYPO took two days.