Several interrupts - how to code this nicely?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
Crashex
Posts: 3
Joined: Wed May 13, 2020 7:14 pm
Contact:

Several interrupts - how to code this nicely?

Post by Crashex » Wed May 13, 2020 7:32 pm

I am writing my first Micropython code - it is my first attempt of using OOP and will be used on ESP32 for a solar tracking system that already works, but currently runs on Arduino UNO. The system has two motors, and I have a motor class with a function that moves the motor left or right depending on the values from the two associated LDR sensors. Each motor is also associated with two limit switches, and I want the motor movement to each side stop immediately when the respective limit switch is pressed (while the possibility of moving to the other side remains active). This is to be done with interrupts (or should I consider an alternative?).
I am not sure where to place my interrupt handler function so that I don't have to write 4 separate functions - outside of the main loop? Inside of the class? Sorry if this sounds confusing or is a downright dumb questions, the examples I can find for ISRs are very simple and don't deal with classes and several interrupts.

Boot file:

Code: Select all

from motor import *
from machine import I2C, Pin
from mp_i2c_lcd1602 import LCD1602
from time import sleep_ms

# Pin numbers for solar tracker components
LDR1 = 36
LDR2 = 39
LDR3 = 34
LDR4 = 35
END1 = 4
END2 = 2
END3 = 15
END4 = 0
REL1 = 32
REL2 = 33
REL3 = 25
REL4 = 26
REL5 = 27
REL6 = 14
LCD_SCL = 22
LCD_SDA = 21
TEMP_CLK  = 18
TEMP_MOSI = 23
TEMP_MISO = 19
TEMP_CS1  = 5
#Timer settings and tolerances
DURATION = 250
TOLERANCE = 15
#Component groups for motors
m1_d_in = (END1, END2)
m1_d_out = (REL1, REL2, REL3)
m1_a_in = (LDR1, LDR2)
m2_d_in = (END3, END4)
m2_d_out = (REL4, REL5, REL6)
m2_a_in = (LDR3, LDR4)

#LCD setup
i2c = I2C(1, sda=Pin(21), scl=Pin(22))
LCD = LCD1602(i2c, 0x27)
#initialization of motors
m1 = motor(m1_d_in, m1_d_out, m1_a_in)
m2 = motor(m2_d_in, m2_d_out, m2_a_in)
#Loop
while True:
    LCD.puts(m1.sensorread(), 0, 1)
    LCD.puts(m2.sensorread(), 9, 1)

    m1.move(DURATION, TOLERANCE)
    m2.move(DURATION, TOLERANCE)

Motor class:

Code: Select all

from machine import Pin, ADC
from time import sleep_ms

class motor:
    def __init__(self, digital_in, digital_out, analog_in):
            self.digital_in = digital_in
            self.endstop = []
            for i in self.digital_in:
                self.endstop[i] = Pin(digital_in[i], Pin.IN)
            self.digital_out = digital_out
            self.relay = []
            for i in self.digital_out:
                self.relay[i] = Pin(digital_out[i], Pin.OUT)
            self.analog_in = analog_in
            self.ldr = []
            for i in self.analog_in:
                self.ldr[i] = ADC(Pin(self.analog_in[i]))
                self.ldr[i].atten(ADC.ATTN_11DB)
    def move(self, duration, tolerance):
        self.duration = duration
        self.tolerance = tolerance
        if self.ldr[0].read() - self.ldr[1].read() > self.tolerance:
            self.relay[0].on()
            self.relay[1].on()
            self.relay[2].off()
        elif self.ldr[1].read() - self.ldr[0].read() > self.tolerance:
            self.relay[0].on()
            self.relay[1].off()
            self.relay[2].on()
        sleep_ms(duration)
    #Read sensors for display
    def sensorread(self):
        result = str(self.ldr[0].read()) + (" ") + str(self.ldr[1].read())
        return result




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

Re: Several interrupts - how to code this nicely?

Post by pythoncoder » Thu May 14, 2020 7:55 am

Your .move method doesn't seem to include a means of stopping the motion after the delay is finished. I suggest adding a .stop method.

In general interrupts are only necessary when you need a response time measured in μs. Using them does involve some complication and I'd avoid them where possible. In a device as slow as a solar tracker they are surely unnecessary. So an amended class would include a .stop method. I would replace the sleep_ms in .move with a loop which checks the limit switches. If they are active, the loop finishes. When this happens .stop is called. Something like:

Code: Select all

end = time.ticks_add(time.ticks_ms(), duration)
while time.ticks_ms() < end:
   if limit_switch_is_active:  # pseudocode
       break
self.stop()
As a very general point, the concept of solar trackers has long puzzled me. They clearly have problems on cloudy days. Yet they track an object whose position can be calculated with extreme precision. The azimuth is a simple function of time of day rotating through 2π radians every 24 hours. The elevation needs a little more maths, but nothing too scary.
Peter Hinch
Index to my micropython libraries.

User avatar
Crashex
Posts: 3
Joined: Wed May 13, 2020 7:14 pm
Contact:

Re: Several interrupts - how to code this nicely?

Post by Crashex » Thu May 14, 2020 11:34 am

Thank you very much for your reply! You are quite right about a tracking system being a weird solution for finding an object we know exactly where it is! I guess I used the LDRs because I could easily understand how they work and how to write some code around them - and was not sure where to find and how to include sun position info into my code at the time I started this project. I would be very happy about any ideas how to go about it! Using a table, a dictionary, or an external file maybe?
As for the stop - yes, I totally forgot the motors should stop! The Arduino code that runs the system currently does stop, luckily! In fact the sleep_ms is supposed to guarantee that the system does only very small movements at each cycle, or it would probably shake itself to bits when we switch it on and it has to drive a longer way towards sun position.

User avatar
Crashex
Posts: 3
Joined: Wed May 13, 2020 7:14 pm
Contact:

Re: Several interrupts - how to code this nicely?

Post by Crashex » Fri May 15, 2020 8:28 am

... Thinking about the sun position algorithm. This presents its own challenges, particularly for our system. We are using window lifting motors from cars to move our mirror. They are not really good for moving to an exact position, and even if I could map their movement somehow, I would not trust that they don't skip sometimes and mess up the whole thing ...

Post Reply