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

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

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, SPI
from time import sleep
spi = SPI(0, sck=Pin(18),mosi=Pin(19),miso=Pin(16), baudrate=100000)
cs = Pin(17, Pin.OUT)
cs.value(1) # disable chip at start


Point4R = Pin(0, Pin.OUT, 0) # w2c4 Point3L/4R
Point4L = Pin(1, Pin.OUT, 0) # w1c4 Point3R/4L
Point1R = Pin(2, Pin.OUT, 1) # Point1R/2L
Point1L = Pin(3, Pin.OUT, 1) # Point1L/2R
Point2L = Pin(4, Pin.OUT, 0) # w6c3
Point2R = Pin(5, Pin.OUT, 0) # w5c3
Point3R = Pin(6, Pin.OUT, 0) # w1c3
Point3L = Pin(7, Pin.OUT, 0) # w2c3
Enter1L = Pin(8, Pin.IN) # w8c3 Enter1L active low
Enter1R = Pin(9, Pin.IN) # w7c3 Enter1R active low
ExitX = Pin(10, Pin.IN) # w6c2 ExitX active low
Exit2L = Pin(11, Pin.IN) # w5c2 Exit2L active low
Exit3L3R = Pin(12, Pin.IN) # w3c3 Exit3L&3R active low
Enter4L = Pin(13, Pin.IN) # w3c1 Enter4L active low
Enter4R = Pin(14, Pin.IN) # w2c1 Enter4R active low
Exit2R = Pin(15, Pin.IN) # w1c1 Exit2R active low

Power0 = 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 timeslot
t=[0,0,0,0]#PWM time slot for each track
power=[0,14,8,12] #how many time slots are 'on' in the PWM cycle for each track
go=[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 track
speed_set=[0,0,0,0] #the control potentiometer readings for each track
chip = 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=1
br=1
bl=1
point1=0 #0=Left
point2=0 #1=Right
point3=0
point4=0
busy02=0
busy13=0
busyXN=0
busyXS=0
while 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 points
If point1 is L then enter1R, track2 power is cut. go[2]=0. Track2 power, go[2]=1, when exit2L or exit2R =1
If point1 is R then enter1L, track0 power is cut. go[0]=0. Track0 power, go[0]=1, when exit2L or exit2R =1
If point4 is L then enter4R, track3 power is cut. go[3]=0. Track3 power, go[3]=1, when exit3L3R=1
If point4 is R then enter4L, track1 power is cut. go[1]=0. Track1 power, go[1]=1, when exit3L3R=1
If point4 is L and busyXN then enter4L, track1 power is cut. go[1]=0. Track1 power, go[1]=1, when exitX=1
If 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 4980

Trending Articles