Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Evaluate the PWM signal

Tue Mar 30, 2021 12:09 pm

Hello

I am looking for an eficiente solution, as you simplest a PWM signal can be evaluated.
The PWM signal comes from a helicopter gyro.
The PWM signal is set up as follows:
Period duration 5.0ms (200Hz), Duty Cycle is between 800us and 2200us.
The signal is actually for a fast digital servo.
I am interested in the time how long the flank is high (800US - 2200US), ie the dutycycle.
This value should be saved and overwritten for each new cycle.
Is there already a function?

Enclosed a picture of the measurement of PWM signal, currently in the picture with 1500us.

Greetings Pascal
PWM_200Hz_2.jpg
PWM_200Hz_2.jpg (161.43 KiB) Viewed 885 times

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Wed Mar 31, 2021 6:54 pm

Has anyone ever evaluated a PWM signal with a PICO?

horuable
Posts: 121
Joined: Sat Mar 06, 2021 12:35 am

Re: Evaluate the PWM signal

Wed Mar 31, 2021 7:20 pm

There are several threads discussing measuring signal timing.
Take a look here and here.

gordon77
Posts: 5685
Joined: Sun Aug 05, 2012 3:12 pm

Re: Evaluate the PWM signal

Wed Mar 31, 2021 7:44 pm

This code will measure the pulsewidth (period at 1).

You'll notice some jitter

Code: Select all

from machine import Pin, PWM
import time

# setup pwm output for test
pwm  = PWM(Pin(16))
pwm.freq(200)
pwm_duty = 30000 # 10550 = 800uS, 30000 = 2200uS 
pwm.duty_u16(pwm_duty)

input_pin  = Pin(17, Pin.IN)
while True:
    while input_pin.value() == 0:
      pass
    start = time.ticks_us()
    while input_pin.value() == 1:
        pass
    end = time.ticks_us()
    duty = end - start
    print (str(duty))
Last edited by gordon77 on Wed Mar 31, 2021 8:45 pm, edited 1 time in total.

User avatar
joan
Posts: 15622
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Evaluate the PWM signal

Wed Mar 31, 2021 7:46 pm

I suspect you are asking the wrong question. Why do you want to know the pulsewidth?

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Wed Mar 31, 2021 9:01 pm

Thanks very much for your responses!
You two helped me a lot.
The sample code also works.
I try to eliminate the tremors with means.

cheers

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Wed Mar 31, 2021 9:06 pm

joan wrote:
Wed Mar 31, 2021 7:46 pm
I suspect you are asking the wrong question. Why do you want to know the pulsewidth?
I read a PWM from a gyro, in the PICO I have to set a dead point (neutral position 1500us + - 120us), then output the modified PWM signal again.
How do I incorporate this dead point into the code, do I still have to look how I do it best !?

User avatar
joan
Posts: 15622
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Evaluate the PWM signal

Wed Mar 31, 2021 9:26 pm

Nitro_fpv wrote:
Wed Mar 31, 2021 9:06 pm
joan wrote:
Wed Mar 31, 2021 7:46 pm
I suspect you are asking the wrong question. Why do you want to know the pulsewidth?
I read a PWM from a gyro, in the PICO I have to set a dead point (neutral position 1500us + - 120us), then output the modified PWM signal again.
How do I incorporate this dead point into the code, do I still have to look how I do it best !?
Do you mean?

Code: Select all

IN   -> OUT
1000 -> 1000
.... -> ....
1378 -> 1378
1379 -> 1379
1380 -> 1500
1381 -> 1500
1500 -> 1500
.... -> 1500
1619 -> 1500
1620 -> 1500
1621 -> 1621
1622 -> 1621
.... -> ....
2000 -> 2000

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Wed Mar 31, 2021 10:08 pm

joan wrote:
Wed Mar 31, 2021 9:26 pm
Nitro_fpv wrote:
Wed Mar 31, 2021 9:06 pm
joan wrote:
Wed Mar 31, 2021 7:46 pm
I suspect you are asking the wrong question. Why do you want to know the pulsewidth?
I read a PWM from a gyro, in the PICO I have to set a dead point (neutral position 1500us + - 120us), then output the modified PWM signal again.
How do I incorporate this dead point into the code, do I still have to look how I do it best !?
Do you mean?

Code: Select all

IN   -> OUT
1000 -> 1000
.... -> ....
1378 -> 1378
1379 -> 1379
1380 -> 1500
1381 -> 1500
1500 -> 1500
.... -> 1500
1619 -> 1500
1620 -> 1500
1621 -> 1621
1622 -> 1621
.... -> ....
2000 -> 2000
Exactly something.
But that would make a very big list.
I thought of a solution with mapping:
-- 800, 1500, 1000, 1400
-- 1501, 2200, 1600, 2000
I only know this from Arduino.
I'm still a beginner with MicroPython.

gordon77
Posts: 5685
Joined: Sun Aug 05, 2012 3:12 pm

Re: Evaluate the PWM signal

Thu Apr 01, 2021 7:28 am

is this what you want ?

Code: Select all

from machine import Pin, PWM
import time

# setup pwm output for test
pwm  = PWM(Pin(16))
pwm.freq(200)
pwm_duty = 30000 # 10550 = 800uS, 30000 = 2200uS 
pwm.duty_u16(pwm_duty)

input_pin  = Pin(17, Pin.IN)
while True:
    while input_pin.value() == 0:
      pass
    start = time.ticks_us()
    while input_pin.value() == 1:
        pass
    end = time.ticks_us()
    duration = end - start
    if duration > 1380 and duration < 1620:
        duration = 1500
    print (str(duration))

User avatar
joan
Posts: 15622
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Evaluate the PWM signal

Thu Apr 01, 2021 8:03 am

Suggested pseudo code

Code: Select all

PHASE_DELAY = 2100 # make slightly longer than longest pulse

while True

   while input low
      pass
   start = now_micro

   while input high
      pass
   end = now_micro

   in_width = end - start
   if in_width > 1380 and in_width < 1620
      out_width = 1500
   else
      out_width = in_width

   sleep (PHASE_DELAY - in_width) micros
   set output high
   sleep out_width micros
   set output low

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Thu Apr 01, 2021 5:53 pm

Hello gordon77
Hello joan

Something similar.
But not linear.

Look in the first code:

Code: Select all

In (us)         Out (us) 

500 - 1000   = 1000
1000 - 1485  = 1000 - 1400
1485 - 1515  = 1500
1515 - 2000  = 1600 - 2000
2000 - 2500  = 2000
fail_save = <500      = 1500
fail_save = >2500     = 1500
fail_save = no signal = 1500

Apparently MicroPython does not know the function "map" (Arduino).
I found something similar this way it might work:

Code: Select all

# Will return a integer
def convert(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min

pwm.duty_u16(convert(pwm_in, 1000, 1485, 1000, 1400))

What do you think of that?

hippy
Posts: 9959
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Evaluate the PWM signal

Thu Apr 01, 2021 7:27 pm

Nitro_fpv wrote:
Thu Apr 01, 2021 5:53 pm
What do you think of that?
Yes, that should work for a single mapping. You can have a multiple mapping by doing something like this ...

Code: Select all

#             __input___   __Output__
mapping = [                      1500  , # Failsafe - For any input value not in any range
            [  500, 1000,  1000, 1000 ],
            [ 1000, 1485,  1000, 1400 ],
            [ 1515, 2000,  1600, 2000 ],
            [ 2000, 2500,  2000, 2000 ],
          ]
          
def map(n, mapping):
    for inmin, inmax, outmin, outmax in mapping[1:]:
        if n >= inmin and n <= inmax:
            i = (n - inmin) / (inmax - inmin)
            o = ((outmax - outmin) * i ) + outmin 
            return int(o)
    return mapping[0]

for n in range(0, 3000, 100):
    print("{:>4} -> {}".format(n, map(n, mapping)))
That should give you ...

Code: Select all

2000 :     :     :     :     ______:     :
     :     :     :     :    /:     |     :
     :     :     :     :   / :     |     :
     :     :     :     :  /  :     |     :
1500 :_____:     :    ___|   :     |_____:__
     :     |     :   | :     :     :     :
     :     |     :  /  :     :     :     :
     :     |     : /   :     :     :     :
1000 :     |______/    :     :     :     :
     :     :     :     :     :     :     :
     0    500   1000  1500  2000  2500  3000
     Input
Last edited by hippy on Thu Apr 01, 2021 7:42 pm, edited 1 time in total.

User avatar
joan
Posts: 15622
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Evaluate the PWM signal

Thu Apr 01, 2021 7:40 pm

@Nitro_fpv
As long as it works it is then down to personal taste.

I find the if/else form easier to understand.

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Thu Apr 01, 2021 8:09 pm

hippy wrote:
Thu Apr 01, 2021 7:27 pm
Nitro_fpv wrote:
Thu Apr 01, 2021 5:53 pm
What do you think of that?
Yes, that should work for a single mapping. You can have a multiple mapping by doing something like this ...

Code: Select all

#             __input___   __Output__
mapping = [                      1500  , # Failsafe - For any input value not in any range
            [  500, 1000,  1000, 1000 ],
            [ 1000, 1485,  1000, 1400 ],
            [ 1515, 2000,  1600, 2000 ],
            [ 2000, 2500,  2000, 2000 ],
          ]
          
def map(n, mapping):
    for inmin, inmax, outmin, outmax in mapping[1:]:
        if n >= inmin and n <= inmax:
            i = (n - inmin) / (inmax - inmin)
            o = ((outmax - outmin) * i ) + outmin 
            return int(o)
    return mapping[0]

for n in range(0, 3000, 100):
    print("{:>4} -> {}".format(n, map(n, mapping)))
That should give you ...

Code: Select all

2000 :     :     :     :     ______:     :
     :     :     :     :    /:     |     :
     :     :     :     :   / :     |     :
     :     :     :     :  /  :     |     :
1500 :_____:     :    ___|   :     |_____:__
     :     |     :   | :     :     :     :
     :     |     :  /  :     :     :     :
     :     |     : /   :     :     :     :
1000 :     |______/    :     :     :     :
     :     :     :     :     :     :     :
     0    500   1000  1500  2000  2500  3000
     Input

Geez, it works the way I thought it would!

I don't understand this line, I'm a MicroPython beginner:
print ("{:> 4} -> {}". format (n, map (n, mapping))) ?
ok, I understood it now: =)


Thank you very much for that.
I will see the days how I can incorporate this into my project.
Last edited by Nitro_fpv on Thu Apr 01, 2021 8:18 pm, edited 2 times in total.

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Thu Apr 01, 2021 8:10 pm

joan wrote:
Thu Apr 01, 2021 7:40 pm
@Nitro_fpv
As long as it works it is then down to personal taste.

I find the if/else form easier to understand.

Yes, of course, it's a lot easier for me as a MicroPython beginner too.
I try to learn.

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Tue Apr 06, 2021 5:17 pm

Hello everybody

With your help and examples I have almost finished my project.
My actual project is this:
Read in the PWM signal, convert it (see table), and then output it again as a PWM signal.

Now I have written the following program for testing:

- For the test, first generate a PWM signal from an analog signal.
- Read PWM signal
- Convert (dead zone, fail save zone, see table).

The problem, however, is reading, if there is no valid PWM signal (unplug the cable at input_pin = pin 17), the program stops and nothing works anymore.
How can I read the PWM so that the program continues to work even if there is no PWM signal?

This code can be tested on a PI PICO with only one potentiometer on pin 28.

Here is the code:

Code: Select all

from machine import Pin, PWM
from time import sleep
import time

input_pin  = Pin(17, Pin.IN)
analogvalue = machine.ADC(28)
pwm = PWM(Pin(15))
pwm.freq(200)

glätten = 0

# mapping analog / pwm
def interpoliert(x, i_m, i_M, o_m, o_M):
    return max(min(o_M, (x - i_m) * (o_M - o_m) // (i_M - i_m) + o_m), o_m)


#             __input___   __Output__
mapping = [                      1500  , # Failsafe - For any input value not in any range
            [  500, 1000,  1000, 1000 ],
            [ 1000, 1485,  1000, 1400 ],
            [ 1515, 2000,  1600, 2000 ],
            [ 2000, 2500,  2000, 2000 ],
          ]
          
def map(n, mapping):
    for idx in range(1, len(mapping)):
        inmin, inmax, outmin, outmax = mapping[idx]
        if n >= inmin and n <= inmax:
            i = (n - inmin) / (inmax - inmin)
            o = ((outmax - outmin) * i ) + outmin 
            return int(o)
    return mapping[0]


while True:
    i = analogvalue.read_u16()
    pwm.duty_u16(interpoliert(i, 200, 65500, 6000, 35000))
    sleep(0.01) #Print
    while input_pin.value() == 0:
      pass
    start = time.ticks_us()
    while input_pin.value() == 1:
        pass
    end = time.ticks_us()
    n = end - start
    print(str(n), map(n, mapping))

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Tue Apr 06, 2021 6:00 pm

Here is the short version:

With this part of the code I read out the PWM signal.
Unfortunately, the program stops if there is no PWM signal or it fails.
What would the solution be so that the program continues to run anyway?

Code: Select all

 while input_pin.value() == 0:
      pass
    start = time.ticks_us()
    while input_pin.value() == 1:
        pass
    end = time.ticks_us()
    n = end - start
    print(str(n), map(n, mapping))

gordon77
Posts: 5685
Joined: Sun Aug 05, 2012 3:12 pm

Re: Evaluate the PWM signal

Tue Apr 06, 2021 6:05 pm

Depending on the frequency you may need to change the number to suit...

Code: Select all

while input_pin.value() == 0:
      pass
start = time.ticks_us()
while input_pin.value() == 1 and time.ticks_us() - start < 10000:
        pass
end = time.ticks_us()
n = end - start
print(str(n), map(n, mapping))
Last edited by gordon77 on Tue Apr 06, 2021 6:38 pm, edited 2 times in total.

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Tue Apr 06, 2021 6:32 pm

gordon77 wrote:
Tue Apr 06, 2021 6:05 pm
Depending on the frequency you may need to change the number to suit...

I tried different numbers (your value 10000), but always got an error message:

"Traceback (most recent call last):
File "<stdin>", line 43, in <module>
AttributeError: 'module' object has no attribute 'ticks'"

gordon77
Posts: 5685
Joined: Sun Aug 05, 2012 3:12 pm

Re: Evaluate the PWM signal

Tue Apr 06, 2021 6:34 pm

Sorry its time.ticks_us().

It should simply time out after that time if it doesn't detect.

Ensure the time (in uS) is greater than the length of the pulse.

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Tue Apr 06, 2021 7:39 pm

Thank you gordon77, your example works now, but the program still stops if no PWM signal is received.
Funny!?

gordon77
Posts: 5685
Joined: Sun Aug 05, 2012 3:12 pm

Re: Evaluate the PWM signal

Tue Apr 06, 2021 7:49 pm

Code: Select all

start = time.ticks_us()
while input_pin.value() == 0 and time.ticks_us() - start < 10000:
        pass
start = time.ticks_us()
while input_pin.value() == 1 and time.ticks_us() - start < 10000:
        pass
end = time.ticks_us()
n = end - start
print(str(n), map(n, mapping))

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Tue Apr 06, 2021 7:58 pm

gordon77 wrote:
Tue Apr 06, 2021 7:49 pm

Code: Select all

start = time.ticks_us()
while input_pin.value() == 0 and time.ticks_us() - start < 10000:
        pass
start = time.ticks_us()
while input_pin.value() == 1 and time.ticks_us() - start < 10000:
        pass
end = time.ticks_us()
n = end - start
print(str(n), map(n, mapping))
Perfect!
Thank you for everything!

Nitro_fpv
Posts: 82
Joined: Tue Mar 30, 2021 11:56 am
Location: Switzerland

Re: Evaluate the PWM signal

Wed Apr 07, 2021 6:06 pm

PWM reading gives me a headache.
I go into the PICO with an absolutely clean and even PWM signal.
I am trying to read the signal and currently output it unprocessed.
Unfortunately the reading is uneven, I can see that very well with the Logiganalyzer that the output of the signal is also uneven.
Also with the print test (see code) you can see that the reading of the signal is uneven.
Enclosed the code and a picture of the analysis:

Code: Select all

from machine import Pin, PWM
from time import sleep
import time

input_pin  = Pin(17, Pin.IN)

pwm = PWM(Pin(15))
pwm.freq(200)

def interpoliert(x, i_m, i_M, o_m, o_M):
    return max(min(o_M, (x - i_m) * (o_M - o_m) // (i_M - i_m) + o_m), o_m)


while True:
    start = time.ticks_us()
    while input_pin.value() == 0 and time.ticks_us() - start < 20000:
        pass
    start = time.ticks_us()
    while input_pin.value() == 1 and time.ticks_us() - start < 20000:
        pass
    end = time.ticks_us()
    n = end - start
    test = str(n)
    test = int(test)
    pwm.duty_u16(interpoliert(test, 1000, 2000, 13100, 26500))
    #print(test)
Image

https://abload.de/img/pwm_new_1swjuu.jpg

Channel 1 measured value P3 and P4 is the reference.
Channel 0 measured value P0, P1, P2 shows the output.
Too imprecise for my application, too much noise.

What could that be?

Return to “MicroPython”