forked from OttoDIY/OttoDIYLib
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathOscillator.cpp
145 lines (120 loc) · 3.66 KB
/
Oscillator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//--------------------------------------------------------------
//-- Oscillator.pde
//-- Generate sinusoidal oscillations in the servos
//--------------------------------------------------------------
//-- (c) Juan Gonzalez-Gomez (Obijuan), Dec 2011
//-- GPL license
//--------------------------------------------------------------
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#include <pins_arduino.h>
#endif
#include "Oscillator.h"
//-- This function returns true if another sample
//-- should be taken (i.e. the TS time has passed since
//-- the last sample was taken
bool Oscillator::next_sample()
{
//-- Read current time
_currentMillis = millis();
//-- Check if the timeout has passed
if(_currentMillis - _previousMillis > _samplingPeriod) {
_previousMillis = _currentMillis;
return true;
}
return false;
}
//-- Attach an oscillator to a servo
//-- Input: pin is the arduino pin were the servo
//-- is connected
void Oscillator::attach(int pin, bool rev)
{
//-- If the oscillator is detached, attach it.
if(!_servo.attached()){
//-- Attach the servo and move it to the home position
_servo.attach(pin);
_pos = 90;
_servo.write(90);
_previousServoCommandMillis = millis();
//-- Initialization of oscilaltor parameters
_samplingPeriod=30;
_period=2000;
_numberSamples = _period/_samplingPeriod;
_inc = 2*M_PI/_numberSamples;
_previousMillis=0;
//-- Default parameters
_amplitude=45;
_phase=0;
_phase0=0;
_offset=0;
_stop=false;
//-- Reverse mode
_rev = rev;
}
}
//-- Detach an oscillator from his servo
void Oscillator::detach()
{
//-- If the oscillator is attached, detach it.
if(_servo.attached())
_servo.detach();
}
/*************************************/
/* Set the oscillator period, in ms */
/*************************************/
void Oscillator::SetT(unsigned int T)
{
//-- Assign the new period
_period=T;
//-- Recalculate the parameters
_numberSamples = _period/_samplingPeriod;
_inc = 2*M_PI/_numberSamples;
};
/*******************************/
/* Manual set of the position */
/******************************/
void Oscillator::SetPosition(int position)
{
write(position);
};
/*******************************************************************/
/* This function should be periodically called */
/* in order to maintain the oscillations. It calculates */
/* if another sample should be taken and position the servo if so */
/*******************************************************************/
void Oscillator::refresh()
{
//-- Only When TS milliseconds have passed, the new sample is obtained
if (next_sample()) {
//-- If the oscillator is not stopped, calculate the servo position
if (!_stop) {
//-- Sample the sine function and set the servo pos
int pos = round(_amplitude * sin(_phase + _phase0) + _offset);
if (_rev) pos=-pos;
write(pos+90);
}
//-- Increment the phase
//-- It is always increased, even when the oscillator is stop
//-- so that the coordination is always kept
_phase = _phase + _inc;
}
}
void Oscillator::write(int position)
{
long currentMillis = millis();
if (_diff_limit > 0) {
int limit = max(1,(((int)(currentMillis - _previousServoCommandMillis)) * _diff_limit) / 1000);
if (abs(position - _pos) > limit) {
_pos += position < _pos ? -limit : limit;
} else {
_pos = position;
}
}
else {
_pos = position;
}
_previousServoCommandMillis = currentMillis;
_servo.write(_pos + _trim);
}