Build a saltwater battery
Clean Power
![© Lead Image © Nelli Valova, 123RF.com © Lead Image © Nelli Valova, 123RF.com](/var/linux_magazin/storage/images/issues/2021/252/saltwater-battery/po-26683-123rf-nelli_valova_123rf_com-steampunk_lights_and_gears_resized.png/793862-1-eng-US/PO-26683-123RF-Nelli_Valova_123RF_com-Steampunk_lights_and_gears_resized.png_medium.png)
© Lead Image © Nelli Valova, 123RF.com
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.
![](/var/linux_magazin/storage/images/issues/2021/252/saltwater-battery/figure-1/793865-1-eng-US/Figure-1_large.png)
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.
![](/var/linux_magazin/storage/images/issues/2021/252/saltwater-battery/figure-2/793868-1-eng-US/Figure-2_large.png)
![](/var/linux_magazin/storage/images/issues/2021/252/saltwater-battery/figure-3/793871-1-eng-US/Figure-3_large.png)
Setup
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(s.next()))/20; } 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(s.next()))/1000; } public void go() { double sumCurrentUnload=0; double sumCurrentLoad=0; double current=0; int mesurementSteps=600;// Sec try { setup(); System.out.println("Start battery charge"); loadOn(); for (int i=1; i<mesurementSteps ; i++) { current = measureCurrent(); sumCurrentLoad +=current; Thread.sleep(1000); } loadOff(); System.out.println("Start battery discharge"); Thread.sleep(2000); unLoadOn(); for (int i=1; i<mesurementSteps ; i++) { current = measureCurrent(); sumCurrentUnload += current; System.out.println("Voltage:"+measureVoltage()); if(current==0.0) break; Thread.sleep(1000); } unLoadOff(); } catch (Exception e) { System.out.println(e); } System.out.println("Charge:"+sumCurrentLoad+" mAs"); System.out.println("Discharge:"+sumCurrentUnload+" mAs"); }// go public static void main(String[] args) { SaltBattery b=new SaltBattery(); b.go(); }// 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) |
---|---|---|
10 |
13,207 |
-395 |
30 |
13,798 |
-440 |
100 |
14,358 |
-462 |
100 |
14,370 |
-483 |
100 |
14,374 |
-507 |
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
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
![Learn More](https://www.linux-magazine.com/var/linux_magazin/storage/images/media/linux-magazine-eng-us/images/misc/learn-more/834592-1-eng-US/Learn-More_medium.png)
News
-
NVIDIA Released Driver for Upcoming NVIDIA 560 GPU for Linux
Not only has NVIDIA released the driver for its upcoming CPU series, it's the first release that defaults to using open-source GPU kernel modules.
-
OpenMandriva Lx 24.07 Released
If you’re into rolling release Linux distributions, OpenMandriva ROME has a new snapshot with a new kernel.
-
Kernel 6.10 Available for General Usage
Linus Torvalds has released the 6.10 kernel and it includes significant performance increases for Intel Core hybrid systems and more.
-
TUXEDO Computers Releases InfinityBook Pro 14 Gen9 Laptop
Sporting either AMD or Intel CPUs, the TUXEDO InfinityBook Pro 14 is an extremely compact, lightweight, sturdy powerhouse.
-
Google Extends Support for Linux Kernels Used for Android
Because the LTS Linux kernel releases are so important to Android, Google has decided to extend the support period beyond that offered by the kernel development team.
-
Linux Mint 22 Stable Delayed
If you're anxious about getting your hands on the stable release of Linux Mint 22, it looks as if you're going to have to wait a bit longer.
-
Nitrux 3.5.1 Available for Install
The latest version of the immutable, systemd-free distribution includes an updated kernel and NVIDIA driver.
-
Debian 12.6 Released with Plenty of Bug Fixes and Updates
The sixth update to Debian "Bookworm" is all about security mitigations and making adjustments for some "serious problems."
-
Canonical Offers 12-Year LTS for Open Source Docker Images
Canonical is expanding its LTS offering to reach beyond the DEB packages with a new distro-less Docker image.
-
Plasma Desktop 6.1 Released with Several Enhancements
If you're a fan of Plasma Desktop, you should be excited about this new point release.