Pages: [1] 2   Go Down
Author Topic: Need simple script to read 1 ppm signal  (Read 1395 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

i need a simple script without any delay or PulseIn to read the timings of a ppm signal from a rc-receiver.

i hav tried ServoDecode, searched in the forum/playground/google,
but i found nothing that i understand (i´m arduino beginner).

It doesn´t have to be accurate, because i want to turn fade an blink leds on and off,thats why i can´t use PulseIn and delay.

Can anyone help me?

thanks,
Daniel
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It doesn´t have to be accurate,

Just use the millis() function to save the time when the signal changes value on the signal wired to a digital input pin. A simple subtraction of the last saved millis() value to the current millis() on the next change will give you the duration of the signal.

Part of learning to write your own sketches is learning the many functions avalible, what they can do for you and how to use them properly. The blink without delay example sketch in the Arduino IDE also shows using the millis() function as a replacement for simple delay commands.

Lefty
 
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49386
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Depending on the speed of the PPM input, micros() might be more suitable.

Quote
i need a simple script without any delay or PulseIn
What's wrong with pulseIn?

Quote
i want to turn fade an blink leds on and off,thats why i can´t use PulseIn and delay.
I don't see the connection. What is generating this PPM signal?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


try interrupts, they are a lean mean ppm counting machine, no delay() no pulseIn(),

Code:
volatile uint32_t ppm = 0;

void IRQ()
{
  ppm++;
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PulseIn automatic puts a delay in the script, because of the pause between the signals.
and my rc-receiver is generating the signal. there is a 20ms delay in the signal and then there comes a signal between 1.5 and 2.5ms that shows the servo in the rc-car in wihich position it has to stand.

i just need a script that tells me if the signal is high for more than 2ms.

with which command can i read if the signal changes on a pin?

i also had a look at interrupts but i think i need an idea to make a sketch that works.

Does anybody have a beginning for me?


//EDIT:
i have the arduino pro mini 5v
my servo data is on pin 2.

i took a second look at interrupts and now i understand that i have to do this:

if pin 2 is rising save the actual millis in (for example) millis_1
if pin 2 is falling save the actual millis in (for example) millis_2

millis_2 - millis_1 = signal_millis
signal_millis is my signal in ms?

but i think i´m to stupid to see how i have to write the sketch.
« Last Edit: July 17, 2011, 05:47:44 pm by Daniel_N » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13739
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

(not tested but should get you started ...
Code:
int pin = 13;
volatile int state = LOW;

void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, IRQ, CHANGE);  // both edges
}

void loop()
{

}

volatile uint32_t time = 0;

void IRQ()
{
  if (digitalRead(2) == HIGH) { time = micros(); return; }  // set time at high edge
 
  time = micros() - time;   // check duration at low edge
  if (time > 2000)
  {
    digitalWrite(pin, HIGH);
    // do your thing here
  } else
  {
    digitalWrite(pin, LOW);
  }
}
your turn ,
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49386
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    // do your thing here
Keep in mind that "your thing" needs to be very fast, Interrupt handlers are not the place to be sending serial data or other activities that take a lot of time.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

"your thing" is actual this:
Code:
// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
int interval = 0;           // interval at which to blink (milliseconds)

int brightness = 10;    // how bright the LED is

#define led1 3
#define led2 5
#define led3 6
#define led4 9
#define fled1 10 //Led on digital pin 10
#define fled2 11 //Led on digital pin 11

unsigned long btnMillis = 0; //clock value to be stored at the time milli() is called

//Fade a led without delaying the rest of the code
//START
unsigned long fadeMillis = 0;
boolean fadeUp = true;
int fadeValue = 0;
void analogFade()
{
  if (millis() - fadeMillis >= 2)
  {
    fadeMillis = millis();

    if (fadeUp == true)
    {
      if (fadeValue < 255)
      {
        fadeValue++;
      }
      else
      {
        fadeUp = false;
        fadeValue--;
      }
    }
    else
    {
      if (fadeValue > 0)
      {
        fadeValue--;
      }
      else
      {
        fadeUp = true;
        fadeValue++;
      }
    }
    analogWrite(fled1, fadeValue);
    analogWrite(fled2, fadeValue);
  }
}
//STOP

   void normallight()
   {
      analogWrite(6, brightness);
      analogWrite(9, brightness);
     
   }

   void frontflash()
   {

 unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(led1, ledState);
    digitalWrite(led2, ledState);

  if (interval == 59)
     interval = 100;
  else if (interval == 100)
     interval = 61;
  else if (interval == 61)
     interval = 800;
  else
     interval = 59;
  }
   }
   
   void flashlight()
   {
     
  analogFade();

  frontflash();
 
  normallight();
   }
   
void setup()
{
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
}

void loop()

  flashlight();
}

you can see it here: at 4:44
In the video you can see my "Lightbox" its just for testing. and yes, i´m german smiley-wink
When its finished it should control the leds on a 1:10 Mustang.

I tried it with PulseIn but i doesn´t work, as you can see here:
you can see, that the PulseIn autmatically delays the whole sketch.

i will now try the sketch from robtillaart, thanks for that smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Its me again smiley

the sketch works, but my fade and blink is very very slow.
fade up and down have to be done in 0.75 seconds but know it takes 10 seconds.
the blink sequence is also slower, not that much, but slower smiley-sad

actual code:
Code:
// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
int interval = 0;           // interval at which to blink (milliseconds)

int brightness = 10;    // how bright the LED is

#define led1 3
#define led2 5
#define led3 6
#define led4 9
#define fled1 10 //Led on digital pin 10
#define fled2 11 //Led on digital pin 11

//Fade a led without delaying the rest of the code
//START
unsigned long fadeMillis = 0;
boolean fadeUp = true;
int fadeValue = 0;
void analogFade()
{
  if (millis() - fadeMillis >= 2)
  {
    fadeMillis = millis();

    if (fadeUp == true)
    {
      if (fadeValue < 255)
      {
        fadeValue++;
      }
      else
      {
        fadeUp = false;
        fadeValue--;
      }
    }
    else
    {
      if (fadeValue > 0)
      {
        fadeValue--;
      }
      else
      {
        fadeUp = true;
        fadeValue++;
      }
    }
    analogWrite(fled1, fadeValue);
    analogWrite(fled2, fadeValue);
  }
}
//STOP

   void normallight()
   {
      analogWrite(6, brightness);
      analogWrite(9, brightness);
     
   }

  void frontflash()
   {

 unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    ledState = 1-ledState;

    // set the LED with the ledState of the variable:
    digitalWrite(led1, ledState);
    digitalWrite(led2, ledState);

  if (interval == 59)
     interval = 100;
  else if (interval == 100)
     interval = 61;
  else if (interval == 61)
     interval = 800;
  else
     interval = 59;
  }
   }
   
   void flashlight()
   {
     
  analogFade();

  frontflash();
 
  normallight();
   }

void all_off()
{
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        analogWrite(6, LOW);
        analogWrite(9, LOW);
        analogWrite(fled1, LOW);
        analogWrite(fled2, LOW);
}


volatile int state = LOW;

void setup()
{
  attachInterrupt(0, IRQ, CHANGE);  // both edges
  Serial.begin(9600); //serial library start
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
}

void loop()
{

}

volatile uint32_t time = 0;

void IRQ()
{
  if (digitalRead(2) == CHANGE) { time = micros(); return; }  // set time at high edge
 
  time = micros() - time;   // check duration at low edge
  if (time > 1000)
  {
      flashlight();
    // do your thing here
  } else
  {
    all_off();
  }
  Serial.println(time);
}
« Last Edit: July 17, 2011, 07:47:03 pm by Daniel_N » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49386
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  if (digitalRead(2) == CHANGE) { time = micros(); return; }  // set time at high edge
The digitalRead() function returns HIGH (1) or LOW (0). Why are you using CHANGE here?

Quote
the sketch works, but my fade and blink is very very slow.
Your interrupt handler takes forever to complete, so it keeps getting interrupted before it is done.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  if (digitalRead(2) == CHANGE) { time = micros(); return; }  // set time at high edge
The digitalRead() function returns HIGH (1) or LOW (0). Why are you using CHANGE here?
I changed it into CHANGE because i tried to read 3 positions of the signal, for example 500microsec, 1000microsec and 1500microsec, but that doesn´t work.

Quote
the sketch works, but my fade and blink is very very slow.
Your interrupt handler takes forever to complete, so it keeps getting interrupted before it is done.
so is there no chance to make it faster?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49386
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
so is there no chance to make it faster?
All that the interrupt handler should do is set a flag that gets looked at on the next pass through loop.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49386
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I changed it into CHANGE because i tried to read 3 positions of the signal, for example 500microsec, 1000microsec and 1500microsec, but that doesn´t work.
This doesn't make sense.

You are attaching the interrupt handler, requesting that it be called whenever the pin goes from HIGH to LOW or from LOW to HIGH - in other words whenever there is a change.
Code:
  attachInterrupt(0, IRQ, CHANGE);  // both edges

In the IRQ function, you use digitalRead() to see what the change was, if it is important. If the return value is HIGH, the transition that triggered the interrupt was from LOW to HIGH (because the pin is now HIGH). If the return value is LOW, the transition that triggered the interrupt was from HIGH to LOW (because the pin is now LOW).

In the IRQ function, you should record WHEN the function was called, if the digitalRead value is HIGH (the trigger was the pin going from LOW to HIGH), then return.

If the digitalRead value is LOW (the trigger was the pin going from HIGH to LOW), then the time since the last call to IRQ tells you whether the pin was HIGH for the required duration, or not.

It is that duration, or true/false decision based on duration, that loop() should be paying attention to.

It is not clear what the code should do if the PPM signal is HIGH for the required duration, or what it should do if the PPM signal is NOT HIGH for the require duration.

The blinking/fading of the LEDs does not seem to relate to the length of the PPM HIGH pulse that I can see.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...
It is not clear what the code should do if the PPM signal is HIGH for the required duration, or what it should do if the PPM signal is NOT HIGH for the require duration.

The blinking/fading of the LEDs does not seem to relate to the length of the PPM HIGH pulse that I can see.
why it is not clear what the code should do when the signal is high or low?
in my opinion it doens´t make sense if the signal is high or low, the important is how long it is high. that controls the led voids.
or i´m missunderstanding something?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49386
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
in my opinion it doens´t make sense if the signal is high or low
OK.

Quote
the important is how long it is high.
If it doesn't matter if the signal is HIGH or LOW, how can it possibly matter how long the signal is HIGH?

Quote
that controls the led voids.
There are no LED voids. There are LED functions.

The RC receiver must be receiving something that makes the signal you are trying to measure HIGH or LOW, or, more specifically, HIGH for some period of time.

You need to explain what it is that makes the signal HIGH (or HIGH for some minimum period of time). You need to make your sketch determine that the signal is HIGH for the required time, or not, and do NOTHING else.

Once you can reliably determine whether the required signal has been received, you need to explain what it supposed to happen when that signal is received.
Logged

Pages: [1] 2   Go Up
Jump to: