আমার এমজি 90 এস সার্ভোস (জিটারিং) নিয়ে একই সমস্যা ছিল, আমার সিগন্যাল লাইনগুলি তুলনামূলকভাবে দীর্ঘ (60 ~ 70 সেমি), সিগন্যালের উপরে 103 (10nF) ক্যাপাসিটার রেখে আমার জন্য সমস্যাটি স্থির করে (আমি ক্যাপাসিটারটি কোথাও কোথাও রেখেছি) মাঝখানে, সেই স্থানে যেখানে মূল সার্ভো কেবলটি আমার অভ্যন্তরীণ তারের সাথে সংযুক্ত থাকে)।
এ ছাড়া আমি স্ট্যান্ডার্ড সার্ভো লাইব্রেরিটি ব্যবহার করতে পারিনি কারণ এটি আড়ডিনো মেগায় প্রথম টাইমারটি টাইমার -5 এবং এটি আমার ফ্রিকোয়েন্সি পরিমাপের জন্য প্রয়োজন need আমি কেবল 10 সার্ভো ব্যবহার করার সাথে সাথে আমি সরো লাইব্রেরি থেকে কী কোডটি বের করে এটিকে টাইমার -1 ব্যবহার করে পরিবর্তন করেছি (প্রতিটি টাইমার মেগায় সর্বাধিক 12 সার্ভো সমর্থন করে)।
একক কোডটি রেফারেন্সের জন্য নীচে, আপনি যদি এটি নিজের প্রকল্পে অন্তর্ভুক্ত করতে চান তবে আপনি কেবল উপরের অংশটি ব্যবহার করতে পারেন, নীচের অংশটি শীর্ষ অংশটি পরীক্ষা করতে হবে (এটি সিরিয়াল পোর্টে শুনবে, আপনি এসএক্স দিতে পারেন) এবং ভিএক্স কমান্ড, যেখানে এসএক্স একটি সার্ডো নির্বাচন করে, এস 0 প্রথম সার্ভো নির্বাচন করবে, ভিএক্স আমাদের মধ্যে সার্ভো অবস্থান নির্ধারণ করবে, সুতরাং v1500 সার্ভো 0 মাঝারি অবস্থানে স্থাপন করবে, ধরে নিবেন আপনি প্রথমে একটি এস 0 কমান্ড দিয়েছেন)।
//----------------------------------------------------------------
// This is the actual servo code extracted from the servo library
//----------------------------------------------------------------
#include <avr/pgmspace.h>
//----converts microseconds to tick (assumes prescale of 8)
#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8)
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
struct s_servar {
//----counter for the servo being pulsed for each timer (or -1 if refresh interval)
int8_t channel;
};
static volatile struct s_servar gl_vars;
//----maximum number of servos controlled by one timer
#define SERVOS_PER_TIMER 12
//----this can not be higher than SERVOS_PER_TIMER
#define SERVO_AMOUNT 6
struct s_servo {
volatile unsigned int ticks;
unsigned char pin;
};
struct s_servo gl_servos[SERVO_AMOUNT] = {
{ usToTicks(DEFAULT_PULSE_WIDTH), 22 },
{ usToTicks(DEFAULT_PULSE_WIDTH), 23 },
{ usToTicks(DEFAULT_PULSE_WIDTH), 24 },
{ usToTicks(DEFAULT_PULSE_WIDTH), 25 },
{ usToTicks(DEFAULT_PULSE_WIDTH), 26 },
{ usToTicks(DEFAULT_PULSE_WIDTH), 27 },
};
ISR(TIMER1_COMPA_vect) {
unsigned char servooff;
if(gl_vars.channel < 0 ) {
//----channel set to -1 indicated that refresh interval completed so reset the timer
TCNT1 = 0;
}
else{
servooff = gl_vars.channel;
if(servooff < SERVO_AMOUNT) {
//----end the pulse
digitalWrite(gl_servos[servooff].pin, LOW);
}
}
//----increment to the next channel
gl_vars.channel++;
servooff = gl_vars.channel;
if(servooff < SERVO_AMOUNT) {
//----set timer interrupt for pulse length
OCR1A = TCNT1 + gl_servos[servooff].ticks;
//----start the pulse
digitalWrite(gl_servos[servooff].pin, HIGH);
}
else {
// finished all channels so wait for the refresh period to expire before starting over
//----allow a few ticks to ensure the next OCR1A not missed
if(((unsigned)TCNT1) + 4 < usToTicks(REFRESH_INTERVAL)) {
OCR1A = (unsigned int)usToTicks(REFRESH_INTERVAL);
}
else {
//----at least REFRESH_INTERVAL has elapsed
OCR1A = TCNT1 + 4;
}
//----this will get incremented at the end of the refresh period to start again at the first channel
gl_vars.channel = -1;
}
}
void InitServoISR() {
unsigned char ct;
gl_vars.channel = -1;
//----init timer 1
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
TIMSK1 |= _BV(OCIE1A); // enable the output compare interrupt
//----set all servo pins to output
for(ct = 0; ct < SERVO_AMOUNT; ct++) {
pinMode(gl_servos[ct].pin, OUTPUT);
}
}
void SetServoMicroSecs(unsigned char servooff, unsigned short value) {
uint8_t oldSREG;
if(servooff < SERVO_AMOUNT) {
//----ensure pulse width is in range
if(value < MIN_PULSE_WIDTH) { value = MIN_PULSE_WIDTH; }
else {
if(value > MAX_PULSE_WIDTH) { value = MAX_PULSE_WIDTH; }
}
value -= TRIM_DURATION;
value = usToTicks(value);
oldSREG = SREG;
cli();
gl_servos[servooff].ticks = value;
SREG = oldSREG;
}
}
//------------------------------------------------
// This is code to test the above servo functions
//------------------------------------------------
#define ERR_OK 0
#define ERR_UNKNOWN 1
#define ERR_OUTOFRANGE 2
#define SERDEBUG_CODE
#define MAX_SER_BUF 12
void setup() {
InitServoISR();
#ifdef SERDEBUG_CODE
Serial.begin(9600);
Serial.println(F("Start"));
#endif
}
void loop() {
#ifdef SERDEBUG_CODE
uint8_t ct, chr;
char buf[MAX_SER_BUF];
ct = 0;
#endif
//----main while loop
while(1) {
#ifdef SERDEBUG_CODE
//--------------------
// Serial Port
//--------------------
while (Serial.available() > 0) {
chr = Serial.read();
if(chr == '\n') {
ProcSerCmd(buf, ct);
ct = 0;
}
else {
//----if for some reason we exceed buffer size we wrap around
if(ct >= MAX_SER_BUF) { ct = 0; }
buf[ct] = chr;
ct++;
}
}
#endif
}
}
//------------------------------
// Serial Port Code
//------------------------------
#ifdef SERDEBUG_CODE
uint16_t RetrieveNumber(char *buf, uint8_t size) {
//--------------------------------------------------------------
// This function tries to convert a string into a 16 bit number
// Mainly for test so no strict checking
//--------------------------------------------------------------
int8_t ct;
uint16_t out, mult, chr;
out = 0;
mult = 1;
for(ct = size - 1; ct >= 0; ct--) {
chr = buf[ct];
if(chr < '0' || chr > '9') { continue; }
chr -= '0';
chr *= mult;
out += chr;
mult *= 10;
}
return(out);
}
void ProcSerCmd(char *buf, uint8_t size) {
//-----------------------------------------------------------
// supported test commands
// sX X = 0 to SERVO_AMOUNT Sets the servo for test
// vX X = MIN to MAX PULSE WIDTH Sets the test servo to value X
//-----------------------------------------------------------
static unsigned char lgl_servooff = 0;
uint8_t chr, errcode;
uint16_t value;
errcode = 0;
while(1) {
chr = buf[0];
//----test commands (used during development)
if(chr == 's') {
value = RetrieveNumber(buf + 1, size - 1);
if(value < 0 || value >= SERVO_AMOUNT) { errcode = ERR_OUTOFRANGE; break; }
lgl_servooff = (unsigned char)value;
break;
}
if(chr == 'v') {
value = RetrieveNumber(buf + 1, size - 1);
if(value < MIN_PULSE_WIDTH || value > MAX_PULSE_WIDTH) { errcode = ERR_OUTOFRANGE; break; }
SetServoMicroSecs(lgl_servooff, value);
break;
}
errcode = ERR_UNKNOWN;
break;
}
if(errcode == 0) {
Serial.println(F("OK"));
}
else {
Serial.write('E');
Serial.println(errcode);
}
}
#endif