Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-extruder support #3256

Merged
merged 30 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ccce15e
Update backend to handle multiple tools
queengooborg Aug 3, 2022
515ef0b
Display multiple tool temperatures on printer-status component
queengooborg Aug 3, 2022
ecf1e15
Fix styling
queengooborg Aug 3, 2022
6412c98
Implement tool selection on filament pages (WIP
queengooborg Aug 3, 2022
29b0d78
Allow for loading/unloading filament from each individual tool
queengooborg Aug 3, 2022
a3e3d1d
Remove leftover debugging
queengooborg Aug 3, 2022
d7e2e98
Indicate which filament spools are currently in use
queengooborg Aug 3, 2022
f332ef9
Place quick-control__controller into its own ng-template for easy reuse
queengooborg Aug 4, 2022
d26ce38
Merge branch 'main' into multi-extruder
queengooborg Oct 22, 2022
1b8b85f
Fix lint
queengooborg Oct 22, 2022
11a0906
Improve UI when filament is already selected
queengooborg Oct 22, 2022
556fd3b
Merge branch 'main' into multi-extruder
queengooborg Nov 21, 2023
cd5877f
Merge branch 'UnchartedBull:main' into multi-extruder
queengooborg May 5, 2024
1e5283c
Merge branch 'main' into multi-extruder
queengooborg Mar 13, 2025
0a14bf4
Add support for 3-4 hotends; add temperature control for 2nd+ tool
queengooborg Mar 14, 2025
e55fc05
Fix filament loading workflow
queengooborg Mar 14, 2025
60bc509
Update layout for single tool and 5 tools
queengooborg Mar 14, 2025
21203a0
Padding fix
queengooborg Mar 14, 2025
d694c0e
Fix handling of no spools selected
queengooborg Mar 14, 2025
07840e4
Add tool setting to control panel
queengooborg Mar 14, 2025
af11b9d
Make bottom bar smaller
queengooborg Mar 14, 2025
896aebf
Update locales
queengooborg Mar 14, 2025
ad2fc61
Fix locale IDs
queengooborg Mar 14, 2025
0d95031
Explicitly define tool command as a type
queengooborg Mar 14, 2025
b4338fb
Add missing import
queengooborg Mar 14, 2025
6ed7339
Merge branch 'UnchartedBull:main' into multi-extruder
queengooborg Mar 16, 2025
d628de3
Merge branch 'main' into multi-extruder
queengooborg Mar 16, 2025
79f545f
Fix formatting
queengooborg Mar 16, 2025
6a06854
Fix formatting (again)
queengooborg Mar 16, 2025
4ca80f8
Merge branch 'main' into multi-extruder
queengooborg Mar 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { ConversionService } from './conversion.service';
import { EventService } from './event.service';
import { ChangeFilamentComponent } from './filament/change-filament/change-filament.component';
import { ChooseFilamentComponent } from './filament/choose-filament/choose-filament.component';
import { ChooseToolComponent } from './filament/choose-tool/choose-tool.component';
import { FilamentComponent } from './filament/filament.component';
import { HeatNozzleComponent } from './filament/heat-nozzle/heat-nozzle.component';
import { MoveFilamentComponent } from './filament/move-filament/move-filament.component';
Expand Down Expand Up @@ -73,6 +74,7 @@ import { URLSafePipe } from './url.pipe';
AppComponent,
BottomBarComponent,
ChooseFilamentComponent,
ChooseToolComponent,
ConfigInvalidComponent,
ConfigSetupComponent,
ControlComponent,
Expand Down
8 changes: 7 additions & 1 deletion src/app/bottom-bar/bottom-bar.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
width: calc(100% - 5.6vw);

td {
width: 33.3%;
font-size: 4vw;
width: 40%;
}

&__printer-name {
text-overflow: ellipsis;
}

&__enclosure-temperature {
text-align: center;
width: 20%;

&-icon {
width: 2.5vw;
Expand Down
14 changes: 14 additions & 0 deletions src/app/control/control.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,20 @@
</div>
</div>

<div class="control__tool-wrapper" *ngIf="printerStatus.tools.length > 1">
<table class="control__tool">
<tr>
<td
class="control__tool-field"
*ngFor="let tool of printerStatus.tools; index as i"
[ngClass]="{ 'control__tool-field-active': selectedTool === i }"
(click)="setTool(i)">
T{{ i }}
</td>
</tr>
</table>
</div>

<div class="control__distance-wrapper">
<table class="control__distance">
<tr>
Expand Down
7 changes: 3 additions & 4 deletions src/app/control/control.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.control {
margin-top: 5vh;
display: flex;
flex-direction: row;
justify-content: space-between;
Expand Down Expand Up @@ -109,9 +108,9 @@
}
}

&__distance {
width: 50vw;
margin-top: 4.5vh;
&__distance,
&__tool {
margin-top: 1.25vh;
display: inline-block;
border-collapse: separate;

Expand Down
30 changes: 27 additions & 3 deletions src/app/control/control.component.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Component } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';

import { ConfigService } from '../config/config.service';
import { NotificationType } from '../model';
import { NotificationType, PrinterStatus } from '../model';
import { OctoprintPrinterProfile } from '../model/octoprint';
import { NotificationService } from '../notification/notification.service';
import { PrinterService } from '../services/printer/printer.service';
import { SocketService } from '../services/socket/socket.service';

@Component({
selector: 'app-control',
templateUrl: './control.component.html',
styleUrls: ['./control.component.scss'],
})
export class ControlComponent {
export class ControlComponent implements OnInit, OnDestroy {
private subscriptions: Subscription = new Subscription();
public printerStatus: PrinterStatus;

public printerProfile: OctoprintPrinterProfile;

public jogDistance = 10;
public selectedTool = 0;
public showExtruder = false;

public constructor(
private printerService: PrinterService,
private configService: ConfigService,
private notificationService: NotificationService,
private socketService: SocketService,
) {
this.showExtruder = this.configService.getShowExtruderControl();
this.printerService.getActiveProfile().subscribe({
Expand All @@ -38,10 +45,27 @@ export class ControlComponent {
});
}

public ngOnInit(): void {
this.subscriptions.add(
this.socketService.getPrinterStatusSubscribable().subscribe((status: PrinterStatus): void => {
this.printerStatus = status;
}),
);
}

public ngOnDestroy(): void {
this.subscriptions.unsubscribe();
}

public setDistance(distance: number): void {
this.jogDistance = distance;
}

public setTool(tool: number): void {
this.selectedTool = tool;
this.printerService.setTool(tool);
}

public extrude(direction: '+' | '-'): void {
if (this.printerProfile.axes['e'].inverted == true) {
direction = direction === '+' ? '-' : '+';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<ng-container *ngIf="!usingM600(); else M600Change">
<span class="filament-heading" i18n="@@load-new-filament">load new filament</span>
<span class="filament-heading" i18n="@@load-new-filament">load new filament into tool {{ selectedTool }}</span>
<span class="change-filament__info" i18n="@@load-new-filament-message"
>only put a little filament in, I'll pull in the rest.</span
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { PrinterService } from '../../services/printer/printer.service';
})
export class ChangeFilamentComponent implements OnInit {
@Input() selectedSpool: FilamentSpool;
@Input() selectedTool: number;

@Output() increasePage = new EventEmitter<void>();

Expand All @@ -36,7 +37,7 @@ export class ChangeFilamentComponent implements OnInit {
}

private initiateM600FilamentChange(): void {
this.printerService.executeGCode('M600');
this.printerService.executeGCode(`M600 T${this.selectedTool}`);
}

public getSpoolWeightLeft(weight: number, used: number): number {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<table class="filaments">
<tr
*ngFor="let spool of filament.filamentSpools"
[ngClass]="{ 'filaments__in-use': currentSpools.includes(spool.id) }"
long-press
matRipple
[matRippleUnbounded]="false"
Expand All @@ -14,6 +15,9 @@
<td class="filaments__type">
<span class="filaments__type-box" [ngStyle]="{ 'border-color': spool.color }">{{ spool.material }}</span>
</td>
<td class="filaments__in-use-icon" *ngIf="currentSpools.includes(spool.id)">
T{{ currentSpools.indexOf(spool.id) }}
</td>
<td class="filaments__name">
{{ spool.displayName }}
</td>
Expand Down
21 changes: 21 additions & 0 deletions src/app/filament/choose-filament/choose-filament.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
&:last-of-type {
line-height: 7vh;
}

&.filaments__in-use-icon {
font-size: 2.4vw;
}
}

tr {
Expand All @@ -44,6 +48,10 @@
border: 0;
position: relative;

&.filaments__in-use {
background-color: #937171;
}

&:first-of-type {
margin-top: 3.5vh;
}
Expand Down Expand Up @@ -116,6 +124,19 @@
width: 62vw;
}

&__in-use .filaments__name {
width: 56vw;
}

&__in-use-icon {
width: 6vw;
text-align: center;
background-image: url('../../../assets/nozzle.svg');
background-position: center;
background-repeat: no-repeat;
background-size: 4.3vw 4.3vw;
}

&__weight-left {
width: 14vw;
text-align: right;
Expand Down
8 changes: 6 additions & 2 deletions src/app/filament/choose-filament/choose-filament.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import { FilamentSpool } from '../../model';
import { FilamentService } from '../../services/filament/filament.service';

@Component({
selector: 'app-filament-choose',
selector: 'app-filament-choose-spool',
templateUrl: './choose-filament.component.html',
styleUrls: ['./choose-filament.component.scss', '../filament.component.scss'],
})
export class ChooseFilamentComponent {
@Output() spoolChange = new EventEmitter<{ spool: FilamentSpool; skipChange: boolean }>();

constructor(public filament: FilamentService) {}
private currentSpools: number[];

constructor(public filament: FilamentService) {
this.currentSpools = (filament.getCurrentSpools() || []).map(s => s.id);
}

public getSpoolWeightLeft(weight: number, used: number): number {
return Math.floor(weight - used);
Expand Down
13 changes: 13 additions & 0 deletions src/app/filament/choose-tool/choose-tool.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<span class="filament-heading" i18n="@@choose-tool">select tool</span>
<table class="tools">
<tr>
<td
class="tool"
*ngFor="let x of numSequence(toolCount); index as i"
matRipple
[matRippleUnbounded]="false"
(click)="setTool(i)">
<p i18n="@@tool-selection">Tool {{ i }}</p>
</td>
</tr>
</table>
39 changes: 39 additions & 0 deletions src/app/filament/choose-tool/choose-tool.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.tools {
margin-top: 2vh;
width: 96vw;
display: block;
height: 67vh;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
padding-right: 1.5vw;

tr {
width: 96vw;

td {
background-color: #718093;
border-radius: 1vw;
padding: 0 1vw;
display: block;
margin-bottom: 2vh;
width: 93vw;
height: 11vh;
transition: color 0.25s;
box-sizing: border-box;
border: 0;
position: relative;
text-align: center;

font-size: 6vw;
font-weight: 500;

&:first-of-type {
margin-top: 3.5vh;
}

&:last-of-type {
margin-bottom: 3.5vh;
}
}
}
}
40 changes: 40 additions & 0 deletions src/app/filament/choose-tool/choose-tool.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { take } from 'rxjs/operators';

import { PrinterStatus } from '../../model';
import { PrinterService } from '../../services/printer/printer.service';
import { SocketService } from '../../services/socket/socket.service';

@Component({
selector: 'app-filament-choose-tool',
templateUrl: './choose-tool.component.html',
styleUrls: ['./choose-tool.component.scss', '../filament.component.scss'],
})
export class ChooseToolComponent {
public toolCount = 1;

@Output() toolChange = new EventEmitter<number>();

public constructor(
private printerService: PrinterService,
private socketService: SocketService,
) {
this.socketService
.getPrinterStatusSubscribable()
.pipe(take(1))
.subscribe((printerStatus: PrinterStatus): void => {
this.toolCount = printerStatus.tools.length;
});
}

public setTool(tool: number): void {
setTimeout(() => {
this.toolChange.emit(tool);
}, 150);
}

//function to return list of numbers from 0 to n-1
numSequence(n: number): Array<number> {
return Array(n);
}
}
26 changes: 17 additions & 9 deletions src/app/filament/filament.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
<ng-container i18n="@@filament-back"> back </ng-container>
</td>
<td class="top-bar__center">
<img src="assets/filament.svg" class="top-bar__center-icon" *ngIf="page === 0" />
<div class="filament__progress-bar-wrapper" *ngIf="page > 0">
<img src="assets/nozzle.svg" class="top-bar__center-icon" *ngIf="page === 0" />
<img src="assets/filament.svg" class="top-bar__center-icon" *ngIf="page === 1" />
<div class="filament__progress-bar-wrapper" *ngIf="page > 1">
<div class="filament__progress-bar" id="progressBar"></div>
</div>
</td>
Expand All @@ -18,28 +19,35 @@
</table>

<div class="filament">
<app-filament-choose (spoolChange)="setSpool($event)" *ngIf="page === 0 && !showCheckmark"></app-filament-choose>
<app-filament-choose-tool
(toolChange)="setTool($event)"
*ngIf="page === 0 && !showCheckmark"></app-filament-choose-tool>
<app-filament-choose-spool (spoolChange)="setSpool($event)" *ngIf="page === 1"></app-filament-choose-spool>
<app-filament-heat-nozzle
(increasePage)="increasePage()"
[currentSpool]="currentSpool"
[selectedSpool]="selectedSpool"
*ngIf="page === 1"></app-filament-heat-nozzle>
[selectedTool]="selectedTool"
*ngIf="page === 2"></app-filament-heat-nozzle>
<app-filament-move-filament
*ngIf="page === 2"
*ngIf="page === 3"
(increasePage)="increasePage()"
[currentSpool]="currentSpool"
[action]="'unload'"></app-filament-move-filament>
<app-filament-change-filament
*ngIf="page === 3"
*ngIf="page === 4"
(increasePage)="increasePage()"
[selectedSpool]="selectedSpool"></app-filament-change-filament>
[selectedSpool]="selectedSpool"
[selectedTool]="selectedTool"></app-filament-change-filament>
<app-filament-move-filament
*ngIf="page === 4"
*ngIf="page === 5"
(increasePage)="increasePage()"
[selectedSpool]="selectedSpool"
[selectedTool]="selectedTool"
[action]="'load'"></app-filament-move-filament>
<app-filament-purge-filament
*ngIf="page === 5 && !showCheckmark"
*ngIf="page === 6 && !showCheckmark"
[selectedTool]="selectedTool"
(purgeDone)="setSpoolSelection()"></app-filament-purge-filament>
<div class="checkmark" *ngIf="showCheckmark">
<ng-lottie
Expand Down
Loading
Loading