Проблемы с PWM на выходе Arduino
- Войдите на сайт для отправки комментариев
Сори если не втом разделе.
Имеется арду 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 ровный без скачков, питание чистое.