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

Why is this so hard?

Post by ebike » Tue Jul 28, 2015 3:21 am

Hi There,

I am having trouble with this langauge: I have the code:

Code: Select all

pin1 = Pin('C6',Pin.OUT_PP )

cycle = 0
def pulser():
    global cycle
    pin1.high()
    pyb.udelay(2)
    pin1.low()
    cycle +=1
    cycle %= 4
  
If I run pulser(), I expect the pin to go high for 2us, but nothing .. if I manually call the pin1.high(), pin1.low() functions it works.
Why is this so hard to do simple things? The counter "cycle" increments and ranges between 0..3 as expected.
I am using a global to test, I should use a local I know ..

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 » Tue Jul 28, 2015 4:59 am

It seems to be working fine for me.

I had to add a couple of import statements, winding up with this as pulser.py:

Code: Select all

import pyb
from pyb import Pin

pin1 = Pin('C6',Pin.OUT_PP )

cycle = 0
def pulser():
    global cycle
    pin1.high()
    pyb.udelay(2)
    pin1.low()
    cycle +=1
    cycle %= 4

while True:
    pulser()
    pyb.udelay(10)
From the REPL I then did import pulser and this is what I captured on my C6 pin (aka Y1) using my logic analyzer:
pulser.png
pulser.png (51.19 KiB) Viewed 10035 times
which shows a high pulse of 17.83 usec, and low for 62.17 - 17.83 = 44.34 usec

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

Re: Why is this so hard?

Post by ebike » Tue Jul 28, 2015 6:49 am

That's strange ... I of course had the import statements as well ..
I will investigate further ..

By the way, what is wrong with this code:

Code: Select all

class Pulser():
    def __init__(self):
        self.tick = 0
        self.pin1 = Pin('C6',Pin.OUT_PP )
        self.pin2 = Pin('C7',Pin.OUT_PP )
        self.pin3 = Pin('C8',Pin.OUT_PP )
        self.pin4 = Pin('C9',Pin.OUT_PP )

    def pulser(self):
        self.pin1.high()
        pyb.udelay(2)
        self.pin1.low()
        self.tick = (self.tick + 1) % 4
If I instantiate the class by:
pp = Pulser.pulser()

Then pp() has the error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function takes 1 positional arguments but 0 were given
I think I am missing something basic ..

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 » Tue Jul 28, 2015 7:59 am

Shouldn't you use:

Code: Select all

pp = Pulser()
pp.pulser()

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

Re: Why is this so hard?

Post by ebike » Tue Jul 28, 2015 9:00 am

They both give the same error ..

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: Why is this so hard?

Post by pfalcon » Tue Jul 28, 2015 9:22 am

It's not hard if you know and understand what you're doing. And Python is in excellent language to learn and understand.

Code: Select all

cycle = 0
def pulser():
    global cycle
    pin1.high()
    pyb.udelay(2)
    pin1.low()
    cycle +=1
    cycle %= 4
There're number of problems with this code. First of all, you have "cycle" variable, on which you perform some operations, but don't really use, that may be a logical error. Another issue is that you don't show how you use the above function. If you call it in a loop without further delay, it will work exactly as you wrote it, specifically: it will set pin high for 2us, then set it low, then almost immediately set to high again for 2us, etc. End result is that the pin almost always will be high, and you won't see any pulses ("low" pulses will be too short for hardware to "notice").
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

Neil
Posts: 15
Joined: Tue Jul 14, 2015 8:51 pm

Re: Why is this so hard?

Post by Neil » Tue Jul 28, 2015 1:43 pm

Note 100% sure it would cause an error, but python convention would have

Code: Select all

class Pulser:
Instead of

Code: Select all

class Pulser():

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Why is this so hard?

Post by pythoncoder » Tue Jul 28, 2015 2:37 pm

I think either declaration will work along with

Code: Select all

class Pulser(object):
Peter Hinch
Index to my micropython libraries.

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

Re: Why is this so hard?

Post by ebike » Tue Jul 28, 2015 8:17 pm

pfalcon wrote:It's not hard if you know and understand what you're doing. And Python is in excellent language to learn and understand.

Code: Select all

cycle = 0
def pulser():
    global cycle
    pin1.high()
    pyb.udelay(2)
    pin1.low()
    cycle +=1
    cycle %= 4
There're number of problems with this code. First of all, you have "cycle" variable, on which you perform some operations, but don't really use, that may be a logical error. Another issue is that you don't show how you use the above function. If you call it in a loop without further delay, it will work exactly as you wrote it, specifically: it will set pin high for 2us, then set it low, then almost immediately set to high again for 2us, etc. End result is that the pin almost always will be high, and you won't see any pulses ("low" pulses will be too short for hardware to "notice").
No, you are making incorrect assumptions. The count is not used, it is just there so I can see if the code is getting executed from REPL, not because of any "logical" error.
I am also calling the code interactively from REPL. You are also also incorrect in your statement about the "low" pulses being too short for hardware to notice. The instructions execute in the order of microseconds, so they are very noticeable with a scope ..
My intention is to have this in an interrupt callback, but it won't even work interactively ..

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

Re: Why is this so hard?

Post by ebike » Tue Jul 28, 2015 9:39 pm

So I got the Pulser class working fine, but it pulses too slow. So I made an in-line assembly function to pulse a pin just once for 2.5us
and I want to call this function in a timer callback, so I did the following:

Code: Select all

@micropython.asm_thumb
def flash_int():
    movwt(r1, stm.GPIOC)

    # get the bit mask for PAC6
    movw(r2, 1 << 6)
    # Turn on
    strh(r2, [r1, stm.GPIO_BSRRL])
    # delay for a bit
    movwt(r4, 50)   #50 = 2.5us
    label(delay_on)
    sub(r4, r4, 1)
    cmp(r4, 0)
    bgt(delay_on)
    #turn off
    strh(r2, [r1, stm.GPIO_BSRRH])


tim4 = Timer(4, freq=200)
tim4.callback(flash_int)
This does not work at all, it should produce a 2.5us pulse every 200hz.

The code in an assembly loop works though, it produces a 200khz square wave as expected:

Code: Select all

def flash_loop(r0):
    # get the GPIOA address in r1
    movwt(r1, stm.GPIOC)

    # get the bit mask for PC6 
    movw(r2, 1 << 6)

    b(loop_entry)

    label(loop1)

    # turn LED on
    strh(r2, [r1, stm.GPIO_BSRRL])

    # delay for a bit
    movwt(r4, 50)
    label(delay_on)
    sub(r4, r4, 1)
    cmp(r4, 0)
    bgt(delay_on)

    # turn LED off
    strh(r2, [r1, stm.GPIO_BSRRH])

    # delay for a bit
    movwt(r4, 50)
    label(delay_off)
    sub(r4, r4, 1)
    cmp(r4, 0)
    bgt(delay_off)

    # loop r0 times
    sub(r0, r0, 1)
    label(loop_entry)
    cmp(r0, 0)
    bgt(loop1)
So what is wrong with the interrupt callback, can I not even do a simple assembly callback this way?
There are no errors produced by python to tell me I have done something wrong. How do I debug something like this?

Post Reply