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
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