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

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.
BeagleBone Black Library for Proteus
Latest version: V1.0 (October 2026, this tutorial)
Helping Tools
- Laptop WiFi Monitor: a laptop on the Wi-Fi of your design: a browser, a TCP / UDP terminal and ping
- Mobile WiFi Monitor: a smartphone that opens the pages of your board and sends it commands
- LCD Library for Proteus V3.0: 16x2, 20x4 and I2C LCDs to show your readings
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:
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.
| Raspberry Pi 4 Model B (2019) | BeagleBone Black Rev C (2014) | |
|---|---|---|
| Processor | BCM2711, four Cortex-A72 cores at 1.5 GHz | AM3358, one Cortex-A8 at 1 GHz, two PRUs |
| RAM, storage | 1 - 8 GB, microSD | 512 MB DDR3, 4 GB eMMC, microSD |
| Network | Gigabit Ethernet, Wi-Fi, Bluetooth | 10/100 Ethernet |
| Analog inputs | none | seven, 12 bits, 0 - 1.8 V |
| Headers | 40 pins | P8 and P9: 92 pins, up to 65 GPIOs |
| Python library | RPi.GPIO, gpiozero | Adafruit_BBIO |
| Size | 85 x 56 mm | 86.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
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.
The Headers P8 and P9
| Pins | What the library does with them |
|---|---|
| P8_7 to P8_19, P8_26 | GPIO (P8_13 and P8_19 also PWM) |
| P9_11 to P9_31, P9_41, P9_42 | GPIO; P9_14, P9_16, P9_42 also PWM |
| P9_17, P9_18, P9_21, P9_22 | SPI0: CS0, D1 (MOSI), D0 (MISO), SCLK - /dev/spidev0.0 |
| P9_19, P9_20 | I2C2: SCL, SDA - bus 2, with the board's pull-ups |
| P9_24, P9_26 | UART1: TXD, RXD - /dev/ttyS1 |
| P9_33, P9_35 to P9_40 | AIN0 to AIN6: the ADC, 0 to 1.8 V |
| P9_32, P9_34 | VDD_ADC (the 1.8 V reference) and GNDA_ADC (the ADC's ground) |
| P9_3 to P9_8 | VDD_3V3, VDD_5V and SYS_5V |
| P8_3 to P8_6, P8_20 to P8_46 | held 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.LIBandTEPMOBILE.LIB. - Proteus Model Files:
TEPNET.DLL(the board, the laptop, the phone and the network), the parts'TEPTDS.DLL,TEPTURBIDITY.DLLandTEPYFS201.DLL, and the TEPPi folder - Python 3.11 and the TEP runtime with Adafruit_BBIO. - Python Code:
blink.pyandwater_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
- Close Proteus and extract the whole zip file, for example to your Desktop.
- Copy the files from Proteus Library Files into the LIBRARY folder of Proteus (usually
C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY). - 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).
- Delete
TEPBBB.IDXfrom the LIBRARY folder if it is there. - 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.
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:
| Part pin | Net label | BeagleBone pin | What it does |
|---|---|---|---|
| TDS VCC, GND | 3V3, GND | P9_3, P9_1 | the meter's supply |
| TDS A | TDS | - | its output, into R1 (15k) |
| Turbidity VCC, GND | 5V, GND | P9_7, P9_1 | the sensor's supply (SYS_5V) |
| Turbidity OUT | TURB | - | its output, into R3 (15k) |
| R1 / R2, R3 / R4 | AIN0, AIN1 | P9_39, P9_40 | the dividers' middles: 0.4 of each output |
| R2, R4 | AGND | P9_34 | the dividers' bottoms on the ADC's ground |
| YF-S201 VCC, GND | 5V, GND | P9_7, P9_1 | the flow sensor's supply |
| YF-S201 OUT | FLOW | P8_12 | the 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:
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:
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
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:
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:
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:
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:
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:
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:
Properties of the BeagleBone Black
| Property | What it does |
|---|---|
| PROGRAM | the Python program (default blink.py; a name next to the project or a full path) |
| AUTOOPEN | the terminal at Run: YES (default) or NO |
| ETHERNET | the cable at Run: IN (default, eth0) or OUT (no network) |
| PYTHON, RUNTIME | a 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