def samplesToFLP(dtxypower, xymmToDac=None): clock_Hz = 60e3 xytickspmm = float(0xffff) / 125 lastPower = None xyticks = [] import numpy as np dtxypower = np.asarray(dtxypower) from OpenFL import FLP result = FLP.Packets() result.append(FLP.TimeRemaining(int(sum(dtxypower[:, 0])))) import numpy as np if xymmToDac is None: tickspmm = float(0xffff) / 125.0 midticks = float(0xffff) / 2 xyToTicks = np.array([[tickspmm, 0, midticks], [0, tickspmm, midticks], [0, 0, 1]]) def xymmToDac(x_mm, y_mm): xy_ticks = xyToTicks.dot((x_mm, y_mm, 1)) x_ticks, y_ticks = xy_ticks[:2] / xy_ticks[-1] return x_ticks, y_ticks for dt_s, x_mm, y_mm, power in dtxypower: #power = mWToNumber(power) if power != lastPower: if xyticks: result.append(FLP.XYMove(xyticks)) xyticks = [] result.append(FLP.LaserPowerLevel(power)) lastPower = power xy_ticks = xymmToDac(x_mm, y_mm) dt_ticks = dt_s * clock_Hz # Deal with potential that the move takes too long to fit in one step: for i in range(int(dt_ticks // 0xffff)): alpha = (i + 1) * 0xffff / dt_ticks x = np.interp(alpha, [0.0, 1.0], [lastxy_ticks[0], xy_ticks[0]]) y = np.interp(alpha, [0.0, 1.0], [lastxy_ticks[1], xy_ticks[1]]) xyticks.append((x, y, 0xffff)) dt_ticks %= 0xffff # Now we just have to do the last little bit. xyticks.append(tuple(xy_ticks) + (dt_ticks, )) lastxy_ticks = xy_ticks if xyticks: result.append(FLP.XYMove(xyticks)) return result
def insert_pause_before(layer, zJog_mm=100, buttonPressMessage="Press to continue."): """ Jog up and wait on button press then resume. This is done when the tilt motor is at its lowest. """ import numpy as np tiltMoves = [x for x in layer if isinstance(x, FLP.TiltMove)] bestAfter = np.argmax(np.cumsum([move.usteps for move in tiltMoves])) lowestTiltMove_i = layer.index(tiltMoves[bestAfter]) insertBefore_i = None zSpeed_usteps_per_s = None zCurrent = None for x in layer[:lowestTiltMove_i]: if isinstance(x, FLP.ZFeedRate): zSpeed_usteps_per_s = x.feedrate if isinstance(x, FLP.ZCurrent): zCurrent = x.current for i in range(lowestTiltMove_i, len(layer)): if isinstance(layer[i], FLP.WaitForMovesToComplete): insertBefore_i = 1 + i break assert insertBefore_i is not None # Now we know where the motors are stopped and tilt is at its lowest. pauseCycle = FLP.Packets() zJog_usteps = int(zJog_mm * FLP.ZMove.usteps_up_per_mm) zJog_mmps = 10.0 pauseCycle.append(FLP.ZCurrent(FLP.ZCurrent.moving_current)) pauseCycle.append(FLP.ZFeedRate(zJog_mmps * abs(FLP.ZMove.usteps_up_per_mm))) pauseCycle.append(FLP.ZMove(zJog_usteps)) pauseCycle.append(FLP.WaitForMovesToComplete()) pauseCycle.append(FLP.WaitButtonPress(buttonPressMessage)) pauseCycle.append(FLP.ZMove(-zJog_usteps)) pauseCycle.append(FLP.WaitForMovesToComplete()) # Restore settings: pauseCycle.append(FLP.ZCurrent(zCurrent)) if zSpeed_usteps_per_s is not None: pauseCycle.append(FLP.ZFeedRate(zSpeed_usteps_per_s)) newLayer = layer[:insertBefore_i] + pauseCycle + layer[insertBefore_i:] return newLayer
def samples_to_FLP(self, xy_mm_dts_s_mW, max_mm=5.0): import FLP clock_Hz = FLP.XYMoveClockRate.moverate_Hz() xyticks = [] import numpy as np xy_mm_dts_s_mW = np.asarray(xy_mm_dts_s_mW) result = FLP.Packets() xydtmW = self.sample_line_segments_mm_s( start_xy_mm=xy_mm_dts_s_mW[0, :2], xys_mm=xy_mm_dts_s_mW[1:, :2], dts_s=xy_mm_dts_s_mW[1:, 2], mWs=xy_mm_dts_s_mW[1:, 3], max_mm=5.0) # Use the starting row, then interpolate elsewhere. xydtmW = np.vstack([ xy_mm_dts_s_mW[:1], np.hstack([xydtmW[:, :2], xydtmW[:, 2:3], xydtmW[:, 3:4]]) ]) last_mW = None lastxy_ticks = self.mm_to_galvo(xydtmW[0][0], xydtmW[0][1]) for x_mm, y_mm, dt_s, mW in xydtmW: if mW != last_mW: if xyticks: result.append(FLP.XYMove(xyticks)) xyticks = [] result.append(FLP.LaserPowerLevel(self.mW_to_ticks(mW))) last_mW = mW xy_ticks = self.mm_to_galvo(x_mm, y_mm) dt_ticks = dt_s * clock_Hz # Deal with potential that the move takes too long to fit in one step: for i in range(int(dt_ticks // 0xffff)): alpha = (i + 1) * 0xffff / dt_ticks x = np.interp(alpha, [0.0, 1.0], [lastxy_ticks[0], xy_ticks[0]]) y = np.interp(alpha, [0.0, 1.0], [lastxy_ticks[1], xy_ticks[1]]) xyticks.append((x, y, 0xffff)) dt_ticks %= 0xffff # Now we just have to do the last little bit. xyticks.append(tuple(xy_ticks) + (dt_ticks, )) lastxy_ticks = xy_ticks if xyticks: result.append(FLP.XYMove(xyticks)) return result
def midi2flp(midifilename, quarternote_s=0.25, skip_leading_rests=True): """ Given a midi file, return a list of FLP.Packets objects, one for each track. """ mf = music21.midi.MidiFile() mf.open(midifilename) mf.read() soundstream = music21.midi.translate.midiFileToStream(mf) tracks = [] for track in soundstream.elements: x = [ x for x in track.flat.elements if isinstance(x, (music21.note.Note, music21.note.Rest)) ] pitchtime = [] for thing in x: if isinstance(thing, music21.note.Rest): pitchtime.append((0, float(thing.duration.quarterLength))) else: pitchtime.append((thing.pitch.frequency, float(thing.duration.quarterLength))) packets = F.Packets([ F.ZCurrent(80), ]) for i, (Hz, time) in enumerate(pitchtime): time *= quarternote_s if Hz == 0: if i != 0 and skip_leading_rests: # Don't start with a rest. packets.append(F.Dwell(s=time)) else: ufreq = Hz * 8 packets += [ F.ZFeedRate(ufreq), F.ZMove(-int(ufreq * 0.5 * float(time))), F.WaitForMovesToComplete(), F.ZMove(int(ufreq * 0.5 * float(time))), F.WaitForMovesToComplete() ] tracks.append(packets) return tracks
def to_flp(stipples, dpi=300, x_mm=0, y_mm=0, laser_pwr=35000, ticks=500, base=100): """" Converts a set of stipples into a list of FLP packets dpi is the image's DPI x_mm and y_mm are the corner location of the image (default 0,0) (where 0,0 is the center of the build platform) laser_power is the laser's power level in ticks ticks is the number of frames the laser spends a black point base is the number of frames the laser spends on a white point """ # Accumulated list of FLP packets packets = F.Packets() # Sort by X to reduce the amount of laser moves necessary stipples = sorted(stipples, key=lambda s: s[0]) # Draw stuff for every point for x, y, i in stipples: # Center position in mm x = mm_to_pos(x / float(dpi) * 25.4 + x_mm) y = mm_to_pos(y / float(dpi) * 25.4 + y_mm) # Decide how long to stay on this point (longer time = darker point) t = int(ceil((ticks - base) * (1 - i)) + base) if t == 0: continue # Move to this stipple's location with the laser off, then pause # briefly to let the controller stabilize packets.append(F.LaserPowerLevel(0)) packets.append(F.XYMove([[x, y, 200], [x, y, 100]])) # Draw the spot with the laser on packets.append(F.LaserPowerLevel(laser_pwr)) packets.append(F.XYMove([[x, y, t]])) return packets
from OpenFL import Printer, FLP import os from datetime import datetime #create directory and change to new directory blocksDir = os.path.join(os.getcwd(), "blocks", datetime.now().strftime('%Y-%m-%d_%H-%M')) try: os.makedirs(blocksDir) except: pass os.chdir(blocksDir) startTime = datetime.now() print("start time is " + str(startTime)) p = Printer.Printer() lastBlock = len(p.list_blocks()) - 1 layerNum = 0 while layerNum <= lastBlock: layerStartTime = datetime.now() block = p.read_block_flp(layerNum) FLP.Packets(block).tofile(str(layerNum).zfill(8) + '.flp') print("block # " + str(layerNum) + " out of " + str(lastBlock) + " saved in " + str(datetime.now() - layerStartTime)) layerNum += 1 print("Total time to complete script was " + str(datetime.now() - startTime))