Проблемы с PWM на выходе Arduino

Нет ответов
kedrikov
Offline
Зарегистрирован: 31.12.2011

Сори если не втом разделе.

Имеется арду nano. На ардуино приходит управляемый пультом PWM с шириной от 1063 до 1954 .  Так же подключен датчик холла по заранее запрограмированным импульсам которого ардуино ограничивает PWM на выходе , а точнее сводит к средней точке 1500 мс независимо от ширины входного сигнала . Чтобы было понятней это каретка с двигателем которая должна ездить на расстояние 50 метров и при этом не бахнуться в стену.

 

Проблема в следующем на входе управляющий PWM ровный прямоугольный без скачков по ширине. А вот на выходе каждые 3-5 секунд наблюдаются скачки шириной от 40до 80 мс маленькой длительности в сторону средней точки 1500мс тем самым каретка слегка дергается  при движении.

Как решить этот вопрос? Спасибо!

Код прилагаю:

//connections
//connect radio receiver to arduino digital pin 3
//connect encoder to to arduino digital pin 2
//connect esc of motor to arduino digital pin 7
//conect led for show calibration mode  to arduino digital 4

//settings
//RcInMin RcInMax set values maximum and minimum values of you radio output in config section


//tests
//after power on led must to be off
//when once comand from radio received - led must to be ON - calibration mode starts, please move forvard or backward for sets limits
//after calibrations end set stick to stop position and wait for led OFF - calibration mode complete
//in work mode between limits you have fast moving , outside of limits you can have only slow speed configured in #define SlowSpeed



#include <Servo.h>
//-----------------config start------------------------------
#define LEDoutPin1 4  //select pins arduino on off outputs 
#define servoPin1 7 //select pin to control motor






#define SlowSpeed 0 //speed out of limits

#define RcInMin 1063 //1000 //minimum and maximum in milliseconds of command chanel 
#define RcInMax 1954 //2000
#define RcInDeadzone 20  
#define outOfRange 200 // signal must to be between calibrationMin - outrange and calibrationMax + outrange else stop motor

#define calibrationTimerTime 5000 //timeot for calibration proccess

//-------------------config end -------------------------






volatile unsigned long  StartTime = micros();
volatile unsigned long  Pulse;
volatile int  rcInPwm;
volatile int RunDirection = 0;

Servo servo1; 
int calibrationstate = 0; // 0 uncalibrated 1 calibration process 2 calibrated
int calibrationTimerStart = 0; //miliseconds when start calibration
int RcInMid = (RcInMin + RcInMax)/2 ;

int calibrationLimitForward = 0;  //variable for store limit
int calibrationLimitBackward = 0;
int calibrationLimitCounter =0;




void setup()
{
pinMode (LEDoutPin1, OUTPUT);
digitalWrite (LEDoutPin1, LOW);

pinMode (2, INPUT);
digitalWrite (2, HIGH);

servo1.attach(servoPin1);  
//servo1.write(servoMid);  //stop motor command
servo1.writeMicroseconds(RcInMid);





 attachInterrupt(1, ch_state, CHANGE);  //two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3). may be used for inerrupt
 attachInterrupt(0, countEncoder, FALLING);  //two external interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3). may be used for inerrupt
//  Serial.begin(115200);
//  Serial.println(CommandRanges[i]) ;

  
}
 
void loop()
{
if ( micros() - StartTime > 1000000UL) rcInPwm = RcInMid; //failsafe
  
 if (rcInPwm > RcInMid - RcInDeadzone && rcInPwm < RcInMid + RcInDeadzone )  
 //we not change direction in dead zone, may to be inertial moving
 servo1.writeMicroseconds(RcInMid);
 else 
{
  if (rcInPwm > RcInMid  ) 
   RunDirection = 1;  
   else     
   RunDirection = -1;
}  


if (calibrationstate == 0) 
{  
 if (rcInPwm > RcInMid - RcInDeadzone && rcInPwm < RcInMid + RcInDeadzone )
   {servo1.writeMicroseconds(RcInMid);} //stop motor
   else
   {
     calibrationstate = 1; //run calibration at next
     calibrationTimerStart = millis(); 
   } 
}

if (calibrationstate == 1) 
{  
 if (rcInPwm > RcInMid - RcInDeadzone && rcInPwm < RcInMid + RcInDeadzone )
   {
      servo1.writeMicroseconds(RcInMid); //stop motor
      if (millis() - calibrationTimerStart >  calibrationTimerTime )
      {
         calibrationstate = 2; //end of calibration by timeout       
      }
     
   } 
   else
   {
     calibrationTimerStart = millis(); //restart timer while motor moving
     runMotor(rcInPwm);
   } 
}


if (calibrationstate == 2) //limited motor runing
{  
 if (rcInPwm > RcInMid - RcInDeadzone && rcInPwm < RcInMid + RcInDeadzone )
   {
     servo1.writeMicroseconds(RcInMid); //stop motor
   } 
   else
   {
     runMotorLimited();
   } 
}



if (calibrationstate == 1)
  digitalWrite (LEDoutPin1, HIGH);
else
  digitalWrite (LEDoutPin1, LOW);



}


void runMotor(int INPWM)
  {
  int servoout = constrain( INPWM, RcInMin, RcInMax);
  servo1.writeMicroseconds(servoout);

  }

void runMotorSlow(int INPWM)
  {
  int servoout = constrain( INPWM, RcInMid - SlowSpeed , RcInMid + SlowSpeed);
  servoout = constrain( servoout, RcInMin, RcInMax);
  servo1.writeMicroseconds(servoout);
  }  
  

void runMotorLimited()
  {
if  (RunDirection == 1)   
  if (calibrationLimitForward > calibrationLimitCounter  ) //check forward limit
    runMotor(rcInPwm);
  else
    runMotorSlow(rcInPwm);
 
 if  (RunDirection == -1)   
  if (calibrationLimitBackward < calibrationLimitCounter  ) 
    runMotor(rcInPwm);
  else
    runMotorSlow(rcInPwm); 




}



void countEncoder() //runs from interupt
{
calibrationLimitCounter  = calibrationLimitCounter + RunDirection;
if (calibrationstate == 1) 
   {
   if (calibrationLimitForward < calibrationLimitCounter) 
                     calibrationLimitForward = calibrationLimitCounter;
                     
   if (calibrationLimitBackward > calibrationLimitCounter) 
                     calibrationLimitBackward = calibrationLimitCounter;   
   }
   
}

void ch_state() //procedure calls from interrupt
{
unsigned long  CurTime = micros();
bool state = digitalRead(3);
if (state==LOW && CurTime > StartTime)
{
 Pulse = CurTime - StartTime;
 if (Pulse < RcInMin - outOfRange  || Pulse > RcInMax + outOfRange)   { 
    rcInPwm = RcInMid;
    servo1.writeMicroseconds(RcInMid);  //stop motor command 
  }
 else {  rcInPwm = Pulse;}
}
else
 StartTime = CurTime;
}

 

Повторюсь,на входе PWM ровный без скачков, питание чистое.