Reefpi Update (Raspberry Pi OS (Trixie) 64bit)

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Hey guys 👋


Over the last few months I’ve been quietly working on getting reef-pi running properly on the latest Raspberry Pi hardware and Raspberry Pi OS (Trixie).


What started as “just a port” turned into fixing a bunch of long-standing annoyances and adding some instrumentation features I’ve wanted for a while.


LINK TO GITHUB


What’s in it so far​

  • Raspberry Pi 5
  • Raspberry Pi OS (Trixie) compatibility
  • Multi-repo local build setup (reef-pi + drivers + hal + rpi)

New Drivers & Hardware Support​


TDS Driver
  • Supports up to 4 TDS modules via ADS1115
  • Designed for smarter RODI system control

Salinity Driver (Robo-Tank isolated conductivity circuit)
  • Improved temperature compensation modeling
  • Improved calibration handling
  • Long-term drift tracking experiments

GPIO Expander Driver (PCF8575)
  • Adds 16 additional I/O per module
  • Up to 8 modules supported
  • Up to 128 additional I/O available

Other Improvements​

  • Fixed calibration issues
  • General backend clean-up
  • Fixes for some long-standing quirks that have annoyed me for years



Why the Salinity Work Matters​


This is where it gets interesting.

The system can continuously monitor salinity and automatically switch your ATO between fresh RODI and saltwater depending on drift.

Instead of blindly topping off with freshwater, the controller can actively correct salinity in either direction — opening the door to much tighter control.

The TDS driver is aimed at making RODI systems smarter and more efficient. That part is still evolving.




⚠️ If You Want to Test​


Please run this on a clean SD card, not your production controller.

That way, if anything doesn’t behave, you can simply power down and reinsert your original SD card and you’re instantly back to normal.

Currently tested on:​

  • Raspberry Pi 5
  • Raspberry Pi 4
  • Raspberry Pi Zero 2 W Rev 1.0



This is a personal fork and totally experimental at this stage.
I’m not affiliated with the official reef-pi project — this is just something I’ve been building and refining.

If upstream ever wants to adopt parts of it, that would be great — but for now this is community testing territory.



Installation​

(Raspberry Pi OS – Debian Trixie)​


There is an official guide you can follow here. Instructions

1771886802741.png

1771886810006.png




Enable Interfaces​


Enable: SSH, i2C & 1-Wire

1771887018819.png

1771887026383.png


1771887034582.png


1771887042827.png




Installation​

Quick Install (Raspberry Pi OS – Debian Trixie)​

On a fresh Raspberry Pi OS system, run:

Bash:
curl -fsSL https://raw.githubusercontent.com/epicfatigue/reef-pi/main/install.sh | sudo bash





What the Installer Does​

The automated installer will:
  • Update the operating system
  • Install required dependencies (Go, Node.js, yarn, git, build tools)
  • Create a dedicated reefpi system user
    ⚠️ Reserved for the service — do not create or modify manually
  • Create required directories under /opt and /var/lib
  • Clone all required repositories (reef-pi, drivers, hal, rpi)
  • Wire local Go module replacements
  • Build the frontend (if enabled)
  • Compile and install the backend binary
  • Create and enable a systemd service
  • Start reef-pi automatically on boot

After installation, access reef-pi at:

Bash:
http://<your-pi-ip>:8080
 
Last edited:

revhtree

Owner Administrator
View Badges
Joined
May 8, 2006
Messages
54,232
Reaction score
120,194
Rating - 100%
1   0   0
Thanks for sharing.
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
yeah i am just trying to pinpoint one error, however it takes time. It has existed in previous versions and has been my biggest pet hate of this product, Modules unload and the API stays active, and the configuration tab disappears. i can easily make a work around but i would rather solve the problem.
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Well good news to anyone following i have fixed all the issues with the migration.
I am just waiting for my salinity i2c interface to come from ROBOTANK and i will upload the build for anyone that's wanting it. If someone is following along and has a bug they want looked into speak now.
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Little Update, i finally got the new version of the Robo-Tank conductivity circuit.

I have started to write the driver, i have also added the ability to use a in tank Temp probe for compensation, for those like me that want accuracy.

Robo-Tank conductivity circuit


1768913212367.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0

Overview of Recent Changes​


I’ve just finished a major round of updates that address something that’s bothered me for a long time.


Previously, the pH module didn’t truly support calibration and ended up being a largely empty or confusing tab. To fix this, I’ve renamed the pH module to Chemistry and expanded it to properly support multiple water-quality sensors.


The Chemistry module can now handle:
  • Salinity probes
  • TDS monitoring
  • PH Monitoring
  • ORP Monitoring
  • Other chemistry-related sensors going forward

Temperature Compensation​


I’ve also added optional temperature compensation, which significantly improves accuracy. You can run without it, but if you want measurements that reflect real-world conditions, temperature compensation is the correct approach.

New Calibration Workflow​


The Calibration tab has been completely redesigned.

Instead of hiding calibration logic inside the driver, the UI now:
  • Displays all the values used by the driver
  • Shows exactly what you should record and enter
  • Gives you full visibility into whether your calibration makes sense
This means no guesswork and no “magic numbers” — you can clearly see how calibration values affect the final reading.



Salinity Example​


Using a salinity probe as an example, the UI now shows significantly more detail via dropdowns.

You can see:
  • Primary salinity (ppt) – the calibrated, final value
  • Observed raw value (mV) – the direct sensor output

Below that, you’ll also see:
One-minute averages for both the calibrated value and the raw mV value

These averaged values are what you should use during calibration, as they smooth out noise and give you stable reference points.

1769227197985.png


Driver Configuration Explained​


In the driver configuration, you’ll see the following key parameters:
  • Address
    The I²C address of the device (for example, 106).
  • AbsD_Fresh
    The raw millivolt reading when the probe is placed in fresh (RO/DI) water.
  • AbsD_53000
    The raw millivolt reading when the probe is placed in a 53,000 µS calibration solution.

These two values define the calibration range for the probe.

1769227401909.png



Temperature Compensation & Debugging​

  • DoTempComp
    Allows you to associate a temperature probe with this device so temperature can be factored into the calculation.
    It’s optional, but recommended if you want truly accurate readings.
  • Debug
    Enables detailed logging so you can see exactly what the driver is doing.
    Turning this on removes all guesswork and makes it much easier to trust and verify the readings.


1769227730396.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Okay anyone that wants to try this.

Make sure you have a raspberry Pi 5 running the newest os.
Do all your updates.

then copy and paste the below.

once its completes.
you will see
Building reef-pi binary...
Done
Workspace kept at: /tmp/reefpi-build
Built binary:
-rwxrwxr-x 1 reefpi reefpi 18M Jan 26 13:57 /tmp/reefpi-build/reef-pi/reef-pi


Then just run /tmp/reefpi-build/reef-pi/reef-pi
And it will start test it if your happy make it into a service.

Enjoy people



Code:
cat > /tmp/build-reefpi.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

FORK_USER="epicfatigue"
BASE="/tmp/reefpi-build"

echo "Using: $BASE"
rm -rf "$BASE"
mkdir -p "$BASE"
cd "$BASE"

echo "Cloning repos..."
git clone "https://github.com/${FORK_USER}/reef-pi" reef-pi
git clone "https://github.com/${FORK_USER}/drivers" drivers
git clone "https://github.com/${FORK_USER}/hal" hal
git clone "https://github.com/${FORK_USER}/rpi" rpi

cd "$BASE/reef-pi"

echo "Applying go.mod replaces..."
go mod edit -replace github.com/reef-pi/drivers="$BASE/drivers"
go mod edit -replace github.com/reef-pi/hal="$BASE/hal"
go mod edit -replace github.com/reef-pi/rpi="$BASE/rpi"

echo "Cleaning..."
make clean || true
go clean -cache -testcache -modcache

echo "Tidying..."
go mod tidy

echo "Installing..."
make install

echo "Building frontend..."
yarn install --frozen-lockfile || yarn install
yarn build

echo "Building reef-pi binary..."
go build -o reef-pi ./commands

echo
echo "Done"
echo "Workspace kept at: $BASE"
echo "Built binary:"
ls -lh "$BASE/reef-pi/reef-pi"
EOF

chmod +x /tmp/build-reefpi.sh
/tmp/build-reefpi.sh
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Not sure if anyone is actually following this but.....

I have added support for pcf8575

Its a very cheap module you can buy.
This will allow you to have an additional 16 GPIO Pins.

These can be inputs or Outputs, not PWM pins, for that you use pca9685.
a Big one if you are like me and have alot of sensors.

1769468886496.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Nice to see some people were following along.


Currently have it up and running on my tank,
Have a few more things i want to tweak.

Tracking Salinity, orb and PH just fine.

Calibration worked well!


1769854418179.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Okay so another issue i found with the latest version of reefpi.

Graphing was broken...
Makes me wish i had of picked the last stable version.

I have found the issue and resolved it.

Anyone lurking in the background have a raspberry pi 5 they would like to test it with?

Surely there are some reefpi users still out there or did this project sit stale for to long ?

1769907317619.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Okay so another thing that always bothered me was not being able to clear charted data.

Temperature and Chemistry charts now have the option to clear data.

1769990059673.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0

Upper & Lower Function Redesign (ATO Support)​


The Upper and Lower Functions have been redesigned and now support ATO as a control target.


For ATO control, a dedicated latch option has been added.
This latch applies only to ATO mode.


This setup is designed for systems that use both premixed saltwater and RODI, each connected to its own ATO.


When the ATO float is triggered (due to evaporation, skimmer loss, etc.), the salinity probe determines which ATO should be active:

  • If salinity is too low, the saltwater ATO is enabled
  • If salinity is too high, the RODI ATO is enabled

The latch ensures that once an ATO is selected, it remains active until the reading returns in range, preventing rapid switching between salt and fresh water.


This allows reef-pi to automatically correct salinity drift, using standard ATO hardware, without oscillation or instability.

1770003967900.png



1770003674941.png
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
Fixed one last annoying issue,

If you cleared your ATO usage the UI would throw an error until the ATO was triggered.

Now it automatically generates a blank graph.

Have pretty much fixed all the errors i was aware of now, might add some new functionality in the future.



1770690454723.png
 

Kurtzisa

Community Member
View Badges
Joined
Mar 21, 2020
Messages
90
Reaction score
73
Location
Parma, Italy
Rating - 0%
0   0   0
I tried a fresh install and then using the db from my old reef-pi, and it works.

the following packages need to be installed, maybe you can put them in the script

golang and npm
after that
npm install -g yarn

after that, i copied the reef-pi directory into my home

now I'm trying to figure out how to automatically start reef-pi on boot with root permissions. 😃
I'm not very good at using Linux☺️
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
I tried a fresh install and then using the db from my old reef-pi, and it works.

the following packages need to be installed, maybe you can put them in the script

golang and npm
after that
npm install -g yarn

after that, i copied the reef-pi directory into my home

now I'm trying to figure out how to automatically start reef-pi on boot with root permissions. 😃
I'm not very good at using Linux☺️


nice work! yes i plan to clean all this up i am just doing some work on getting all the math correct and will do another code push.



its awesome someone as attempted to use it.
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
233
Reaction score
124
Location
Melbourne
Rating - 0%
0   0   0
I noticed salinity was inversely tracking temperature.


This indicated that the measurement chain was not correctly normalized to 25°C.


Although the PIC hardware assumes a 25°C reference, the actual temperature coefficient of the full measurement system (probe + analog frontend + ADC scaling) did not match the standard seawater assumption of 0.019/°C.


By analyzing 12 hours of logged data, I performed a regression of conductivity vs temperature and derived the effective temperature coefficient of this specific system:


AlphaPerC ≈ 0.001145 /°C


After applying this value in the driver, the correlation between salinity and temperature dropped to nearly zero, and the salinity graph flattened.


This coefficient represents the behavior of this specific PCB + probe + calibration chain. Other hardware revisions may differ.




1771236324062.png








Important Practical Note​


If someone else uses:
  • Different board revision
  • Different probe
  • Different gain scaling

They should run the same log regression script and compute their own alpha.


It takes 30 seconds, run the following,

as you can see from the screen shot my script with my hardware determined a
AlphaperC = 0.001145.



1771236188830.png



#### How to run it ########

journalctl -u reef-pi --since "12 hours ago" -o cat \
| grep 'robotank_cond' | grep ' ch=0 ' \
| python3 fit_alpha.py --absd-rodi 1010.0 --absd-std 24.328 --ref-us 53000 --ref-temp 25.0



Code:
#!/usr/bin/env python3
import argparse
import re
import sys
from math import isnan

LINE_RE = re.compile(
    r"\|d\|=(?P<d>\d+(?:\.\d+)?)\s+temp=(?P<t>\d+(?:\.\d+)?)C"
)

def parse_args():
    p = argparse.ArgumentParser(description="Estimate alphaPerC from robotank_cond logs (ch=0 lines).")
    p.add_argument("--absd-rodi", type=float, required=True, help="AbsD_RODI calibration value (e.g. 1010.0)")
    p.add_argument("--absd-std", type=float, required=True, help="AbsD_Std calibration value (e.g. 24.328)")
    p.add_argument("--ref-us", type=float, default=53000.0, help="Reference uS/cm for standard solution (default 53000)")
    p.add_argument("--ref-temp", type=float, default=25.0, help="Reference temp C (default 25.0)")
    p.add_argument("--min-dt", type=float, default=0.15, help="Ignore points with |T-ref| < this (default 0.15C)")
    return p.parse_args()

def us_from_d(d, absd_rodi, absd_std, ref_us):
    denom = (absd_rodi - absd_std)
    if denom == 0:
        raise ValueError("AbsD_RODI == AbsD_Std; invalid calibration")
    x = (absd_rodi - d) / denom
    # same clamp style as driver
    if x < 0: x = 0.0
    if x > 1.2: x = 1.2
    return x * ref_us

def linreg(x, y):
    # returns intercept A, slope B, r
    n = len(x)
    sx = sum(x); sy = sum(y)
    sxx = sum(v*v for v in x)
    syy = sum(v*v for v in y)
    sxy = sum(a*b for a,b in zip(x,y))
    denom = (n*sxx - sx*sx)
    if denom == 0:
        return float("nan"), float("nan"), float("nan")
    B = (n*sxy - sx*sy) / denom
    A = (sy - B*sx) / n
    # correlation r
    denom_r = ((n*sxx - sx*sx) * (n*syy - sy*sy)) ** 0.5
    r = (n*sxy - sx*sy) / denom_r if denom_r != 0 else float("nan")
    return A, B, r

def main():
    args = parse_args()

    xs = []  # deltaT
    ys = []  # us_meas

    for line in sys.stdin:
        m = LINE_RE.search(line)
        if not m:
            continue
        d = float(m.group("d"))
        t = float(m.group("t"))
        dt = (t - args.ref_temp)
        if abs(dt) < args.min_dt:
            continue
        us_meas = us_from_d(d, args.absd_rodi, args.absd_std, args.ref_us)
        xs.append(dt)
        ys.append(us_meas)

    n = len(xs)
    if n < 20:
        print(f"Not enough points after filtering: n={n} (need ~20+).", file=sys.stderr)
        sys.exit(2)

    A, B, r = linreg(xs, ys)
    if isnan(A) or A == 0:
        print("Regression failed (A is NaN/0).", file=sys.stderr)
        sys.exit(2)

    alpha = B / A

    # Check how well this alpha removes temperature correlation
    us_ref = [y / (1.0 + alpha*x) for x, y in zip(xs, ys)]
    _, _, r_after = linreg(xs, us_ref)

    print("=== robotank alpha fit ===")
    print(f"points_used: {n}")
    print(f"A (approx us@{args.ref_temp:.2f}C): {A:.3f}")
    print(f"B (dus/dT):                 {B:.3f} uS/°C")
    print(f"alphaPerC = B/A:            {alpha:.8f}  (i.e. {alpha*100:.4f}% per °C)")
    print(f"corr(us_meas, dT):          {r:.4f}")
    print(f"corr(us_ref(alpha), dT):    {r_after:.4f}   (closer to 0 is better)")
    print()
    print("Tip: if corr(us_ref(alpha), dT) is still strongly non-zero,")
    print("either the window isn’t stable salinity, or the model isn’t purely linear with temp.")

if __name__ == "__main__":
    main()
 

Kurtzisa

Community Member
View Badges
Joined
Mar 21, 2020
Messages
90
Reaction score
73
Location
Parma, Italy
Rating - 0%
0   0   0
I need some advice on how to automatically start reef-pi on raspberry, after which I'll be happy to help you do some tests
 

TOP 10 Trending Threads

DO YOU THINK TECHNOLOGICAL ADVANCEMENTS ARE MORE HELPFUL OR HURTFUL TO REEFING?

  • More helpful.

    Votes: 54 40.6%
  • More hurtful.

    Votes: 5 3.8%
  • I think it depends mostly on the technology.

    Votes: 53 39.8%
  • I think it dependsmostly on the reefer behind the technology.

    Votes: 40 30.1%
Back
Top
Home
Post thread…
Market
What's new