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
Posts: 6
Joined: Mon Feb 11, 2019 12:10 pm

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: 1243
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
Posts: 6
Joined: Mon Feb 11, 2019 12:10 pm

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: 24
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
Posts: 6
Joined: Mon Feb 11, 2019 12:10 pm

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: 24
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
Posts: 6
Joined: Mon Feb 11, 2019 12:10 pm

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
Posts: 6
Joined: Mon Feb 11, 2019 12:10 pm

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: 24
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: 3241
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

Post Reply