-1

EDIT: Thanks to the age old tradition of unplugging and plugging everything back in I got it to work; I reflashed the WiPy module and reinstalled the Pymakr plugin.

I am currently in the process of writing a PID-controller for micropython (we have to make a linefollower). I have implemented the PID algorithm in microPython as a class.

I will be using the WiPy module from Pycom to control my linefollower.

For now the actual program doesn't do much, I just wanted to test if the program was reasonably fast, as such I have some random numbers for the input and the K-values and the output function is just left empty.

However whenever I try to run a little test script where I create the object and calculate the PID a 100 times, I get an attributeError in the init of the PID-class. This is the method that gives me trouble:

def __init__(self, input_func, output_func, P_factor=1.0, I_factor=0.0,
             D_factor=0.0):

    ... previous variable declarations ...

    # Initializer for the time. This will form the basis for the timebased
    # calculations. This time will mark the start of a time-block.
    self.last_calculate_time = utime.ticks_ms()

The last line is the one that gives me trouble. The main program has this in it:

def motorOutput(PID_output):
    """
    Function for driving the two motors depending on the PID output.
    """
    pass

def generateInput():
    """
    Return a random float
    """
    return 2.5


if __name__ == "__main__":

    print("creating PID controller")
    PID_controller = PID.PID(generateInput, motorOutput, 1.0, 0.5, 1.5)
    counter = 0
    print("starting loop")
    while counter < 1000:
        counter += 1
        PID_controller.calculate()

    print("finished loop")

This is the output that I get when running the file:

>>> Running main.py

>>>
>>> creating PID controller
╝Traceback (most recent call last):
File "<stdin>", line 60, in <module>
File "/flash/lib/PID.py", line 95, in __init__
AttributeError: 'PID' object has no attribute 'last_calculate_time'
╝>
MicroPython v1.8.6-621-g17ee404e on 2017-05-25; WiPy with ESP32
Jonas
  • 121,568
  • 97
  • 310
  • 388

1 Answers1

0

You're receiving this error because you are attempting to assign an attribute which hasn't been declared and I assume you are using python 2's classic class style. Add a definition for last_calculate_time in your PID class such as last_calculate_time = None and then it should work as expected.

A more suitable approach would be passing object as an argument to your class definition as below, causing it to be treated as a New Style Class:

class PID(object):
    def __init__(self):
        self.last_calculate_time = utime.ticks_ms()

More information can be seen at: https://wiki.python.org/moin/NewClassVsClassicClass

Robbie Dunn
  • 116
  • 4
  • Thank you for the quick reply! I already had the object as a class argument. I tried initializing the variable as None first and then assigning the value. However now I get the same error, but in the actual calculate method instead of the init – Pieter-Jan Cassiman Nov 23 '18 at 17:01
  • @Pieter-JanCassiman apologies for assuming that was the problem! Hmm have you done some testing on the output of `utime.ticks_ms()` ? Maybe hardcode the value temporarily to see if that helps? – Robbie Dunn Nov 23 '18 at 17:08
  • Aha! We are on to something! The ticks_ms() is indeed the problem. It says that the module has no attribute ticks_ms(). Which is strange since that is what the documentation told me to use... – Pieter-Jan Cassiman Nov 23 '18 at 17:36
  • Just tested this using an online micropython CLI and worked for me. What is the import statement you're using for utime? – Robbie Dunn Nov 23 '18 at 18:00
  • I was using "import utime", But I have just deleted all the plugin and reinstalled it. I have also reflashed the firmware to the board, and that seemed to have fixed the problem. – Pieter-Jan Cassiman Nov 23 '18 at 18:04
  • Glad its fixed! – Robbie Dunn Nov 23 '18 at 18:09