Introduction: Raspberry Pi Based Torrent Server
Personally I’m started to have interests about Raspberry Pi (RPI) due to the thinking of making effective torrent server.
Before using RPI, I have quite old PC which is not welcomed by any of my family members because of low performance.
Usually that bulky PC takes significant space in my room and old Windows XP messed with various malware as MS discontinued the technical support.
That’s why I’m making this small torrent server box (size about 15cm(W) x 10cm(D) x 12cm(H)).
This is second upgrade from the first torrent server box I had made before.
Step 1: Previous Torrent Server Box
This is version 1 RPI torrent server which installed with 1 IDE and 1 SATA hard disks which are quite old and capacity is about 300GB even summing up sizes of both HDDs.
The HDDs are quite noisy when transmission is continually downloading segments of files.
But eventually both disks are failed with frequent data write and removes.
As this torrent server is lacking any visual indications, it a little bit inconvenient to check possible disk full and how many files are downloaded now.
Also due to the lacking of any cooling capability, RPI usually become sluggish in performance and finally unresponsive when turning the server on for all day long.
And as no power supply is included, three (3) sets of external power modules and cables are used including one for the RPI, two for both HDDs.
And overall shape assembled is a little bit bulky, crude and a little bit ugly also.
That’s why the second version is made as shown in this indestructible.
Step 2: Component Wiring Diagram
Arduino board and 74HC595 shift register circuits are interconnected together along with power supply and FAN control circuits as shown in the picture above.
Also RPI connected with three components such as cooling FAN circuit, bi-color LED blinking circuit and external 240GB SSD.
Dedicated power supply also connected to RPI for supplying stable 5V power.
You can check detail circuit information in each instructable as follows.
***
- Disk usage/file download indicators (1), (2) are explained in https://www.instructables.com/Disk-Usage-and-File-Download-Indicator/ (Disk Usage and File Download Indicator)
- Cooling FAN circuit (3) detail can be found in https://www.instructables.com/Raspberry-Pi-Box-of-Cooling-FAN-With-CPU-Temperatu/ (Raspberry Pi Box of Cooling FAN With CPU Temperature Indicator)
- Details of bi-color blinking indicator (4) can be found in https://www.instructables.com/circuits/raspberry-pi/projects/recent/ (Raspberry Pi Shutdown Indicator)
***
This project is final outcome by combining all previous work results to make unattended and heavy duty kind of torrent server.
The completed torrent server version 2 is using RPI and Arduino together.
Basically RPI is used for running transmission server to download files.
Arduino is added for showing disk usage level and number of download finished files.
RPI and Arduino is communicating via USB serial port for sending/receiving disk usage and file count data.
Cooling FAN control circuit and FAN operation indicator is also included to support diverse visual indication.
According to the LEDs status as shown in the head of this page, less than 60% of 240GB SSD disk space is used, three download finished files are available and FAN is operating currently.
With self descriptive indications of the torrent server, frequent remote terminal connection and running this or that commands are not necessary.
This server will operate as unattended manner with own power supply and LAN communication link to download files for all day long.
Step 3: Parts
Please check other instructables for detail about electronic components used for making circuits.
The followings are add-ons or making torrent server.
***
- Raspberry Pi 3B+ (As transmission is somewhat I/O intensive application, RPI 3B+ can fully support workload required by the server)
- 25W RPI power supply with small form factor (5cm(W) x 7.5(D) x 3cm(H)
- About 10W (5V x 1.7A) miniature power supply for Arduino and other circuits
- 240GB Western Digital 2.5” SSD
- SATA to USB SSD interface connector
- USB type B to type A cable
Acrylic boards size of 15cm(W) x 10cm(D) x 4mm or 3mm(H) and metal supporters are basic necessity for making chassis for the system and circuit boards.
Step 4: Power Supply and Wiring
No conventional 220v female power socket and standard male power cable is used to reduce overall chassis size.
Power cable is stripped and L (Live), N (Neutral), G (Grounding) wires are fixed on 3 Pin terminal block (220V 10A rating) as shown in the picture above.
Subsequently two power supply modules are fed with power by wiring wires to the 3 pin terminal block.
Each end of power wire is terminated with circular rug and bolting down to the 3 pin terminal block.
For electrical wiring, please use proper rating of cables which can stand 220V and more than 5A current as minimum.
And always high level of cautions is mandatory to handle 220V live power lines for safety.
Also insulating all exposed metal sleeve and cable conductor is required to prevent unexpected shorts.
One more important thing to note is any 5V power lines of RPI and Arduino should not connected to each other as separate power supply is used.
Common grounding (connecting ground together) can be possible if that is necessary but 5V lines should not be connected together for preventing any malfunction of RPI and Arduino boards.
That why I’m using opto-couplers to interface cooling FAN and bi-color blinking circuits to non RPI power supply of circuit portion.
Step 5: Communication Between RPI and Arduino
Various cables are shown in the picture above such as SSD SATA/USB cable, USB serial (Type-B -> Arduino abd Type-A -> RPI) cable, LAN Ethernet cable, RPI power cable, Arduino power cable.
Among these cables, USB serial cable is the most special as it should be manually made with slight connection modification as follows
- Select standard USB cable (Type-B one side and Type-A other end) and cut middle section and make total length about 25cm in my case (Blue color cable in the picture above is USB serial cable)
- When strip USB cable 4 wires are encased inside sheath for wiring connectors such as red (5V), black (Ground), Green/White (data)
- Red wire (5V) should be not connected as RPI and Arduino has their own power supply
- Other wires (Black, Green and White) should be connected as the same wise to the original connections for supporting serial communication
Except USB serial cable, all other cables can be connected to the designated ports or connectors without any modification if length is appropriate.
Step 6: RPI Python and Arduino Sketch Programs
Actually this is the most time-consuming part in the project as serial communication requires synchronization between RPI and Arduino.
In this application, RPI is command sender and Arduino is receiver of LED control command.
As disk usage indicator circuit has 5 LEDs, pre-defined command is sent to the Arduino such as “disk 3” command is sent when 45% of disk space is used by RPI.
Then Arduino listening serial port and catch “disk 3” command then turn on Green #1, #2, #3 LEDs.
Sending downloaded number of files is simpler than disk usage.
As Arduino expecting two digits of file count (Because two 7 segment is used), additional “0” should be append when number of files are less than 10.
Otherwise two digits number is sent to Arduino with command “file”.
When Arduino receiving “file” command with two digital number, Arduino simply driving two 7 segment LED display to show the number.
***
Let’s look at the RPI code first.
*** Start of code
#!/usr/bin/env python3
import serial
import time, os
# Extract disk usage percentage from df –h command
# I mounted my external SSD (/dev/sda2) to /mnt/myhdd
# setting transmission setting.json download directory as /mnt/myhdd/download
def df_result_get():
cmd = 'df -h > used_space.txt'
os.system(cmd)
lines = []
with open('used_space.txt') as f:
lines = f.read().splitlines()
for sth in lines:
if sth.find('myhdd') >= 0:
tmp_str = sth.split(' ')
for any in tmp_str:
if any.find('%') >= 0:
used = any.replace('%', '')
return used
# finding number of files in the /mnt/myhdd/download directory
def count_files():
dir = '/mnt/myhdd/download'
list = os.listdir(dir) # dir is your directory path
number_files = len(list)
return number_files
if __name__ == '__main__':
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
ret_val = df_result_get()
print('\n\n'+ret_val+'\n\n')
space = int(ret_val)
# I don’t know why but just one serial write is not properly activating Arduino
# Therefore, 3 times of command writing is performed
for i in range(0, 3):
ser.flush()
# disk usage command is sending to Arduino
if space >= 0 and space <= 20:
ser.write(b"disk 1\n")
time.sleep(5)
elif space > 20 and space <= 40:
ser.write(b"disk 2\n")
time.sleep(5)
elif space > 40 and space <= 60:
ser.write(b"disk 3\n")
time.sleep(5)
elif space > 60 and space <= 80:
ser.write(b"disk 4\n")
time.sleep(5)
elif space > 80 and space <= 100:
ser.write(b"disk 5\n")
time.sleep(5)
# Number of downloaded files is read and file command is sending to Arduino
file_cnt = count_files()
print('\n\nNumber of files: '+str(file_cnt)+'\n\n')
if file_cnt >= 0 and file_cnt < 10:
cnt = '0'+str(file_cnt)
elif file_cnt >= 10:
cnt = str(file_cnt)
cnt_str = 'file '+cnt+'\n'
ser.write(cnt_str.encode('utf-8'))
time.sleep(5)
*** End of code
When you understand programming logic, python code is very straight forward and simple.
For executing this code, pyserial module should be installed with the following command.
$ python3 -m pip install pyserial
***
Also “/dev/ttyUSB0” special file should be used for serial data write.
This special file only created when RPI is connected with powered on Arduino and connected with correctly wired USB cable.
If Arduino is not turned on or USB cable wiring is not correct, “/dev/ttyUSB0” is not created and seen with “ls –al” command.
You can’t make this special file by other methods.
And even if you make this special device file in any other methods, serial communication will not possible.
Then let see Arduino Sketch program.
*** Start of code
int dataPin = 6; // Data pin of (14) 74HC595 which control 5 LED indicator
int latchPin = 5; // Latch pin of (12) 74HC595
int clockPin = 4; // Clock pin (11) of 74HC595
int DATA = 13; // Data pin of (14) 74HC595 which control two 7 segment LED display
int LATCH = 12; // Latch pin of (12) 74HC595 is connected to Digital pin 5
int CLOCK = 11; // Clock pin (11) of 74HC595 is connected to Digital pin 6
byte digit10 = 0;
byte digit1 = 0;
byte num = 0;
String recv_num = "";
String data = "";
byte leds = 0;
// Configuring output ports and initialize serial port
void setup() {
Serial.begin(9600); //Starting serial communication
// Initiallize 5 dot LEDs
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
// Initialize number
pinMode(LATCH, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(CLOCK, OUTPUT);
}
void loop() {
data = "";
if (Serial.available() > 0) {
// Read serial port
data = Serial.readStringUntil('\n');
if(data.indexOf("disk")>=0) {
// If received command is controlling 5 LEDs
leds = char_to_bar(data[5]);
disk_quota();
delay(200);
}
// if received command is showing number on 7 segment LED display
else if(data.indexOf("file")>=0) {
digit10 = char_to_byte(data[5]);
digit1 = char_to_byte(data[6]);
digit10 = digit10 << 4;
num = digit10 | digit1;
ledDisplay();
delay(200);
}
}
}
// LED display pattern for controlling 5 LEDs
// This routine convert numeric digit to LED bar type displaying pattern
byte char_to_bar(char cc) {
char bar[6] = {
B00000000,
B10000000,
B11000000,
B11100000,
B11110000,
B11111000
};
int bit_pattern;
bit_pattern = cc -48;
return(bar[bit_pattern]);
}
// Shifting and displaying 8bit LED pattern to control 5 LEDS shows disk usage
void disk_quota() {
for (int i = 0; i < 8; i++) {
updateShiftRegister();
delay(200);
}
}
// Controlling 74HC595 for dot type 5 LED display
void updateShiftRegister() {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, LSBFIRST, leds);
digitalWrite(latchPin, HIGH);
}
// This routine convert base10 numeric digit to 8bit binary digits
byte char_to_byte(char c) {
char bin_num[10] ={
B00000000,
B00000001,
B00000010,
B00000011,
B00000100,
B00000101,
B00000110,
B00000111,
B00001000,
B00001001
};
int pos;
pos = c - 48;
return(bin_num[pos]);
}
// Shifting displaying number to two 7 segment LEDs
void ledDisplay() {
for (int i = 0; i < 8; i++) // Turn on bit by bit
{
updateNumber();
delay(20);
}
}
// Controlling 74HC595 for number display
void updateNumber() {
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, LSBFIRST, num);
digitalWrite(LATCH, HIGH);
}
Command receiving Arcuino sketch program is more complex as it control 74HC595.
But overall control logic is very straight forward.
Please look at https://www.instructables.com/Disk-Usage-and-File-Download-Indicator/ (Disk Usage and File Download Indicator) instructable for more detail about 74HC595 shift register control.
Step 7: Finishing
I don’t know this is final project for making torrent server with RPI.
But for a quite long time in the future this will serve sufficiently to download files.
And as shown in the previous instructable https://www.instructables.com/Raspberry-Pi-NFS-and-Samba-File-Server/ (Raspberry Pi NFS and Samba File Server), download files will be stored to another file server for management and retention.
Up to this is the story for making refined torrent server.
Thanks for reading.