Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: PulsePosition not working

  1. #1
    Junior Member
    Join Date
    Sep 2020
    Posts
    7

    PulsePosition not working

    Hello!

    I am trying the LoopBack example on Teensy 3.2 and Arduino 1.8.5 OSX. I downloaded the newest version from GitHub but still it won't work. There is nothing popping up in the serial console.
    I want to READ from a RC receiver and with another, easy interrupt based example like this:

    Code:
    // Define which pin we’re using to accept the signal
    #define RCPIN 1
    
    // We have to declare as volatile as this will be modified
    // by the interrupt routine, and read outside of it
    volatile uint16_t channel;
    uint16_t channel_start;
    
    void setup() {
    Serial.begin(115200);
    Serial.println("Starting…");
    
    // Mark the pin as an INPUT
    pinMode(RCPIN, INPUT);
    
    // Attach an interrupt handler to be called whenever
    // the pin changes from LOW to HIGH or vice versa
    attachInterrupt(RCPIN, RCchannel, CHANGE);
    }
    
    void loop() {
    // Output the channel value
    Serial.print("RC channel:\t");
    Serial.println(channel);
    delay(50);
    }
    
    void RCchannel() {
    // If the pin is HIGH, start a timer
    if (digitalRead(RCPIN) == HIGH) {
    channel_start = micros();
    } else {
    // The pin is now LOW so output the difference
    // between when the timer was started and now
    channel = (uint16_t) (micros() – channel_start);
    }
    }
    It works! So no electrical issue. Any idea where to start debugging?

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,593
    You might try updating to the latest IDE. On my T3.2 I ran PulsePosition lib loopback example with pin 9 jumpered to pin 10. I also added while(!Serial); as the first thing in setup(). Sketch works for me on 1.8.13/1.53
    Code:
    ...
    239 :  600.02  1500.00  759.23  1500.00  1500.00  1234.54  
    240 :  600.02  1500.00  759.23  1500.00  1500.00  1234.54  
    241 :  600.02  1500.00  759.23  1500.00  1500.00  1234.54  
    242 :  600.02  1500.00  759.23  1500.00  1500.00  1234.54
    ...
    https://github.com/PaulStoffregen/PulsePosition

  3. #3
    Junior Member
    Join Date
    Sep 2020
    Posts
    7
    Hi!

    I realised that PPM means that several servo channels are somewhat encoded in one wire? My receiver has 3 outputs with a servo channel each.. so I guess it is a different technology? PWM vs. PPM?

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,912
    In many cases like this, it might help to know more information, like what receiver you are using... Also how you have it hooked up and the like.

  5. #5
    Junior Member
    Join Date
    Sep 2020
    Posts
    7
    Hello!

    Connection:
    GND<-->GND
    CH1 <-> PIN10
    5V <-> 5V
    Click image for larger version. 

Name:	61lwHfHFTvL._AC_SL1000_.jpg 
Views:	5 
Size:	64.9 KB 
ID:	22072

  6. #6
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,912
    I could be wrong, but I think you will only receive one channel pin pin, with a simple pulse that centers around 1500us
    You can probably get the value using: pulseIn (https://www.arduino.cc/reference/en/...ed-io/pulsein/)

    There are other ways as well, like setting up interrupts, but may not be very accurate.
    As PulsePositionInput allows pin 10, I am pretty sure one could create a version of the library that maybe captures the time of when pin goes high and goes low to return the width...

  7. #7
    Junior Member
    Join Date
    Sep 2020
    Posts
    7
    PulseIn looks sufficient for reading one channel. Is the version that is used for Teensy interrupt based?

  8. #8
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,912
    Nope, just a hard loop.

    If you look at the sources(pins_teensy.c)
    Code:
    #if defined(KINETISK)
    uint32_t pulseIn_high(volatile uint8_t *reg, uint32_t timeout)
    {
    	uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC;
    	uint32_t usec_start, usec_stop;
    
    	// wait for any previous pulse to end
    	while (*reg) {
    		if (--timeout_count == 0) return 0;
    	}
    	// wait for the pulse to start
    	while (!*reg) {
    		if (--timeout_count == 0) return 0;
    	}
    	usec_start = micros();
    	// wait for the pulse to stop
    	while (*reg) {
    		if (--timeout_count == 0) return 0;
    	}
    	usec_stop = micros();
    	return usec_stop - usec_start;
    }
    
    uint32_t pulseIn_low(volatile uint8_t *reg, uint32_t timeout)
    {
    	uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC;
    	uint32_t usec_start, usec_stop;
    	
    	// wait for any previous pulse to end
    	while (!*reg) {
    		if (--timeout_count == 0) return 0;
    	}
    	// wait for the pulse to start
    	while (*reg) {
    		if (--timeout_count == 0) return 0;
    	}
    	usec_start = micros();
    	// wait for the pulse to stop
    	while (!*reg) {
    		if (--timeout_count == 0) return 0;
    	}
    	usec_stop = micros();
    	return usec_stop - usec_start;
    }
    
    // TODO: an inline version should handle the common case where state is const
    uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout)
    {
    	if (pin >= CORE_NUM_DIGITAL) return 0;
    	if (state) return pulseIn_high(portInputRegister(pin), timeout);
    	return pulseIn_low(portInputRegister(pin), timeout);;
    }

  9. #9
    Junior Member
    Join Date
    Sep 2020
    Posts
    7
    Well OK than maybe even my quick and dirty solution from the internet I posted at the beginning is better.

  10. #10
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,912
    In the past I often started with a quick and dirty, which at times is sufficient depending on how accurate do you need it.

    Something like: (Note typing in on fly so probably issue)...

    Code:
    volatile uint32_t last_pulse_width = 0;
    uint32_t pulse_start_time = 0;  
    void pulse_width_isr() {
        uint32_t isr_time = micros();
        if (digitalReadFast(10) {
            pulse_start_time = isr_time;
        } else {
            last_pulse_width = isr_time - pulse_start_time;
        }
    }
    
    void setup() {
        attachInterrupt(10, &pulse_width_isr);
        ...
    }
    
    void loop() {
        ...
        if (last_pulse_width ...
    }
    This is pretty basic, I grab the micros at start of ISR so both paths should hopefully have about same interrupt delay time.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •