diff --git a/Makefile b/Makefile index 1c2ffe66..24573c73 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ BETA_PKG_NAME := bbctrl-$(BETA_VERSION) SUBPROJECTS := avr boot pwr2 jig SUBPROJECTS := $(patsubst %,src/%,$(SUBPROJECTS)) +$(info SUBPROJECTS="$(SUBPROJECTS)") WATCH := src/pug src/pug/templates src/stylus src/js src/resources Makefile WATCH += src/static diff --git a/src/avr/Makefile b/src/avr/Makefile index 53b7c964..5ac6ad10 100644 --- a/src/avr/Makefile +++ b/src/avr/Makefile @@ -1,6 +1,6 @@ # Makefile for the project Bulidbotics firmware PROJECT = bbctrl-avr-firmware -MCU = atxmega192a3u +MCU = atxmega256a3u CLOCK = 32000000 # SRC diff --git a/src/avr/src/config.h b/src/avr/src/config.h index e9f77a78..69209571 100644 --- a/src/avr/src/config.h +++ b/src/avr/src/config.h @@ -142,7 +142,7 @@ enum { #define STEP_TIMER_POLL ((uint16_t)(STEP_TIMER_FREQ * 0.001)) // 1ms #define STEP_TIMER_ISR TCC0_OVF_vect #define STEP_LOW_LEVEL_ISR ADCB_CH0_vect -#define STEP_PULSE_WIDTH (F_CPU * 0.000002) // 2uS w/ clk/1 .. modified to 10uS by doug +#define STEP_PULSE_WIDTH (F_CPU * 0.000002) // 2uS w/ clk/1 #define SEGMENT_MS 4 #define SEGMENT_TIME (SEGMENT_MS / 60000.0) // mins diff --git a/src/avr/src/motor.c b/src/avr/src/motor.c index 8509c240..c69639fe 100644 --- a/src/avr/src/motor.c +++ b/src/avr/src/motor.c @@ -60,6 +60,7 @@ typedef struct { uint16_t microsteps; // microsteps per full step bool reverse; bool enabled; + float pulse_length; // length of step pulses in microseconds float step_angle; // degrees per whole step float travel_rev; // mm or deg of travel per motor revolution float min_soft_limit; @@ -178,6 +179,15 @@ void motor_init() { } +float get_pulse_length(int motor) {return motors[motor].pulse_length;} + + +void set_pulse_length(int motor, float value) { + motors[motor].pulse_length = value; + motors[motor].timer->CCA = value * F_CPU; +} + + bool motor_is_enabled(int motor) {return motors[motor].enabled;} int motor_get_axis(int motor) {return motors[motor].axis;} diff --git a/src/avr/src/oled.c b/src/avr/src/oled.c index 5e236803..c52b96ce 100644 --- a/src/avr/src/oled.c +++ b/src/avr/src/oled.c @@ -139,6 +139,6 @@ void oled_splash() { oled_init(); _writeStringAt((char *) "Controller booting",1,5); _writeStringAt((char *) "Please wait...",3,5); - _writeStringAt((char *) "(c) Buildbotics LLC",4,5); + _writeStringAt((char *) "(c) Buildbotics LLC",5,5); _delay_us(100); }; diff --git a/src/avr/src/vars.def b/src/avr/src/vars.def index 6894a81b..27444478 100644 --- a/src/avr/src/vars.def +++ b/src/avr/src/vars.def @@ -39,6 +39,7 @@ VAR(motor_axis, an, u8, MOTORS, 1, 1) // Maps motor to axis VAR(motor_enabled, me, b8, MOTORS, 1, 1) // Motor enabled +VAR(pulse_length, pl, f32, MOTORS, 1, 1) // length of step pulses VAR(drive_current, dc, f32, MOTORS, 1, 1) // Max motor drive current VAR(idle_current, ic, f32, MOTORS, 1, 1) // Motor idle current diff --git a/src/boot/Makefile b/src/boot/Makefile index c09a60e5..2c347f53 100644 --- a/src/boot/Makefile +++ b/src/boot/Makefile @@ -1,6 +1,6 @@ # Makefile for the project Bulidbotics bootloader PROJECT = bbctrl-avr-boot -MCU = atxmega192a3u +MCU = atxmega256a3u CLOCK = 32000000 TARGET = $(PROJECT).elf @@ -19,7 +19,7 @@ CFLAGS += -Isrc # Linker flags LDFLAGS += $(COMMON) -Wl,-u,vfprintf -lprintf_flt -lm -LDFLAGS += -Wl,--section-start=.text=0x030000 +LDFLAGS += -Wl,--section-start=.text=0x040000 LIBS += -lm # Programming flags diff --git a/src/js/settings-motor.js b/src/js/settings-motor.js index 84eb4805..eaad44e2 100644 --- a/src/js/settings-motor.js +++ b/src/js/settings-motor.js @@ -54,12 +54,17 @@ module.exports = { }, - maxStepsPerSecond: function () {return 250000}, + maxStepsPerSecond: function () {return (0.5 / this.motor['step-length'])}, - maxMaxVelocity: function () { // In meters per minute - let metersPerUStep = this.umPerStep / this.motor.microsteps / 1000000 - return 1 * (this.maxStepsPerSec * 60 * metersPerUStep).toFixed(3) + maxMaxVelocity: function () { + let maxUStepsPerSecond = 0.5 / this.motor['step-length']; + let uStepsPerRevolution = + (360.0 / this.motor['step-angle']) * this.motor['microsteps']; + let maxRPS = maxUStepsPerSecond / uStepsPerRevolution; + + return parseFloat((maxRPS * 60.0 * this.motor['travel-per-rev'] / 1000) + .toFixed(3)); // returns max vel in meters / minute }, @@ -119,6 +124,10 @@ module.exports = { events: { 'input-changed': function() { Vue.nextTick(function () { + // set step length to default of 2ms if user selects internal drivers + if (this.motor['type-of-driver'] == 'internal') + this.$set('motor["step-length"]', 0.000002); + // Limit max-velocity if (this.invalidMaxVelocity) this.$set('motor["max-velocity"]', this.maxMaxVelocity); @@ -127,6 +136,7 @@ module.exports = { if (this.invalidStallVelocity) this.$set('motor["search-velocity"]', this.maxStallVelocity); + this.$dispatch('config-changed'); }.bind(this)) return true; @@ -136,8 +146,34 @@ module.exports = { methods: { show: function (name, templ) { + if (name == 'step-length' && this.motor['type-of-driver'] == 'internal') + return false; + + if (this.motor['type-of-driver'] == 'generic external' && + name == 'homing-mode') return false; + + if (this.motor['type-of-driver'] == 'internal' && + name == 'homing-mode-external') return false; + + if ((this.motor['type-of-driver'] == 'generic external') && + ['stall-microstep', 'stall-volts', 'stall-sample-time', + 'stall-current'].includes(name)) return false; + if (templ.hmodes == undefined) return true; - return templ.hmodes.indexOf(this.motor['homing-mode']) != -1; + + if (this.motor['type-of-driver'] == 'internal') + return templ.hmodes.indexOf(this.motor['homing-mode']) != -1; + + return templ.hmodes.indexOf(this.motor['homing-mode-external']) != -1; + }, + + + showCategory: function (name) { + if (name == 'power' && this.motor['type-of-driver'] == 'generic external') + return false + + return true; } } + } diff --git a/src/pug/templates/settings-motor.pug b/src/pug/templates/settings-motor.pug index 05b44f1d..6f0450a7 100644 --- a/src/pug/templates/settings-motor.pug +++ b/src/pug/templates/settings-motor.pug @@ -30,7 +30,7 @@ script#settings-motor-template(type="text/x-template") h1 Motor {{index}} Configuration .pure-form.pure-form-aligned - fieldset(v-for="category in template.motors.template", :class="$key") + fieldset(v-for="category in template.motors.template", v-if='showCategory($key)', :class="$key") h2 {{$key}} templated-input(v-for="templ in category", v-if="show($key, templ)", diff --git a/src/py/bbctrl/Comm.py b/src/py/bbctrl/Comm.py index 18f26939..2efd34d4 100644 --- a/src/py/bbctrl/Comm.py +++ b/src/py/bbctrl/Comm.py @@ -265,7 +265,6 @@ def connect(self): try: # Resume once current queue of GCode commands has flushed self.queue_command(Cmd.RESUME) - self.queue_command(Cmd.set('ct', 128)) self.queue_command(Cmd.HELP) # Load AVR commands and variables except Exception as e: diff --git a/src/py/bbctrl/LCD.py b/src/py/bbctrl/LCD.py index 026d94e4..8fd84bfc 100644 --- a/src/py/bbctrl/LCD.py +++ b/src/py/bbctrl/LCD.py @@ -54,10 +54,10 @@ def __init__(self, ctrl): self.screen = self.new_screen() try: - self.oled = OLED(self.ctrl) - except: - pass + self.oled = OLED(self.ctrl) + except: pass self.wrote_to_oled = False + self.set_message('Loading...') self._redraw(False) @@ -122,12 +122,10 @@ def _redraw(self, now = True): def _update(self): self.timeout = None try: - self.oled - self.oled.writePage(self.page.data) - self.wrote_to_oled = True - return - except: - self.wrote_to_oled = False + self.oled.writePage(self.page.data) + self.wrote_to_oled = True + return + except: pass try: if self.lcd is None: diff --git a/src/py/bbctrl/oled.py b/src/py/bbctrl/oled.py index e10d7c8f..2ba1baee 100644 --- a/src/py/bbctrl/oled.py +++ b/src/py/bbctrl/oled.py @@ -2,7 +2,7 @@ # # # This file is part of the Buildbotics firmware. # # # -# Copyright (c) 2015 - 2021, Buildbotics LLC, All rights reserved. # +# Copyright (c) 2015 - 2023, Buildbotics LLC, All rights reserved. # # # # This Source describes Open Hardware and is licensed under the # # CERN-OHL-S v2. # @@ -24,40 +24,178 @@ # For more information, email info@buildbotics.com # # # ################################################################################ - import time -from luma.core.interface.serial import i2c -from luma.oled.device import ssd1306 -from luma.core.render import canvas -from PIL import Image +import errno + +try: + try: + import smbus + except: + import smbus2 as smbus +except: + smbus = None __all__ = ['OLED'] +fontTable = {" ": [0x00, 0x00, 0x00, 0x00, 0x00], + "!": [0x00, 0x00, 0x2f, 0x00, 0x00], + '"': [0x00, 0x07, 0x00, 0x07, 0x00], + "#": [0x14, 0x7f, 0x14, 0x7f, 0x14], + "$": [0x24, 0x2a, 0x7f, 0x2a, 0x12], + "%": [0x23, 0x13, 0x08, 0x64, 0x62], + "&": [0x36, 0x49, 0x55, 0x22, 0x50], + "'": [0x00, 0x05, 0x03, 0x00, 0x00], + "(": [0x00, 0x1c, 0x22, 0x41, 0x00], + ")": [0x00, 0x41, 0x22, 0x1c, 0x00], + "*": [0x14, 0x08, 0x3E, 0x08, 0x14], + "+": [0x08, 0x08, 0x3E, 0x08, 0x08], + ",": [0x00, 0x00, 0xA0, 0x60, 0x00], + "-": [0x08, 0x08, 0x08, 0x08, 0x08], + ".": [0x00, 0x60, 0x60, 0x00, 0x00], + "/": [0x20, 0x10, 0x08, 0x04, 0x02], + "0": [0x3E, 0x51, 0x49, 0x45, 0x3E], + "1": [0x00, 0x42, 0x7F, 0x40, 0x00], + "2": [0x42, 0x61, 0x51, 0x49, 0x46], + "3": [0x21, 0x41, 0x45, 0x4B, 0x31], + "4": [0x18, 0x14, 0x12, 0x7F, 0x10], + "5": [0x27, 0x45, 0x45, 0x45, 0x39], + "6": [0x3C, 0x4A, 0x49, 0x49, 0x30], + "7": [0x01, 0x71, 0x09, 0x05, 0x03], + "8": [0x36, 0x49, 0x49, 0x49, 0x36], + "9": [0x06, 0x49, 0x49, 0x29, 0x1E], + ":": [0x00, 0x36, 0x36, 0x00, 0x00], + ";": [0x00, 0x56, 0x36, 0x00, 0x00], + "<": [0x08, 0x14, 0x22, 0x41, 0x00], + "=": [0x14, 0x14, 0x14, 0x14, 0x14], + ">": [0x00, 0x41, 0x22, 0x14, 0x08], + "?": [0x02, 0x01, 0x51, 0x09, 0x06], + "@": [0x32, 0x49, 0x59, 0x51, 0x3E], + "A": [0x7C, 0x12, 0x11, 0x12, 0x7C], + "B": [0x7F, 0x49, 0x49, 0x49, 0x36], + "C": [0x3E, 0x41, 0x41, 0x41, 0x22], + "D": [0x7F, 0x41, 0x41, 0x22, 0x1C], + "E": [0x7F, 0x49, 0x49, 0x49, 0x41], + "F": [0x7F, 0x09, 0x09, 0x09, 0x01], + "G": [0x3E, 0x41, 0x49, 0x49, 0x7A], + "H": [0x7F, 0x08, 0x08, 0x08, 0x7F], + "I": [0x00, 0x41, 0x7F, 0x41, 0x00], + "J": [0x20, 0x40, 0x41, 0x3F, 0x01], + "K": [0x7F, 0x08, 0x14, 0x22, 0x41], + "L": [0x7F, 0x40, 0x40, 0x40, 0x40], + "M": [0x7F, 0x02, 0x0C, 0x02, 0x7F], + "N": [0x7F, 0x04, 0x08, 0x10, 0x7F], + "O": [0x3E, 0x41, 0x41, 0x41, 0x3E], + "P": [0x7F, 0x09, 0x09, 0x09, 0x06], + "Q": [0x3E, 0x41, 0x51, 0x21, 0x5E], + "R": [0x7F, 0x09, 0x19, 0x29, 0x46], + "S": [0x46, 0x49, 0x49, 0x49, 0x31], + "T": [0x01, 0x01, 0x7F, 0x01, 0x01], + "U": [0x3F, 0x40, 0x40, 0x40, 0x3F], + "V": [0x1F, 0x20, 0x40, 0x20, 0x1F], + "W": [0x3F, 0x40, 0x38, 0x40, 0x3F], + "X": [0x63, 0x14, 0x08, 0x14, 0x63], + "Y": [0x07, 0x08, 0x70, 0x08, 0x07], + "Z": [0x61, 0x51, 0x49, 0x45, 0x43], + "[": [0x00, 0x7F, 0x41, 0x41, 0x00], + "\\": [0x55, 0xAA, 0x55, 0xAA, 0x55], + "]": [0x00, 0x41, 0x41, 0x7F, 0x00], + "^": [0x04, 0x02, 0x01, 0x02, 0x04], + "_": [0x40, 0x40, 0x40, 0x40, 0x40], + "`": [0x00, 0x03, 0x05, 0x00, 0x00], + "a": [0x20, 0x54, 0x54, 0x54, 0x78], + "b": [0x7F, 0x48, 0x44, 0x44, 0x38], + "c": [0x38, 0x44, 0x44, 0x44, 0x20], + "d": [0x38, 0x44, 0x44, 0x48, 0x7F], + "e": [0x38, 0x54, 0x54, 0x54, 0x18], + "f": [0x08, 0x7E, 0x09, 0x01, 0x02], + "g": [0x18, 0xA4, 0xA4, 0xA4, 0x7C], + "h": [0x7F, 0x08, 0x04, 0x04, 0x78], + "i": [0x00, 0x44, 0x7D, 0x40, 0x00], + "j": [0x40, 0x80, 0x84, 0x7D, 0x00], + "k": [0x7F, 0x10, 0x28, 0x44, 0x00], + "l": [0x00, 0x41, 0x7F, 0x40, 0x00], + "m": [0x7C, 0x04, 0x18, 0x04, 0x78], + "n": [0x7C, 0x08, 0x04, 0x04, 0x78], + "o": [0x38, 0x44, 0x44, 0x44, 0x38], + "p": [0xFC, 0x24, 0x24, 0x24, 0x18], + "q": [0x18, 0x24, 0x24, 0x18, 0xFC], + "r": [0x7C, 0x08, 0x04, 0x04, 0x08], + "s": [0x48, 0x54, 0x54, 0x54, 0x20], + "t": [0x04, 0x3F, 0x44, 0x40, 0x20], + "u": [0x3C, 0x40, 0x40, 0x20, 0x7C], + "v": [0x1C, 0x20, 0x40, 0x20, 0x1C], + "w": [0x3C, 0x40, 0x30, 0x40, 0x3C], + "x": [0x44, 0x28, 0x10, 0x28, 0x44], + "y": [0x1C, 0xA0, 0xA0, 0xA0, 0x7C], + "z": [0x44, 0x64, 0x54, 0x4C, 0x44], + "{": [0x00, 0x10, 0x7C, 0x82, 0x00], + "|": [0x00, 0x00, 0xFF, 0x00, 0x00], + "}": [0x00, 0x82, 0x7C, 0x10, 0x00], + "~": [0x00, 0x06, 0x09, 0x09, 0x06] #degrees symbol + } + class OLED: + def __init__(self,ctrl): + self.ctrl = ctrl + self.log = ctrl.log.get('oled') + self.i2c_bus = None + self.ft = fontTable + block = [0xae, 0xd5, 0x80, 0xa8, 0x3f, 0xd3, 0x00, 0x40 | 0, + 0x8d, 0x14, 0x20, 0x00, 0xa0 | 1, 0xc8, 0xda, 0x12, 0x81, + 0x80, 0xd9, 0xf1, 0xdb, 0x20, 0xa4, 0xa6, 0xaf] + self.connect() + self.i2c_bus.write_i2c_block_data(0x3c, 0, block) + time.sleep(.0001) + self.clear_block = [] + i = 0 + while i < 32: + self.clear_block.append(0x00) + i = i + 1 + self.oled_clear(); - def __init__(self,ctrl): - self.log = ctrl.log.get('OLED') - self.device = 0 - try: - self.device = ssd1306(i2c(port=1, address=0x3c), width = 128, height=64, rotate=0) - self.device.contrast(1) - except: - pass - - def write(self,message="hello",col=0,row=0): - with canvas(self.device,dither=True) as draw: - text_size = draw.textsize(message) - draw.text((row,col * 8),message,fill='white') - - def writePage(self,page): - with canvas(self.device,dither=True) as draw: - j = 0 - while j < 4: - s = "" - i = 0 - while i < 20: - s = s + str(page[i][j]) + def connect(self): + if self.i2c_bus is None: + self.i2c_bus = smbus.SMBus(1) + + def gotorowcol(self,row,col): + block = [0x21,col,0x7f,0x22,row,0x7] + self.i2c_bus.write_i2c_block_data(0x3c, 0, block) + time.sleep(.0001) + + def oled_clear(self): + self.connect() + self.gotorowcol(0,0) + i = 0 + while i < 32: + self.i2c_bus.write_i2c_block_data(0x3c, 0x40, self.clear_block) + time.sleep(0.0001) + i = i + 1 + + def writeStringAt(self,s,row,col): + self.connect() + self.gotorowcol(row,col) + i = 0 + while (i < len(s)): + d = self.ft[s[i]] + block = [] + j = 0 + while j < 5: + block.append(d[j]) + j = j + 1 i = i + 1 - text_size = draw.textsize(s) - draw.text((0,5 + j*12),s,fill='white') - j = j + 1 + self.i2c_bus.write_i2c_block_data(0x3c, 0x40, block) + + def writePage(self,data): + self.connect() + i = 0 + while i < len(data[i]): + s = "" + j = 0 + while j < len(data): + s = s + data[j][i] + j = j + 1 + self.writeStringAt(s,2*i + 1,5) + i = i + 1 + + def get(self,c): return fontTable[c] + diff --git a/src/resources/config-template.json b/src/resources/config-template.json index 88617f46..bcc11cd6 100644 --- a/src/resources/config-template.json +++ b/src/resources/config-template.json @@ -46,7 +46,21 @@ "code": "an" } }, - + "driver": { + "type-of-driver": { + "type": "enum", + "values": ["internal","generic external"], + "default": "internal", + "code": "dt" + }, + "step-length": { + "type": "float", + "min": 0, + "unit": "seconds", + "default": 0.000002, + "code": "pl" + } + }, "power": { "enabled": { "type": "bool", @@ -150,6 +164,12 @@ }, "homing": { + "homing-mode-external": { + "type": "enum", + "values": ["manual", "switch-min", "switch-max"], + "default": "manual", + "code": "ho" + }, "homing-mode": { "type": "enum", "values": [