Проблемы с 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 ровный без скачков, питание чистое.