PH Controller /c02 Scrubber for reefpi (With Push notifications)

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
188
Reaction score
86
Location
Melbourne
Rating - 0%
0   0   0
Hey All,

I wrote a little service last night as Reef Pi was unable to control my co2 Scrubber with Reef Pi.
This was just thrown together and I as I normally write in Java and I will continue working on this when I get the time.

I use a a motorised ball valve you can find here Motorized Ball Valve
1-2-3-4-1-2-Motorized-Ball-Valve-220V-12V-24V-3-Wire-2-Point.jpg_Q90.jpg_.webp


Basically this unit only has 3 wires so it requires a relay to work.
I used a 240v one with a 240v Relay. So power on will make the valve open power off would make it close.
I also Used Pushover for push notifications.

This valve is attached to a 3 way T.

T is as follows
1: To Skimmer air intake
2: Co2 Scrubber
3: Ball Valve

When valve it closed air will be drawn through the scrubber
When valve is open air will take the path of least resistance through the valve (Saves a hell of alot of media)



Code is below for whoever wants to use it.
Also Check if Media is expired and will send a push notification to your phone
Also check if the skimmer cup is full (Currently using an ATO you cannot alert on it being off, or i have missed this along the way)
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
188
Reaction score
86
Location
Melbourne
Rating - 0%
0   0   0
main.py

Python:
import reefpi
import time
import logging

# Probe Equipment ID
PH_Probe = 5
# co2Scrubber Equipment ID
co2_Scrubber = 4
# Skimmer Equipment ID
skimmer = 3
# Probe Upper Limit when this is reached Valve will Open
phProbeUpperLimit = 8.3
# Probe Lower limit when this is reached Valve will close
phProbeLowerLimit = 8.1
# PH Value when to trigger media is dropping in effectiveness (colour change is not reliable )
phMediaChangeLimit = 8
# Init media Counter (Starts High resets on first alert)
mediaCounter = 720
# Init Skimmer counter (Starts High resets on first alert)
skimmerCounter = 720
# Alert can only be thrown ever sleepTime * mediaThreshold e.g. 60 * 720 = 43,200seconds (12 Hours)
mediaThreshold = 720
# Alert can only be thrown ever sleepTime * mediaThreshold e.g. 60 * 720 = 43,200seconds (12 Hours)
skimmerThreshold = 720
# Sleep Timer in seconds
sleepTime = 60
# Logging setup
logging.basicConfig(filename='phMonitor.log', encoding='utf-8', level=logging.INFO)
# Authenticate our session
reefpi.authenticateSession()

# Never Ending while loop this should be run as a service
try:
    while True:
        phReading = reefpi.getPHProbeReading(PH_Probe)
        logging.info('Current Reading ' + str(phReading))
        mediaCounter = mediaCounter + 1
        skimmerCounter = skimmerCounter + 1
        # Check if the PH reading is below lower limit
        if phReading < phProbeLowerLimit:
            logging.info('Probe is below the lower limit turn CO2 Scrubber on')
            # Check if the equipment is already in desired state.
            if reefpi.equipmentRunning(co2_Scrubber):
                logging.info('Equipment already on')
            else:
                # Turn Equipment on
                logging.info('Turning co2 Scrubber ON')
                reefpi.sendMessage('PH Probe Status Change',
                                   'Current Reading:' + str(phReading) + ' Turning C02 Scrubber On')
                reefpi.toggleEquipmentOn(co2_Scrubber)
        # Check if the PH reading is above upper limit
        if phReading > phProbeUpperLimit:
            logging.info('Probe is above the upper limit turn CO2 Scrubber off')
            # Check if the equipment is already in desired state.
            if not reefpi.equipmentRunning(co2_Scrubber):
                logging.info('Equipment already off')
            else:
                # Turn Equipment on
                logging.info('Turning co2 Scrubber Off')
                reefpi.sendMessage('PH Probe Status Change',
                                   'Current Reading:' + str(phReading) + ' Turning C02 Scrubber off')
                reefpi.toggleEquipmentOff(co2_Scrubber)
        # Checks if ph PHReading is below media change limit
        # So we know when to change the media.
        if phReading < phMediaChangeLimit:
            logging.warning('Media Has Expired')
            if mediaCounter > mediaThreshold:
                mediaCounter = 1
                reefpi.sendMessage('PH Probe Status Change', 'Current Reading:' + str(phReading) + ' Media has Expired')

        # Check if Skimmer is still running.
        # Skimmer has float switch when triggered skimmer turns off unable to throw an alert for this.
        if not reefpi.equipmentRunning(skimmer):
            logging.warning('Skimmer Offline')
            if skimmerCounter > skimmerThreshold:
                skimmerCounter = 1
                reefpi.sendMessage('Skimmer Offline', 'Check Skimmer Cup ')

        time.sleep(sleepTime)

# Catch all Exception
except Exception as e:
    logging.exception('Exception:'+str(e))
    reefpi.sendMessage('Exception Encountered', 'Exception:'+str(e))



reefpi.py

Python:
import requests
import smtplib
from email.message import EmailMessage

# Reefpi user
user = 'reef-pi'
# Reefpi password
password = 'reef-pi'
# Reefpi Hostname
hostname = '192.168.0.15'
# set your email and password
email_address = "[email protected]"
# please use App Password
email_password = "passwordsadsa"
# Init Session
session = requests.Session()
# Alert email address (the recipient )(Use Pushover for push notifications)
pushoverEmail = '[email protected]'
# smtp settings gmail
smtpAddress = 'smtp.gmail.com'
# smtp Port
smtpPort = 465


# Authenticate session
def authenticateSession():
    url = "http://"+hostname+"/auth/signin"
    credentials = {"user": user, "password": password}
    headers = {"accept": "application/json",
               "content-type": "application/json",
               "x-api-version": "120",
               }
    session.post(url, headers=headers, json=credentials, verify=False)

#   Checks if Session is Valid
def sessionValid(request):
    if request.status_code == 200:
        return True
    else:
        return False

# Read Probe Value
def getPhProbeReadings(equipmentID):
    r = session.get('http://'+hostname+'/api/phprobes/'+str(equipmentID)+'/readings')
    return r.json()

# Gets the last reading
def getPHProbeReading(equipmentID):
    readings = getPhProbeReadings(equipmentID)
    currentReadings = readings.get('current')
    lastRead = currentReadings[-1].get('value')
    return lastRead

# Get Equipment List
def getEuipmentList():
    r = session.get('http://'+hostname+'/api/equipment')
    return r.json()

# Get Inlet List
def getInletList():
    r = session.get('http://'+hostname+'/api/inlets')
    return r.json()

# Get Equipment by ID
def getEquipmentByID(equipmentID):
    r = session.get('http://'+hostname+'/api/equipment/'+str(equipmentID))
    return r.json()

# Get PH Probes
def getPhProbeList():
    r = session.get('http://'+hostname+'/api/phprobes')
    return r.json()

# Turn equipment off
def toggleEquipmentOff(equipmentID):
    session.post('http://'+hostname+'/api/equipment/'+str(equipmentID)+'/control', json={"on": False})

# Turn equipment on
def toggleEquipmentOn(equipmentID):
    session.post('http://'+hostname+'/api/equipment/'+str(equipmentID)+'/control', json={"on": True})

# Checks if Equipment is running
def equipmentRunning(equipmentID):
    equipment = getEquipmentByID(equipmentID)
    return equipment.get('on')

#
def sendMessage(subject,message):
    # create email
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = email_address
    msg['To'] = pushoverEmail
    msg.set_content(message)

    # send email
    with smtplib.SMTP_SSL(smtpAddress, smtpPort) as smtp:
        smtp.login(email_address, email_password)
        smtp.send_message(msg)


@Ranjib
@robsworld78
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
188
Reaction score
86
Location
Melbourne
Rating - 0%
0   0   0
I understand Some people might need a diagram so i just made this and i tried to make it more readable for those without an electronic background.

I would not trust these for a million operations an hour, hence with the above script they will not be working overtime and should last the life of the tank.
It was very hard to find a valve that would be able to allow the required airflow, i was going to make one but for the price you cannot go past these.
Diagram.JPG
 

Ranjib

7500 Club Member
View Badges
Joined
Apr 16, 2016
Messages
9,843
Reaction score
17,058
Location
Pleasant Hill, Concord
Rating - 0%
0   0   0
This is super cool. Thank you for sharing. If theres an apetite to use it for many others, we can add a dedicated driver for this
 

geologeek

Community Member
View Badges
Joined
Apr 21, 2010
Messages
65
Reaction score
39
Location
UK
Rating - 0%
0   0   0
This is very clever, but for those of us who are much less clever, how exactly does one go about implementing this on their raspberry pi's? What is in the files "import time", "import logging" and "import requests" for example? I am just dipping my toes into the likes of Arduino IDE and do not know how this is accomplished alongside the reefpi program. Any help for us lesser mortals?
 
OP
OP
epicfatigue

epicfatigue

Active Member
View Badges
Joined
Oct 21, 2020
Messages
188
Reaction score
86
Location
Melbourne
Rating - 0%
0   0   0
This is very clever, but for those of us who are much less clever, how exactly does one go about implementing this on their raspberry pi's? What is in the files "import time", "import logging" and "import requests" for example? I am just dipping my toes into the likes of Arduino IDE and do not know how this is accomplished alongside the reefpi program. Any help for us lesser mortals?
What you are seeing is importing packages.

I can write an installer so you would just download it and execute some commands.
But as Rajib said he might be able to make this a driver.
 

Sral

Valuable Member
View Badges
Joined
May 2, 2022
Messages
1,006
Reaction score
976
Location
Germany
Rating - 0%
0   0   0
Another question, since I have no idea:
how does the scrubber actually work ? :grinning-face-with-sweat:
Please keep in mind that I'm a complete noob to Reefkeeping (although with a good understanding of chemistry and physics).
 

geologeek

Community Member
View Badges
Joined
Apr 21, 2010
Messages
65
Reaction score
39
Location
UK
Rating - 0%
0   0   0
Well, I got that much, but what is the geometry of the flow of water and air there and what kind of medium would you be using ? :grinning-face-with-sweat:
The medium is essentially soda lime with I believe ethyl violet as the indicator. As the co2 reacts with the soda lime to create water and heat, it reduces the pH of the soda lime which turns purple due to the Ethyl violet.
 

Sral

Valuable Member
View Badges
Joined
May 2, 2022
Messages
1,006
Reaction score
976
Location
Germany
Rating - 0%
0   0   0
The medium is essentially soda lime with I believe ethyl violet as the indicator. As the co2 reacts with the soda lime to create water and heat, it reduces the pH of the soda lime which turns purple due to the Ethyl violet.
Thanks ! The other part would be to understand what kind of skimmer one would be talking about within the context of a reef-tank, but as far as I understand it's probably some biologically active filtering element that requires oxygen to feed the filtering microbes. Does that sound about right ?

Seems like a somewhat common thing now that I'm reading some other threads about this, where people have used ambient air from outside the cupboard.

Personally, I'll be on the exact opposite end, adding CO2 to my planted freshwater aquarium to reach 20mg/l CO2 @ 4 KH and ph~6.9. I think made a rough calculation some time ago and got these equilibrium CO2 concentrations in the water for ambient CO2-levels:
400ppm ambient ~ 0.4 mg/l in (fresh) water
20,000ppm ambient ~ 20mg/l in (fresh) water

Out of interest: do you know the CO2 levels in your reef-tank ?
Judging from this very limited table, you'll likely be close to 1mg/l CO2 with a pH of 8.3 and 8KH, is that plausible ?
 
Last edited:

Reefing threads: Do you wear gear from reef brands?

  • I wear reef gear everywhere.

    Votes: 41 16.3%
  • I wear reef gear primarily at fish events and my LFS.

    Votes: 15 6.0%
  • I wear reef gear primarily for water changes and tank maintenance.

    Votes: 1 0.4%
  • I wear reef gear primarily to relax where I live.

    Votes: 30 12.0%
  • I don’t wear gear from reef brands.

    Votes: 145 57.8%
  • Other.

    Votes: 19 7.6%
Back
Top