/ CircuitPython_Slider / code.py
code.py
1 # SPDX-FileCopyrightText: 2019 Liz Clark for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 import time 6 import displayio 7 import terminalio 8 import adafruit_imageload 9 from adafruit_display_text.label import Label 10 from adafruit_featherwing import minitft_featherwing 11 from adafruit_motorkit import MotorKit 12 from adafruit_motor import stepper 13 14 # setup stepper motor 15 kit = MotorKit() 16 17 # setup minitft featherwing 18 minitft = minitft_featherwing.MiniTFTFeatherWing() 19 20 # setup bitmap file locations 21 five_minBMP = "/5min_bmp.bmp" 22 ten_minBMP = "/10min_bmp.bmp" 23 twenty_minBMP = "/20min_bmp.bmp" 24 hourBMP = "/60min_bmp.bmp" 25 runningBMP = "/camSlide_bmp.bmp" 26 reverseqBMP = "/reverseQ_bmp.bmp" 27 backingUpBMP = "/backingup_bmp.bmp" 28 stopBMP = "/stopping_bmp.bmp" 29 30 # variables for state machines in loop 31 mode = 0 32 onOff = 0 33 pause = 0 34 stop = 0 35 z = 0 36 37 # image groups 38 five_minGroup = displayio.Group() 39 ten_minGroup = displayio.Group() 40 twenty_minGroup = displayio.Group() 41 hourGroup = displayio.Group() 42 reverseqGroup = displayio.Group() 43 backingUpGroup = displayio.Group() 44 stopGroup = displayio.Group() 45 progBarGroup = displayio.Group() 46 47 # bitmap setup for all of the menu screens 48 five_minBG, five_minPal = adafruit_imageload.load( 49 five_minBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 50 ) 51 five_minDis = displayio.TileGrid(five_minBG, pixel_shader=five_minPal) 52 ten_minBG, ten_minPal = adafruit_imageload.load( 53 ten_minBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 54 ) 55 ten_minDis = displayio.TileGrid(ten_minBG, pixel_shader=ten_minPal) 56 twenty_minBG, twenty_minPal = adafruit_imageload.load( 57 twenty_minBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 58 ) 59 twenty_minDis = displayio.TileGrid(twenty_minBG, pixel_shader=twenty_minPal) 60 hourBG, hourPal = adafruit_imageload.load( 61 hourBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 62 ) 63 hourDis = displayio.TileGrid(hourBG, pixel_shader=hourPal) 64 runningBG, runningPal = adafruit_imageload.load( 65 runningBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 66 ) 67 runningDis = displayio.TileGrid(runningBG, pixel_shader=runningPal) 68 reverseqBG, reverseqPal = adafruit_imageload.load( 69 reverseqBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 70 ) 71 reverseqDis = displayio.TileGrid(reverseqBG, pixel_shader=reverseqPal) 72 backingUpBG, backingUpPal = adafruit_imageload.load( 73 backingUpBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 74 ) 75 backingUpDis = displayio.TileGrid(backingUpBG, pixel_shader=backingUpPal) 76 stopBG, stopPal = adafruit_imageload.load( 77 stopBMP, bitmap=displayio.Bitmap, palette=displayio.Palette 78 ) 79 stopDis = displayio.TileGrid(stopBG, pixel_shader=stopPal) 80 81 # setup for timer display when camera is sliding 82 text_area = Label(terminalio.FONT, text=" ") 83 text_area.x = 55 84 text_area.y = 65 85 86 # adding the bitmaps to the image groups so they can be displayed 87 five_minGroup.append(five_minDis) 88 ten_minGroup.append(ten_minDis) 89 twenty_minGroup.append(twenty_minDis) 90 hourGroup.append(hourDis) 91 progBarGroup.append(runningDis) 92 progBarGroup.append(text_area) 93 reverseqGroup.append(reverseqDis) 94 backingUpGroup.append(backingUpDis) 95 stopGroup.append(stopDis) 96 97 # setting button states on minitft featherwing to None 98 down_state = None 99 up_state = None 100 a_state = None 101 b_state = None 102 select_state = None 103 104 # arrays to match up with the different slide speeds 105 # graphics menu array 106 graphics = [five_minGroup, ten_minGroup, twenty_minGroup, hourGroup] 107 # delay for the stepper motor 108 speed = [0.0154, 0.034, 0.0688, 0.2062] 109 # time duration for the camera slide 110 slide_duration = [300, 600, 1200, 3600] 111 # beginning timer display 112 slide_begin = ["5:00", "10:00", "20:00", "60:00"] 113 # stepper motor steps that corresponds with the timer display 114 # fmt: off 115 slide_checkin = [ 860, 1720, 2580, 3440, 4300, 5160, 116 6020, 6880, 7740, 8600, 9460, 10320, 117 11180, 12040, 12900, 13760, 14620, 15480, 118 16340, 17195] 119 # fmt: on 120 # variable that counts up through the slide_checkin array 121 check = 0 122 123 # start time 124 begin = time.monotonic() 125 print(begin) 126 # when feather is powered up it shows the initial graphic splash 127 minitft.display.show(graphics[mode]) 128 129 while True: 130 # setup minitft featherwing buttons 131 buttons = minitft.buttons 132 # define the buttons' state changes 133 if not buttons.down and down_state is None: 134 down_state = "pressed" 135 if not buttons.up and up_state is None: 136 up_state = "pressed" 137 if not buttons.select and select_state is None: 138 select_state = "pressed" 139 if not buttons.a and a_state is None: 140 a_state = "pressed" 141 if not buttons.b and b_state is None: 142 b_state = "pressed" 143 # scroll down to change slide duration and graphic 144 if buttons.down and down_state == "pressed": 145 # blocks the button if the slider is sliding or 146 # in an in-between state 147 if pause == 1 or onOff == 1: 148 mode = mode 149 down_state = None 150 else: 151 mode += 1 152 down_state = None 153 if mode > 3: 154 mode = 0 155 print("Mode:,", mode) 156 minitft.display.show(graphics[mode]) 157 # scroll up to change slide duration and graphic 158 if buttons.up and up_state == "pressed": 159 # blocks the button if the slider is sliding or 160 # in an in-between state 161 if pause == 1 or onOff == 1: 162 mode = mode 163 up_state = None 164 else: 165 mode -= 1 166 up_state = None 167 if mode < 0: 168 mode = 3 169 print("Mode: ", mode) 170 minitft.display.show(graphics[mode]) 171 # workaround so that the menu graphics show after a slide is finished 172 if mode == mode and pause == 0 and onOff == 0: 173 minitft.display.show(graphics[mode]) 174 # starts slide 175 if buttons.select and select_state == "pressed" or z == 2: 176 # blocks the button if the slider is sliding or 177 # in an in-between state 178 if pause == 1 or onOff == 1: 179 # print("null") 180 select_state = None 181 else: 182 # shows the slider is sliding graphic 183 minitft.display.show(progBarGroup) 184 # gets time of button press 185 press = time.monotonic() 186 print(press) 187 # displays initial timer 188 text_area.text = slide_begin[mode] 189 # resets button 190 select_state = None 191 # changes onOff state 192 onOff += 1 193 # changes z state 194 z = 0 195 if onOff > 1: 196 onOff = 0 197 # number of steps for the length of the aluminum extrusions 198 for i in range(17200): 199 # for loop start time 200 start = time.monotonic() 201 # gets actual duration time 202 real_time = start - press 203 # creates a countdown from the slide's length 204 end = slide_duration[mode] - real_time 205 # /60 since time is in seconds 206 mins_remaining = end / 60 207 if mins_remaining < 0: 208 mins_remaining += 60 209 # gets second(s) count 210 total_sec_remaining = mins_remaining * 60 211 # formats to clock time 212 mins_remaining, total_sec_remaining = divmod(end, 60) 213 # microstep for the stepper 214 kit.stepper1.onestep(style=stepper.MICROSTEP) 215 # delay determines speed of the slide 216 time.sleep(speed[mode]) 217 if i == slide_checkin[check]: 218 # check-in for time remaining based on motor steps 219 print("0%d:%d" % (mins_remaining, total_sec_remaining)) 220 print(check) 221 if total_sec_remaining < 10: 222 text_area.text = "%d:0%d" % ( 223 mins_remaining, 224 total_sec_remaining, 225 ) 226 else: 227 text_area.text = "%d:%d" % (mins_remaining, total_sec_remaining) 228 check = check + 1 229 if check > 19: 230 check = 0 231 if end < 10: 232 # displays the stopping graphic for the last 10 secs. 233 minitft.display.show(stopGroup) 234 # changes states after slide has completed 235 kit.stepper1.release() 236 pause = 1 237 onOff = 0 238 stop = 1 239 check = 0 240 # delay for safety 241 time.sleep(2) 242 # shows choice menu 243 minitft.display.show(reverseqGroup) 244 # b is defined to stop the slider 245 # only active if the slider is in the 'stopped' state 246 if buttons.b and b_state == "pressed" and stop == 1: 247 # z defines location of the camera on the slider 248 # 0 means that it is opposite the motor 249 if z == 0: 250 b_state = None 251 time.sleep(1) 252 minitft.display.show(backingUpGroup) 253 # delay for safety 254 time.sleep(2) 255 # brings camera back to 'home' at double speed 256 for i in range(1145): 257 kit.stepper1.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE) 258 time.sleep(1) 259 kit.stepper1.release() 260 # changes states 261 pause = 0 262 stop = 0 263 # 1 means that the camera is next to the motor 264 if z == 1: 265 b_state = None 266 time.sleep(2) 267 # changes states 268 pause = 0 269 stop = 0 270 z = 0 271 # a is defined to slide in reverse of the prev. slide 272 # only active if the slider is in the 'stopped' state 273 if buttons.a and a_state == "pressed" and stop == 1: 274 # z defines location of the camera on the slider 275 # 1 means that the camera is next to the motor 276 if z == 1: 277 a_state = None 278 time.sleep(2) 279 stop = 0 280 pause = 0 281 # 2 allows the 'regular' slide loop to run 282 # as if the 'select' button has been pressed 283 z = 2 284 # 0 means that the camera is opposite the motor 285 if z == 0: 286 a_state = None 287 # same script as the 'regular' slide loop 288 time.sleep(2) 289 minitft.display.show(progBarGroup) 290 press = time.monotonic() 291 print(press) 292 text_area.text = slide_begin[mode] 293 onOff += 1 294 pause = 0 295 stop = 0 296 if onOff > 1: 297 onOff = 0 298 for i in range(17200): 299 start = time.monotonic() 300 real_time = start - press 301 end = slide_duration[mode] - real_time 302 mins_remaining = end / 60 303 if mins_remaining < 0: 304 mins_remaining += 60 305 total_sec_remaining = mins_remaining * 60 306 mins_remaining, total_sec_remaining = divmod(end, 60) 307 # only difference is that the motor is stepping backwards 308 kit.stepper1.onestep( 309 direction=stepper.BACKWARD, style=stepper.MICROSTEP 310 ) 311 time.sleep(speed[mode]) 312 if i == slide_checkin[check]: 313 print("0%d:%d" % (mins_remaining, total_sec_remaining)) 314 if total_sec_remaining < 10: 315 text_area.text = "%d:0%d" % ( 316 mins_remaining, 317 total_sec_remaining, 318 ) 319 else: 320 text_area.text = "%d:%d" % (mins_remaining, total_sec_remaining) 321 check = check + 1 322 if check > 19: 323 check = 0 324 if end < 10: 325 minitft.display.show(stopGroup) 326 # state changes 327 kit.stepper1.release() 328 pause = 1 329 onOff = 0 330 stop = 1 331 z = 1 332 check = 0 333 time.sleep(2) 334 minitft.display.show(reverseqGroup)