Use PWM to slowly lower pen
This commit is contained in:
parent
ab5b2c61e6
commit
c9a3535df9
4 changed files with 73 additions and 13 deletions
|
|
@ -1 +1 @@
|
||||||
282
|
319
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
// #define PIN_USB_PULLUP 15 // PA15 - 1.5 kΩ to D+
|
// #define PIN_USB_PULLUP 15 // PA15 - 1.5 kΩ to D+
|
||||||
|
|
||||||
// Port B
|
// Port B
|
||||||
#define PIN_PEN_STATE 6 // PB6
|
#define PIN_PEN_STATE 6 // PB6 - TIM4_CH1
|
||||||
|
|
||||||
// Port C
|
// Port C
|
||||||
#define PIN_LED 13 // PC13 - Status LED
|
#define PIN_LED 13 // PC13 - Status LED
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ MODULE_OWNS_PIN(GPIOA, PIN_OUTPUT_X);
|
||||||
MODULE_OWNS_PIN(GPIOA, PIN_OUTPUT_Y);
|
MODULE_OWNS_PIN(GPIOA, PIN_OUTPUT_Y);
|
||||||
MODULE_OWNS_PIN(GPIOB, PIN_PEN_STATE);
|
MODULE_OWNS_PIN(GPIOB, PIN_PEN_STATE);
|
||||||
MODULE_OWNS_PERIPHERAL(TIM1);
|
MODULE_OWNS_PERIPHERAL(TIM1);
|
||||||
|
MODULE_OWNS_PERIPHERAL(TIM4);
|
||||||
|
|
||||||
static HPGL_Movement_t Output_Buffer[CONFIG_BUFFER_MOVEMENTS];
|
static HPGL_Movement_t Output_Buffer[CONFIG_BUFFER_MOVEMENTS];
|
||||||
static const HPGL_Movement_t *Output_BufferRead = Output_Buffer;
|
static const HPGL_Movement_t *Output_BufferRead = Output_Buffer;
|
||||||
static HPGL_Movement_t *Output_BufferWrite = Output_Buffer;
|
static HPGL_Movement_t *Output_BufferWrite = Output_Buffer;
|
||||||
static bool Output_PenIsDown;
|
//static bool Output_PenIsDown;
|
||||||
|
static unsigned int Output_PenState = OUTPUT_PEN_UP;
|
||||||
static unsigned int Output_DelayCounter = 0;
|
static unsigned int Output_DelayCounter = 0;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
@ -26,7 +28,7 @@ static Output_Coordinate_t Output_CurrentLineStart = {0, 0};
|
||||||
static Output_Coordinate_t Output_CurrentLineEnd = {0, 0};
|
static Output_Coordinate_t Output_CurrentLineEnd = {0, 0};
|
||||||
static unsigned int Output_CurrentLineLength;
|
static unsigned int Output_CurrentLineLength;
|
||||||
static unsigned int Output_CurrentLinePosition;
|
static unsigned int Output_CurrentLinePosition;
|
||||||
static unsigned int Output_CurrentVelocity = OUTPUT_LENGTH_SCALE / 2;
|
static unsigned int Output_CurrentVelocity = OUTPUT_LENGTH_SCALE / 3;
|
||||||
|
|
||||||
bool Output_EnqueueMovement(HPGL_Movement_t movement)
|
bool Output_EnqueueMovement(HPGL_Movement_t movement)
|
||||||
{
|
{
|
||||||
|
|
@ -60,14 +62,14 @@ bool Output_EnqueueMovement(HPGL_Movement_t movement)
|
||||||
|
|
||||||
static void Output_PenDown(void)
|
static void Output_PenDown(void)
|
||||||
{
|
{
|
||||||
GPIOB->BRR = (1 << PIN_PEN_STATE);
|
Output_PenState = OUTPUT_PEN_START;
|
||||||
Output_PenIsDown = true;
|
TIM4->CCR1 = Output_PenState;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Output_PenUp(void)
|
static void Output_PenUp(void)
|
||||||
{
|
{
|
||||||
GPIOB->BSRR = (1 << PIN_PEN_STATE);
|
Output_PenState = OUTPUT_PEN_UP;
|
||||||
Output_PenIsDown = false;
|
TIM4->CCR1 = Output_PenState;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int Output_ApproximateLength(int dx, int dy)
|
static unsigned int Output_ApproximateLength(int dx, int dy)
|
||||||
|
|
@ -100,17 +102,18 @@ static bool Output_FetchNextPoint(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
const HPGL_Movement_t *movement = Output_BufferRead;
|
const HPGL_Movement_t *movement = Output_BufferRead;
|
||||||
if(movement->pen_down != Output_PenIsDown)
|
if(movement->pen_down != (Output_PenState == OUTPUT_PEN_DOWN))
|
||||||
{
|
{
|
||||||
if(movement->pen_down)
|
if(movement->pen_down)
|
||||||
{
|
{
|
||||||
Output_PenDown();
|
Output_PenDown();
|
||||||
|
Output_DelayCounter = OUTPUT_PEN_DOWN_DELAY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Output_PenUp();
|
Output_PenUp();
|
||||||
|
Output_DelayCounter = OUTPUT_PEN_UP_DELAY;
|
||||||
}
|
}
|
||||||
Output_DelayCounter = OUTPUT_PEN_DELAY;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,8 +142,38 @@ static void Output_Position(Output_Coordinate_t position)
|
||||||
TIM1->CCR2 = compare_y;
|
TIM1->CCR2 = compare_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the pen PWM output if the pen is currently moving, return false
|
||||||
|
// otherwise
|
||||||
|
static bool Output_UpdatePen(void)
|
||||||
|
{
|
||||||
|
// Only the downwards motion of the pen is smoothed. Thus, the direction is
|
||||||
|
// implied within the state variable (intermediate values only occur while
|
||||||
|
// the pen is being lowered).
|
||||||
|
if((Output_PenState == OUTPUT_PEN_DOWN)
|
||||||
|
|| (Output_PenState == OUTPUT_PEN_UP))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output_PenState += OUTPUT_PEN_STEP;
|
||||||
|
if(Output_PenState >= OUTPUT_PEN_STOP)
|
||||||
|
{
|
||||||
|
Output_PenState = OUTPUT_PEN_DOWN;
|
||||||
|
}
|
||||||
|
TIM4->CCR1 = Output_PenState;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Output_Tick(void)
|
void Output_Tick(void)
|
||||||
{
|
{
|
||||||
|
// Do not move while pen is lowered
|
||||||
|
if(Output_UpdatePen())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a bit longer after each pen state change
|
||||||
if(Output_DelayCounter > 0)
|
if(Output_DelayCounter > 0)
|
||||||
{
|
{
|
||||||
Output_DelayCounter--;
|
Output_DelayCounter--;
|
||||||
|
|
@ -188,6 +221,7 @@ void Output_Tick(void)
|
||||||
void Output_Init(void)
|
void Output_Init(void)
|
||||||
{
|
{
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
|
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
|
||||||
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
|
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
|
||||||
|
|
||||||
|
|
@ -202,7 +236,7 @@ void Output_Init(void)
|
||||||
|
|
||||||
GPIOB->CRL = (GPIOB->CRL
|
GPIOB->CRL = (GPIOB->CRL
|
||||||
& ~(0xf << (4 * PIN_PEN_STATE)))
|
& ~(0xf << (4 * PIN_PEN_STATE)))
|
||||||
| (0x6 << (4 * PIN_PEN_STATE)) // OD output, 2 MHz
|
| (0xe << (4 * PIN_PEN_STATE)) // AF-OD output, 2 MHz
|
||||||
;
|
;
|
||||||
|
|
||||||
TIM1->CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1
|
TIM1->CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1
|
||||||
|
|
@ -213,6 +247,13 @@ void Output_Init(void)
|
||||||
TIM1->DIER = TIM_DIER_UIE;
|
TIM1->DIER = TIM_DIER_UIE;
|
||||||
TIM1->CR1 = TIM_CR1_CEN;
|
TIM1->CR1 = TIM_CR1_CEN;
|
||||||
NVIC_EnableIRQ(TIM1_UP_IRQn);
|
NVIC_EnableIRQ(TIM1_UP_IRQn);
|
||||||
|
|
||||||
|
TIM4->CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
|
||||||
|
TIM4->CCER = TIM_CCER_CC1P | TIM_CCER_CC1E;
|
||||||
|
TIM4->PSC = OUTPUT_PEN_PRESCALER - 1;
|
||||||
|
TIM4->ARR = OUTPUT_PEN_RELOAD;
|
||||||
|
TIM4->CCR1 = OUTPUT_PEN_UP;
|
||||||
|
TIM4->CR1 = TIM_CR1_CEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIM1_UP_IRQHandler(void)
|
void TIM1_UP_IRQHandler(void)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hpgl.h"
|
#include "hpgl.h"
|
||||||
|
#include "clock.h"
|
||||||
|
|
||||||
// PWM coordinate output settings
|
// PWM coordinate output settings (reoslution also determines the movement
|
||||||
|
// timer tick frequency)
|
||||||
#define OUTPUT_PWM_RESOLUTION 15 // In bits
|
#define OUTPUT_PWM_RESOLUTION 15 // In bits
|
||||||
#define OUTPUT_PWM_OFFSET 300 // Minimum value
|
#define OUTPUT_PWM_OFFSET 300 // Minimum value
|
||||||
|
|
||||||
|
|
@ -16,7 +18,24 @@
|
||||||
#define OUTPUT_LENGTH_SCALE (1 << 3)
|
#define OUTPUT_LENGTH_SCALE (1 << 3)
|
||||||
|
|
||||||
// Delay after initiating pen-up/-down before continuing movements
|
// Delay after initiating pen-up/-down before continuing movements
|
||||||
#define OUTPUT_PEN_DELAY 200 // In timer ticks
|
#define OUTPUT_PEN_UP_DELAY 200 // In movement timer ticks
|
||||||
|
#define OUTPUT_PEN_DOWN_DELAY 20 // In movement timer ticks
|
||||||
|
|
||||||
|
// PWM frequency for the pen state output
|
||||||
|
#define OUTPUT_PEN_FREQUENCY 120 // In Hertz
|
||||||
|
|
||||||
|
// Resulting timer settings for pen PWM output
|
||||||
|
#define OUTPUT_PEN_PRESCALER (CLOCK_APB1 / OUTPUT_PEN_FREQUENCY / 65535 + 1)
|
||||||
|
#define OUTPUT_PEN_RELOAD ((uint16_t)(CLOCK_APB1 / OUTPUT_PEN_FREQUENCY \
|
||||||
|
/ OUTPUT_PEN_PRESCALER - 1))
|
||||||
|
#define OUTPUT_PEN_UP 0
|
||||||
|
#define OUTPUT_PEN_DOWN (OUTPUT_PEN_RELOAD + 1)
|
||||||
|
|
||||||
|
// Start and stop duty cycles and duty cycle step (per movement timer tick) for
|
||||||
|
// gracefully lowering the pen
|
||||||
|
#define OUTPUT_PEN_START ((unsigned int)(0.4 * OUTPUT_PEN_RELOAD))
|
||||||
|
#define OUTPUT_PEN_STOP ((unsigned int)(0.43 * OUTPUT_PEN_RELOAD))
|
||||||
|
#define OUTPUT_PEN_STEP ((unsigned int)(0.0001 * OUTPUT_PEN_RELOAD))
|
||||||
|
|
||||||
void Output_Init(void);
|
void Output_Init(void);
|
||||||
bool Output_EnqueueMovement(HPGL_Movement_t movement);
|
bool Output_EnqueueMovement(HPGL_Movement_t movement);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue