Servo driver to drive an Arm. Some fixes needed for threads

This commit is contained in:
philsson 2018-08-29 22:43:10 +02:00
parent 5076ec7446
commit 652f24532a
2 changed files with 199 additions and 0 deletions

152
src/drivers/servo.cpp Normal file
View File

@ -0,0 +1,152 @@
#include "src/drivers/Servo.h"
#include "mbed-os/rtos/Thread.h"
namespace drivers {
namespace {
Thread* pServoThread;
double posToPulseWidthInUs(double position)
{
return (position/2+1.5)*1000;
}
typedef struct {
double from;
double to;
double intervalInSec;
PwmOut* pServo;
} SweepData;
typedef struct {
double latestPosition;
PwmOut* pServo;
} NodData;
void sweepWorker(SweepData* pSweepData)
{
SweepData sweepData = *pSweepData;
double resolution(24);
double range(sweepData.to - sweepData.from);
double value(sweepData.to);
double increment(range/resolution);
while (true)
{
value += increment;
if (value >= sweepData.to)
{
increment = -abs(increment);
}
else if (value <= sweepData.from)
{
increment = abs(increment);
}
sweepData.pServo->pulsewidth_us(posToPulseWidthInUs(value));
// E.g resolution 10 will give a 100ms delay between steps
Thread::wait(1000/resolution);
}
}
void nodWorker(NodData* pNodData)
{
pNodData->pServo->pulsewidth_us(posToPulseWidthInUs(pNodData->latestPosition-0.4));
Thread::wait(500);
pNodData->pServo->pulsewidth_us(posToPulseWidthInUs(pNodData->latestPosition));
}
}
Servo::Servo(PinName servoArm)
: m_servo(servoArm)
, m_dir(1)
, m_inMovement(false)
, m_latestPosition(0.0)
{
center();
}
void Servo::center()
{
//stop();
setPosition(0.0);
}
void Servo::resetTimers()
{
m_servo.period_ms(20);
}
void Servo::setPosition(double position)
{
/* TODO: For now we need to call "stop()"
before setting pos when we know we've ran a thread before
Stop does not work here for some reason */
//stop();
double increment = position*500.0;
if (increment < -500)
{
increment = -500;
}
else if (increment > 500)
{
increment = 500;
}
m_servo.pulsewidth_us(1500 + increment*(double)m_dir);
m_latestPosition = position;
}
void Servo::invert()
{
m_dir = -1;
}
void Servo::sweep(double from, double to, double intervalInSec)
{
pServoThread = new Thread;
SweepData sweepData;
sweepData.from = from;
sweepData.to = to;
sweepData.intervalInSec = intervalInSec;
sweepData.pServo = &m_servo;
pServoThread->start(callback(sweepWorker, &sweepData));
wait(5); // Task will run for at least this long (can get destroyed after)
}
void Servo::nod()
{
NodData nodData;
nodData.pServo = &m_servo;
nodData.latestPosition = m_latestPosition;
pServoThread = new Thread;
pServoThread->start(callback(nodWorker, &nodData));
wait(1);
pServoThread->join(); // Wait for the nod to end
}
void Servo::stop()
{
if (pServoThread->get_state() != Thread::Deleted)
{
pServoThread->terminate();
}
if (pServoThread != NULL)
{
delete pServoThread;
}
}
} // namespace drivers

47
src/drivers/servo.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include "mbed.h"
namespace drivers {
class Servo
{
public:
Servo(PinName servoArm);
void center();
//! Will set the reset the period and center the servo
void resetTimers();
//! in range [-1,1]
void setPosition(double position);
//! changes the direction of this arm
void invert();
//! Will start sweeping the servo without end
void sweep(double from, double to, double intervalInSec);
//! The servo will nod like a gentleman
void nod();
//! Stops any active movement (Thread)
void stop();
public:
PwmOut m_servo;
private:
int m_dir;
bool m_inMovement;
double m_latestPosition;
};
} // namespace drivers