I have a Raspberry Pi that is connected to a breadboard. I'm using a BC548 transistor. I would like to know what to code so that if the green wire touches water a LED turns on. This is the circuit.

enter image description here

Below is my sample code and an explanation of it

I'm using flask to have a web server. This is my code:

import RPi.GPIO as GIO
from flast import Flask

GPIO.output(12,GPIO.LOW)     //resets the led

app = Flast(__name__)
def index():
    return 'Hello'
    //i want to add code here if(wire touches water) GPIO.output(12,1)

if __name__ == '__mnain__':
    app.run(debug=True, host='')


I would like to add something like if (wire touches water) then GPIO.output(12, 1) in index(). How can I do this?

I'm new to the Python language and the Raspberry Pi. Although, my main language is Java and I can learn the Python syntax.

  • How do you think the Pi is going to know wether or not a wire is in water? I don't think the Pi will be able to detect current differences that accurately and you should probably look into water sensors Commented Jan 29, 2017 at 14:19
  • 1
    There is a video on youtube that uses only breadboard and having the same materials the wire detects water and LED is turned on. I want to implement it in raspberry pi. Commented Jan 29, 2017 at 14:27
  • What micro controller did they use? Although if you'd like to try you could try a circuit like this one allaboutcircuits.com/projects/… substituting the second wire and button for the water which is also conductive and should be connected to ground at some point Commented Jan 29, 2017 at 14:36
  • What is the YouTube link?
    – mlhDev
    Commented Jan 29, 2017 at 17:20
  • Could you provide the circuit, and not a picture !
    – MatsK
    Commented Aug 26, 2017 at 20:57

4 Answers 4


This answer intended to answer your specific question, but also to provide an example of an engineering approach to the problem.

How to detect water

There are many ways that water could be detected by a circuit. We could use a float and a microswitch, or a capacitive level sensor, or a float with a magnet and a reed switch, or bounce a laser off the surface of the water into an optical receiver or use an ultrasonic range finder or... you get the idea. However, based on the parts you've already chosen, I'm going to guess that what you intend is to detect the water by passing a small current through it. One way to do this is to have two electrodes with a voltage potential between them. If the two electrodes are in air, no current flows because air is an insulator. If the two electrodes are in water, a small current flows because water conducts. The conductivity of water is somewhere in the range of around 5e-6 S/m (deionized water) to around 5 S/m (seawater), while the conductivity of air is around 5e-9 S/m for relatively humid air. If you're not familiar with it S is for siemens which is just the reciprocal of an ohm.

Some assumptions

Although the Pi has both 5V and 3.3V available, all of its I/O is 3.3V, so let's use that voltage for convenience. Further, let's say that the two electrodes are 1 cm apart. It's not critical that they are exactly this distance apart, but it gives us a reasonable number to use in calculations. Further, let's assume that we want to minimize the cost and complexity of the circuit and its associated software. Further, I'm assuming that it is sufficient to detect the presence or absence of water and that level detection is not a requirement. The rest of this answer proceeds with those assumptions. I'm also going to largely assume that you have read and understood this answer which describes some fundamental concepts about transistor circuit design.

First calculations

First, let's say that we have 3.3V potential across electrodes 1 cm apart and that the medium between the electrodes is air with a conductivity of 5e-9 S/m. The current flowing would be 3.3V * 5e-9 S/m * 0.01 m = 1.65e-10 A or 0.165 nA. That is a very small current, as expected. Now let's repeat the calculation with deionized water with a conductivity of about 5e-6 S/m: 3.3V * 5e-6 S/m * 0.01 m = 165 nA. This is still a small current, but it's a thousand times greater than the current in air, so it may be possible to detect the difference. At the other end of the range, with seawater, we get 3.3V * 5 S/m * 0.01 m = 0.165A = 165mA which is much, much larger. With these calculations, the task is to be able to differentiate between a current of 0.165nA and 165nA. Anything larger than 165nA means that water, or some media that conducts at least as well as water, is between the electrodes.

Another way to look at it is to calculate the resistance. For electrodes separated by 1cm in air, that would be 1 / (0.01 m * 5e-9 S/m) = 20e9 ohms = 20 G ohms. For deionized water this would be 1 / ( 0.01 m * 5e-6 S/m ) = 20e6 ohms = 20 M ohms, and for seawater 1 / ( 0.01 m * 5 S/m ) = 20 ohms.

Transistor circuit design

We want to be able to have a binary output based on whether water is present. That is we want a "yes" or "no" answer. For that reason, we probably want to have the transistor operate like a switch (on/off) rather than as an amplifier. As a practical matter, this usually means operating the transistor not in its linear region, as we would want for an amplifier, but in either fully saturated or fully cut-off. To fully turn on an NPN transistor such as the BC548 you have, typically means applying a voltage of at least 0.7V from B (base) to E (emitter). Let's see if we can do this with a simple voltage divider. What this means is that we'd like to choose a value for R2 so that 3.3 V * R2 / (R1 + R2) = 0.7 when R1 < 20M ohms and close to 0V when R1 > 20M ohms.

If we choose a 10M ohm resistor for R2, it gets us pretty close. Here's a schematic for the resulting circuit:


simulate this circuit – Schematic created using CircuitLab

Simulating this circuit with values of R1 ranging from 20 ohms to 20 G ohms, we get the following logarithmic plot of the output voltage:

voltage graph

As you can see, there is a fairly sharp transition from 0 to 3.3V right around the 20M ohm value.

Other considerations

By drawing minimal collector current, we can have a nice sharp transition from on to off. That is why R3 has a value of 1M ohm resistor. Finally, consider what would happen if the electrodes were accidentally shorted together. That would effectively make R1 (which represents the resistance of electrodes and the media between them) effectively a 0 ohm connection -- a dead short. If VBE is 0.7V, that means that in order to have a voltage drop of (3.3V - 0.7V = 2.6V), across that short, we need to have infinite current, which is likely to seriously annoy whatever is trying to supply power (your Pi!) and maybe "let the magic smoke out." We don't want that! So for a little bit of safety, we add the 10K resistor R4 which limits the current. Since the values of R1 and R2 are so large, this doesn't affect the voltage much, so the circuit functions about the same way as without it under normal conditions.


Here's a simple flask template. Name this index.html and put it into a directory named templates.


setTimeout(function() {
}, 3000);
<h1>Water sensor</h1>
<p>Water was {{ water }} </p>

Note that this has a tiny Javascript function that automatically reloads the page every three seconds. It's not a great design, but it will get you started. Next, create the Python code to drive this page. Call it water.py:


from flask import Flask, render_template
import RPi.GPIO as GPIO

waterpin = 12

app = Flask(__name__)

def water() :
    return ["detected", "not detected"][GPIO.input(waterpin)]

def index():
    return render_template('index.html', water=water())

if __name__ == '__main__':
    GPIO.setup(waterpin, GPIO.IN)
    app.run(debug=True, host='')

Now construct the circuit, keeping in mind that instead of R1, what you'll really have is a pair of wires that will serve as your electrodes. The exact type of transistor is not very critical, but the values of the resistors should be pretty close to what's shown. In my case, I didn't have a 10M resistor, so I used a 3.3M resistor instead, and I didn't have a BCM538, but I happened to have a 2N2222A handy (both are common and inexpensive NPN transistors), so I used that. Connect the ground to ground on the Pi (pin 6), connect the 3.3V line (pin 1 on the Pi) and then connect the line labeled Vout (the collector of the transistor) to a GPIO port (I used pin 12 to be consistent with your earlier attempt).


After installing Flask and the GPIO modules on the Pi. We can run the code from the command line by using the command python3 water.py. By default, this will start a server on port 5000. Navigate to it using either a browser on the Pi itself or on another computer which shares a network connection with it.

I just tried it on a RPi 3 that I have nearby and it worked perfectly.


The easiest way is probably to make the wire-water circuit emulate a switch, with current limiting resistors. Have a look at this diagram.

Current limiting resistors (Found here)

If you just hang the ground wire and the pin wire, the pin will detect when the circuit is closed by the water. I doubt you will need the transistor, but you will have to test.

As for the code, you will have to define a pin as IN, and then read that continuously. Have a look at the source of the image above for some examples.

  • The questioner ask, how can a water level be detected with a transistor circuit...
    – MatsK
    Commented Aug 26, 2017 at 20:43
  • I love the idea of using a Flask or Bottle server to measure liquid height.
    – NomadMaker
    Commented Jul 17, 2018 at 6:16
  • @MatsK x-y problem...
    – Bex
    Commented Nov 25, 2018 at 12:57

HCSR04 is a cheap ultrasonic range sensor. Place HCSRO4 on the roof of water tank. Rig up the circuit according to this article. Then rig up a motor to the #GPIO1O of Raspberry Pi via a relay for refill your tank automatically. This article may help you to connect relay module properly https://www.raspberry-solutions.com/connect-relay-to-raspberry-pi/ . Then open terminal and run following command

git clone git:github.com/chipprogrammers/water_level.git

• Then run

sudo python ultrasonic.py

If you want a web integration to run this create a database python and sqlite. Then create a flask server app to show this database.

If you are thinking about real time monitoring of water level you can use Flask or alternatively Bottle server. I am using bottle server here. You want to install Bottle server using following commands sudo apt-get install python3-bottle or sudo apt-get install python-bottle. Then go to the Justgage and download some JavaScript to show our readings interactively. But I don't prefer you to use new version of justgage since it made me some trouble. justguage. 1.0.1.min.js and raphael.2.1.0.min.js are old versions of js files of justgage. That is still I am using. Now it is the time to rigging up the circuit and writing codes. Circuit should rig up according to first article. My code looks like:

import os, time
import RPi.GPIO as GPIO
from bottle import route, run, template
def water_level():
    # Use BCM GPIO references
    # instead of physical pin numbers

    # Define GPIO to use on Pi
    GPIO_ECHO    = 24

    # Speed of sound in cm/s at temperature
    temperature = 20
    speedSound = 33100 + (0.6*temperature)

    # Set pins as output and input
    GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
    GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo

    # Set trigger to False (Low)
    GPIO.output(GPIO_TRIGGER, False)

    # Allow module to settle

    # Send 10us pulse to trigger
    GPIO.output(GPIO_TRIGGER, True)
    # Wait 10us
    GPIO.output(GPIO_TRIGGER, False)
    start = time.time()

    while GPIO.input(GPIO_ECHO)==0:
        start = time.time()

    while GPIO.input(GPIO_ECHO)==1:
        stop = time.time()

    # Calculate pulse length
    elapsed = stop-start

    # Distance pulse travelled in that time is time
    # multiplied by the speed of sound (cm/s)
    distance = elapsed * speedSound

    # That was the distance there and back so halve the value
    distance = distance / 2
    distance1=100-distance #since 100c.m is depth of tank
    distance2= abs(distance1)

    return water_level
def index():
    return template('raphael.2.1.0.min.js')

def index():
    return template('justgage.1.0.1.min.js')

run(host='', port=80)

Since we are rendering some HTML to working of this system(main.html). Create this file using touch command and edit main.html as following:

<marquee><h1>Water is precious</h1></marquee>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="raphael"></script>
<script src="justgage"></script>

function callback(tempStr, status){
    if (status == "success") {
        temp = parseFloat(tempStr).toFixed(2);
        setTimeout(getReading, 1000);
    else {
        alert("There was a problem");

function getReading(){
    $.get('/temp', callback);


<div id="smallbuddy" style="width:960px; height:740px"</div>

var g = new JustGage({
    id: "smallbuddy",
    value: 100,
    min: 0,
    max: 100,
    title: "Water Level in cm"

Make sure that js, html and python script is in same folder.

  • A motor? What is the motor for?
    – Bex
    Commented May 30, 2017 at 10:19
  • @Bex Turning on and off motor automatically to refill tank...
    – Arun
    Commented May 30, 2017 at 10:28
  • The questioner ask, how can a water level be detected with a transistor circuit...
    – MatsK
    Commented Aug 26, 2017 at 20:43
  • The ultrasonic sensor must be protected from condensation.
    – user2497
    Commented Oct 2, 2017 at 18:04

It is better to done this project with ultrasonic range sensor like HCSR04. But it has also some problems since HCSR04 is not water proof and it never shows when water correct value if water came 5cm near to the sensor. If you are going to stick with this method this article will be more helpful for you. In this article there is a program named weblamp.py. I believes this program is really helpful for know the button status( or short circuit due to water) using flask server or bottle server. Sorry... I added new answer instead editing this answer.

  • 1
    This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
    – Milliways
    Commented May 30, 2017 at 5:47
  • @Milliways It is not easy to find out difference in water level using transistor switch as per Mohammed Ali. I am also think he is correct. Alternate solution is HCSR04. That is why I mentioned about HCSR04.
    – Arun
    Commented May 30, 2017 at 5:53
  • 1
    While I think you have a point (being that there may be other, better ways to detect water levels than hanging wires into the tank), I also think that this is not really an answer. If you would elaborate on how to set it up, how to use it and how to write code, this would be a good answer.
    – Bex
    Commented May 30, 2017 at 8:17
  • Per previous comments, this doesn't provide a particularly useful resource for the OP. I think it is just about relevant enough to qualify as a bad answer, however. I've downvoted it as such - if you'd like to flesh it out to provide a complete answer I'd be happy to remove my downvote.
    – goobering
    Commented May 30, 2017 at 9:22
  • @goobering Taken your criticism as a challenge and created water level monitoring system using HCSR04. The video is available here drive.google.com/file/d/0B5HkM_BeqkJxWlZRMlUwX1VsSU0/…
    – Arun
    Commented May 31, 2017 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.