TypeError in Viper routine but no floats in sight

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
nedkonz
Posts: 24
Joined: Thu Aug 05, 2021 9:58 pm

TypeError in Viper routine but no floats in sight

Post by nedkonz » Tue Aug 24, 2021 9:30 pm

Perhaps someone could help me figure out why I'm getting an exception in my ISR code.

I've been working on a stepper motor library which calculates timer periods on the fly during acceleration.
I'm currently limited to about 600 pulses/second on each of three motors; past that I run out of the micropython.schedule() queue. I'm calling micropython.schedule() to handle a floating point expression after each timer interrupt.

I'm trying to use the Viper emitter to get better speed out of the ISR. The 'micropython.native' emitter worked OK but I need more speed.

The problem that I'm running into is this: During execution I get an exception from the interrupt handler that looks like this:

Code: Select all

uncaught exception in Timer(8) interrupt handler
TypeError: can't convert float to int
uncaught exception in Timer(13) interrupt handler
TypeError: can't convert float to int
uncaught exception in Timer(4) interrupt handler
TypeError: can't convert float to int
I've put casts on everything I could find in the routine, and made sure that none of my object's instance variables hold floats.

So I'm at a loss as to what exactly is causing this complaint.

My ISR looks like this:

Code: Select all

    @micropython.viper
    def _compute_new_speed(self, t):
        self._step_pin.value(int(1))
        # are we at the target speed  yet?
        self._at_speed = False
        if bool(self._decelerating):
            self._at_speed = ((int(self._direction) == int(self._target_direction)) \
                and (int(self._speed) <= int(self._target_speed)))
            if int(self._n) >= int(0):   # we've hit int(0) speed; check for a change in direction
                # will print after ISR
                # micropython.schedule(self._cached_debug, self._cached_msg2)
                self._direction = int(self._target_direction)
                self._decelerating = False
                if int(self._direction) == DIRECTION_CW:
                    self._direction_pin.value(int(1))
                    self._reverse_direction_pin.value(int(0))
                else:
                    self._direction_pin.value(int(0))
                    self._reverse_direction_pin.value(int(1))
        else:
            self._at_speed = bool(int(self._speed) >= int(self._target_speed))

        if bool(self._at_speed):
            # micropython.schedule(self._cached_debug, self._cached_msg)
            # self.pulse_debug_pin()
            self._n = int(0)
            self._speed = int(self._target_speed)
            self._position = int(self._position) + int(self._direction) # update position
            # set the timer period
            if int(self._target_speed) != int(0):
                self._cn = int(int(TIMER_FREQUENCY) // int(self._target_speed))
                t.period(int(self._cn) - int(1))
                t.callback(self._cached_update_position)
            else:
                # stop timer output (and callbacks)
                t.deinit()
                self._cn = int(0)
            return

        # update speed and timer period
        self._speed = int(int(TIMER_FREQUENCY) // int(self._cn))
        t.period(int(self._cn) - int(1))

        # update position
        self._position = int(self._position) + int(self._direction)

        # update _cn and _n after ISR:
        micropython.schedule(self._cached_update_cn, None)

        self._step_pin.value(int(0))
Can anyone spot the float? I can't.
Thanks!

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: TypeError in Viper routine but no floats in sight

Post by Roberthh » Wed Aug 25, 2021 5:52 am

What ate the initial values in self?

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

Re: TypeError in Viper routine but no floats in sight

Post by pythoncoder » Wed Aug 25, 2021 9:17 am

I've never tried Viper in an ISR, but it should work. I suggest including

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)
This might give you a line number where the fault is occurring. One shot in the dark is that Viper likes type hints. Failing all this, the "brute force and ignorance" way to locate the offending line is to comment out bits of your ISR until the error goes away.
Peter Hinch
Index to my micropython libraries.

nedkonz
Posts: 24
Joined: Thu Aug 05, 2021 9:58 pm

Re: TypeError in Viper routine but no floats in sight

Post by nedkonz » Wed Aug 25, 2021 1:02 pm

Roberthh wrote:
Wed Aug 25, 2021 5:52 am
What ate the initial values in self?
Assuming you meant 'are', not 'ate':

Here's a list (taken after a move finished, so several of the values are 0, which they wouldn't be in the ISR):

Code: Select all

_step_pin: Pin(Pin.cpu.A6, mode=Pin.OUT)
_direction_pin: Pin(Pin.cpu.B6, mode=Pin.OUT)
_reverse_direction_pin: Pin(Pin.cpu.C7, mode=Pin.OUT)
_debug_pin: Pin(Pin.cpu.C7, mode=Pin.OUT)
_name: motor3
_position: 0 # signed integer
_speed: 0 # unsigned integer
_direction: 1 # -1 or 1
_target_speed: 500 # unsigned integer
_target_direction: 1 # -1 or 1
_n: 0 # signed integer
_cn: 6169 # unsigned integer
_c0: 6169 # unsigned integer
_cmin: 60 # unsigned integer
_max_speed: 2400 # unsigned integer
_max_acceleration: 4800 # unsigned integer

nedkonz
Posts: 24
Joined: Thu Aug 05, 2021 9:58 pm

Re: TypeError in Viper routine but no floats in sight

Post by nedkonz » Wed Aug 25, 2021 1:09 pm

pythoncoder wrote:
Wed Aug 25, 2021 9:17 am
I've never tried Viper in an ISR, but it should work. I suggest including

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)
This might give you a line number where the fault is occurring. One shot in the dark is that Viper likes type hints. Failing all this, the "brute force and ignorance" way to locate the offending line is to comment out bits of your ISR until the error goes away.
Thanks for the suggestions!

I have an emergency buffer allocated already. But unfortunately I am not getting a line number.

As you can see from my code, I've type-hinted everything in the ISR.

I've tried commenting out the lines with the divisions but it didn't help.

I'm now trying to write the ISR in C but am not sure how to extend a Python class with C.
I'll make a new post about that.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: TypeError in Viper routine but no floats in sight

Post by Roberthh » Wed Aug 25, 2021 1:48 pm

What's about self._decelerating?

nedkonz
Posts: 24
Joined: Thu Aug 05, 2021 9:58 pm

Re: TypeError in Viper routine but no floats in sight

Post by nedkonz » Wed Aug 25, 2021 3:35 pm

Roberthh wrote:
Wed Aug 25, 2021 1:48 pm
What's about self._decelerating?
it's a bool.

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

Re: TypeError in Viper routine but no floats in sight

Post by dhylands » Wed Aug 25, 2021 5:05 pm

Have you tried renaming your callback and then make _compute_new_speed be a non-viper python function which just calls the renamed _compute_new_speed with a try/catch and then put a print of the exception in the catch. Something like:

Code: Select all

def _compute_new_speed(self, t):
  try:
      self._viper_compute_new_speed(t)
  except Exception as err:
      sys.print_exception(err)

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

Re: TypeError in Viper routine but no floats in sight

Post by pythoncoder » Wed Aug 25, 2021 5:46 pm

nedkonz wrote:
Wed Aug 25, 2021 1:09 pm
...
As you can see from my code, I've type-hinted everything in the ISR...
Not in the code you posted. I'd expect to see (for example)

Code: Select all

        self._at_speed : bool = False
I also wonder if a type hint on the first line would help

Code: Select all

    def _compute_new_speed(self : ptr32, t : ptr32):
but I'm not sure if those types are right. Objects are passed by reference, but perhaps in place of ptr32 you need your class name and Timer.

Please see this doc re Viper and type hints.
Peter Hinch
Index to my micropython libraries.

nedkonz
Posts: 24
Joined: Thu Aug 05, 2021 9:58 pm

Re: TypeError in Viper routine but no floats in sight

Post by nedkonz » Wed Aug 25, 2021 6:22 pm

pythoncoder wrote:
Wed Aug 25, 2021 5:46 pm
nedkonz wrote:
Wed Aug 25, 2021 1:09 pm
...
As you can see from my code, I've type-hinted everything in the ISR...
Not in the code you posted. I'd expect to see (for example)

Code: Select all

        self._at_speed : bool = False
I just tried that exact line in a Viper function, and it crashed mpy-cross with an assertion:

Code: Select all

MPY accelstepper.py
Assertion failed: (vtype_val == VTYPE_PYOBJ), function emit_native_store_attr, file ../py/emitnative.c, line 1733.
make: *** [build/accelstepper.mpy] Abort trap: 6

Post Reply