MarkBryanMilligan / LanternPowerMonitor

The Lantern Power Monitor is a Raspberry Pi service, Java Web Service, and Android application that allow you to monitor every electrical breaker in your house, regardless of how many panels or breakers you have.
GNU General Public License v3.0
80 stars 26 forks source link

Multiple SPI buses? #23

Open kitlaan opened 2 years ago

kitlaan commented 2 years ago

(Do you want to turn on Discussions, to not clutter up Issues?)

Disclaimer: I'm brand new to this equipment, so take this with a dish of salt...

I was reading some of the posts about your design, and noticed your statement about pegging a single core. Since you have two MCP3008 chips (on the same SPI, and select between the two), this means you sample each round-robin.

Since Raspberry Pis have (at least) two SPI buses, have you thought about putting each MCP3008 on an independent bus, and thus read them simultaneously with two threads?

And then extrapolating from there, could you piggyback two PCBs to a single RasPi (and thus get 16x2 CTs hooked up, at your currently designed sampling rate)?

Alternatively, it looks like the RasPi4 has even more SPI buses (looks like 4 are feasible), so you could possibly read four MCP3008s simultaneously (at the cost of maxing out all the pi's cores...).

MarkBryanMilligan commented 2 years ago

Yeah, I'll turn on discussions after this kickstarter is finished. Multithreading and increasing the sample rate is definitely something I've considered. The accuracy is so good with what I'm doing now I didn't feel like adding complexity to improve it further. I'd be more interested in adding complexity if it meant being able to add more MCP3008s. How would you wire up 4 chips to one pi?

kitlaan commented 2 years ago

Here's my theory...

Use SPI0 + 2 CS as you have currently (pins 19/21/23/24/26). Use SPI1 + 2 CS for a second board (pins 38/35/40/12/11/36). I imagine running two threads concurrently each running its own SPI could get you the current accuracy, but now with double the number of CTs (semaphores notwithstanding).

Assuming that even works, I wonder if you can split the AC transformer to both boards...

I guess the simplest experiment (once I get boards) is rather than stacking the PCB to the pi directly, just wire them up manually, each to its own SPI.

MarkBryanMilligan commented 2 years ago

I need to look into how to access SPI1. I'm using wiringPi for all of this interaction and the guy who maintains that rage quit a while ago, and I'm not sure if it provides access to SPI1. Maybe there's a newer library I should be using.

If it's really possible to do that, I would just redesign the board to put it all in one, and then I only need to use one port for the voltage, and 31 for current. That would be pretty amazing. Even a pi zero 2 w has plenty of cpu room to double the ports.

kitlaan commented 2 years ago

Here's what I ran across this during the googling-fest in the last hour...

MarkBryanMilligan commented 2 years ago

I really need to rewrite the pi code in C. It'd be so much faster and I'd have so much control over memory. I went with java so I could use the same data model on the pi, the server, and the android app. I pre-allocate all the memory for the SPI reads in java so garbage collection isn't triggered, but it'd be more deterministic in C. To really optimize I probably need to switch to C. JNI works and all, but man I hate it. Why are you throwing all of these good ideas out here on the most stressful night I can remember waiting for a kickstarter to hit its goal!?!?

kitlaan commented 2 years ago

Sorry; I only started digging because there's only hours left and I'm itching to poke around. 😀 I wish I had run across this project months ago...

I'd be pretty happy if you switched to C/C++ as I could help with development (as my Java's pretty much completely been paged out in the last two decades).

MarkBryanMilligan commented 2 years ago

Let's see how tonight goes. Regardless of whether the kickstarter succeeds or fails, I want to optimize the pi. If we could get 31 breakers on one pi, it would crush anything else out there.

kitlaan commented 2 years ago

Since I can't leave well enough alone (and I don't know how to turn off my brain on PTO)... I was pondering how you could have a single PCB module supply 16 plugs but allow them to be multipurpose.

Some half-baked thoughts:

aka, you could have a single board made (thus not needing to keep track of different SKUs) that folks can buy in the multiples they need instead of a single big board that costs a lot. (I'm handwaving that "doubling" the board components basically doubles the cost.)

Since the voltage divider circuit cost isn't huge, If you just have the board maker populate everything (instead of two runs of with and without), that keeps to one board (again, SKU management).

The 40-pin header cost adds up (annoyingly) and is a waste of pins. SPI0 uses a block of 2x4 pins, so maybe saving you the few cents there gives you the funds for stocking some adaptor boards.

As for the adaptor board... depending on how you lay out the connector pins, the case could be (raspi 4 w/ four boards = 63 breakers) 4x the width of your current one (and lots of empty standoff space), or 2x2. If for other raspis, 2x width (31 breakers).

Or I'm just overthinking this and have folks solder wires to a header and its a little messier.

Either way, making it modular also makes the configuration a LOT more complicated, but it doesn't change the complexity of the "single PCB case" (assuming you hide the modular mechanism behind a toggle/button).

kitlaan commented 2 years ago

And so I don't lose it in all my tabs...

TL;DR -- if someone wants to use Raspi4 3-4x SPI (aka 32-63 breakers) they need to use a different pinout than the Raspi3/zero2/Raspi4 1-2x SPI (1-31 breakers) configuration.

4 SPI   2 SPI
x x   x x
3 x   _ x
3 x   _ x
4cs 5   _ _
x 5   x _
_ 6cs   1cs 1cs
6cs x   _ x
_ _   _ _
x 3cs   x _
_ x   0 x
_ 4cs   0 _
_ _   0 0cs
x 4   x 0cs
3cs 3   _ _
4 x   _ x
4 5cs   _ _
5 x   _ x
6 _   1 1cs
5cs 6   _ 1
x 6   x 1

(where x is reserved, _ is an unused gpio, and cs marks the default CS pins)

Even without using the default CS pins, it doesn't look like the pin usage can be shuffled around enough to make things co-located.

kitlaan commented 2 years ago

Did some more reading on how the raspi deals with SPI.

Through the Linux Device Tree Overlay mechanism, the the GPIO+drivers are configured to deal with hardware. The defaults limit to what the hardware provides for chip selects, but they can be customized to do more.

So in theory, the PCB could be made with one of these configurations (each with their tradeoffs):

  1. each SPI w/ N chip selects -- total sampling rate is divided by N (aka as you have today, N=2)
  2. M SPIs with N chip selects -- total sampling rate is M/N (aka today you have, M=1, N=2)

Of course we have the hardware limitations:

I'm not sure what design intent you want to go with, but it seems like a reasonable "prebuilt configuration" would be:

Alternatively, what I described a few days back:

References:

kitlaan commented 2 years ago

Came up with yet another PCB design idea to allow one board to meet lots of needs. (I think this can handle the 3-phase flow?)

Someone that wants to add another chip-select (CS2) would have to solder to PCB0's header pins (bleh), but seems feasible. (Alternatively, another solder pad to daisy-chain CS2... since SPI1 already has default support for 3 chip-selects... so there would just need to be a custom DTB to add one for SPI0.)

Alternatively, someone that wants to use a different SPI layout entirely would just not use the stacking 2x20 header and manually solder wires to the proper layout.

MarkBryanMilligan commented 2 years ago

I just migrated from wiringpi to pigpio. This will allow using the other SPI channels. Needed a couple changes to pi4j to get it to work, so I'll try to get those submitted next. I've never contributed to someone else's project before, so gotta go figure that out.