Merge pull request #84 from saifullah-N/v1.3.0

V1.3.0
This commit is contained in:
ControlledImpedance
2023-09-03 20:36:56 -04:00
committed by GitHub
19 changed files with 185 additions and 67 deletions

2
.gitignore vendored
View File

@@ -23,6 +23,6 @@ __pycache__
/package-lock.json /package-lock.json
/src/bbserial/linux-rpi-raspberrypi-kernel* /src/bbserial/linux-rpi-raspberrypi-kernel*
/src/bbserial/raspberrypi-kernel* /src/bbserial/raspberrypi-kernel*
*.rej
*.elf *.elf
*.hex *.hex

View File

@@ -26,7 +26,7 @@ PKG_NAME := bbctrl-$(VERSION)
SUBPROJECTS := avr boot pwr jig SUBPROJECTS := avr boot pwr jig
ifndef HOST ifndef HOST
HOST=onefinity HOST=onefinity.local
endif endif
ifndef PASSWORD ifndef PASSWORD

View File

@@ -1,6 +1,6 @@
{ {
"name": "bbctrl", "name": "bbctrl",
"version": "1.2.1", "version": "1.3.0",
"homepage": "https://onefinitycnc.com/", "homepage": "https://onefinitycnc.com/",
"repository": "https://github.com/OneFinityCNC/onefinity", "repository": "https://github.com/OneFinityCNC/onefinity",
"license": "GPL-3.0+", "license": "GPL-3.0+",

View File

@@ -3,6 +3,7 @@
cd /mnt/host cd /mnt/host
scons -j 8 -C cbang disable_local="re2 libevent" scons -j 8 -C cbang disable_local="re2 libevent"
export CBANG_HOME="/mnt/host/cbang" export CBANG_HOME="/mnt/host/cbang"
export LC_ALL=C
CAMOTICS_ROOT="/mnt/host/camotics" CAMOTICS_ROOT="/mnt/host/camotics"
CAMOTICS_PLAN="${CAMOTICS_ROOT}/src/gcode/plan" CAMOTICS_PLAN="${CAMOTICS_ROOT}/src/gcode/plan"

View File

@@ -58,6 +58,7 @@ typedef enum
SPINDLE_TYPE_SUNFAR_E300, SPINDLE_TYPE_SUNFAR_E300,
SPINDLE_TYPE_OMRON_MX2, SPINDLE_TYPE_OMRON_MX2,
SPINDLE_TYPE_V70, SPINDLE_TYPE_V70,
SPINDLE_TYPE_PWNCNC,
} spindle_type_t; } spindle_type_t;
typedef void (*deinit_cb_t)(); typedef void (*deinit_cb_t)();

View File

@@ -29,7 +29,6 @@
#include "modbus.h" #include "modbus.h"
#include "rtc.h" #include "rtc.h"
#include "config.h" #include "config.h"
#include "estop.h"
#include "pgmspace.h" #include "pgmspace.h"
#include <util/atomic.h> #include <util/atomic.h>
@@ -49,6 +48,7 @@ typedef enum
REG_FREQ_SET, REG_FREQ_SET,
REG_FREQ_SIGN_SET, REG_FREQ_SIGN_SET,
REG_FREQ_SCALED_SET,
REG_STOP_WRITE, REG_STOP_WRITE,
REG_FWD_WRITE, REG_FWD_WRITE,
@@ -170,6 +170,18 @@ const vfd_reg_t v70_regs[] PROGMEM = {
{REG_DISABLED}, {REG_DISABLED},
}; };
const vfd_reg_t pwncnc_regs[] PROGMEM = {
{REG_MAX_FREQ_READ, 0x0007, 0}, // Read max frequency
{REG_FREQ_SCALED_SET, 0xa001, 10000}, // Set scaled frequency
{REG_FREQ_READ, 0x9000, 0}, // Read frequency
{REG_FWD_WRITE, 0xa000, 1}, // Run forward
{REG_REV_WRITE, 0xa000, 2}, // Run reverse
{REG_STOP_WRITE, 0xa000, 5}, // Stop
{REG_DISCONNECT_WRITE, 0xa000, 5}, // Stop
{REG_STATUS_READ, 0xb000, 0}, // Read status
{REG_DISABLED},
};
static vfd_reg_t regs[VFDREG]; static vfd_reg_t regs[VFDREG];
static vfd_reg_t custom_regs[VFDREG]; static vfd_reg_t custom_regs[VFDREG];
@@ -209,8 +221,7 @@ static bool _next_state()
else else
vfd.state = REG_FREQ_SET; vfd.state = REG_FREQ_SET;
break; break;
case REG_FREQ_SCALED_SET:
case REG_FREQ_SIGN_SET:
if (vfd.power < 0) if (vfd.power < 0)
vfd.state = REG_REV_WRITE; vfd.state = REG_REV_WRITE;
else if (0 < vfd.power) else if (0 < vfd.power)
@@ -219,6 +230,15 @@ static bool _next_state()
vfd.state = REG_STOP_WRITE; vfd.state = REG_STOP_WRITE;
break; break;
// case REG_FREQ_SIGN_SET:
// if (vfd.power < 0)
// vfd.state = REG_REV_WRITE;
// else if (0 < vfd.power)
// vfd.state = REG_FWD_WRITE;
// else
// vfd.state = REG_STOP_WRITE;
// break;
case REG_STOP_WRITE: case REG_STOP_WRITE:
case REG_FWD_WRITE: case REG_FWD_WRITE:
case REG_REV_WRITE: case REG_REV_WRITE:
@@ -226,7 +246,8 @@ static bool _next_state()
break; break;
case REG_STATUS_READ: case REG_STATUS_READ:
if (vfd.shutdown || estop_triggered()) // if (vfd.shutdown || estop_triggered()) vfd.state = REG_DISCONNECT_WRITE;
if (vfd.shutdown)
vfd.state = REG_DISCONNECT_WRITE; vfd.state = REG_DISCONNECT_WRITE;
else if (vfd.changed) else if (vfd.changed)
@@ -289,7 +310,8 @@ static void _modbus_cb(bool ok, uint16_t addr, uint16_t value)
{ {
if (regs[vfd.reg].fails < 255) if (regs[vfd.reg].fails < 255)
regs[vfd.reg].fails++; regs[vfd.reg].fails++;
if (vfd.shutdown || estop_triggered()) // if (vfd.shutdown || estop_triggered()) _disconnected();
if (vfd.shutdown)
_disconnected(); _disconnected();
else else
_connect(); _connect();
@@ -373,6 +395,11 @@ static bool _exec_command()
reg.value = vfd.power * vfd.max_freq; reg.value = vfd.power * vfd.max_freq;
break; break;
case REG_FREQ_SCALED_SET:
write = true;
reg.value = fabs(vfd.power) * reg.value;
break;
case REG_CONNECT_WRITE: case REG_CONNECT_WRITE:
case REG_STOP_WRITE: case REG_STOP_WRITE:
case REG_FWD_WRITE: case REG_FWD_WRITE:
@@ -452,6 +479,10 @@ void vfd_spindle_init()
case SPINDLE_TYPE_V70: case SPINDLE_TYPE_V70:
_load(v70_regs); _load(v70_regs);
break; break;
case SPINDLE_TYPE_PWNCNC:
_load(pwncnc_regs);
break;
default: default:
break; break;
} }

View File

@@ -417,6 +417,7 @@ module.exports = new Vue({
delete settings.tool["tool-type"]; delete settings.tool["tool-type"];
this.config["selected-tool-settings"][selected_tool] = settings; this.config["selected-tool-settings"][selected_tool] = settings;
this.display_units = this.config.settings["units"];
try { try {
await api.put("config/save", this.config); await api.put("config/save", this.config);

View File

@@ -91,7 +91,9 @@ module.exports = {
return this.$root.display_units; return this.$root.display_units;
}, },
set: function(value) { set: function(value) {
this.config.settings.units = value;
this.$root.display_units = value; this.$root.display_units = value;
this.$dispatch("config-changed");
} }
}, },

View File

@@ -90,7 +90,7 @@ module.exports = {
}, },
reload: function(file) { reload: function(file) {
if (file == this.file) { if (file != this.file) {
return; return;
} }
this.clear(); this.clear();

View File

@@ -8,7 +8,7 @@ module.exports = {
computed: { computed: {
has_user_value: function () { has_user_value: function () {
var type = this.model["reg-type"]; var type = this.model["reg-type"];
return type.indexOf("write") != -1 || type.indexOf("fixed") != -1; return type.includes("write") || type.includes("fixed") || type.includes("scaled");
}, },
}, },

View File

@@ -27,6 +27,10 @@ module.exports = {
type: "PWM Spindle", type: "PWM Spindle",
name: "Laser (J Tech, etc)", name: "Laser (J Tech, etc)",
}, },
{
id: "pwncnc-vfd",
name: "PwnCNC VFD",
},
{ {
id: "pwm", id: "pwm",
name: "PWM Spindle", name: "PWM Spindle",
@@ -82,6 +86,11 @@ module.exports = {
name: "OMRON MX2", name: "OMRON MX2",
unsupported: true, unsupported: true,
}, },
{
id: "v70-vfd",
name: "V70",
unsupported: true
}
], ],
}; };
}, },

View File

@@ -43,7 +43,7 @@ script#tool-view-template(type="text/x-template")
label.units RPM label.units RPM
fieldset.modbus-program( fieldset.modbus-program(
v-if="is_modbus && this.tool_type != 'HUANYANG VFD'") v-if="is_modbus && tool_type != 'HUANYANG VFD' && tool_type != 'PWNCNC VFD'")
h2 Active Modbus Program h2 Active Modbus Program
p(v-if="$root.modified") p(v-if="$root.modified")
| (Click #[tt(class="save") Save] to activate the selected | (Click #[tt(class="save") Save] to activate the selected
@@ -81,9 +81,7 @@ script#tool-view-template(type="text/x-template")
tr(v-for="(index, reg) in config['modbus-spindle'].regs", tr(v-for="(index, reg) in config['modbus-spindle'].regs",
is="modbus-reg", :index="index", :model.sync="reg", is="modbus-reg", :index="index", :model.sync="reg",
:template="template['modbus-spindle'].regs.template", :template="template['modbus-spindle'].regs.template",
v-if="!index || reg['reg-type'] != 'disabled' || " + v-if="!index || reg['reg-type'] != 'disabled' || config['modbus-spindle'].regs[index - 1]['reg-type'] != 'disabled'")
"config['modbus-spindle'].regs[index - 1]['reg-type'] != " +
"'disabled'")
.notes(v-if="tool_type == 'HUANYANG VFD'") .notes(v-if="tool_type == 'HUANYANG VFD'")
h2 Notes h2 Notes
@@ -380,3 +378,65 @@ script#tool-view-template(type="text/x-template")
| |
| and spindle type. The VFD must be rebooted after changing | and spindle type. The VFD must be rebooted after changing
| the above settings. | the above settings.
.notes(v-if="tool_type.startsWith('V70')")
h2 Notes
p Set the following using the VFD's front panel.
table.modbus-regs.fixed-regs
tr
th Address
th Value
th Meaning
th Description
tr
td.reg-addr F001
td.reg-value 2
td Communication port
td Control mode
tr
td.reg-addr P0.0.04
td.reg-value 9
td Modbus
td Frequency source A
tr
td.reg-addr P0.1.00
td.reg-value 0
td Source A
td Frequency source
tr
td.reg-addr P4.1.00
td.reg-value 3
td 9600 BAUD
td Must match #[tt baud] above
tr
td.reg-addr F002
td.reg-value 2
td Communication port
td Frequency setting selection
tr
td.reg-addr F163
td.reg-value 1
td Slave address
td Must match #[tt bus-id] above
tr
td.reg-addr F164
td.reg-value 1
td 9600 BAUD
td Must match #[tt baud] above
tr
td.reg-addr F165
td.reg-value 3
td 8 data, no parity, 1 stop, RTU
td Must match #[tt parity] above
p
| Other settings according to the
|
a(href="https://buildbotics.com/upload/vfd/stepperonline-v70.pdf",
target="_blank") Stepper Online V70 VFD manual
.notes(v-if="tool_type.startsWith('PWNCNC')")
h2 Notes
p For support and more information about the PwnCNC Spindle Kit, please visit #{''}
a(href="https://pwncnc.com/onefinity-controller", target="_blank")
| https://pwncnc.com/onefinity-controller

View File

@@ -43,7 +43,7 @@ class Config(object):
self.values = {} self.values = {}
try: try:
self.version = "1.2.1" self.version = "1.3.0"
# Load config template # Load config template
with open(get_resource('http/config-template.json'), 'r', with open(get_resource('http/config-template.json'), 'r',
@@ -156,6 +156,7 @@ class Config(object):
def _upgrade(self, config): def _upgrade(self, config):
version = config['version'] version = config['version']
version = version.split('b')[0] # Strip off any "beta" suffix version = version.split('b')[0] # Strip off any "beta" suffix
version = version.split('-')[0]
version = tuple(map(int, version.split('.'))) # Break it into a tuple of integers version = tuple(map(int, version.split('.'))) # Break it into a tuple of integers
if version < (1, 0, 7): if version < (1, 0, 7):

View File

@@ -23,7 +23,10 @@ class FileHandler(bbctrl.APIHandler):
filename = self.request.path.split('/')[-1] filename = self.request.path.split('/')[-1]
self.uploadFilename = url_unescape(filename) \ self.uploadFilename = url_unescape(filename) \
.replace('\\', '/') \ .encode("ascii", errors="replace") \
.decode() \
.replace('\\', '_') \
.replace('/', '_') \
.replace('#', '-') \ .replace('#', '-') \
.replace('?', '-') .replace('?', '-')
@@ -71,7 +74,8 @@ class FileHandler(bbctrl.APIHandler):
def get(self, filename): def get(self, filename):
if not filename: if not filename:
raise HTTPError(400, 'Missing filename') raise HTTPError(400, 'Missing filename')
filename = os.path.basename(filename)
filename = os.path.basename(url_unescape(filename))
try: try:
with open(self.get_upload(filename).encode('utf8'), 'r') as f: with open(self.get_upload(filename).encode('utf8'), 'r') as f:

View File

@@ -139,6 +139,12 @@ class Mach(Comm):
if log['msg'] == 'Switch not found': if log['msg'] == 'Switch not found':
self.estop() self.estop()
def _end_cycle(self):
if (self._get_cycle() != 'idle' and self._is_ready()
and not self.planner.is_busy() and not super().is_active()):
self.planner.position_change()
self._set_cycle('idle')
def _update(self, update): def _update(self, update):
# Detect motor faults # Detect motor faults

View File

@@ -32,7 +32,7 @@ import os
import bbctrl import bbctrl
from watchdog.observers import Observer from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler from watchdog.events import FileSystemEventHandler
import glob
class UploadChangeHandler(FileSystemEventHandler): class UploadChangeHandler(FileSystemEventHandler):
def __init__(self, state): def __init__(self, state):
self.state = state self.state = state
@@ -123,14 +123,12 @@ class State(object):
if not os.path.exists(upload): if not os.path.exists(upload):
os.mkdir(upload) os.mkdir(upload)
from shutil import copy
copy(bbctrl.get_resource('http/buildbotics.nc'), upload)
for path in os.listdir(upload): files = filter(os.path.isfile, glob.glob(upload + '/*'))
if os.path.isfile(upload + '/' + path): # Sort list of files based on last modification time in ascending order
files.append(path) files = sorted(files, key=os.path.getmtime, reverse=True)
files = list(map(lambda f: f.replace("./upload/", ""), files))
files.sort()
self.set('files', files) self.set('files', files)
if len(files): self.select_file(files[0]) if len(files): self.select_file(files[0])

View File

@@ -270,7 +270,9 @@
"YL600, YL620, YL620-A VFD (Beta)", "YL600, YL620, YL620-A VFD (Beta)",
"FR-D700 (Beta)", "FR-D700 (Beta)",
"Sunfar E300 (Beta)", "Sunfar E300 (Beta)",
"OMRON MX2" "OMRON MX2",
"V70",
"PwnCNC VFD"
], ],
"default": "Disabled", "default": "Disabled",
"code": "st" "code": "st"
@@ -364,6 +366,7 @@
"max-freq-fixed", "max-freq-fixed",
"freq-set", "freq-set",
"freq-signed-set", "freq-signed-set",
"freq-scaled-set",
"stop-write", "stop-write",
"forward-write", "forward-write",
"reverse-write", "reverse-write",

View File

@@ -1,5 +1,5 @@
{ {
"version": "1.2.1", "version": "1.3.0",
"settings": { "settings": {
"junction-accel": 200000, "junction-accel": 200000,
"max-deviation": 0.05, "max-deviation": 0.05,

View File

@@ -1,18 +1,19 @@
import { get, type Writable } from "svelte/store"; import { get, type Writable } from "svelte/store";
export function listenForChange<T>(writable: Writable<T>, cb: (value: T) => void) {
const priorValue = get(writable);
const unsubscribe = writable.subscribe((value) => {
if (value !== priorValue) {
unsubscribe();
cb(value);
}
});
}
export function waitForChange<T>(writable: Writable<T>): Promise<T> { export function waitForChange<T>(writable: Writable<T>): Promise<T> {
return new Promise((resolve) => { let unsubscribe:()=>{};
listenForChange(writable, (value) => resolve(value)); const promise = new Promise(resolve => {
}); let receivedInitial = false;
let previousValue : any;
unsubscribe = writable.subscribe(value => {
if (!receivedInitial) {
receivedInitial = true;
previousValue = value;
} else if (value !== previousValue) {
resolve(value);
}
});
});
promise.then(unsubscribe);
return promise;
} }