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