BeagleBone Black Library for Proteus: a water station with TDS, turbidity and flow sensors and a web page

BeagleBone Black Library for Proteus: ADC, TDS, Turbidity, Flow

2.5K Views
40
700
60
25
60
PCBWay

Hello friends, I hope you all are doing great. Today, I am going to share the BeagleBone Black Library for Proteus. The BeagleBone Black is the open-hardware Linux board from BeagleBoard.org: a Texas Instruments AM3358 with one Cortex-A8 core at 1 GHz, 512 MB of RAM, 4 GB of eMMC, Ethernet, and two 46-pin expansion headers, P8 and P9, with 65 GPIOs and a 12-bit analog-to-digital converter. With this library the BeagleBone runs your Python program against the circuit in Proteus 8.5, on our virtual network.

Updates

BeagleBone Black Library for Proteus

Latest version: V1.0 (October 2026, this tutorial)

Helping Tools

After our eleven Raspberry Pi boards and the Jetson Nano Library for Proteus, this is the next board of our series of single-board computers, and like every library of the series it connects the board to different modules and serves a web page. The BeagleBone has what a Raspberry Pi lacks - analog inputs - so this time it is a drinking-water station: a TDS meter and a turbidity sensor on the ADC, a YF-S201 flow sensor on a GPIO, the four blue user LEDs as status lights, and a page on a laptop and a phone that says whether the water is safe to drink.

NOTICE: this library does not run Debian. It runs your Python program, with the same Python library a BeagleBone uses for its headers, its ADC, its buses and its network, in step with the simulation. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the BeagleBone Black board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the BeagleBone Black Library for Proteus:

BeagleBone Black Library for Proteus: a water station with TDS, turbidity and flow sensors and a web page
Figure: The BeagleBone Black Library for Proteus: BB1 runs water_station.py - salty, cloudy water flowing, so all four user LEDs are lit, and the laptop's page says TDS TOO HIGH and TOO CLOUDY.

What is the BeagleBone Black?

BeagleBoard.org released the BeagleBone Black in 2013 for about 45 dollars, as an open-hardware board for makers and engineers: every schematic and layout file is public. The Rev C of 2014 gave it 4 GB of eMMC and Debian, and that is the board still sold today. Its heart is the TI Sitara AM3358: one Cortex-A8 core at 1 GHz, plus two small real-time processors, the PRUs, that can toggle pins far faster than Linux can.

For electronics the important parts are the two expansion headers, P8 and P9, along the long edges: 92 pins with up to 65 GPIOs, four UARTs, two I2C and two SPI buses, eight PWM outputs and seven analog inputs that read 0 to 1.8 V. A Raspberry Pi has no ADC at all, so a BeagleBone reads a potentiometer, a light sensor or a water probe without an extra chip. In Python the pins are named by their place on the header - "P8_10", "P9_39" - through Adafruit_BBIO.

The Raspberry Pi 4 Model B and the BeagleBone Black
Raspberry Pi 4 Model B (2019)BeagleBone Black Rev C (2014)
ProcessorBCM2711, four Cortex-A72 cores at 1.5 GHzAM3358, one Cortex-A8 at 1 GHz, two PRUs
RAM, storage1 - 8 GB, microSD512 MB DDR3, 4 GB eMMC, microSD
NetworkGigabit Ethernet, Wi-Fi, Bluetooth10/100 Ethernet
Analog inputsnoneseven, 12 bits, 0 - 1.8 V
Headers40 pinsP8 and P9: 92 pins, up to 65 GPIOs
Python libraryRPi.GPIO, gpiozeroAdafruit_BBIO
Size85 x 56 mm86.4 x 54.6 mm

In Proteus, our Raspberry Pi Model B Library for Proteus covers how a board runs a Python program: the program and Proteus work in lockstep, every sleep, pin wait and bus transfer moves the simulation clock, and the Python libraries answer as on the real board. The Raspberry Pi 4 Model B, the Raspberry Pi 5, the Raspberry Pi 400 and the Jetson Nano followed. The BeagleBone adds two things: its two headers and its ADC, which reads the real voltage of a pin in the circuit.

Features of the BeagleBone Black Library for Proteus

  • The board as it looks: the black board with its black female headers, the AM3358, the eMMC, the DDR3, the power chip, the Ethernet jack, the 5 V jack, the USB host socket, the serial header J1, the POWER, RESET and BOOT buttons, the blue power LED and the four blue user LEDs - at the real size of 86.4 x 54.6 mm.
  • The ADC: AIN0 to AIN6 read their pins in the circuit, 12 bits over 0 to 1.8 V, through Adafruit_BBIO.ADC or the board's IIO files; VDD_ADC gives the 1.8 V reference, and more than 1.8 V on a pin brings a warning.
  • Adafruit_BBIO.GPIO: setup, output, input and cleanup by header key, the pulls, edges with callbacks, and the user LEDs USR0 to USR3 - about 8 us a GPIO call, as on the 1 GHz Cortex-A8.
  • PWM, UART, I2C and SPI: Adafruit_BBIO.PWM on the PWM pins, UART1 with pyserial on /dev/ttyS1, I2C2 as bus 2 with smbus2, SPI0 with spidev.
  • Ethernet: eth0 with the cable in, 192.168.1.51, the name beaglebone.local; sockets and http.server work on it.
  • Your Python program: any .py file in the PROGRAM property; Python 3.11 and its standard library are included.
  • The terminal: the prompt debian@beaglebone:~$, the output, the errors, a line for input(), and a Board tab with the GPIOs, AIN0 to AIN6 in volts, the user LEDs and the supply pins - with our TEP header, no Windows title bar.
  • A complete package: about 13.8 MB with the board, Python, the runtime, the TDS, turbidity, flow and monitor libraries and the demo, without the source code of the models.

The BeagleBone Black in Proteus

BeagleBone Black in Proteus: the board with its P8 and P9 headers and the user LEDs lit
Figure: The part as the library draws it, running: the blue power LED and the user LEDs USR0 to USR3 lit, P8 along the top and P9 along the bottom, each of the 92 pins with a colour-coded tag.

Search BEAGLEBONE in Pick Devices; the device BEAGLEBONE BLACK is in TEPBBB.LIB (Microprocessor ICs, BeagleBone), with the prefix BB. The board is drawn at its real size, 86.4 x 54.6 mm, turned a quarter turn so that the Ethernet jack faces left: P8 runs along the top, P9 along the bottom, pin 1 of both at the Ethernet end, as on the real board. Each header's 46 pins leave the board as one comb - P8 up, P9 down - and every pin has a tag in the colour of its kind: the 5 V pins red, VDD_3V3 orange, DGND black, GPIO green, I2C blue, SPI pink, UART purple, PWM amber, the ADC teal, and grey for the pins the eMMC and the HDMI framer hold. Click the AM3358 or the serial header J1 to open the terminal, and the Ethernet jack to plug or unplug the cable.

BeagleBone Black in Proteus running a program, its header pins wired to net labels
Figure: BB1 in the demo, running: FLOW on P8_12 at the top; DGND, VDD_3V3, SYS_5V, GNDA_ADC, AIN0 and AIN1 on P9 at the bottom. USR0 shows the program running, and USR3 is lit - the turbidity probe is not calibrated yet.

The Headers P8 and P9

P8 and P9 in the library
PinsWhat the library does with them
P8_7 to P8_19, P8_26GPIO (P8_13 and P8_19 also PWM)
P9_11 to P9_31, P9_41, P9_42GPIO; P9_14, P9_16, P9_42 also PWM
P9_17, P9_18, P9_21, P9_22SPI0: CS0, D1 (MOSI), D0 (MISO), SCLK - /dev/spidev0.0
P9_19, P9_20I2C2: SCL, SDA - bus 2, with the board's pull-ups
P9_24, P9_26UART1: TXD, RXD - /dev/ttyS1
P9_33, P9_35 to P9_40AIN0 to AIN6: the ADC, 0 to 1.8 V
P9_32, P9_34VDD_ADC (the 1.8 V reference) and GNDA_ADC (the ADC's ground)
P9_3 to P9_8VDD_3V3, VDD_5V and SYS_5V
P8_3 to P8_6, P8_20 to P8_46held by the eMMC and the HDMI framer, as at power-on - not modelled

The GPIOs work at 3.3 V and are not 5 V tolerant; the analog inputs take 1.8 V at most. Adafruit_BBIO names a pin by its header key, "P9_12", or by its GPIO name, "GPIO1_28", and the library takes both.

The ADC

Each AIN pin is an analog pin in Proteus: the model reads the voltage of its node in the circuit and turns it into 0 to 4095. ADC.read() gives 0.0 to 1.0 of 1.8 V and ADC.read_raw() the raw count, and a program can also read /sys/bus/iio/devices/iio:device0/in_voltage0_raw, as on the real board. A read takes about 0.16 ms of simulation. If a pin goes above 1.8 V, the reading stops at 4095 and the simulation log warns that a real ADC would be damaged.

The User LEDs

The four blue LEDs next to the Ethernet jack belong to Linux until a program takes them: USR0 shows the heartbeat, two blinks a second, USR2 the CPU, USR3 the eMMC during the boot. GPIO.setup("USR0", GPIO.OUT) hands one to the program, which is how the demo turns them into status lights.

Ethernet

The ETHERNET property says whether the cable is in at Run: IN (the default) brings up eth0, OUT leaves the board without a network. The BeagleBone is 192.168.1.51, named beaglebone.local, on our router TEP-WiFi - the router of our Wi-Fi parts and of the Laptop WiFi Monitor and the Mobile WiFi Monitor. A click on the jack while the simulation runs pulls the cable or plugs it back.

Download BeagleBone Black Library for Proteus

Click the button below to download BeagleBone-Black-Library-for-Proteus-v1.0.zip (about 13.8 MB with Python included, without the source code of the models):

BeagleBone Black Library for Proteus V1.0
  • README.txt: the device, the ADC, the network, installation, the demo, the headers, the properties, troubleshooting and the limits.
  • Proteus Library Files: TEPBBB.LIB (the BeagleBone Black) and the demo's parts: TEPTDS.LIB, TEPTURBIDITY.LIB, TEPYFS201.LIB, TEPLAPTOP.LIB and TEPMOBILE.LIB.
  • Proteus Model Files: TEPNET.DLL (the board, the laptop, the phone and the network), the parts' TEPTDS.DLL, TEPTURBIDITY.DLL and TEPYFS201.DLL, and the TEPPi folder - Python 3.11 and the TEP runtime with Adafruit_BBIO.
  • Python Code: blink.py and water_station.py.
  • Proteus Simulation: the demo project, its program and copies of the DLLs.

No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.

How to Install BeagleBone Black Library for Proteus

  1. Close Proteus and extract the whole zip file, for example to your Desktop.
  2. Copy the files from Proteus Library Files into the LIBRARY folder of Proteus (usually C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY).
  3. Copy everything from Proteus Model Files - the DLLs and the TEPPi folder - into the MODELS folder, replacing an older TEPNET.DLL and TEPPi folder (these are the newest; they also run our Raspberry Pi boards and the Jetson Nano).
  4. Delete TEPBBB.IDX from the LIBRARY folder if it is there.
  5. Start Proteus, press P and search for BEAGLEBONE.

There is nothing else to install: Python comes in the TEPPi folder, so you need no Python on your PC.

Demo: a Drinking-Water Station

Open BeagleBone-Black-Water-Station.pdsprj. BB1 runs water_station.py on Ethernet. The sensors come from our own libraries, each with its article: U1 from the TDS Meter Library for Proteus, U2 from the Turbidity Sensor Library for Proteus and U3 from the YF-S201 Water Flow Sensor Library for Proteus. All three are the Advance versions: each opens a pop-up window at Run where you change the water. PC1 is the Laptop WiFi Monitor and MOB1 the Mobile WiFi Monitor, both on the router the BeagleBone's cable goes to.

BeagleBone Black Proteus simulation: TDS, turbidity and flow sensors, two dividers, a laptop and a phone
Figure: The whole demo: the titles, BB1 with its header pins going to net labels, the two dividers R1 to R4, the TDS meter, the turbidity sensor and the flow sensor, and the laptop and the phone.

A TDS meter measures the salts dissolved in water - total dissolved solids, in ppm - from the water's conductivity, with an output of 0 to 2.3 V. A turbidity sensor shines light through the water and measures how much gets through: 4.2 V for clear water, less as the water gets cloudy, in NTU. The YF-S201 is a small water turbine with a Hall sensor: it gives 7.5 pulses a second for every litre per minute, 450 pulses a litre. Net labels connect everything:

The wiring of the water station
Part pinNet labelBeagleBone pinWhat it does
TDS VCC, GND3V3, GNDP9_3, P9_1the meter's supply
TDS ATDS-its output, into R1 (15k)
Turbidity VCC, GND5V, GNDP9_7, P9_1the sensor's supply (SYS_5V)
Turbidity OUTTURB-its output, into R3 (15k)
R1 / R2, R3 / R4AIN0, AIN1P9_39, P9_40the dividers' middles: 0.4 of each output
R2, R4AGNDP9_34the dividers' bottoms on the ADC's ground
YF-S201 VCC, GND5V, GNDP9_7, P9_1the flow sensor's supply
YF-S201 OUTFLOWP8_12the pulses, counted by the program

The Dividers

The turbidity sensor gives up to 4.5 V, but an AIN pin takes 1.8 V at most. So each sensor feeds a divider: 15k from the sensor to the pin, 10k from the pin to GNDA_ADC. The pin sees 10 / (15 + 10) = 0.4 of the output - 4.5 V becomes 1.8 V, the top of the ADC - and the program multiplies back by 2.5. The TDS meter would fit without one, but the same divider keeps both channels alike:

Two 15k and 10k voltage dividers for the BeagleBone Black ADC inputs in Proteus
Figure: Closer: R1 and R2 between TDS and AIN0, R3 and R4 between TURB and AIN1, both on AGND.
def volts(samples):
    """A sensor's output from its ADC readings (0.0 - 1.0 of 1.8 V): their average, scaled back through the divider."""
    return sum(samples) / len(samples) * 1.8 / DIVIDER

From Volts to the Water

The TDS meter's maker publishes the conversion: the voltage, corrected to 25 C, gives the conductivity as a cubic, and the TDS is half of it:

def tds_ppm(v, temp=25.0):
    """The TDS meter's published conversion: the voltage at 25 C, then EC (uS/cm) as a cubic, TDS = EC / 2."""
    v = v / (1 + 0.02 * (temp - 25))
    return max(0.0, (133.42 * v ** 3 - 255.86 * v ** 2 + 857.39 * v) * 0.5)

The turbidity sensor's curve runs from 4.2 V for clear water down to about 2.5 V for 3000 NTU. Its output moves with its supply and every probe differs a little, so a probe must be calibrated: the program keeps the voltage this probe gives in clear water and scales every reading by it:

def turbidity_ntu(v, v_clear=4.2):
    """The turbidity sensor's published curve (2.5 - 4.2 V at 5 V); clear water above it, 3000 NTU or more below it. The output moves
    with the supply and every probe differs: v_clear is this probe's voltage in clear water (CAL CLEAR on the page), the curve's 4.2 V
    until then."""
    v = v * 4.2 / v_clear
    if v >= 4.2:
        return 0.0
    if v < 2.56:
        return 3000.0
    return max(0.0, -1120.4 * v * v + 5742.3 * v - 4352.9)

The Flow

Each pulse of the YF-S201 is a FALLING edge on P8_12. Adafruit_BBIO.GPIO calls a function on every edge, and the function only counts:

def on_pulse(channel):
    pulses[0] += 1

Measuring

A thread reads both channels ten times a second. Near clear water the turbidity curve is steep, so a few millivolts of noise are tens of NTU: the program averages the turbidity over the last 5 s and the TDS over the last second. Every second it works out the flow from the pulses counted, adds the litres, and decides the verdict:

        for _ in range(10):
            tds_s.append(ADC.read('AIN0'))
            tur_s.append(ADC.read('AIN1'))
            time.sleep(0.1)
        v_tds, v_tur = volts(tds_s), volts(tur_s)
        n, now = pulses[0], time.monotonic()
        with lock:
            tds, ntu = tds_ppm(v_tds), turbidity_ntu(v_tur, state['v_clear'])
            state['flow'] = (n - seen) / (now - at) / 7.5
            state['litres'] += (n - seen) / PULSES_PER_LITRE
            state['tds'], state['ntu'], state['v_tur'] = tds, ntu, v_tur
            bad = (['TDS TOO HIGH'] if tds > state['tds_limit'] else []) + (['TOO CLOUDY'] if ntu > state['ntu_limit'] else [])
            state['verdict'] = ' and '.join(bad) if bad else 'SAFE TO DRINK'
            s = dict(state)

Then the four user LEDs show the state - USR0 lights while the program runs, USR1 while water flows, USR2 when the TDS is over its limit, USR3 when the water is cloudy:

        for led, on in zip(LEDS, (True, s['flow'] > 0.5, tds > s['tds_limit'], ntu > s['ntu_limit'])):
            GPIO.output(led, GPIO.HIGH if on else GPIO.LOW)

The Web Page

The page shows the verdict, the TDS and its limit, the turbidity with its limit and the probe's voltage, and the flow, with REFRESH and links for the limits, the calibration and the litres:

PAGE = """<html><head><title>BeagleBone water station</title></head><body>
<p>Water: <b>{verdict}</b></p>
<p>TDS: {tds:.0f} ppm (limit {tds_limit} ppm)</p>
<p>Turbidity: {ntu:.0f} NTU (limit {ntu_limit} NTU) - the probe {v_tur:.2f} V, clear water {v_clear:.2f} V</p>
<p>Flow: {flow:.1f} L/min - total {litres:.2f} L</p>
<p><a href="/">REFRESH</a></p>
<p><a href="/tds?limit=300">TDS 300</a> <a href="/tds?limit=500">TDS 500</a> <a href="/tds?limit=1000">TDS 1000</a></p>
<p><a href="/ntu?limit=50">NTU 50</a> <a href="/ntu?limit=100">NTU 100</a> <a href="/cal">CAL CLEAR</a></p>
<p><a href="/reset">RESET LITRES</a></p>
</body></html>"""

/tds and /ntu set the limits, /reset puts the litres back to 0, and /cal keeps the probe's voltage of that moment as its clear-water voltage:

    def do_GET(self):
        url = urlparse(self.path)
        q = parse_qs(url.query)
        limit = q.get('limit', [''])[0]
        with lock:
            if url.path == '/tds' and limit.isdigit():
                state['tds_limit'] = int(limit)
            elif url.path == '/ntu' and limit.isdigit():
                state['ntu_limit'] = int(limit)
            elif url.path == '/reset':
                state['litres'] = 0.0
            elif url.path == '/cal' and state['v_tur'] > 2.5:            # (the probe in clear water now: its voltage is the zero)
                state['v_clear'] = state['v_tur']
            s = dict(state)
        body = PAGE.format(**s).encode()

At the start the program sets up the ADC, gives the four user LEDs a one-second lamp test, sets up the flow pin with its callback, waits for the network, starts the measuring thread and serves on port 8000:

ADC.setup()
for led in LEDS:                                                    # the user LEDs: a lamp test, then the status
    GPIO.setup(led, GPIO.OUT)
    GPIO.output(led, GPIO.HIGH)
print('water_station.py - drinking-water station on the BeagleBone Black')
print('TDS on AIN0 (P9_39), turbidity on AIN1 (P9_40), both through 15k / 10k; YF-S201 on %s' % FLOW_PIN)
GPIO.setup(FLOW_PIN, GPIO.IN)
GPIO.add_event_detect(FLOW_PIN, GPIO.FALLING, callback=on_pulse)
print('waiting for the network ...')
time.sleep(1)
for led in LEDS:
    GPIO.output(led, GPIO.LOW)
while my_ip() == '0.0.0.0':
    time.sleep(0.5)
threading.Thread(target=measure, daemon=True).start()
print('serving on http://%s:%d/' % (my_ip(), PORT))
HTTPServer(('', PORT), Handler).serve_forever()

Run the Demo

Press Run. eth0 is up and the page is served about 1.5 s after Run. The water at the probes is tap water - 250 ppm and 1 NTU - and the tap is closed. But the turbidity probe is new: its supply sags a little under its load, its clear-water voltage is 4.01 V instead of the curve's 4.2 V, and so it reads the tap water as about 645 NTU. TOO CLOUDY, and USR3 lights:

BeagleBone Black in Proteus running the drinking-water station
Figure: The demo running: BB1 on Ethernet, the dividers, the three sensors, the laptop and the phone.
debian@beaglebone:~$ python3 water_station.py
water_station.py - drinking-water station on the BeagleBone Black
TDS on AIN0 (P9_39), turbidity on AIN1 (P9_40), both through 15k / 10k; YF-S201 on P8_12
waiting for the network ...
serving on http://192.168.1.51:8000/
20:29:20  TDS 239 ppm  645 NTU  0.0 L/min  0.00 L  TOO CLOUDY
BeagleBone Black terminal in Proteus: the water station serves its page
Figure: The terminal: the prompt, the program's first lines - the ADC inputs, the flow pin, the network and the address of the page - and the first reading.
TDS Meter Advance pop-up in Proteus: tap water and the output
Figure: The TDS meter's pop-up: tap water at 250 ppm, its output and the presets.
Turbidity Sensor Advance pop-up in Proteus: tap water and the output
Figure: The turbidity sensor's pop-up: tap water at 1 NTU and the probe's output.
YF-S201 Advance pop-up in Proteus with the tap closed
Figure: The flow sensor's pop-up: the tap OFF, no pulses.

Open the Page

On the laptop click Browser, check the address http://192.168.1.51:8000/ and click Go; on the phone the same. The laptop shows the links as text, the phone as buttons:

Laptop WiFi Monitor in Proteus showing the BeagleBone water station page
Figure: The laptop before the calibration: tap water read as TOO CLOUDY, the probe at 4.01 V against the curve's 4.20 V.
Mobile WiFi Monitor in Proteus showing the BeagleBone water station page with buttons
Figure: The phone: the same page; the limits, CAL CLEAR and RESET LITRES are buttons.

Calibrate the Probe

The water at the probe is clear, so click CAL CLEAR on the laptop. The program keeps 4.01 V as this probe's clear water, the next reading is 0 NTU, and the verdict turns to SAFE TO DRINK:

Laptop WiFi Monitor in Proteus after CAL CLEAR on the BeagleBone page
Figure: The laptop after CAL CLEAR: clear water 4.01 V.
Laptop WiFi Monitor in Proteus: the BeagleBone water station says safe to drink
Figure: The laptop after REFRESH: SAFE TO DRINK - 241 ppm, 0 NTU.

Open the Tap

In the flow sensor's pop-up click TAP. The pulses start, the program counts them, and a second later the page shows 6.0 L/min and the litres adding up; USR1 lights:

Mobile WiFi Monitor in Proteus: the BeagleBone water station with water flowing
Figure: The phone after REFRESH: 6.0 L/min and the first litres.
YF-S201 Advance pop-up in Proteus with the tap open
Figure: The flow sensor's pop-up: the tap open, the pulses and the litres.

Bad Water: Every LED On

Now spoil the water. In the turbidity sensor's pop-up click RIVER - 250 NTU - and in the TDS meter's pop-up SEA, far over the meter's range. Over the next seconds the TDS climbs to about 1040 ppm and the turbidity to about 250 NTU: TDS TOO HIGH and TOO CLOUDY. USR1, USR2 and USR3 light up beside USR0 - all four user LEDs on:

BeagleBone Black in Proteus with all four user LEDs lit by the program
Figure: Closer: the running board with every LED on - the power LED and USR0 to USR3: the program runs, water flows, the TDS is too high and the water is cloudy.
Laptop WiFi Monitor in Proteus: the BeagleBone water station alarm
Figure: The laptop after REFRESH: TDS TOO HIGH and TOO CLOUDY.
TDS Meter Advance pop-up in Proteus with sea water over the range
Figure: The TDS meter's pop-up: sea water - the output stops at the top of its range.
Turbidity Sensor Advance pop-up in Proteus with river water
Figure: The turbidity sensor's pop-up: river water at 250 NTU.

The Limits

In the turbidity sensor's pop-up click CLEAR, and in the TDS meter's MINERAL - clear mineral water at 420 ppm. The page says SAFE TO DRINK again with about 400 ppm, under the 500 ppm limit. Then tap TDS 300 on the phone: for a stricter limit the same water is TDS TOO HIGH, and USR2 lights. RESET LITRES starts the count again:

Mobile WiFi Monitor in Proteus: mineral water safe to drink on the BeagleBone page
Figure: The phone with mineral water: about 400 ppm, SAFE TO DRINK.
Mobile WiFi Monitor in Proteus after the TDS 300 button on the BeagleBone page
Figure: The phone after TDS 300: the limit 300 ppm.
Mobile WiFi Monitor in Proteus after RESET LITRES on the BeagleBone page
Figure: The phone after RESET LITRES: the litres back to 0.
Laptop WiFi Monitor in Proteus: the BeagleBone water station at the end of the run
Figure: The laptop after REFRESH: TDS TOO HIGH at the 300 ppm limit, the water still flowing.

The terminal logs every change of the water, the flow and the verdict, and every click on the page:

20:29:27  the page: /cal - TDS limit 500 ppm, NTU limit 50, clear water 4.01 V, 0.00 L
20:29:28  TDS 241 ppm  0 NTU  0.0 L/min  0.00 L  SAFE TO DRINK
20:29:31  TDS 241 ppm  0 NTU  5.6 L/min  0.09 L  SAFE TO DRINK
20:29:32  TDS 241 ppm  0 NTU  6.0 L/min  0.19 L  SAFE TO DRINK
20:29:37  TDS 241 ppm  17 NTU  6.0 L/min  0.70 L  SAFE TO DRINK
20:29:38  TDS 241 ppm  68 NTU  6.0 L/min  0.80 L  TOO CLOUDY
20:29:39  TDS 241 ppm  118 NTU  6.0 L/min  0.90 L  TOO CLOUDY
20:29:40  TDS 585 ppm  166 NTU  6.1 L/min  1.00 L  TDS TOO HIGH and TOO CLOUDY
20:29:41  TDS 995 ppm  214 NTU  6.0 L/min  1.10 L  TDS TOO HIGH and TOO CLOUDY
20:29:42  TDS 1039 ppm  245 NTU  6.0 L/min  1.20 L  TDS TOO HIGH and TOO CLOUDY
20:29:47  TDS 1043 ppm  207 NTU  6.1 L/min  1.70 L  TDS TOO HIGH and TOO CLOUDY
20:29:48  TDS 1043 ppm  157 NTU  6.0 L/min  1.80 L  TDS TOO HIGH and TOO CLOUDY
20:29:49  TDS 1042 ppm  107 NTU  6.0 L/min  1.90 L  TDS TOO HIGH and TOO CLOUDY
20:29:50  TDS 1043 ppm  55 NTU  6.0 L/min  2.00 L  TDS TOO HIGH and TOO CLOUDY
20:29:51  TDS 1043 ppm  3 NTU  6.0 L/min  2.10 L  TDS TOO HIGH
20:29:53  TDS 629 ppm  0 NTU  6.0 L/min  2.30 L  TDS TOO HIGH
20:29:54  TDS 419 ppm  0 NTU  6.1 L/min  2.40 L  SAFE TO DRINK
20:29:55  TDS 404 ppm  0 NTU  6.0 L/min  2.50 L  SAFE TO DRINK
20:29:59  the page: /tds?limit=300 - TDS limit 300 ppm, NTU limit 50, clear water 4.01 V, 2.90 L
20:30:00  TDS 402 ppm  2 NTU  6.1 L/min  3.00 L  TDS TOO HIGH
20:30:02  the page: /reset - TDS limit 300 ppm, NTU limit 50, clear water 4.01 V, 0.00 L

The Terminal

The terminal opens at Run, in the look of our TEP Serial Monitor Advance for Proteus - our own TEP header, no Windows title bar. Its Monitor tab shows the program's output (OUT), errors (ERR) and the lines you type for input() (IN). The Board tab shows the board live - the GPIOs by header key, AIN0 to AIN6 in volts, the user LEDs, the supply pins - and RESTART PROGRAM starts the program again:

BeagleBone Black terminal in Proteus: the water station log
Figure: The terminal after the run: the readings, the calibration, the alarms and every click on the page.
BeagleBone Black terminal Board tab in Proteus: the GPIOs, the ADC inputs and the LEDs
Figure: The Board tab: the AM3358 at 1 GHz, the GPIOs by header key, AIN0 and AIN1 in volts, the user LEDs, the supply pins, water_station.py and the speed.

Properties of the BeagleBone Black

Double-click the BeagleBone to change them
PropertyWhat it does
PROGRAMthe Python program (default blink.py; a name next to the project or a full path)
AUTOOPENthe terminal at Run: YES (default) or NO
ETHERNETthe cable at Run: IN (default, eth0) or OUT (no network)
PYTHON, RUNTIMEa python.exe and a runtime folder of your own (empty: the TEPPi folder)

Your own programs go next to your project; set PROGRAM to the file's name. The default blink.py blinks an LED on P8_10 and the user LED USR3 together:

import time
import Adafruit_BBIO.GPIO as GPIO

LED_PIN = 'P8_10'
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.setup('USR3', GPIO.OUT)
try:
    while True:
        GPIO.output(LED_PIN, GPIO.HIGH)
        GPIO.output('USR3', GPIO.HIGH)
        print('LED on')
        time.sleep(0.5)
        GPIO.output(LED_PIN, GPIO.LOW)
        GPIO.output('USR3', GPIO.LOW)
        print('LED off')
        time.sleep(0.5)
finally:
    GPIO.cleanup()

Troubleshooting

  • RuntimeError: You must setup() ADC prior to calling read. - call ADC.setup() first.
  • A warning that an AIN pin is over 1.8 V: put a divider between the sensor and the pin.
  • ValueError: P8_27 is used by the HDMI framer: use one of the free pins in the table above.
  • The turbidity reads cloudy in clear water: calibrate - CAL CLEAR with clear water at the probe.
  • No flow: the sensor's OUT on P8_12 and the tap open in its pop-up; DRIP gives no pulses.
  • No module named 'RPi': RPi.GPIO and gpiozero are Raspberry Pi libraries - on a BeagleBone use Adafruit_BBIO.
  • The page does not open: the address is http://192.168.1.51:8000/ and the program must have printed "serving on". A monitor sometimes needs Go a second time. Use the page's REFRESH link - the monitors' Reload repeats the last link.
  • The TEPPi folder was not found: copy it from Proteus Model Files into MODELS, or next to your project.

Things to Know Before Using a Real BeagleBone Black

  • The ADC: never more than 1.8 V on an AIN pin - the ADC is damaged; take the reference from VDD_ADC and the ground from GNDA_ADC.
  • 3.3 V pins: the GPIOs are not 5 V tolerant. The YF-S201 pulls its output up to its own 5 V supply, so put a divider (for example 10k and 20k) or a level shifter between its OUT and P8_12.
  • The pins' modes: on the current Debian images many pins can be several things; config-pin sets a pin's mode (for example config-pin P9_24 uart), and UART.setup does it for the UART.
  • The HDMI pins: to use P8_27 to P8_46 as GPIOs, switch the video off in /boot/uEnv.txt.
  • The software: the BeagleBoard.org Debian images come with Adafruit_BBIO; the demo uses nothing newer than Python 3.7.
  • The power: use a 5 V supply of 2 A on the barrel jack when sensors hang on the headers; the USB port gives less.

Limitations of the Simulation

  • The board does not run Debian: there is no desktop, no shell commands, no apt and no config-pin. It runs one Python program.
  • The PRUs, the other UARTs, I2C1, SPI1, the eQEP encoders and the CAN buses are not modelled, nor the pins the eMMC and the HDMI framer hold.
  • The micro-HDMI, USB, the microSD card's files and the POWER, RESET and BOOT buttons are drawn but not simulated.
  • The ADC has no sampling capacitor here: a source of a few kohm reads true, where a real AM3358 may want a buffer or a slower sampling.
  • The 5V and 3V3 pins are logic levels: a module that reads its own supply sees 5 V on either.
  • C programs and Python packages with C code do not run. Pure Python code takes no simulation time; only the pin, bus, ADC, sleep and network calls move the clock.
  • The router, the board's address, the boot time and the terminal are TEP additions.
  • BeagleBone and BeagleBoard are trademarks of the BeagleBoard.org Foundation; this library is not made or endorsed by BeagleBoard.org, Texas Instruments, Adafruit or Labcenter.
  • Tested in Proteus 8.5 in October 2026 (the demo as shipped, about 15 % of real time on our PC with the three pop-ups, the two monitors and the terminal open). Proteus 7 is not supported.

So, that was all about the BeagleBone Black Library for Proteus. I hope it helps you try the BeagleBone with real sensors before you touch the hardware - two analog sensors read through dividers on its ADC, a flow sensor counted on a GPIO, the user LEDs as status lights, and a web page that calibrates the probe and judges the water from a laptop or a phone. If you use the library in a project, please share it in the comments or in our forum, and if you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!


Comments

0

Join the conversation