Introduction: Generating Voltage With an Ergometer Bike

The project’s elaboration consisted in the assembly of a “game” with the objective to pedal in an ergometer bike connected to a generator and a tower of lamps that are activated as the engine speed increases – which occurs accorded to the bicycle pedaling. The system was based on reading – through an analog port of an Arduino Mega – the instant voltage generated, then transmitting this data to a Raspberry Pi 3 via serial RX-TX communication and the subsequent activation of the lamps via relay.

Step 1: Materials:

  • 1 Raspberry Pi 3;
  • 1 Arduino Mega 2560;
  • 1 Relay Shield with 10 Relays 12 V;
  • 10 Incandescent Lamps 127 V;
  • 1 Ergometer Bike;
  • 1 Electrical Machine (Generator) 12 V;
  • Resistors (1x1kΩ, 2x10kΩ);
  • 1 Electrolytic Capacitor 10 µF;
  • 1 Zener Diode 5.3 V;
  • 1.5 mm Cable (red, black, brown);
  • 1 MDF tower with support for 10 lamps.

Step 2: System Blocks Diagram:

Step 3: System Operation:

The system is based on the transformation of the kinetic energy generated when cycling the bicycle in electric energy responsible for the activation of the relays that will turn the lamps on.

The voltage generated by the generator is read by an analog pin of Arduino and is sent via RX-TX to the Raspberry Pi. The activation of the relays is proportional to the voltage generated - the higher the voltage, the more relays will be triggered and more lamps will light up.

Step 4: Mechanics Aspects

In order to mechanically couple the DC generator to the bicycle, the belt system had to be replaced by the system used on common bicycles (consisting of a crown, chain and pinion). A metal plate was welded to the bicycle frame so that the engine could be secured by screws. After that, the pinion was welded to the generator shaft so that the chain could be placed, interconnecting the pedal system to the generator.

Step 5: Voltage Reading:

To read the generator’s voltage using Arduino is necessary to connect the positive pole of the electrical machine to the A0 pin of the controller and the negative pole to the GND – to avoid that the maximum voltage of the generator is greater than the 5 V of the Arduino pins, a voltage filter using a capacitor of 10 µF, a resistor of 1 kΩ and a Zener diode of 5.3 V was constructed and connected between the controller and the generator. The firmware loaded in Arduino is very simple and consists only of reading an analog port, multiply the value read by the constant 0.0048828125 (5/1024, that is the Arduino’s GPIO voltage divided by the number of bits of its analog port) and sending the variable to the Serial – the code will be available in the article.

The procedure for enabling RX-TX communication in Raspberry Pi is a bit more complex, and you must follow the procedure described in the link. Briefly, you need to edit a file called “inittab” – located in “/etc/inittab” –, comment the line “T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100” (if the file isn’t founded in Raspberry’s OS, you must enter the command: “sudo leafpad /boot/config.txt” and append the line “enable_uart=1” to the end of file). Once this is done, you must reopen the LX Terminal and disable the Serial with the commands "sudo systemctl stop serial-getty@ttyS0.service" and "sudo systemctl disable serial-getty@ttyS0.service". After that you have to execute the command "sudo leafpad /boot/cmdline.txt", delete the line "console = serial0,115200", save the file and restart the device. In order for RX-TX communication to be possible, the Serial library must be installed on Raspberry Pi with the command "sudo apt-get install -f python-serial" and import the library into the code by inserting the "import serial" line, initializing the serial by inserting the line "ser = serial.Serial (" / dev / ttyS0 ", 9600)" and the read of the voltage sent by the Arduino using the command “ser.readline()” – the full code used in Raspberry will be made available at the end of the article.

Following the procedure described above, the read and send voltage step is complete.

Step 6: Arduino Programming:

As previously stated, the code responsible for reading the voltage generated when cycling is very simple.

Firstly, it’s necessary to choose the A0 pin as the responsible for reading the voltage.

In the "void setup ()" function, you need to set pin A0 to INPUT with "pinMode(sensor, INPUT)" command and select the serial port transmission speed using the "Serial.begin(9600)" command.

In the "void loop ()", the "Serial.flush ()" function is used to clear the buffer every time it terminates sending information via serial; the voltage reading is performed by the function "analogRead (sensor)" – remembering that it is necessary to convert the value read by the analog port to Volts – process cited in the "reading voltage" section of the article.

Also, in the "void loop ()" function, it is necessary to convert the variable x from float to string, since this is the only way to send the variable via RX-TX. The last step in the loop function is to print the string in the serial port so that it can be sent to Raspberry - for this you must use the "Serial.println (y)" function. The line "delay (100)" has been added to the code only so that the variable is sent in intervals of 100 ms - if this time is not respected, the Serial overload will occur, generating possible crashes in the program.

voltage_read.ino

float sensor = A0;
voidsetup() {
pinMode(sensor,INPUT);
Serial.begin(9600);
}
voidloop() {
Serial.flush();
float x=analogRead(sensor)*0.0048828125*16.67;
String y="";
y+=x;
Serial.println(y);
delay(100);
}
view rawvoltage_read.ino hosted with ❤ by GitHub

Step 7: Raspberry Pi 3 Programming:

lamps_bike.py

import os #import the os library (used to clear the screen when necessary)
import RPi.GPIOas gpio #import library used to control the Raspnerry’s GPIO
import serial #import library responsible for the serial communication
import time #import library that makes it possible to use the delay function
import subprocess #import library responsible for play the songs
#start serial
ser = serial.Serial("/dev/ttyS0",9600) #define the device name and the baud rate
#clear screen
clear =lambda: os.system('clear')
#set pins for relay control
gpio.setmode(gpio.BOARD)
gpio.setup(11,gpio.OUT) #lamp 10
gpio.setup(12,gpio.OUT) #lamp 9
gpio.setup(13,gpio.OUT) #lamp 8
gpio.setup(15,gpio.OUT) #lamp 7
gpio.setup(16,gpio.OUT) #lamp 6
gpio.setup(18,gpio.OUT) #lamp 5
gpio.setup(19,gpio.OUT) #lamp 4
gpio.setup(21,gpio.OUT) #lamp 3
gpio.setup(22,gpio.OUT) #lamp 2
gpio.setup(23,gpio.OUT) #lamp 1
#start records
name=["None"]*10
voltage=[0.00]*10
#read records file
f =open('records','r')
for i inrange(10): #the 10 best scores appear on the list
name[i]=f.readline()
name[i]=name[i][:len(name[i])-1]
voltage[i]=f.readline()
voltage[i]=float(voltage[i][:len(voltage[i])-1])
f.close()
clear()
#set the max voltage
max=50.00
#turn the lamps off
for i inrange(11,24,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.HIGH) #set to HIGH, the relays are turned off
#start
whileTrue:
#initial screen
print"Records:\n"
for i inrange(10):
print name[i],":",voltage[i],"V"
current_name=raw_input("Write your name to start: ")
clear()
#Change max value
if current_name =="max":
max=input("Write the max voltage: (2 decimal places)")
clear()
else:
#start warning
for i inrange(11,24,1): #the loop starts in the PIN 11 and stop in PIN 24
if i!=14and i!=17and i!=20: #PIN 14 and 20 are GND pins and 20 is a 3.3 V pin
gpio.output(i,gpio.LOW) #turn the lamps on
time.sleep(0.5)
k=10
for i inrange (23,10,-1):
clear()
if i!=14and i!=17and i!=20:
subprocess.Popen(['aplay','Audios/'+str(k)+'.wav'])
time.sleep(0.03)
clear()
print"Prepare!\n",k
time.sleep(1)
k-=1
gpio.output(i,gpio.HIGH) #turn the lamps off (one by one)
subprocess.Popen(['aplay','Audios/go.wav']) #plays the start music
time.sleep(0.03)
clear()
print"GO!"
time.sleep(1)
clear()
#voltage read
current_voltage=0.00
voltage1=0.00
for i inrange(200):
ser.flushInput()
previous=voltage1
voltage1=float(ser.readline()) #collects Arduino’s data transferred by RX-TX
clear()
print voltage1,"V"
if voltage1>current_voltage:
current_voltage=voltage1
# depending on the voltage generated, more lamps light up.
if voltage1<max/10:
for i inrange(11,24,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=max/10:
gpio.output(11,gpio.LOW)
for i inrange(12,24,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=2*max/10:
for i inrange (11,13,1):
gpio.output(i,gpio.LOW)
for i inrange(13,24,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=3*max/10:
for i inrange (11,14,1):
gpio.output(i,gpio.LOW)
for i inrange(15,24,1):
if i!=17and i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=4*max/10:
for i inrange (11,16,1):
if i!=14:
gpio.output(i,gpio.LOW)
for i inrange(16,24,1):
if i!=17and i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=5*max/10:
for i inrange (11,17,1):
if i!=14:
gpio.output(i,gpio.LOW)
for i inrange(18,24,1):
if i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=6*max/10:
for i inrange (11,19,1):
if i!=14and i!=17:
gpio.output(i,gpio.LOW)
for i inrange(19,24,1):
if i!=20:
gpio.output(i,gpio.HIGH)
if voltage1>=7*max/10:
for i inrange (11,20,1):
if i!=14and i!=17:
gpio.output(i,gpio.LOW)
for i inrange(21,24,1):
gpio.output(i,gpio.HIGH)
if voltage1>=8*max/10:
for i inrange (11,22,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.LOW)
for i inrange(22,24,1):
gpio.output(i,gpio.HIGH)
if voltage1>=9*max/10:
for i inrange (11,23,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.LOW)
gpio.output(23,gpio.HIGH)
if voltage1>=max:
for i inrange (11,24,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.LOW)
if voltage1<previous-2.0:
break
#turn the lamps off
for i inrange (11,24,1):
if i!=14and i!=17and i!=20:
gpio.output(i,gpio.HIGH)
#victory music
if current_voltage>=max:
subprocess.Popen(['aplay','Audios/rocky.wav'])
time.sleep(0.03)
clear()
print"VERY GOOD, YOU WON!"% (u'\u00c9',u'\u00ca',u'\u00c2')
for i inrange(10):
for j inrange(11,24,1):
if j!=14and j!=17and j!=20:
gpio.output(j,gpio.LOW)
time.sleep(0.05)
for j inrange(11,24,1):
if j!=14and j!=17and j!=20:
gpio.output(j,gpio.HIGH)
time.sleep(0.05)
time.sleep(0.5)
subprocess.Popen(['aplay','Audios/end.wav'])
time.sleep(0.03)
clear()
print"End game...\n",current_voltage,"V"
#records
time.sleep(1.2)
reached=0
for i inrange(10):
if current_voltage > voltage[i]:
reached+=1
temp_voltage=voltage[i]
voltage[i]=current_voltage
current_voltage=temp_voltage
temp_name=name[i]
name[i]=current_name
current_name=temp_name
if reached >0:
subprocess.Popen(['aplay','Audios/record.wav'])
time.sleep(0.03)
clear()
f =open('records','w')
for i inrange(10):
f.write(name[i])
f.write("\n")
f.write(str(voltage[i]))
f.write("\n")
f.close()
clear()
view rawlamps_bike.py hosted with ❤ by GitHub

Step 8: Electric Scheme:

The Arduino and the Raspberry Pi 3 are powered by a 5V source with 3A current.

The electrical circuit starts with the connection of the DC generator (coupled to the bicycle) to the Arduino through a voltage filter composed of a Zener diode of 5.3V, a capacitor of 10μF and a resistor of 1kΩ – the filter input is connected to the generator terminals and the output is connected to the A0 port and the GND of the controller.

The Arduino is connected to Raspberry via RX-TX communication – performed through a resistive divider using 10kΩ resistors (required by the controllers' ports operating at different voltages).

Raspberry Pi's GPIOs are connected to the relays responsible for turning on the lamps. The “COM” of all relays was interconnected and connected to the phase (AC grid) and the “N.O” (normally open) of each relay was connected to each lamp and the neutral of the AC grid was interconnected to all the lamps. Thus, when the GPIO responsible for each relay is activated, the relay is switched to the phase of the AC network and turn on the respective lamp.

Step 9: Results:

After the final assembly of the project, it was verified that it worked as expected – according to the speed that the user pedals on the bike, more voltage is generated and more lamps light up.