Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8037

MicroPython • Re: multithreading with Raspberry Pi Pico for model railroad

$
0
0
I say chaps,
It's been a while, but here is code which works, sort of. The voltage from potentiometers is compared to the back e.m.f. which is measured at the last time-slot for each track, during which there is no power applied. The PWM waveforms are phased to even out the demand a bit. There is interface circuitry between the Pico and the 12volt track stuff of course.
TTFN

Code:

class MCP3008:    def __init__(self, spi, cs, ref_voltage=3.3):        """        Create MCP3008 instance        Args:            spi: configured SPI bus            cs:  pin to use for chip select            ref_voltage: r        """        self.cs = cs        self.cs.value(1) # ncs on        self._spi = spi        self._out_buf = bytearray(3)        self._out_buf[0] = 0x01        self._in_buf = bytearray(3)        self._ref_voltage = ref_voltage    def reference_voltage(self) -> float:        """Returns the MCP3xxx's reference voltage as a float."""        return self._ref_voltage    def read(self, pin, is_differential=False):        """        read a voltage or voltage difference using the MCP3008.        Args:            pin: the pin to use            is_differential: if true, return the potential difference between two pins,        Returns:            voltage in range [0, 1023] where 1023 = VREF (3V3)        """        self.cs.value(0) # select        self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)        self._spi.write_readinto(self._out_buf, self._in_buf)        self.cs.value(1) # turn off        return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]from machine import Pin, SPIfrom time import sleepspi = SPI(0, sck=Pin(18),mosi=Pin(19),miso=Pin(16), baudrate=100000)cs = Pin(17, Pin.OUT)cs.value(1) # disable chip at startPoint4R = Pin(0, Pin.OUT, 0) # w2c4 Point3L/4RPoint4L = Pin(1, Pin.OUT, 0) # w1c4 Point3R/4LPoint1R = Pin(2, Pin.OUT, 1) # Point1R/2LPoint1L = Pin(3, Pin.OUT, 1) # Point1L/2RPoint2L = Pin(4, Pin.OUT, 0) # w6c3Point2R = Pin(5, Pin.OUT, 0) # w5c3Point3R = Pin(6, Pin.OUT, 0) # w1c3Point3L = Pin(7, Pin.OUT, 0) # w2c3Enter1L  = Pin(8, Pin.IN) # w8c3 Enter1L active lowEnter1R  = Pin(9, Pin.IN) # w7c3 Enter1R active lowExitX    = Pin(10, Pin.IN) # w6c2 ExitX active lowExit2L   = Pin(11, Pin.IN) # w5c2 Exit2L active lowExit3L3R = Pin(12, Pin.IN) # w3c3 Exit3L&3R active lowEnter4L  = Pin(13, Pin.IN) # w3c1 Enter4L active lowEnter4R  = Pin(14, Pin.IN) # w2c1 Enter4R active lowExit2R   = Pin(15, Pin.IN) # w1c1 Exit2R active lowPower0 = Pin(22, Pin.OUT, 1)Power1 = Pin(26, Pin.OUT, 1)Power2 = Pin(27, Pin.OUT, 1)Power3 = Pin(28, Pin.OUT, 1)dt=0.001 #length of timeslott=[0,0,0,0]#PWM time slot for each trackpower=[0,14,8,12] #how many time slots are 'on' in the PWM cycle for each trackgo=[1,1,1,1] # stop/go for each track, controlled by "points_set"speed_actual=[0,0,0,0] #the back-emf reading for each trackspeed_set=[0,0,0,0] #the control potentiometer readings for each trackchip = MCP3008(spi, cs)def speed_read_and_set(track,go): # for each track when its timeslot=0 and outputs stop/go for that track#    print('slot=',t)    speed_set[track] = go*chip.read(track) #reads potentiometer on CH0 to CH3 which are on pins 1 to 4 of the MCP3008. "go"=1 or 0    speed_actual[track] = chip.read(track+4) #reads back_e.m.f. on pins 5 to 8 of the MCP3008# MCP3008 outputs in range 0 to 1023    if speed_actual[track] > speed_set[track]+64 and power[track]>0:        power[track]=power[track]-1    if speed_actual[track] < speed_set[track]-64 and power[track]<15:        power[track]=power[track]+1#    print("speed_set",track,"=",speed_set[track],"speed_actual=",speed_actual[track],"power",track,"=",power[track])a=1br=1bl=1point1=0 #0=Leftpoint2=0 #1=Rightpoint3=0point4=0busy02=0busy13=0busyXN=0busyXS=0while True: #read all the sensors    enter1L = not Enter1L.value()    enter1R = not Enter1R.value()    exitX = not ExitX.value()    exit2L = not Exit2L.value()    enter4L = not Enter4L.value()    enter4R = not Enter4R.value()    exit3L3R = not Exit3L3R.value()    exit2R = not Exit2R.value()    if enter1L or enter1R: #set the "busy" variables. Could control signals?        busy02=1    if exit2L or exit2R:        busy02=0    if enter4R or enter4L:        busy13=1    if exit3L3R:        busy13=0    if enter4L:        busyXS=1    if exitX:        busyXS=0    if (enter1L or enter1R) and point2:        busyXN=1#Change points as necessary#Point1 changes when a train approaches other side, unless the next zone of contention is busy.    if enter1L and busy02:        go[0]=0    elif enter1L and point1:        go[0]=1        point1=0        Point1R.value(0)        Point1L.value(1)    if enter1R and busy02:        go[2]=0    elif enter1R and not point1:        go[2]=1        point1=1        Point1R.value(1)        Point1L.value(0)    #Point2 changes when a train passes over    if exit2R and br: #Exit2R        point2=0        Point2R.value(0)        Point2L.value(1)        print ("Point2=L")        br=0    elif exit2R==0:        br=1    if exit2L and bl: #Exit2L        point2=1        Point2R.value(1)        Point2L.value(0)        print ("Point2=R")        bl=0    elif exit2R==0:        bl=1                #Point3   toggles when train exits    if exit3L3R and a: # Exit3L&3R are wire_or        Point3R.value(not point3)# Point3L/4R        Point3L.value(point3) # Point3R/4L        if point3:            print ("Point3=L")        else:            print ("Point3=R")        a=0        point3=not point3    elif not exit3L3R and not a:        a=1 #ready for next time but repeated chattering stopped while 'exit3L3R' is true        #Point4 changes when a train approaches other side, unless the next zone of contention is busy.    if enter4L and busy13 orbusyXN:        go[0]=0    elif enter1L and point4:        go[0]=1        point4=0        Point4R.value(0)        Point4L.value(1)    if enter4R and busy13:        go[3]=0    elif enter4R and not point4:        go[4]=1        point4=1        Point4R.value(1)        Point4L.value(0)"""Trains stop and go according to point settings and contention at pointsIf point1 is L then enter1R, track2 power is cut. go[2]=0. Track2 power, go[2]=1, when exit2L or exit2R =1If point1 is R then enter1L, track0 power is cut. go[0]=0. Track0 power, go[0]=1, when exit2L or exit2R =1If point4 is L then enter4R, track3 power is cut. go[3]=0. Track3 power, go[3]=1, when exit3L3R=1If point4 is R then enter4L, track1 power is cut. go[1]=0. Track1 power, go[1]=1, when exit3L3R=1If point4 is L and busyXN then enter4L, track1 power is cut. go[1]=0. Track1 power, go[1]=1, when exitX=1If point2 is R and busyXS then enter1R or enter1L, track2 power is cut. go[2]=0. Track2 power, go[2]=1, when exit2R=1"""     if t[0]<15:        t[0]=t[0]+1 #time slot is incremented for track0    else:        t[0]=0    t[1]=t[0]-4 #time slot is incremented for track1    if t[1]<0:        t[1]=t[0]+12    t[2]=t[0]-8 #time slot is incremented for track2    if t[2]<0:        t[2]=t[0]+8    t[3]=t[0]-12 #time slot is incremented for track3    if t[3]<0:    t[3]=t[0]+4 #   print(t[0],t[1],t[2],t[3])        #set PWM duty cycle, for track[n]    if t[0]==0:        Power0.value(0)        sleep(dt)        speed_read_and_set(0,go[0])    elif t[1]==0:        Power1.value(0)        sleep(dt)        speed_read_and_set(1,go[1])    elif t[2]==0:        Power2.value(0)        sleep(dt)        speed_read_and_set(2,go[2])    elif t[3]==0:        Power3.value(0)        sleep(dt)        speed_read_and_set(3,go[3])    else:        sleep(dt)    if t[0] > power[0]:        Power0.value(1)    if t[0] < power[0]:        Power0.value(0)    if t[1] > power[1]:        Power1.value(1)    if t[1] < power[1]:        Power1.value(0)    if t[2] > power[2]:        Power2.value(1)    if t[2] < power[2]:        Power2.value(0)    if t[3] > power[3]:        Power3.value(1)    if t[3] < power[3]:        Power3.value(0)

Statistics: Posted by rickticktock — Fri Nov 08, 2024 4:28 pm



Viewing all articles
Browse latest Browse all 8037

Trending Articles