Why is this so hard?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
ebike
Posts: 55
Joined: Thu Jul 16, 2015 9:36 pm

Re: Why is this so hard?

Post by ebike » Wed Jul 29, 2015 5:58 am

dhylands wrote:
What exactly are you trying to do?
Dang, I thought I was quite clear in what I wanted to do, I will repeat.

I want to pulse 8 outputs one-after-the other for say 2us each, total of 16us. The function to do all that is called from a timer callback.
The code I posted (which you asked for) does 2 of the 8 outputs in a assembly loop. The tim4 callback runs the code.
Interactively adjusting the freq of tim4 allows me to play with the cycle time of sending the pulse sequence.
To go faster than the above, you're going to have to use a different technique or code it in C.
Why would C be faster than assembly, that is crazy .....

You have the code I posted in my last post, try running that at between 20 and 50Khz and you will see what I mean about
locking up REPL .. what you have done does not simulate what I have done ..

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Why is this so hard?

Post by dhylands » Wed Jul 29, 2015 6:17 am

ebike wrote:
dhylands wrote:
What exactly are you trying to do?
Dang, I thought I was quite clear in what I wanted to do, I will repeat.

I want to pulse 8 outputs one-after-the other for say 2us each, total of 16us. The function to do all that is called from a timer callback.
The code I posted (which you asked for) does 2 of the 8 outputs in a assembly loop. The tim4 callback runs the code.
Interactively adjusting the freq of tim4 allows me to play with the cycle time of sending the pulse sequence.
Perhaps I should have asked why are you trying to do this? What is it that you're trying to control that you need a 500 kHz pulse stream? There are other ways of generating pulse streams, but without knowing the nature of the pulse stream, I can't really recommend anything.
To go faster than the above, you're going to have to use a different technique or code it in C.
Why would C be faster than assembly, that is crazy .....
There is a certain amount of overhead in the generic C timer IRQ handler (about 2 usec) and then there is a bit more overhead involved in dispatch the python assembler routine (even though the routine is written in assembler, it still goes part of the python VM to get to your routine).

If you were to write a custom interrupt handler in C you would be able to remove that overhead.

ebike
Posts: 55
Joined: Thu Jul 16, 2015 9:36 pm

Re: Why is this so hard?

Post by ebike » Wed Jul 29, 2015 7:17 am

dhylands wrote: Perhaps I should have asked why are you trying to do this? What is it that you're trying to control that you need a 500 kHz pulse stream? There are other ways of generating pulse streams, but without knowing the nature of the pulse stream, I can't really recommend anything.
I don't need a continuous 500khz pulse stream, just a 16us (8 x 2us) one at a variable frequency ... quite a difference.

I have experimented and have found I can go as fast as 40khz with all 8 outputs going (16us) and REPL stays up.
I only need 20khz max, so I think this solution will suffice. It still gives me roughly 50% cpu for other mundane tasks including REPL.
(..maybe you could confirm that cpu usage better than me if you can be bothered .. ;) )

The only other solution I can think of is adding an external shift register, then I can use a timer as a one-shot for the 2us. I will resort to that if I find the current solution too cpu intensive .. (which reminds me, can the timer class be extended to support one-shot mode?)

ebike
Posts: 55
Joined: Thu Jul 16, 2015 9:36 pm

Re: Why is this so hard?

Post by ebike » Thu Jul 30, 2015 11:15 pm

Regarding one-shot mode or monostable mode. It would be great if this could be added to the timer class ...
In the meantime, can someone point out how to access the timer registers with the stm module, that would be great ..

It seems I have to set the OPM bit in CR1 register ...

Thanks,

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Why is this so hard?

Post by dhylands » Fri Jul 31, 2015 12:19 am

Here's some code I wrote that used stm:
https://github.com/dhylands/upy-example ... py#L61-L64

You need to be careful in that stm only supports small ints, which are 31 bits wide. So you can run into errors when trying to read/write registers using stm.mem32 and the high bit of the register is set.

For most peripherals you can use stm.mem16 and just fiddle with 16 bits at a time. Some peripherals don't allow 16-bit access. You need to check the reference manual to be sure.

The timers can be accessed using 8/16/32 bit accesses.

ebike
Posts: 55
Joined: Thu Jul 16, 2015 9:36 pm

Re: Why is this so hard?

Post by ebike » Sat Aug 01, 2015 12:15 am

Thanks, would be good to know where the tumer defines are that you used.

On another similar issue, why is this not possible?

Code: Select all

class Pulser:
    def __init__(self, freq=5, duty=1):
    
        self.Freq = freq
        self.Duty = duty
        self.Pin = Pin('A15')
        self.tim2 = Timer(2, freq=freq)
        self.ch = tim2.channel(1, Timer.PWM, pin=self.Pin)
        self.ch.pulse_width_percentage(duty)

    def setFreq(self, freq):
        self.Freq = freq
        self.ch.pulse_width_percentage(self.Duty)
I get:
AttributeError: 'TimerChannel' object has no attribute 'pulse_width_percentage'
when I manually go: ch = pulse_width_percentage(1) that is fine, but not part of a class ..

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Why is this so hard?

Post by dhylands » Sat Aug 01, 2015 12:50 am

ebike wrote:Thanks, would be good to know where the tumer defines are that you used.
I'm not sure which defines you're referring to. The stm constants come from the stm module. You can use dir(stm) to get a list of the constants, or use help(stm) to get a list of the constants along with their values.

If you're refering to the stuff mentioned in the comments, then that all came from the Reference Manual: http://www.st.com/web/en/resource/techn ... 031020.pdf
On another similar issue, why is this not possible?

Code: Select all

class Pulser:
    def __init__(self, freq=5, duty=1):
    
        self.Freq = freq
        self.Duty = duty
        self.Pin = Pin('A15')
        self.tim2 = Timer(2, freq=freq)
        self.ch = tim2.channel(1, Timer.PWM, pin=self.Pin)
        self.ch.pulse_width_percentage(duty)

    def setFreq(self, freq):
        self.Freq = freq
        self.ch.pulse_width_percentage(self.Duty)
I get:
AttributeError: 'TimerChannel' object has no attribute 'pulse_width_percentage'.
That would be because there is no attribute_pulse_width_percentage method. It's called pulse_width_percent.
http://docs.micropython.org/en/latest/l ... th_percent
when I manually go: ch = pulse_width_percentage(1) that is fine, but not part of a class ..
The only way that should work would be if you provided a function called pulse_width_percentage.

Post Reply