Compare commits
15 Commits
master
...
feature/pr
Author | SHA1 | Date |
---|---|---|
|
634a4bb1f5 | 4 years ago |
|
4093d7c273 | 4 years ago |
|
cab04de5bf | 4 years ago |
|
fe9d3d0d22 | 4 years ago |
|
3493020ce9 | 4 years ago |
|
cd09906fec | 4 years ago |
|
4e344e5f9b | 4 years ago |
|
3d3a456418 | 4 years ago |
|
f55d802410 | 4 years ago |
|
93492bb510 | 4 years ago |
|
8ee7ff1c25 | 4 years ago |
|
5d0534df47 | 4 years ago |
|
a19d0c566f | 5 years ago |
|
95bd4e0c00 | 5 years ago |
|
2ae3d7c8e3 | 5 years ago |
10 changed files with 25891 additions and 0 deletions
@ -0,0 +1,41 @@ |
|||
*.swp |
|||
bin/* |
|||
|
|||
# Created by https://www.toptal.com/developers/gitignore/api/c++ |
|||
# Edit at https://www.toptal.com/developers/gitignore?templates=c++ |
|||
|
|||
### C++ ### |
|||
# Prerequisites |
|||
*.d |
|||
|
|||
# Compiled Object files |
|||
*.slo |
|||
*.lo |
|||
*.o |
|||
*.obj |
|||
|
|||
# Precompiled Headers |
|||
*.gch |
|||
*.pch |
|||
|
|||
# Compiled Dynamic libraries |
|||
*.so |
|||
*.dylib |
|||
*.dll |
|||
|
|||
# Fortran module files |
|||
*.mod |
|||
*.smod |
|||
|
|||
# Compiled Static libraries |
|||
*.lai |
|||
*.la |
|||
*.a |
|||
*.lib |
|||
|
|||
# Executables |
|||
*.exe |
|||
*.out |
|||
*.app |
|||
|
|||
# End of https://www.toptal.com/developers/gitignore/api/c++ |
@ -0,0 +1,125 @@ |
|||
#include <include/a4988.h> |
|||
#include <pigpio.h> |
|||
#include <queue> |
|||
#include <cmath> |
|||
#include <thread> |
|||
#include <string> |
|||
#include <memory> |
|||
|
|||
#include <iostream> |
|||
|
|||
namespace simon { |
|||
namespace a4988 { |
|||
c_allegro_4988::c_allegro_4988(std::unique_ptr<a4988_settings_t> ptr_set) |
|||
: m_ptr_set(std::move(ptr_set)), m_initialized(false), m_alive(true) |
|||
{ |
|||
|
|||
} |
|||
void c_allegro_4988::run(void) |
|||
{ |
|||
if (!m_initialized) { |
|||
initialize(); |
|||
} |
|||
while(m_alive) |
|||
{ |
|||
if (!m_queue.empty()) { |
|||
auto cmd = m_queue.front(); |
|||
// Distinguish between different tytpes of commands and derive type
|
|||
if (*cmd == "move") { |
|||
auto move = std::static_pointer_cast<c_move>(cmd); |
|||
if (!set_pwm_freq(std::round(1e6/move->period_us))) { |
|||
// TODO: proper error handling
|
|||
} |
|||
gpioHardwarePWM(m_ptr_set->gpio_step, m_pwm_freq, PI_HW_PWM_RANGE/2); |
|||
gpioWrite(m_ptr_set->gpio_dir, move->dir); |
|||
auto t_sleep = move->period_us*move->steps; |
|||
std::this_thread::sleep_for(std::chrono::microseconds(t_sleep)); |
|||
gpioHardwarePWM(m_ptr_set->gpio_step, m_pwm_freq, 0); |
|||
} |
|||
else if (*cmd == "enable") { |
|||
auto enable = std::static_pointer_cast<c_enable>(cmd); |
|||
gpioWrite(m_ptr_set->gpio_en, enable->enabled); |
|||
} |
|||
else if (*cmd == "kill") { |
|||
m_alive = false; |
|||
} |
|||
else { |
|||
// TODO: Throw an exception here
|
|||
} |
|||
m_queue.pop(); |
|||
} |
|||
else { |
|||
// Idle
|
|||
} |
|||
} |
|||
} |
|||
void c_allegro_4988::post(std::shared_ptr<c_cmd> cmd) |
|||
{ |
|||
m_queue.push(cmd); |
|||
} |
|||
void c_allegro_4988::post_move(const unsigned steps, const bool dir, |
|||
const unsigned period_us) |
|||
{ |
|||
auto move(std::make_shared<c_move>(steps, dir, period_us)); |
|||
auto cmd = std::static_pointer_cast<c_cmd>(move); |
|||
m_queue.push(cmd); |
|||
} |
|||
|
|||
void c_allegro_4988::initialize(void) |
|||
{ |
|||
// TODO: proper error management throwing exceptions
|
|||
if(m_ptr_set == nullptr) { |
|||
return; |
|||
} |
|||
// Configure clock source for PWM
|
|||
gpioCfgClock(CFG_SAMPLE_RATE_US, CFG_PERIPHERAL_SRC_PCM, CFG_DEPRECATED_ARG); |
|||
// Initialize pigpio library
|
|||
gpioInitialise(); |
|||
// Configure as outputs
|
|||
gpioSetMode(m_ptr_set->gpio_en, PI_OUTPUT); |
|||
gpioSetMode(m_ptr_set->gpio_dir, PI_OUTPUT); |
|||
// Initialize outputs
|
|||
enable(); |
|||
gpioWrite(m_ptr_set->gpio_dir, 0); |
|||
// Set PWM to 0
|
|||
m_pwm_freq = 1000; |
|||
gpioHardwarePWM(m_ptr_set->gpio_step, m_pwm_freq, 0); |
|||
m_initialized = true; |
|||
} |
|||
int c_allegro_4988::enable(void) |
|||
{ |
|||
// TODO: proper error handling
|
|||
auto enable(std::make_shared<c_enable>(true)); |
|||
auto cmd = std::static_pointer_cast<c_cmd>(enable); |
|||
m_queue.push(cmd); |
|||
return 0; |
|||
} |
|||
int c_allegro_4988::disable(void) |
|||
{ |
|||
// TODO: proper error handling
|
|||
auto enable(std::make_shared<c_enable>(false)); |
|||
auto cmd = std::static_pointer_cast<c_cmd>(enable); |
|||
m_queue.push(cmd); |
|||
return 0; |
|||
} |
|||
void c_allegro_4988::kill(void) |
|||
{ |
|||
// TODO: proper error handling
|
|||
auto kill(std::make_shared<c_kill>()); |
|||
auto cmd = std::static_pointer_cast<c_cmd>(kill); |
|||
m_queue.push(cmd); |
|||
} |
|||
int c_allegro_4988::set_pwm_freq(const unsigned pwm_freq) |
|||
{ |
|||
if (pwm_freq > PI_HW_PWM_MAX_FREQ) { |
|||
return 1; |
|||
} |
|||
m_pwm_freq = pwm_freq; |
|||
return 0; |
|||
} |
|||
unsigned c_allegro_4988::get_microsteps(void) |
|||
{ |
|||
return m_ptr_set->gpio_microsteps; |
|||
} |
|||
} // namespace a4988
|
|||
} // namespace simon
|
@ -0,0 +1,87 @@ |
|||
#include <include/stepper.h> |
|||
#include <thread> |
|||
#include <functional> |
|||
#include <iostream> |
|||
#include <fstream> |
|||
#include <memory> |
|||
#include <cmath> |
|||
|
|||
namespace simon { |
|||
namespace stepper { |
|||
c_stepper::c_stepper(const std::string& axis, const std::string& fname) |
|||
{ |
|||
auto file_content = read_file(fname); |
|||
auto j_set = json::parse(file_content); |
|||
if (!j_set["axis_configurations"].is_array()) { |
|||
std::cout << "Expected an array in the configuration below \"axis_configurations\"." << "\n"; |
|||
// TODO: Throw exception
|
|||
} |
|||
extract_settings(j_set, axis); |
|||
m_driver_thread = std::thread(std::bind(&a4988::c_allegro_4988::run, &(*m_ptr_a4988))); |
|||
} |
|||
|
|||
c_stepper::~c_stepper() |
|||
{ |
|||
m_ptr_a4988->kill(); |
|||
m_driver_thread.join(); |
|||
} |
|||
|
|||
void c_stepper::extract_settings(const json& j_set, const std::string& axis) |
|||
{ |
|||
int ind = 0; |
|||
for (const auto& j_axis_conf : j_set["axis_configurations"]) { |
|||
ind++; |
|||
if (j_axis_conf["id"].is_string()) { |
|||
if (j_axis_conf["id"] == axis) { |
|||
auto a_ptr = std::make_unique<a4988::a4988_settings_t>( |
|||
a4988::a4988_settings_t ({ |
|||
// TODO: Do more sanitizing before retrieving this data
|
|||
.gpio_en = j_axis_conf["a4988"]["gpio_en"], |
|||
.gpio_step = j_axis_conf["a4988"]["gpio_step"], |
|||
.gpio_dir = j_axis_conf["a4988"]["gpio_dir"], |
|||
.gpio_microsteps = j_axis_conf["a4988"]["microsteps"] |
|||
}) |
|||
); |
|||
m_ptr_a4988 = std::make_unique<a4988::c_allegro_4988>(std::move(a_ptr)); |
|||
m_stepper = { |
|||
// TODO: Do more sanitizing before retrieving this data
|
|||
.gear_reduction = j_axis_conf["stepper"]["gear_reduction"], |
|||
.steps_per_revolution = j_axis_conf["stepper"]["steps_per_revolution"], |
|||
.clockwise = j_axis_conf["stepper"]["clockwise"] |
|||
}; |
|||
break; |
|||
} |
|||
} else { |
|||
// TODO:Throw exception
|
|||
std::cerr << "Expected a string in the configuration below [\"axis_configurations\"][" << ind << "][\"id\"]\n"; |
|||
} |
|||
} |
|||
} |
|||
|
|||
std::string c_stepper::read_file(const std::string& fname) const |
|||
{ |
|||
std::ifstream input_stream(fname); |
|||
if (!input_stream) { |
|||
// TODO: Throw exception here
|
|||
std::cerr << "Can't open input file!"; |
|||
} |
|||
std::string line; |
|||
std::string jstring; |
|||
while (getline(input_stream, line)) { |
|||
jstring += line; |
|||
} |
|||
return jstring; |
|||
} |
|||
|
|||
float c_stepper::rotate(const float& degrees) |
|||
{ |
|||
auto steps_360 = m_stepper.gear_reduction |
|||
* m_stepper.steps_per_revolution |
|||
* static_cast<float>(m_ptr_a4988->get_microsteps()); |
|||
auto steps = static_cast<unsigned>((std::abs(degrees)/360.0f) * steps_360); |
|||
bool direction = (degrees < 0) ? !m_stepper.clockwise : m_stepper.clockwise; |
|||
m_ptr_a4988->post_move(steps, direction, 100); |
|||
return steps; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,85 @@ |
|||
#ifndef INCLUDED_DRIVER_ALLEGRO_4988 |
|||
#define INCLUDED_DRIVER_ALLEGRO_4988 |
|||
|
|||
#define CFG_SAMPLE_RATE_US 5 |
|||
#define CFG_PERIPHERAL_SRC_PCM 1 |
|||
#define CFG_DEPRECATED_ARG 0 |
|||
|
|||
#include <queue> |
|||
#include <string> |
|||
#include <memory> |
|||
|
|||
namespace simon { |
|||
namespace a4988 { |
|||
typedef struct |
|||
{ |
|||
const unsigned gpio_en; |
|||
const unsigned gpio_step; |
|||
const unsigned gpio_dir; |
|||
const unsigned gpio_microsteps; |
|||
} a4988_settings_t; |
|||
|
|||
class c_cmd |
|||
{ |
|||
public: |
|||
explicit c_cmd(const std::string cmd) : m_cmd(cmd) {} |
|||
bool operator==(const std::string& vgl) { |
|||
return (vgl==m_cmd ? true : false); |
|||
} |
|||
virtual ~c_cmd(void) noexcept {} |
|||
private: |
|||
const std::string m_cmd; |
|||
}; |
|||
|
|||
class c_move : public c_cmd |
|||
{ |
|||
public: |
|||
const unsigned steps; |
|||
const bool dir; |
|||
const unsigned period_us; |
|||
c_move(const unsigned isteps, const bool idir, |
|||
const unsigned iperiod_us) |
|||
: c_cmd("move"), steps(isteps), dir(idir), period_us(iperiod_us){} |
|||
}; |
|||
|
|||
class c_enable : public c_cmd |
|||
{ |
|||
public: |
|||
const bool enabled; |
|||
explicit c_enable(const bool ienabled) |
|||
: c_cmd("enable"), enabled(ienabled) {} |
|||
}; |
|||
|
|||
class c_kill : public c_cmd |
|||
{ |
|||
public: |
|||
c_kill(void) |
|||
: c_cmd("kill") {} |
|||
}; |
|||
|
|||
class c_allegro_4988 |
|||
{ |
|||
public: |
|||
explicit c_allegro_4988(std::unique_ptr<a4988_settings_t> ptr_set); |
|||
int enable(void); |
|||
int disable(void); |
|||
void kill(void); |
|||
void post(std::shared_ptr<c_cmd> cmd); |
|||
void post_move(const unsigned steps, const bool dir, |
|||
const unsigned period_us); |
|||
void run(void); |
|||
unsigned get_microsteps(void); |
|||
private: |
|||
std::unique_ptr<a4988_settings_t> m_ptr_set; |
|||
bool m_initialized; |
|||
std::queue<std::shared_ptr<c_cmd>> m_queue; |
|||
unsigned m_pwm_freq; |
|||
bool m_alive; |
|||
private: |
|||
void initialize(void); |
|||
int set_pwm_freq(const unsigned pwm_freq); |
|||
}; |
|||
} // namespace a4988
|
|||
} // namespace simon
|
|||
|
|||
#endif /*INCLUDED_DRIVER_ALLEGRO_4988*/ |
@ -0,0 +1,36 @@ |
|||
#ifndef INCLUDED_HAL_STEPPER |
|||
#define INCLUDED_HAL_STEPPER |
|||
|
|||
#include <include/a4988.h> |
|||
#include <lib/json.hpp> |
|||
#include <thread> |
|||
|
|||
namespace simon { |
|||
namespace stepper { |
|||
|
|||
using json = nlohmann::json; |
|||
|
|||
typedef struct { |
|||
float gear_reduction; |
|||
float steps_per_revolution; |
|||
bool clockwise; |
|||
} settings_t; |
|||
|
|||
class c_stepper |
|||
{ |
|||
public: |
|||
c_stepper(const std::string& axis, const std::string& fname); |
|||
~c_stepper(); |
|||
float rotate(const float& degrees); |
|||
private: |
|||
settings_t m_stepper; |
|||
std::unique_ptr<a4988::c_allegro_4988> m_ptr_a4988; |
|||
std::thread m_driver_thread; |
|||
private: |
|||
std::string read_file(const std::string& fname) const; |
|||
void extract_settings(const json& j_set, const std::string& axis); |
|||
}; |
|||
} // namespace stepper
|
|||
} // namespace simon
|
|||
|
|||
#endif /*INCLUDED_HAL_STEPPER*/ |
File diff suppressed because it is too large
@ -0,0 +1,38 @@ |
|||
#include <iostream> |
|||
#include <include/stepper.h> |
|||
#include <boost/program_options.hpp> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
using namespace simon; |
|||
namespace po = boost::program_options; |
|||
po::options_description desc("This small program allows to control SMcam. Allowed options"); |
|||
desc.add_options() |
|||
("help", "Produce help message") |
|||
("axis", po::value<std::string>(), "Name of the axis to rotate") |
|||
("settings", po::value<std::string>(), "Settings file name") |
|||
("rotate", po::value<int>(), "Rotation in degrees. Positive means clockwise."); |
|||
po::variables_map vm; |
|||
po::store(po::parse_command_line(argc, argv, desc), vm); |
|||
po::notify(vm); |
|||
if (vm.count("help")) { |
|||
std::cout << desc << "\n"; |
|||
return EXIT_FAILURE; |
|||
} |
|||
stepper::c_stepper* ptr_stepper = nullptr; |
|||
if (vm.count("axis") && vm.count("settings")) { |
|||
auto axis = vm["axis"].as<std::string>(); |
|||
auto fname_settings = vm["settings"].as<std::string>(); |
|||
ptr_stepper = new stepper::c_stepper(axis, fname_settings); |
|||
if (vm.count("rotate")) { |
|||
auto degrees = vm["rotate"].as<int>(); |
|||
ptr_stepper->rotate(degrees); |
|||
} |
|||
} else { |
|||
std::cerr << "Please specify axis and settings file.\n"; |
|||
return EXIT_FAILURE; |
|||
} |
|||
if (ptr_stepper != nullptr) |
|||
delete ptr_stepper; |
|||
return EXIT_SUCCESS; |
|||
} |
@ -0,0 +1,7 @@ |
|||
#!/bin/bash |
|||
SAMCAM_HOME=/home/pi/camera_steering_sw |
|||
SETTINGS_FILE=$SAMCAM_HOME/settings.json |
|||
ANGLE=-10 |
|||
AXIS=elevation |
|||
export PATH=$SAMCAM_HOME/bin:$PATH |
|||
SaMcam --axis $AXIS --settings $SETTINGS_FILE --rotate $ANGLE |
@ -0,0 +1,7 @@ |
|||
#!/bin/bash |
|||
SAMCAM_HOME=/home/pi/camera_steering_sw |
|||
SETTINGS_FILE=$SAMCAM_HOME/settings.json |
|||
ANGLE=10 |
|||
AXIS=elevation |
|||
export PATH=$SAMCAM_HOME/bin:$PATH |
|||
SaMcam --axis $AXIS --settings $SETTINGS_FILE --rotate $ANGLE |
@ -0,0 +1,18 @@ |
|||
{ |
|||
"axis_configurations": [ |
|||
{ |
|||
"stepper": { |
|||
"gear_reduction": 64.0, |
|||
"steps_per_revolution": 32, |
|||
"clockwise" : false |
|||
}, |
|||
"a4988": { |
|||
"microsteps": 16, |
|||
"gpio_dir": 22, |
|||
"gpio_en": 17, |
|||
"gpio_step": 18 |
|||
}, |
|||
"id": "elevation" |
|||
} |
|||
] |
|||
} |
Loading…
Reference in new issue