| @@ -0,0 +1,125 @@ | |||
| # Software Requirements for Whiteboard Writer | |||
| ## Design documentation | |||
| In the design document we have defined five functions that have to be performed. | |||
| 1. Move marker on board | |||
| 2. Move Wiper on Board | |||
| 3. Switch Tools | |||
| 4. Lift Marker | |||
| 5. Move carriage | |||
| We already decided to not implement the tool switch. | |||
| This also means that the wiper is probably not something that is going to be achieved either. | |||
| We will split these function into software requirements. | |||
| ## Move marker on board | |||
| The marker is specifically moved by the SCARA. | |||
| The SCARA itself is attached to the carriage. | |||
| This carriage is then moved in function 5. | |||
| Therefore the following things are required: | |||
| * The software has to parse the path data. Such that it nows what to draw. | |||
| * The software has to control the motors. | |||
| * The software has to be able to home the motors. | |||
| * The software will implement the feedforward control behavior. | |||
| * The software must be able to write data at the correct position independent of the carriage position. | |||
| ## Lift marker. | |||
| The servo will lift the marker. For this the servo needs a PWM signal. | |||
| This is purely feedforward. | |||
| * The software has to send out the correct PWM signal when the marker needs to be lifted according to the data. | |||
| ## Move carriage | |||
| For this the software has to move the steppermotors such that the carriage moves. | |||
| Similar to the move marker on board. | |||
| * The software must parse the next plot location. | |||
| * The software has to control the motors. | |||
| * The software has to be able to home the carriage. | |||
| * The software must calculate where the carriage is. | |||
| # Required structures. | |||
| ## Motor driver | |||
| The motors are powered themself with stepper controllers. | |||
| The controllers have a direction pin and a step pin. | |||
| For that I will build a struct in the code with the following assets: | |||
| * Step-pin | |||
| * Direction-pin | |||
| * Max-speed | |||
| * Max-acceleration | |||
| * Microstep (int = 1, 2, 4, 8, 16, 32) | |||
| * Divisions (int = 200) | |||
| * Angle | |||
| * Velocity | |||
| * Homing sensor | |||
| * Homing angle | |||
| ## Path instructions | |||
| For the pathing instruction we need to be able to read the next path instructions. | |||
| For this we need to be able to store a list with points. | |||
| For path instructions it might be useful to look in to [wtk](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry) | |||
| Maybe I can just work with characters and a path for each. | |||
| The system must be able to plan positions. Where to write stuff and if the carriage should be moved or only the SCARA. | |||
| ## Point lib | |||
| A point struct is needed. | |||
| This struct contains two integers. | |||
| We need some point calculations. | |||
| Add, subtract, distance, angle etc. | |||
| Probably just use [ccVector](https://github.com/jobtalle/ccVector) | |||
| or [gb_math.h](https://github.com/gingerBill/gb/blob/master/gb_math.h) | |||
| ## Kinematics struct | |||
| * ArmLengthA float | |||
| * Motor motor1 | |||
| * ArmLengthB float | |||
| * Motor motor2 | |||
| * PullyLocationC Point2D | |||
| * Motor motor3 | |||
| * PullyLocationD Point2D | |||
| * Motor motor4 | |||
| ## Inverse kinematics | |||
| We need to be able to calculate the angles from the position of the motor. | |||
| This is done with the cosine-law. | |||
| Also required for the carriage. | |||
| ## Forward kinematics | |||
| We need to be able to calculate the positions from the angles of the motor. | |||
| Also required for the carriage. | |||
| ## Main | |||
| The main function has to start everything off course. | |||
| It will call the initialisation functions of everything. | |||
| ## Homing | |||
| Before the actual writing, we need to know where my steppers are. | |||
| As they do not have a complete reference. | |||
| The is done by sensors. | |||
| Some sensor will detect the arm in a certain position. | |||
| Then we know the actual angle, and can set the actual angle position. | |||
| ## Sensors | |||
| The sensors need to be read and return a boolean. | |||
| Currently they are planned to be some light gates, with an analog output. | |||
| Struct | |||
| * Sensor pin | |||
| * Threshold value | |||
| @@ -0,0 +1,44 @@ | |||
| #infdef SENSOR_H | |||
| #define SENSOR_H | |||
| #include <stdint.h> | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| typedef struct { | |||
| uint8_t lower; | |||
| uint8_t upper; | |||
| adc_t line; | |||
| adc_res_t res; | |||
| } sensor_params_t; | |||
| typedef struct { | |||
| sensor_params_t p; | |||
| } sensor_t | |||
| /** | |||
| * @brief Initializes the sensor | |||
| * | |||
| * @param[in] dev device settings struct | |||
| * @param[in] params settings for parameters | |||
| */ | |||
| int sensor_init(sensor_t *dev, const sensor_params_t *params); | |||
| /** | |||
| * @brief Read data from the sensor and checks the value is between given thresholds | |||
| * | |||
| * @param[in] dev device settings struct | |||
| * @param[out] data boolean that is true when sensor value is within thresholds. | |||
| */ | |||
| int sensor_read(sensor_t *dev, bool *data); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* SENSOR_H */ | |||
| @@ -0,0 +1,29 @@ | |||
| #ifndef SENSOR_PARAMS_H | |||
| #define SENSOR_PARAMS_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #include "board.h" | |||
| #include "adc.h" | |||
| #ifndef SENSOR_PARAMS | |||
| #define SENSOR_PARAMS \ | |||
| { .upper = STEPPER_PARAM_UPPER, \ | |||
| .lower = STEPPER_PARAM_LOWER, \ | |||
| .line = STEPPER_PARAM_LINE, \ | |||
| .res = STEPPER_PARAM_RES, \ | |||
| } | |||
| #endif | |||
| static const sensor_params_t sensor_params[] = { | |||
| SENSOR_PARAMS | |||
| }; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* SENSOR_PARAMS_H */ | |||
| @@ -0,0 +1,70 @@ | |||
| #infdef STEPPER_H | |||
| #define STEPPER_H | |||
| #include <stdint.h> | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** | |||
| * @brief Status and error codes | |||
| */ | |||
| enum { | |||
| STEPPER_OK = 0, | |||
| STEPPER_NO = -1, | |||
| }; | |||
| /** | |||
| * @brief Direction for stepper | |||
| */ | |||
| typedef enum { | |||
| STEPPER_FORWARD = 0x0, | |||
| STEPPER_REVERSE = 0x1, | |||
| } stepper_direction_t; | |||
| /** | |||
| * @brief Data structure holding the device parameters needed for initialization | |||
| */ | |||
| typedef struct { | |||
| gpio_t step_pin; | |||
| gpio_t dir_pin; | |||
| uint8_t addr; | |||
| uint8_t vel_max; | |||
| uint8_t acc_max; | |||
| uint8_t microstep; | |||
| uint16_t division; | |||
| float angle; | |||
| float velocity; | |||
| sensor_t sensor; | |||
| float homing_angle; | |||
| } stepper_params_t; | |||
| /** | |||
| * @brief Device Descriptor for Stepper controller | |||
| */ | |||
| typedef struct { | |||
| stepper_params_t p; | |||
| } stepper_t | |||
| int stepper_init(stepper_t *dev, const stepper_params_t *params); | |||
| int stepper_set_velocity(stepper_t *dev, float *velocity); | |||
| int stepper_homing(stepper_t *dev); | |||
| int stepper_get_angle(stepper_t *dev, float *angle); | |||
| int stepper_step(stepper_t *dev, stepper_direction_t *direction); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* STEPPER_H */ | |||
| @@ -0,0 +1,69 @@ | |||
| #ifndef STEPPER_PARAMS_H | |||
| #define STEPPER_PARAMS_H | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #include "board.h" | |||
| #ifndef STEPPER_STEP_PIN | |||
| #define STEPPER_STEP_PIN GPIO_PIN(0, 0) | |||
| #endif | |||
| #ifndef STEPPER_DIR_PIN | |||
| #define STEPPER_DIR_PIN GPIO_PIn(0, 1) | |||
| #endif | |||
| #ifndef STEPPER_UART | |||
| #define STEPPER_UART UART(0) | |||
| #endif | |||
| #ifndef STEPPER_VEL_MAX | |||
| #define STEPPER_VEL_MAX STEPPER_VEL_MAX_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_ACC_MAX | |||
| #define STEPPER_ACC_MAX STEPPER_ACC_MAX_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_MICROSTEP | |||
| #define STEPPER_MICROSTEP STEPPER_MICROSTEP_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_DIVISION | |||
| #define STEPPER_DIVISION STEPPER_DIVISION_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_ANGLE | |||
| #define STEPPER_ANGLE STEPPER_ANGLE_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_VELOCITY | |||
| #define STEPPER_VELOCITY STEPPER_VELOCITY_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_SENSOR | |||
| #define STEPPER_SENSOR STEPPER_SENSOR_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_HOMING_ANGLE | |||
| #define STEPPER_HOMING_ANGLE STEPPER_HOMING_ANGLE_DEFAULT | |||
| #endif | |||
| #ifndef STEPPER_PARAMS | |||
| #define STEPPER_PARAMS \ | |||
| { .step_pin = stepper_param_step_pin, \ | |||
| .dir_pin = stepper_param_dir_pin, \ | |||
| .addr = stepper_param_addr, \ | |||
| .vel_max = stepper_param_vel_max, \ | |||
| .acc_max = stepper_param_acc_max, \ | |||
| .microstep = stepper_param_microstep, \ | |||
| .division = stepper_param_division, \ | |||
| .angle = stepper_param_angle, \ | |||
| .velocity = stepper_param_velocity, \ | |||
| .sensor = stepper_param_sensor, \ | |||
| .homing_angle = stepper_param_homing_angle, \ | |||
| } | |||
| #endif | |||
| static const stepper_params_t stepper_params[] = { | |||
| STEPPER_PARAMS | |||
| }; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* STEPPER_PARAMS_H */ | |||
| @@ -0,0 +1,30 @@ | |||
| #include "periph/gpio.h" | |||
| #include "periph/uart.h" | |||
| #include "stepper.h" | |||
| #include "sensor.h" | |||
| #define ENABLE_DEBUG (0) | |||
| #include "debug.h" | |||
| int stepper_init(stepper_t *dev, const stepper_params_t *params) | |||
| { | |||
| assert(dev && params); | |||
| dev->p = *params; | |||
| return STEPPER_OK; | |||
| } | |||
| int stepper_step(stepper_t *dev, stepper_direction_t *direction) | |||
| { | |||