This commit is contained in:
2026-05-18 19:49:40 +02:00
commit 27fc2d2757
170 changed files with 6571 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
from picamera import PiCamera
from time import sleep
'''
This script helps to test the functionality of the Raspberry Pi camera.
The script must be run dicrectly on the Raspberry Pi (not in the Docker container)
'''
camera = PiCamera()
camera.start_preview()
sleep(5)
camera.stop_preview()
@@ -0,0 +1,96 @@
import Adafruit_PCA9685
import yaml
import time
import os
config_filename = '../config/exomy.yaml'
def get_driving_pins():
pin_list = []
with open(config_filename, 'r') as file:
param_dict = yaml.load(file)
for key, value in param_dict.items():
if('pin_drive_' in str(key)):
pin_list.append(value)
return pin_list
def get_drive_pwm_neutral():
with open(config_filename, 'r') as file:
param_dict = yaml.load(file)
for key, value in param_dict.items():
if('drive_pwm_neutral' in str(key)):
return value
default_value = 300
print('The parameter drive_pwm_neutral could not be found in the exomy.yaml \n')
print('It was set to the default value: '+ default_value + '\n')
return default_value
if __name__ == "__main__":
print(
'''
$$$$$$$$\ $$\ $$\
$$ _____| $$$\ $$$ |
$$ | $$\ $$\ $$$$$$\ $$$$\ $$$$ |$$\ $$\
$$$$$\ \$$\ $$ |$$ __$$\ $$\$$\$$ $$ |$$ | $$ |
$$ __| \$$$$ / $$ / $$ |$$ \$$$ $$ |$$ | $$ |
$$ | $$ $$< $$ | $$ |$$ |\$ /$$ |$$ | $$ |
$$$$$$$$\ $$ /\$$\ \$$$$$$ |$$ | \_/ $$ |\$$$$$$$ |
\________|\__/ \__| \______/ \__| \__| \____$$ |
$$\ $$ |
\$$$$$$ |
\______/
'''
)
print(
'''
This script helps you to set the neutral values of PWM of the driving motors correctly.
It will send the intended signal for "not moving" to all the motors.
On each motor you have to turn the correction screw until the motor really stands still.
'''
)
if not os.path.exists(config_filename):
print("exomy.yaml does not exist. Finish config_motor_pins.py to generate it.")
exit()
pwm = Adafruit_PCA9685.PCA9685()
'''
The drive_pwm_neutral value is determined from the exomy.yaml file.
But it can be also calculated from the values of the PWM board and motors,
like shown in the following calculation:
# For most motors a pwm frequency of 50Hz is normal
pwm_frequency = 50.0 # Hz
pwm.set_pwm_freq(pwm_frequency)
# The cycle is the inverted frequency converted to milliseconds
cycle = 1.0/pwm_frequency * 1000.0 # 20 ms
# The time the pwm signal is set to on during the duty cycle
on_time = 1.5 # ms
# Duty cycle is the percentage of a cycle the signal is on
duty_cycle = on_time/cycle # 0.075
# The PCA 9685 board requests a 12 bit number for the duty_cycle
value = int(duty_cycle*4096.0) # 307
'''
value = get_drive_pwm_neutral()
pin_list = get_driving_pins()
for pin in pin_list:
pwm.set_pwm(pin, 0, value)
time.sleep(0.1)
raw_input('Press any button if you are done to complete configuration\n')
for pin in pin_list:
pwm.set_pwm(pin, 0, 0)
@@ -0,0 +1,220 @@
import Adafruit_PCA9685
import time
from shutil import copyfile
import os
DRIVE_MOTOR, STEER_MOTOR = [0, 1]
pos_names = {
1: 'fl',
2: 'fr',
3: 'cl',
4: 'cr',
5: 'rl',
6: 'rr',
}
pin_dict = {
}
pwm = Adafruit_PCA9685.PCA9685()
# For most motors a pwm frequency of 50Hz is normal
pwm_frequency = 50.0 # Hz
pwm.set_pwm_freq(pwm_frequency)
# The cycle is the inverted frequency converted to milliseconds
cycle = 1.0/pwm_frequency * 1000.0 # ms
# The time the pwm signal is set to on during the duty cycle
on_time_1 = 2.4 # ms
on_time_2 = 1.5 # ms
# Duty cycle is the percentage of a cycle the signal is on
duty_cycle_1 = on_time_1/cycle
duty_cycle_2 = on_time_2/cycle
# The PCA 9685 board requests a 12 bit number for the duty_cycle
value_1 = 200 #int(duty_cycle_1*4096.0)
value_2 = 400#int(duty_cycle_2*4096.0)
class Motor():
def __init__(self, pin):
self.pin_name = 'pin_'
self.pin_number = pin
def wiggle_motor(self):
# Set the motor to the second value
pwm.set_pwm(self.pin_number, 0, value_2)
# Wait for 1 seconds
time.sleep(1.0)
# Set the motor to the first value
pwm.set_pwm(self.pin_number, 0, value_1)
# Wait for 1 seconds
time.sleep(1.0)
# Set the motor to neutral
pwm.set_pwm(self.pin_number, 0, 307)
# Wait for half seconds
time.sleep(0.5)
# Stop the motor
pwm.set_pwm(self.pin_number, 0, 0)
def stop_motor(self):
# Turn the motor off
pwm.set_pwm(self.pin_number, 0, 0)
def print_exomy_layout():
print(
'''
1 fl-||-fr 2
||
3 cl-||-cr 4
5 rl====rr 6
'''
)
def update_config_file():
file_name = '../config/exomy.yaml'
template_file_name = file_name+'.template'
if not os.path.exists(file_name):
copyfile(template_file_name, file_name)
print("exomy.yaml.template was copied to exomy.yaml")
output = ''
with open(file_name, 'rt') as file:
for line in file:
for key, value in pin_dict.items():
if(key in line):
line = line.replace(line.split(': ', 1)[
1], str(value) + '\n')
break
output += line
with open(file_name, 'w') as file:
file.write(output)
if __name__ == "__main__":
print(
'''
$$$$$$$$\ $$\ $$\
$$ _____| $$$\ $$$ |
$$ | $$\ $$\ $$$$$$\ $$$$\ $$$$ |$$\ $$\
$$$$$\ \$$\ $$ |$$ __$$\ $$\$$\$$ $$ |$$ | $$ |
$$ __| \$$$$ / $$ / $$ |$$ \$$$ $$ |$$ | $$ |
$$ | $$ $$< $$ | $$ |$$ |\$ /$$ |$$ | $$ |
$$$$$$$$\ $$ /\$$\ \$$$$$$ |$$ | \_/ $$ |\$$$$$$$ |
\________|\__/ \__| \______/ \__| \__| \____$$ |
$$\ $$ |
\$$$$$$ |
\______/
'''
)
print(
'''
###############
Motor Configuration
This scripts leads you through the configuration of the motors.
First we have to find out, to which pin of the PWM board a motor is connected.
Look closely which motor moves and type in the answer.
Ensure to run the script until the end, otherwise your changes will not be saved!
This script can always be stopped with ctrl+c and restarted.
All other controls will be explained in the process.
###############
'''
)
for pin_number in range(16):
motor = Motor(pin_number)
motor.stop_motor()
for pin_number in range(16):
motor = Motor(pin_number)
motor.wiggle_motor()
type_selection = ''
while(1):
print("Pin #{}".format(pin_number))
print(
'Was it a steering or driving motor that moved, or should I repeat the movement? ')
type_selection = raw_input('(d)rive (s)teer (r)epeat - (n)one (f)inish_configuration\n')
if(type_selection == 'd'):
motor.pin_name += 'drive_'
print('Good job\n')
break
elif(type_selection == 's'):
motor.pin_name += 'steer_'
print('Good job\n')
break
elif(type_selection == 'r'):
print('Look closely\n')
motor.wiggle_motor()
elif(type_selection == 'n'):
print('Skipping pin')
break
elif(type_selection == 'f'):
print('Finishing calibration at pin {}.'.format(pin_number))
break
else:
print('Input must be d, s, r, n or f\n')
if (type_selection == 'd' or type_selection == 's'):
while(1):
print_exomy_layout()
pos_selection = raw_input(
'Type the position of the motor that moved.[1-6] or (r)epeat\n')
if(pos_selection == 'r'):
print('Look closely\n')
else:
try:
pos = int(pos_selection)
if(pos >= 1 and pos <= 6):
motor.pin_name += pos_names[pos]
break
else:
print('The input was not a number between 1 and 6\n')
except ValueError:
print('The input was not a number between 1 and 6\n')
pin_dict[motor.pin_name] = motor.pin_number
print('Motor set!\n')
print('########################################################\n')
elif (type_selection == 'f'):
break
print('Now we will step through all the motors and check whether they have been assigned correctly.\n')
print('Press ctrl+c if something is wrong and start the script again. \n')
for pin_name in pin_dict:
print('moving {}'.format(pin_name))
print_exomy_layout()
pin = pin_dict[pin_name]
motor = Motor(pin)
motor.wiggle_motor()
raw_input('Press button to continue')
print("You assigned {}/12 motors.".format(len(pin_dict.keys())))
print('Write to config file.\n')
update_config_file()
print(
'''
$$$$$$$$\ $$\ $$\ $$\ $$\
$$ _____|\__| \__| $$ | $$ |
$$ | $$\ $$$$$$$\ $$\ $$$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$$ |
$$$$$\ $$ |$$ __$$\ $$ |$$ _____|$$ __$$\ $$ __$$\ $$ __$$ |
$$ __| $$ |$$ | $$ |$$ |\$$$$$$\ $$ | $$ |$$$$$$$$ |$$ / $$ |
$$ | $$ |$$ | $$ |$$ | \____$$\ $$ | $$ |$$ ____|$$ | $$ |
$$ | $$ |$$ | $$ |$$ |$$$$$$$ |$$ | $$ |\$$$$$$$\ \$$$$$$$ |
\__| \__|\__| \__|\__|\_______/ \__| \__| \_______| \_______|
''')
@@ -0,0 +1,147 @@
import Adafruit_PCA9685
import yaml
import time
import os
config_filename = '../config/exomy.yaml'
def get_steering_motor_pins():
steering_motor_pins = {}
with open(config_filename, 'r') as file:
param_dict = yaml.load(file)
for param_key, param_value in param_dict.items():
if('pin_steer_' in str(param_key)):
steering_motor_pins[param_key] = param_value
return steering_motor_pins
def get_steering_pwm_neutral_values():
steering_pwm_neutral_values = {}
with open(config_filename, 'r') as file:
param_dict = yaml.load(file)
for param_key, param_value in param_dict.items():
if('steer_pwm_neutral_' in str(param_key)):
steering_pwm_neutral_values[param_key] = param_value
return steering_pwm_neutral_values
def get_position_name(name):
position_name = ''
if('_fl' in name):
position_name = 'Front Left'
elif('_fr' in name):
position_name = 'Front Right'
elif('_cl' in name):
position_name = 'Center Left'
elif('_cr' in name):
position_name = 'Center Right'
elif('_rl' in name):
position_name = 'Rear Left'
elif('_rr' in name):
position_name = 'Rear Right'
return position_name
def update_config_file(steering_pwm_neutral_dict):
output = ''
with open(config_filename, 'rt') as file:
for line in file:
for key, value in steering_pwm_neutral_dict.items():
if(key in line):
line = line.replace(line.split(': ', 1)[
1], str(value) + '\n')
break
output += line
with open(config_filename, 'w') as file:
file.write(output)
if __name__ == "__main__":
print(
'''
$$$$$$$$\ $$\ $$\
$$ _____| $$$\ $$$ |
$$ | $$\ $$\ $$$$$$\ $$$$\ $$$$ |$$\ $$\
$$$$$\ \$$\ $$ |$$ __$$\ $$\$$\$$ $$ |$$ | $$ |
$$ __| \$$$$ / $$ / $$ |$$ \$$$ $$ |$$ | $$ |
$$ | $$ $$< $$ | $$ |$$ |\$ /$$ |$$ | $$ |
$$$$$$$$\ $$ /\$$\ \$$$$$$ |$$ | \_/ $$ |\$$$$$$$ |
\________|\__/ \__| \______/ \__| \__| \____$$ |
$$\ $$ |
\$$$$$$ |
\______/
'''
)
print(
'''
This script helps you to set the neutral pwm values for the steering motors.
You will iterate over all steering motors and set them to a neutral position.
The determined value is written to the config file.
Commands:
a - Decrease value for current pin
d - Increase value for current pin
q - Finish setting value for current pin
[Every of these commands must be confirmed with the enter key]
ctrl+c - Exit script
------------------------------------------------------------------------------
'''
)
if not os.path.exists(config_filename):
print("exomy.yaml does not exist. Finish config_motor_pins.py to generate it.")
exit()
pwm = Adafruit_PCA9685.PCA9685()
# For most motors a pwm frequency of 50Hz is normal
pwm_frequency = 50.0 # Hz
pwm.set_pwm_freq(pwm_frequency)
# The cycle is the inverted frequency converted to milliseconds
cycle = 1.0/pwm_frequency * 1000.0 # ms
# The time the pwm signal is set to on during the duty cycle
on_time = 1.5 # ms
# Duty cycle is the percentage of a cycle the signal is on
duty_cycle = on_time/cycle
# The PCA 9685 board requests a 12 bit number for the duty_cycle
initial_value = int(duty_cycle*4096.0)
# Get all steering pins
steering_motor_pins = get_steering_motor_pins()
pwm_neutral_dict = get_steering_pwm_neutral_values()
# Iterating over all motors and fine tune the zero value
for pin_name, pin_value in steering_motor_pins.items():
pwm_neutral_name = pin_name.replace('pin_steer_', 'steer_pwm_neutral_')
pwm_neutral_value = pwm_neutral_dict[pwm_neutral_name]
print('Set ' + get_position_name(pin_name) + ' steering motor: \n')
while(1):
# Set motor
pwm.set_pwm(pin_value, 0, pwm_neutral_value)
time.sleep(0.1)
print('Current value: ' + str(pwm_neutral_value) + '\n')
input = raw_input(
'q-set / a-decrease pwm neutral value/ d-increase pwm neutral value\n')
if(input is 'q'):
print('PWM neutral value for ' + get_position_name(pin_name) +
' has been set.\n')
break
elif(input is 'a'):
print('Decreased pwm neutral value')
pwm_neutral_value-= 5
elif(input is 'd'):
print('Increased pwm neutral value')
pwm_neutral_value += 5
pwm_neutral_dict[pwm_neutral_name] = pwm_neutral_value
update_config_file(pwm_neutral_dict)
print("Finished configuration!!!")
@@ -0,0 +1,94 @@
import Adafruit_PCA9685
import time
import sys
'''
This script helps to test pwm motors with the Adafruit PCA9685 board
Example usage:
python motor_test.py 3
Performs a motor test for the motor connected to pin 3 of the PWM board
'''
# Check if the pin number is given as an argument
if len(sys.argv) < 2:
print('You must give the pin number of the motor to be tested as argument.')
print('E.g: python motor_test.py 3')
print('Tests the motor connected to pin 3.')
exit()
# Set the pin of the motor
pin = int(sys.argv[1])
print('Pin: '+str(pin))
pwm = Adafruit_PCA9685.PCA9685()
# For most motors a pwm frequency of 50Hz is normal
pwm_frequency = 50.0 #Hz
pwm.set_pwm_freq(pwm_frequency)
# The cycle is the inverted frequency converted to milliseconds
cycle = 1.0/pwm_frequency * 1000.0 #ms
# The time the pwm signal is set to on during the duty cycle
on_time = 2.0 #ms
selection = ''
while(selection != '0'):
print("What do you want to test?")
print("1. Min to Max oscilation")
print('2. Incremental positioning')
print('0. Abort')
selection = raw_input()
if (int(selection) == 1):
min_t = 0.5 # ms
max_t = 2.5 # ms
mid_t = min_t+max_t/2
print("pulsewidth_min = {:.2f}, pulsewidth_max = {:.2f}".format(min_t, max_t))
# *_dc is the percentage of a cycle the signal is on
min_dc = min_t/cycle
max_dc = max_t/cycle
mid_dc = mid_t/cycle
dc_list = [min_dc, mid_dc, max_dc, mid_dc]
for dc in dc_list:
pwm.set_pwm(pin, 0, int(dc*4096.0))
time.sleep(2.0)
if (int(selection) == 2):
curr_t = 1.5 # ms
curr_dc = curr_t/cycle
step_size = 0.1 # ms
step_size_scaling = 0.2
dc_selection = ''
while (dc_selection != '0'):
dc_selection = raw_input('a-d: change pulsewidth | w-s: change step size | 0: back to menu\n')
if dc_selection == 'a':
curr_t = curr_t - step_size
elif dc_selection == 'd':
curr_t = curr_t + step_size
elif dc_selection == 's':
step_size = step_size*(1-step_size_scaling)
elif dc_selection == 'w':
step_size = step_size*(1+step_size_scaling)
curr_dc = curr_t/cycle
curr_pwm = int(curr_dc*4096.0)
print("t_current:\t{0:.4f} [ms]\nstep_size:\t{1:.4f} [ms]\ncurr_pwm: {2:.2f}".format(curr_t, step_size, curr_pwm))
pwm.set_pwm(pin, 0, curr_pwm)
# The PCA 9685 board requests a 12 bit number for the duty_cycle
pwm.set_pwm(pin, 0, 0)
@@ -0,0 +1,14 @@
import Adafruit_PCA9685
import time
import sys
'''
This script simply stops all the motors, in case they were left in a running state.
'''
pwm = Adafruit_PCA9685.PCA9685()
# For most motors a pwm frequency of 50Hz is normal
pwm_frequency = 50.0 # Hz
pwm.set_pwm_freq(pwm_frequency)
for pin_number in range(16):
pwm.set_pwm(pin_number, 0, 0)