2 weeks of Hardware-in-the-loop testing + LiFePO4 cell build!

Didn't blow up the cells. The two 6s packs had all their copper bus bars installed. It was really fantastic to not have to spot weld hundreds of cells together. The shape of the bus bar will allow a small amount of bending in the main spine without transmitting excess bending loads into the terminal of the battery. This is why I went with this type of bent bus bar instead of an M14-M10 female-female threaded coupler. Shout out to @sendcutsend for the fast turnaround time on the parts. $100 shipped for a few dozen laser cut and precision bent brackets made in the USA. It’s truly a great time to be doing hardware.

I admit that shrinking the 4” heatshrink was extraordinarily satisfying. The fit inside the 3” Triclamp tube is super snug, maybe .005” gap. Each cell gets a balance wire at the midpoint of the bus bar, and that runs back to the BMS. I went with the Enepaq TinyBMS from Lithuania. The quality of the build was good, and their software was quite straightforward. It can use UART, Modbus, or CAN. Currently, I’m running fairly conservative settings, as this is my first time using LiFePO4

  • Charge upper cutoff: 3.55v

  • Lower voltage cutoff: 2.9v

  • Charge rate = 0.3c

The Chinese LiFePO4 cells are tracking together fairly well. The manufacture said they would match cells, and everything seems to be within 4mv on average.

Now that I’ve got a 1000whr (50ah@20v) flight battery hooked up, the HITL cart can run through the whole night with the entire system on (Starlink, servos, Pi, Gopros, ect). I still need to walk through all possible voltage scenarios to verify that the MPPT and BMS are behaving as expected. My worst fear is an unrecoverable scenario where the Sunsaver MPPT gets into a fault state and doesn’t power the load channel on, which is upstream of the whole system. This can happen if it doesn’t detect a valid battery on the charge lines. This could happen if the BMS takes the battery offline. I’m considering if it’s a good idea to route the raw solar cell 36v lines (55v open circuit) to the PCB as an emergency backup. It would seem silly to have a perfectly healthy 300w array and be dead in the matter if the BMS has a bad day and doesn’t connect the battery. In this case, I could limp it on solar power alone back to land. I would have to buck the 55v down to my 24v system voltage, but that’s doable.

Currently, I’m on the fence about whether I should run a single 6s pack or dual 6s packs. There is room in the 10ft Triclamp spine for two packs, but I’m afraid of adding too much complexity to the power management system. A second BMS would be required, and switching logic to cycle between the packs on a weekly basis. The number of cycles for running a single pack(~300) isn’t super high compared to a reasonable LiFePO4 lifetime. Is it really worth the extra weight to have fault tolerance in this one particular area, when I still only have one solar array and one MPPT? The spacecraft systems engineers can chime in here. We might just do a lot of testing and send it?

Logging:

Grafana+InfluxDB continue to crush it. I am a huge believer in logging every channel of every device, 24/7. It baffles me when I see legit startups without a unified data ecosystem and DAQ systems. Lots to say there, but I digress...

It's slightly scary to charge a giant homemade battery for the first time off a brand new solar system. I was watching super closely for weird behavior. The voltage curve for LiFePO4 is so flat, you really need a few hundredths of a voltage resolution to see movement during most of the curve. You can see the solar voltage and power production fluctuating as clouds passed by. The 300w array peaked at 250w. More important is the integrated energy collected, about 800whr, or 2.88MJ. This equals a specific performance of 2.66 watts/array_watt/day. Pretty decent performance for a cloudy day. On a sunny day, would hope to see closer to 4.0.

Python pulls everything off Modbus, I2C, rs232 and pushes to the InfluxDB container every 5 seconds, for a few tenths of a watt cpu load. Anytime day or night, I can switch on Tailscale on my phone and pull up the real-time stats on the outdoor HITL+Starlink table.







GoPro is Working… Mostly

As I mentioned before, the GoPro is a bit of a finicky device to work with, and it seems like a lot of you have had similar experiences. I love the image quality, exposure control, and Timewarp stabilization. But, unfortunately, it's not really designed to be a long-duration camera. While it's incredibly rugged and battle-tested in the field, the interface does present some issues that need to be managed.

The backup option is a more traditional IP camera like a HikVision. The problem is that all these cams have potato image quality, especially with a 1/3" CMOS sensor. If we have any hope of capturing the Milky Way, it has to be either a GoPro or a DSLR. Shoutout to @radshaan and his team of sharp engineers. I sent them a GoPro Hero 12, and they've been helping with the codebase.

Quick Overview of the System Architecture:

  • Raspberry Pi 4 as the bare-metal compute

  • GoPro Hero 12 with the battery removed, running Labsfirmware and a USB power mod

  • USB connection via a powered 2.4A USB 2.0 hub

  • Docker (@Docker) containers, including a dedicated GoPro container

  • Portainer (@portainerio)

  • InfluxDB (@InfluxDB)

  • Grafana (@grafana)

  • Tailscale (@Tailscale)

  • Google Bucket storage

The GoPro uses a USB-NCM network adapter and communicates via HTTP requests. GoPro maintains a moderately well-documented API, but the tricky part revolves around the USB network adapter. If the container crashes or gets interrupted during a capture event (e.g., while the shutter is open), it tends to leave the GoPro in an odd port state. This usually results in one of two outcomes: the USB device either doesn't show up at all, or the ETH2 network adapter won’t ping. Both are frustrating and difficult to recover from. Typically, I have to drive to the lab and physically unplug the device.

The ideal solution is a managed USB port where I can disconnect both data and power lines on command. My plan is to route the USB data lines through my PCB and use a TI eFuse on the 5V VCC lines. This will allow me to perform a hard power cycle since the GoPro won’t have a battery. So far, every time I’ve power-cycled it, the GoPro comes back clean once I rebind the USB port and renew the IP on ETH. PCB Is like #6 on the priority list...

It’s been a lot of trial and error to figure out how to manipulate the various setting IDs through the API. There are about 200 settings controlling everything from frame rate to resolution, and the tricky part is you can only adjust the settings for the current mode. For example, if you’re in Timelapse mode, you can’t alter Video mode settings. There isn’t a clear map of mode-to-settings, so I’ve been slowly figuring out what works.

I've really enjoyed working with Docker containers throughout this project. To be honest, my DevOps skills have been a bit behind the curve, but I’ve been making an effort to catch up. It’s great having completely isolated environments for all my different tasks, whether they're short- or long-duration processes. Trying to manage this through async or threading in one big Python file would’ve been a total nightmare. The containers let me keep everything neatly separated—the InfluxDB database, the sensors, the flaky GoPro, and the navigation systems. Big shoutout to @portainerio for sponsoring me with a business license. I’ve been using their platform long before they found me on Twitter because, frankly, I think CLI is overrated. A clean UI for managing containers just makes sense.

Today was the first day that the entire pipeline functioned end to end. I rebooted the Pi at 8 a.m., and all containers started automatically. The GoPro container wiped its SD card, configured the modes, and initiated a 2-hour timelapse with a 30-second interval per frame. Once it finished, the file was retrieved over USB and uploaded to a Google storage bucket through the API, all over the Starlink Mini connection. Every few hours, I can check my Google Drive to see the latest timelapse clip. Pretty cool stuff! Next, I need to dive into the NightLapse settings, which are optimized for low-light capture. Maybe I can even convince someone to turn off the parking lot lights...

It took about a week of waking up at 5:30 a.m. to get a few hours of coding in before work, testing everything in the back parking lot with my outdoor HITL environment. Now, it's stable enough that I can do most of the work remotely via Starlink. Hopefully, in the next 2-3 weeks, I’ll have a quick PCB design ready for the USB-unplugger-omatic and the setup will be bulletproof.

The last two-week sprint goal was to get the entire hardware-software stack operational and see if everything worked as expected. Now that it's stable, I can begin more thorough testing and return to the much-neglected mechanical work on the hull. My large pile of SendCutSend parts is staring at me, just waiting to be assembled. Hopefully this weekend I can get out a keel mechanical update.









Next
Next

Battery Spine Fab Has Begun! Steel Is Real.