Detect a change in PWM signal

Hello,

I am trying to detect a change in the PVM signal using arduino uno. Basically a change in the controller, changes the PWM signal's duty cycle output from the receiver. The whole thing is an RC Car. I would like to detect the signals so that i can actuate the servo when it is steered right or left accordingly.

But i'm not able to detect the change. Firstly i used digitalRead function and tried to calculate offtime and ontime delay but didn't observe any change even when the car is steered through the controller.

Then i tried using analogRead function to calculate offtime and ontime delays. Again couldn't detect the change in signal.

I tried to convert PWM signal to analog using low pass filter and input the analog signal to arduino. I couldn't detect a small change even here.

I just print the state of the signal in serial manager and operate my controller and see if i could observe any change in the values. But its all the same.

Is my method incorrect? What might be the possible solution for this? Any other method to be tried?

Please help me.

I would be grateful if somebody answers this.

Thank you.

I think the only thing you need to do is time the period that the pulse is actually high. To achieve this I'd setup an interrupt to trigger on the rising edge. Within this interrupt store the current value of micros() in a global variable.

Meanwhile in your loop function, you also want to poll the same pin, looking for the level to go LOW. When it does, simply deduct that global variable from the new value of micros() and store this difference in another global variable (perhaps called pulseWidth).

Also within your loop function, every second Serial.print the current value of pulseWidth. With a bit of experimentation, you'll get the drift of how the value relates to position.

Then you can modify your code to map, pulseWidth to the value you need to send to your servo.

Just as a finger in the water (or is it a toe in the air) , try this out (you'll have to use pin 2 for your input)

void setup()
{
  pinMode(2,INPUT);
  attachInterrupt(0,pulseFrontEdge,RISING);
  Serial.begin(9600);
}

volatile unsigned long lastEdge=0;
unsigned long pulseWidth=0;
unsigned long lastReport=0;
bool lastState=0;
void loop()
{
  unsigned long M=micros();
  unsigned long t=millis();
  bool currentState=digitalRead(2);

  if( (currentState == LOW) && (lastState == HIGH) )
    pulseWidth = M - lastEdge;

  if ((t-lastReport)>1000)
  {
    Serial.print("Pulse Width = ");
    Serial.println(pulseWidth,DEC);
    lastReport=t;
  }
lastState=currentState;
}

void pulseFrontEdge()
{
  lastEdge=micros();  
}

Oops, Edited to add the extra = sign to the single one

Sure. Thanks a lot. :slight_smile:

My outputs are,

In Normal Mode

Pulse Width = 8896
Pulse Width = 6764
Pulse Width = 3684
Pulse Width = 1636
Pulse Width = 12928
Pulse Width = 10888
Pulse Width = 7840
Pulse Width = 5800
Pulse Width = 2752
Pulse Width = 14304
Pulse Width = 11888
Pulse Width = 9840
Pulse Width = 7800
Pulse Width = 5792
Pulse Width = 3756
Pulse Width = 14304
Pulse Width = 12892
Pulse Width = 9844
Pulse Width = 7800
Pulse Width = 4728
Pulse Width = 2692
Pulse Width = 13972
Pulse Width = 11852
Pulse Width = 8824
Pulse Width = 6796
Pulse Width = 3724
Pulse Width = 1696
Pulse Width = 14012
Pulse Width = 10944
Pulse Width = 8800
Pulse Width = 5760
Pulse Width = 3724
Pulse Width = 14304
Pulse Width = 12988
Pulse Width = 9908
Pulse Width = 7888
Pulse Width = 4728
Pulse Width = 2688

When steered to the right,

Pulse Width = 14312
Pulse Width = 12044
Pulse Width = 9988
Pulse Width = 6912
Pulse Width = 4860
Pulse Width = 2812
Pulse Width = 14308
Pulse Width = 12976
Pulse Width = 9892
Pulse Width = 7840
Pulse Width = 4748
Pulse Width = 2716
Pulse Width = 13888
Pulse Width = 11848
Pulse Width = 8772
Pulse Width = 6720
Pulse Width = 3644
Pulse Width = 1612
Pulse Width = 12860
Pulse Width = 10724
Pulse Width = 8648
Pulse Width = 5608
Pulse Width = 3540
Pulse Width = 14316
Pulse Width = 12752
Pulse Width = 9584
Pulse Width = 7532
Pulse Width = 4456
Pulse Width = 2400
Pulse Width = 13692
Pulse Width = 11636
Pulse Width = 8448
Pulse Width = 6396
Pulse Width = 4348
Pulse Width = 1308
Pulse Width = 13560
Pulse Width = 10508

When steered to the left,

Pulse Width = 14392
Pulse Width = 12052
Pulse Width = 10012
Pulse Width = 6936
Pulse Width = 4896
Pulse Width = 1824
Pulse Width = 14108
Pulse Width = 10936
Pulse Width = 8888
Pulse Width = 6848
Pulse Width = 3776
Pulse Width = 14308
Pulse Width = 13000
Pulse Width = 10860
Pulse Width = 7784
Pulse Width = 5712
Pulse Width = 2664
Pulse Width = 14320
Pulse Width = 11868
Pulse Width = 9820
Pulse Width = 7656
Pulse Width = 5636
Pulse Width = 3592
Pulse Width = 14312
Pulse Width = 12772
Pulse Width = 9712
Pulse Width = 7584
Pulse Width = 4508
Pulse Width = 2440
Pulse Width = 13716
Pulse Width = 11664
Pulse Width = 8612
Pulse Width = 6548
Pulse Width = 3372

Aha, I think I've seen the folly in my code. Try adding lastState=currentState; at the end of the loop function.

(I've just edited my code listing above)

Try the attached code and feed the PWM signal into (UNO) pin 2 (all assuming it's 5V DC). Then open a serial monitor @ 115200 baud and see what values you get when steering left & right. It only updates every second so hold the steering over for at least a couple of seconds in each direction to see what you get then post the results.

Frequency_Counter.ino (2.73 KB)