Build a saltwater battery

Clean Power

© Lead Image © Nelli Valova,

© Lead Image © Nelli Valova,

Article from Issue 252/2021

Rechargeable lithium batteries are expensive, and manufacturing them damages the environment. Saltwater batteries offer a cheaper and greener approach to storing energy.

The supply of lithium is finite, mining lithium pollutes the environment, and the batteries are expensive. None of this applies to saltwater batteries. Common household utensils are all you need to build one for yourself.

Energy turnaround and environmental benefits are some of today's central topics. However, it is not just a matter of making energy production more green but of looking at all aspects of the energy industry. It makes no sense to store clean solar power in lithium-ion batteries if producing them causes massive environmental damage. Recycling these batteries is also problematic. For stationary use, the saltwater battery offers a truly ecological alternative.

Everyone is shaped by their knowledge and experiences. When I first heard about storing energy in saltwater batteries, my first thought was: That can't possibly work. What about the electrochemical voltage series and the anode and cathode made of the same material? No, that's really impossible. A simple experimental setup quickly shed light on the matter. Spoiler alert: It worked!

Test Setup

The rather simple experimental setup comprises three jam jars containing pencil leads wrapped in handkerchiefs. The electrolyte in the jars is a solution of Glauber's salt [1], often used as a home remedy.

If you don't have any Glauber's salt in the house, you can find some online [2]. Glauber's salt is absolutely harmless compared with lithium. The only thing it sometimes causes, when injested, is diarrhea, which is why it serves as a natural laxative in the materia medica.

To activate many ions to transport the charge, you need to dissolve as much salt as possible in the water. As Figure 1 shows, about 20g of Glauber's salt can be dissolved in 100ml of water at a room temperature of 20 C [3]. The jam jars each happen to hold about 100ml of water, so I dissolved 20g of Glauber's salt in each.

Figure 1: The amount of salt that can be dissolved in water. The blue line is Glauber's salt. (Graph: Wikimedia, TheKiteGuy, CC0 1.0 [4])

The job of charging and discharging the battery is handled by a program. A relay module [5] switches the connections to the power supply unit and consumer. To measure the current, I used an INA3221 module [6]. In this experiment, I only need one of the three measuring inputs, but the module was already available in my tinkering box. The circuit diagram for the test setup is shown in Figure 2, and the complete setup is shown in Figure 3.

Figure 2: Circuit diagram for the test setup for measuring the charging and discharging cycles.
Figure 3: The test setup for the saltwater battery.


For the project, I used the latest generation Raspberry Pi OS Lite. You can use RPI Imager [7] to transfer the system to the memory card.

The INA3221 module is controlled over the I2C interface, which you need to enable by typing:

sudo raspi-config

In the interface, navigate to 5 Interfacing Options | P5 I2C and select YES. Next, install Java and some additional tools on the Raspberry Pi:

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install default-jdk i2c-tools wiringpi

The experimental setup is now ready to test. To begin, you scan the I2C bus to find the devices (Listing 1). As expected, the INA3221 module resides on address 0x40.

Listing 1

Scanning the I2C Bus

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Use the commands

$ gpio mode 1 out
$ gpio mode 4 out
$ gpio write 1 0
$ gpio write 1 1
$ gpio write 4 0
$ gpio write 4 1

to make sure the relay is connected correctly. The first two lines set the GPIOs to output mode. The next two lines activate relay 1 for loading and switch it off again. The final two lines do the same for relay 2. The switching logic of the relay module is inverted, but this need not cause any confusion.

Measuring Program

To calculate the charge in this do-it-yourself battery, you need a small program that measures the current and time during charging and discharging. If the discharge current reaches 0mA, the battery is completely discharged.

When charging, things are a bit trickier, because you don't know the end-of-charge voltage of the battery, so you simply charge for a certain time at 12V. In principle, you should charge with a voltage at which no gases escape from the battery. If your set-up starts to bubble, you need to reduce the charging voltage.

The program for the test setup is coded in Java. The i2c-detect and gpio tools control the GPIO and read out the measured values; the Java program starts these tools as sub-processes (Listing 2).

Listing 2

Controlling and Measuring

01 import java.util.Scanner;
02 public class SaltBattery {
03   public void setup() throws Exception {
04     new ProcessBuilder( "/usr/bin/gpio","mode","1","out" ).start();
05     new ProcessBuilder( "/usr/bin/gpio","mode","4","out" ).start();
06    loadOff();
07    unLoadOff();
08  }
09  public int switchBytes(int input){
10    input =((input & 0x00ff) << 0x08)|((input >> 0x08)&0x0ff);
11    int sign=1;
12    if (0<(input&0x8000)){
13      sign=-1;
14      input=((~input)&0xffff)+1;
15    }
16  return sign*input;
17  }
18  public void loadOn() throws Exception {
19    new ProcessBuilder( "/usr/bin/gpio","write","1","0" ).start();
20  }
21  public void loadOff() throws Exception {
22    new ProcessBuilder( "/usr/bin/gpio","write","1","1" ).start();
23  }
24  public void unLoadOn() throws Exception {
25    new ProcessBuilder( "/usr/bin/gpio","write","4","0" ).start();
26  }
27  public void unLoadOff() throws Exception {
28    new ProcessBuilder( "/usr/bin/gpio","write","4","1" ).start();
29  }
30  public double measureCurrent() throws Exception {
    Process p = new ProcessBuilder("i2cget","-y","1","0x40","0x03","w").start();
    Scanner s = new Scanner(p.getInputStream());
    return switchBytes(Integer.decode(;
  public double measureVoltage() throws Exception {
    Process p = new ProcessBuilder("i2cget","-y","1","0x40","0x04","w").start();
    Scanner s = new Scanner(p.getInputStream());
    return switchBytes(Integer.decode(;
  public void go() {
    double sumCurrentUnload=0;
    double sumCurrentLoad=0;
    double current=0;
    int mesurementSteps=600;// Sec
    try {
      System.out.println("Start battery charge");
      for (int i=1; i<mesurementSteps ; i++) {
        current = measureCurrent();
        sumCurrentLoad +=current;
      System.out.println("Start battery discharge");
      for (int i=1; i<mesurementSteps ; i++) {
        current = measureCurrent();
        sumCurrentUnload += current;
        if(current==0.0) break;
    } catch (Exception e) {
    System.out.println("Charge:"+sumCurrentLoad+" mAs");
    System.out.println("Discharge:"+sumCurrentUnload+" mAs");
  }// go
  public static void main(String[] args) {
    SaltBattery b=new SaltBattery();
  }// main
}// class

The switchBytes() method (line 9) plays a special role: It swaps the high and low bytes and interprets the most significant bit as a sign. If the number is negative, the program forms the two's complement and sets the sign. These hacks are needed because the INA3221 module delivers the measured values in a machine language format that Java does not understand.

The measurement program is in the go() method (line 40). The first for loop (lines 49-53) measures the current once per second when the battery is charging, giving the amount of energy stored in the battery. The second for loop (lines 58-64) discharges the battery with a load resistor. When discharging, the program outputs the current voltage of the battery with each measurement. Here, too, it determines the amount of energy extracted.

At the end of the cycle, the script outputs the measured values. To find out a little about the characteristics of the battery, I discharged it with different load resistances (Table 1).

Table 1

Discharge Results

Load Resistance (ohms)

Stored (mA)

Discharged (mA)
















Not surprisingly, the battery built from household objects does not have particularly good efficiency. Much of the charge energy is lost, but it also clearly shows that the battery does store energy. Moreover, it looks like the capacity increases with the number of charging cycles; noticeably, the battery delivers slightly more power with less discharge.

This small test series shows that a saltwater battery works in principle. In the next section, I take a look at a commercially available saltwater battery.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • ACPI Tools

    Linux offers some useful command-line tools that leverage the ACPI power management framework to display detailed data on the status of a laptop battery.

  • AcpiTool and PowerTOP

    AcpiTool and PowerTOP ensure a sustainable battery lifetime and guarantee low energy consumption of laptops running Linux by identifying power hogs and maintaining the battery.

  • Rasp Pi Fox Trap

    As a countermeasure to predators of rare ground-breeding birds, live traps are monitored by a microcontroller and a Raspberry Pi.

  • Pico Sleep Mode

    The Raspberry Pi Pico's high-performance chip is trimmed for I/O and does not try to save power. However, a few tricks in battery mode can keep it running longer.

  • Perl: Google Chart Instructions

    A CPAN module passes drawing instructions in object-oriented Perl to Google Chart, which draws visually attractive diagrams.

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95

Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs