AttributeError: 'module' object has no attribute 'Pin'

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
walli_90

AttributeError: 'module' object has no attribute 'Pin'

Post by walli_90 » Mon Feb 11, 2019 12:53 pm

Hi,

I am using a pyboard as controller for two DC motors in a (not yet) autonomous robot.
I wrote a module (motor_driver) containing the functions for basic movement and imported it in main.py. So I can access the console and run the functions manually.
But when I call a function of motor_driver in the console I only get "AttributeError: 'module' object has no attribute 'Pin'". Importing motor_driver manually and calling e.g. move resuts in: "name 'move' not defined" or something like that...

Can you spot a mistake in the code? I really don't know where to start searching...

main.py
#########
import machine
import pyb
import utime
from motor_driver import move, turn, curve
from oled1306 import show_lcd

motor_driver.py
##########
import pyb
import utime
from math import pi
from oled1306 import show_lcd
# Pins right motor
rm_cw = pyb.Pin('Y2', pyb.Pin.OUT_PP) # Clockwise rotation
rm_ccw = pyb.Pin('Y3', pyb.Pin.OUT_PP) # Counterclockwise rotation
rm_pwm = pyb.Pin("Y1") # PWM signal
...

Firmware is v1.9.4


Just to add:
Previous versions of the code worked and I have not touched the imports or pin layout since.
Last edited by walli_90 on Tue Feb 12, 2019 10:41 am, edited 3 times in total.

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

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by Roberthh » Mon Feb 11, 2019 9:19 pm

Which line is flagged as wrong?

walli_90

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by walli_90 » Tue Feb 12, 2019 7:14 am

This one:

rm_cw = pyb.Pin('Y2', pyb.Pin.OUT_PP) # Clockwise rotation

Hanilein
Posts: 29
Joined: Thu Jul 12, 2018 11:40 am
Location: Christchurch, New Zealand

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by Hanilein » Tue Feb 12, 2019 9:07 am

Hmmm, I tried that on the fly, it works...
Can you please post a bit more of your code, and the REPL screen output as well?
Ivo Gorny

walli_90

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by walli_90 » Tue Feb 12, 2019 10:34 am

motor_driver.py
############

Code: Select all

import pyb
import utime
from math import pi

from oled1306 import show_lcd

# Pins right motor
rm_cw = pyb.Pin('Y2', pyb.Pin.OUT_PP)  # Clockwise rotation
rm_ccw = pyb.Pin('Y3', pyb.Pin.OUT_PP)  # Counterclockwise rotation
rm_pwm = pyb.Pin("Y1")  # PWM signal
# Pins left motor
lm_cw = pyb.Pin('Y5', pyb.Pin.OUT_PP)
lm_ccw = pyb.Pin('Y6', pyb.Pin.OUT_PP)
lm_pwm = pyb.Pin("Y4")
# Initialize
rm_cw.low()
rm_ccw.low()
lm_cw.low()
lm_ccw.low()

# Initialize PWM timers
max_freq = 8000  # Maximal frequency [Hz] for PWM timer
# Right motor
tim_r = pyb.Timer(8, freq=max_freq)
ch_r = tim_r.channel(1, pyb.Timer.PWM, pin=rm_pwm)
ch_r.pulse_width_percent(0)
# Left motor
tim_l = pyb.Timer(4, freq=max_freq)
ch_l = tim_l.channel(4, pyb.Timer.PWM, pin=lm_pwm)
ch_r.pulse_width_percent(0)

def distancetimer(distance, speed):
    """Calculate time for robot to move 'distance' and set timer"""
    speedbase = 490/100
    speedfinal = speedbase * speed
    timtime = int((distance/speedfinal) * 1000)
    utime.sleep_ms(timtime)

def accelerate(spd_in):
    """Smooth acceleration at motors' start"""
    delay = 2
    temp_perc = 0

    while spd_in > temp_perc:
        temp_perc += 1
        ch_r.pulse_width_percent(temp_perc)
        ch_l.pulse_width_percent(temp_perc)
        utime.sleep_ms(delay)

def reset_motors():
    rm_cw.low()
    rm_ccw.low()
    lm_cw.low()
    lm_ccw.low()

def brake(spd=0):
    """Stop motors smoothly"""
    delay = 5

    while spd > 0:
        spd -= 1
        ch_r.pulse_width_percent(spd)
        ch_l.pulse_width_percent(spd)
        utime.sleep_ms(delay)

    rm_cw.high()
    rm_ccw.high()
    lm_cw.high()
    lm_ccw.high()

Code: Select all

def move(speed, direction, distance):
    """
    Moves forward or backward with defined speed and for a defined distance
    args: speed int(0, 100), direction int(1, 2), distance int()[mm]
    """
    reset_motors()

    if direction == 1:
        # Move forward
        rm_cw.high()
        lm_cw.high()
        accelerate(speed)
        ch_r.pulse_width_percent(speed)
        ch_l.pulse_width_percent(speed)
        distancetimer(distance, speed)
    elif direction == 2:
        # Move backward
        rm_ccw.high()
        lm_ccw.high()
        accelerate(speed)
        ch_r.pulse_width_percent(speed)
        ch_l.pulse_width_percent(speed)
        distancetimer(distance, speed)
    else:
        pass

    brake(speed)

def turn(speed, direction, degree):
    """
    Turns left or right (pinwheel) for a defined angular degree
    args: speed int(0, 100), direction int(3, 4), degree int(0, 360)[°]
    """
    reset_motors()

    if direction == 3:
        # Turn left
        rm_cw.high()
        lm_ccw.high()
        accelerate(speed)
        ch_r.pulse_width_percent(speed)
        ch_l.pulse_width_percent(speed)
        distance = 2.75 * degree
        distancetimer(distance, speed)
    elif direction == 4:
        # Turn right
        rm_ccw.high()
        lm_cw.high()
        accelerate(speed)
        ch_r.pulse_width_percent(speed)
        ch_l.pulse_width_percent(speed)
        distance = 2.75 * degree
        distancetimer(distance, speed)
    else:
        pass

    brake(speed)

def curve(speed, direction, degree, radius):
    """
    Turn left or right. Wheel on the inside is stopped.
    args: speed int(0, 100), radius int()[mm],
        direction int(3, 4), degree int(-360, 360)[°]
    """
    reset_motors()

    if degree < 0:
        # Turn left
        distance = 5.5 * degree
        distance = distance * -1
        if direction == 1:
            rm_cw.high()
            ch_r.pulse_width_percent(speed)
        elif direction == 2:
            rm_ccw.high()
            ch_r.pulse_width_percent(speed)
        distancetimer(distance, speed)
    elif degree > 0:
        # Turn right
        distance = 5.5 * degree
        if direction == 1:
            lm_cw.high()
            ch_l.pulse_width_percent(speed)
        elif direction == 2:
            lm_ccw.high()
            ch_l.pulse_width_percent(speed)
        distancetimer(distance, speed)
    else:
        pass

    brake(speed)

Apart from the imports main.py is empty.

Hanilein
Posts: 29
Joined: Thu Jul 12, 2018 11:40 am
Location: Christchurch, New Zealand

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by Hanilein » Tue Feb 12, 2019 6:34 pm

It still works :o

The only difference is, that I don't have the Oled Driver, so that's commented out.

Code: Select all

MicroPython v1.9.2 on 2017-08-23; PYBv1.1 with STM32F405RG
Type "help()" for more information.
>>> import motor_driver
>>> motor_driver.brake()
>>> motor_driver.accelerate(100)
>>>
  • just for our peace of mind: comment out the Oled Driver line and try.
  • Remove all other unneeded imports and parts from the code, piece by piece, and try
  • Test various functions of your driver in the console - is the error always there/always the same pin?
Ivo Gorny

walli_90

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by walli_90 » Wed Feb 13, 2019 7:05 am

Hanilein wrote:
Tue Feb 12, 2019 6:34 pm
  • just for our peace of mind: comment out the Oled Driver line and try.
  • Remove all other unneeded imports and parts from the code, piece by piece, and try
That is basically what I tried on monday for almost three hours.
  • Commented out all unnecessary imports
  • Removed the new functions one after the other
... and it still did not work. Only when setting back to last week's master branch, it suddenly functioned as expected.

Yesterday I started with the old master, adding functions and testing each piece immediately. I have not yet transfered everything, but it seems to work so far...

walli_90

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by walli_90 » Fri Feb 15, 2019 8:31 am

I rewrote the whole program starting from last week's master. Now everything works and I have no idea where the error was. :|

Only out of curiosity... May it be, that the pyboard fails to load modules, if there is an excessive folder sturcture on the flash?

Hanilein
Posts: 29
Joined: Thu Jul 12, 2018 11:40 am
Location: Christchurch, New Zealand

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by Hanilein » Fri Feb 15, 2019 9:50 pm

walli_90 wrote:
Fri Feb 15, 2019 8:31 am
I rewrote the whole program starting from last week's master. Now everything works and I have no idea where the error was. :|
Well done!
walli_90 wrote:
Fri Feb 15, 2019 8:31 am
Only out of curiosity... May it be, that the pyboard fails to load modules, if there is an excessive folder sturcture on the flash?
Hmmm, I don't know, but what I know is, that during loading a module uses more memory, because the source code is converted to bytecode, and that is smaller than the py-file. This is decribed here: http://docs.micropython.org/en/latest/r ... tion-phase

I'd like to know, how much RAM I have left, so what I do is:

Code: Select all

import gc
gc.collect()
baseline=gc.mem_alloc() # used to calculate the RAM used for the Library
gc.collect();print('\n\nUsed RAM:{:>6}   Free Ram:{:>6}   Net used:{:>6}'.format(gc.mem_alloc(),gc.mem_free(),gc.mem_alloc()-baseline));gc.collect()
import clock
gc.collect();print('\n\nUsed RAM:{:>6}   Free Ram:{:>6}   Net used:{:>6}'.format(gc.mem_alloc(),gc.mem_free(),gc.mem_alloc()-baseline));gc.collect()
 
First I import the garbage collect module, then I memorize the current RAM usage
I print the values of Used RAM, Free RAM and Net used RAM (the latter obviously zero during this first call).
After importing a module (here my clock.py I am busy with right now), I print the values again:

Code: Select all

Used RAM:  2496   Free Ram: 99712   Net used:     0
Used RAM: 14288   Free Ram: 87920   Net used: 11792
Now i know, that the module occupies 11kb after import, and I still have 87kb left, which means, if I would import this module after having imported other modules, I need at least 11kb free RAM, plus whatever is needed for conversion, plus my heap I need to run my whole program.
Ivo Gorny

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

Re: AttributeError: 'module' object has no attribute 'Pin'

Post by pythoncoder » Mon Feb 18, 2019 7:02 am

walli_90 wrote:
Tue Feb 12, 2019 10:34 am
...
Apart from the imports main.py is empty.
I would suggest having main.py completely empty during development; also issuing a soft reset (ctrl-D) between each run. I have seen similar errors: I've never managed to pin down the exact cause, but they seem to stem from failing to "clear the decks" between each program run.
Peter Hinch
Index to my micropython libraries.

Post Reply