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+
|
||||
|
||||
// Port B
|
||||
#define PIN_PEN_STATE 6 // PB6
|
||||
#define PIN_PEN_STATE 6 // PB6 - TIM4_CH1
|
||||
|
||||
// Port C
|
||||
#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(GPIOB, PIN_PEN_STATE);
|
||||
MODULE_OWNS_PERIPHERAL(TIM1);
|
||||
MODULE_OWNS_PERIPHERAL(TIM4);
|
||||
|
||||
static HPGL_Movement_t Output_Buffer[CONFIG_BUFFER_MOVEMENTS];
|
||||
static const HPGL_Movement_t *Output_BufferRead = 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;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -26,7 +28,7 @@ static Output_Coordinate_t Output_CurrentLineStart = {0, 0};
|
|||
static Output_Coordinate_t Output_CurrentLineEnd = {0, 0};
|
||||
static unsigned int Output_CurrentLineLength;
|
||||
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)
|
||||
{
|
||||
|
|
@ -60,14 +62,14 @@ bool Output_EnqueueMovement(HPGL_Movement_t movement)
|
|||
|
||||
static void Output_PenDown(void)
|
||||
{
|
||||
GPIOB->BRR = (1 << PIN_PEN_STATE);
|
||||
Output_PenIsDown = true;
|
||||
Output_PenState = OUTPUT_PEN_START;
|
||||
TIM4->CCR1 = Output_PenState;
|
||||
}
|
||||
|
||||
static void Output_PenUp(void)
|
||||
{
|
||||
GPIOB->BSRR = (1 << PIN_PEN_STATE);
|
||||
Output_PenIsDown = false;
|
||||
Output_PenState = OUTPUT_PEN_UP;
|
||||
TIM4->CCR1 = Output_PenState;
|
||||
}
|
||||
|
||||
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;
|
||||
if(movement->pen_down != Output_PenIsDown)
|
||||
if(movement->pen_down != (Output_PenState == OUTPUT_PEN_DOWN))
|
||||
{
|
||||
if(movement->pen_down)
|
||||
{
|
||||
Output_PenDown();
|
||||
Output_DelayCounter = OUTPUT_PEN_DOWN_DELAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
Output_PenUp();
|
||||
Output_DelayCounter = OUTPUT_PEN_UP_DELAY;
|
||||
}
|
||||
Output_DelayCounter = OUTPUT_PEN_DELAY;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -139,8 +142,38 @@ static void Output_Position(Output_Coordinate_t position)
|
|||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
Output_DelayCounter--;
|
||||
|
|
@ -188,6 +221,7 @@ void Output_Tick(void)
|
|||
void Output_Init(void)
|
||||
{
|
||||
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
|
||||
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
|
||||
|
||||
|
|
@ -202,7 +236,7 @@ void Output_Init(void)
|
|||
|
||||
GPIOB->CRL = (GPIOB->CRL
|
||||
& ~(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
|
||||
|
|
@ -213,6 +247,13 @@ void Output_Init(void)
|
|||
TIM1->DIER = TIM_DIER_UIE;
|
||||
TIM1->CR1 = TIM_CR1_CEN;
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#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_OFFSET 300 // Minimum value
|
||||
|
||||
|
|
@ -16,7 +18,24 @@
|
|||
#define OUTPUT_LENGTH_SCALE (1 << 3)
|
||||
|
||||
// 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);
|
||||
bool Output_EnqueueMovement(HPGL_Movement_t movement);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue