V2: Add proxy for pumps and sensors

Took 30 minutes
This commit is contained in:
Tobias Hopp 2023-01-24 00:34:41 +01:00
parent c9a0ac68c4
commit 243715dab7
11 changed files with 111 additions and 29 deletions

12
DOCME.md Normal file
View File

@ -0,0 +1,12 @@
# Willkommen!
Willkommen im iTender Projekt von Tobias Hopp und Nick Thiele.
Sie befinden sich in der internen Code-Dokumentation von iTender.
Hier befinden sich Methoden und Klassen vom iTender, von Web-Client, über die WebSocket-App bis hin zum Server.
Die Bedienung dieser Dokumentation erscheint anfangs vielleicht holprig, allerdings ist sie leichter als gedacht.
Du willst vermutlich hier hin ->
[iTender Klasse](classes/iTender.iTender.html)

View File

@ -1 +1,19 @@
# iTender
Willkommen im iTender Projekt von Tobias Hopp und Nick Thiele.
Das Projekt ist entstanden in einer Unterrichtseinheit zum Thema Abschlussprojekt.
Wir (Nick und Tobias) dachten zuerst an eine KI gesteuertes Auto, welches allerdings relativ schnell durch den iTender verworfen wurde.
Der iTender ist längst über dem Niveau eines Schul-Projektes und befindet sich in stetigem Wachstum.
Bereits über 100 Stunden an Programmierarbeit, mehr als 20 Stunden Design sowie 50+ Stunden Dokumentationsaufwand sind in das Projekt geflossen.
Wie man leicht heraus lesen kann, nutzen wir auch viel unserer Freizeit für unser außergewöhnliches Projekt.
Das Projekt war anfangs nur sehr einfach geplant, mit einer Möglichkeit aus einer kleinen Liste Drinks zu wählen, welche dann zubereitet werden.
Die Idee lag bei einem kleinen 2-Zeiligem LCD-Display, welches mit einem Drehsensor verbunden ist und dann die Drinks mischt.
Nun ja, wie man unschwer am Produkt erkennen kann, ist unsere Idee etwas expandiert.
Nicht nur, dass wir kein LCD-Display, sondern ein hochauflösendes Farbdisplay nutzen, viel mehr noch, dass wir eine Cloud, eine vollwertige Benutzeroberfläche, Handy Unterstützung und vieles mehr anbieten.
Die Liste hört grundlegend nicht mehr auf, wird sich aber im Benutzer-Handbuch vom iTender unter Features wiederfinden.

View File

@ -10,7 +10,8 @@
"compile": "tsc && webpack",
"compileStart": "yarn run compile && yarn start",
"watchTS": "tsc --watch",
"watchWP": "webpack --watch"
"watchWP": "webpack --watch",
"doc": "typedoc"
},
"dependencies": {
"@serialport/parser-readline": "^10.5.0",
@ -37,6 +38,7 @@
"morgan": "^1.10.0",
"net-ping": "^1.2.3",
"onoff": "^6.0.3",
"pi-hx711": "^1.2.0",
"pug": "^3.0.2",
"rpi-gpio": "^2.1.7",
"rpi-ws281x-native": "^1.0.4",

View File

@ -1,14 +0,0 @@
export class HX711 {
private clockPin: number;
private dataPin: number;
constructor(dataPin: number, clockPin: number) {
this.clockPin = clockPin;
this.dataPin = dataPin;
}
public measure(): number {
return 0;
}
}

View File

@ -7,6 +7,9 @@ import {clearInterval} from "timers";
import {IContainer} from "./database/IContainer";
import {iTender} from "./iTender";
import debug from "debug";
import {ArduinoProxyPayload} from "./ArduinoProxyPayload";
import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType";
import {ArduinoProxy} from "./ArduinoProxy";
const isPI = require("detect-rpi");
@ -54,9 +57,18 @@ export class Mixer {
// Start pump here
try {
await MyGPIO.setup(x.container.pumpPin, GPIO.DIR_OUT)
if (x.container.pumpProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, {
pin: x.container.pumpPin,
mode: "DIGITAL",
value: 255
});
await ArduinoProxy.sendRequest(payload);
} else {
await MyGPIO.setup(x.container.pumpPin, GPIO.DIR_OUT)
await MyGPIO.write(x.container.pumpPin, true);
}
await MyGPIO.write(x.container.pumpPin, true);
} catch (e) {
if (isPI()) {
log("[ERROR] GPIO I/O Error " + e);
@ -83,7 +95,17 @@ export class Mixer {
log(`Stopping output of pump ${x.container.pumpPin}`);
// Stop pump here
try {
await MyGPIO.write(x.container.pumpPin, false);
if (x.container.pumpProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, {
pin: x.container.pumpPin,
mode: "DIGITAL",
"value": 0
});
await ArduinoProxy.sendRequest(payload);
} else {
await MyGPIO.write(x.container.pumpPin, false);
}
} catch (e) {
if (isPI()) {
log("[ERROR] GPIO I/O Error " + e);
@ -143,12 +165,21 @@ export class Mixer {
for (let jobIngredient of this._currentJob.amounts) {
// stop pump pin
try {
await MyGPIO.write(jobIngredient.container.pumpPin, false);
if (jobIngredient.container.pumpProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, {
pin: jobIngredient.container.pumpPin,
mode: "DIGITAL",
"value": 0
});
await ArduinoProxy.sendRequest(payload);
} else {
await MyGPIO.write(jobIngredient.container.pumpPin, false);
}
} catch (e) {
}
// ToDo
// ToDo v2 calc
let container: IContainer = jobIngredient.container;
let deltaStartStop = (this._currentJob.endAt.getTime() - this._currentJob.startedAt.getTime()) / 1000;

View File

@ -1,6 +1,7 @@
import GPIO from "rpi-gpio";
import Container from "./database/Container";
import debug from "debug";
import {IContainer} from "./database/IContainer";
const log = debug("itender:gpio");
@ -45,12 +46,15 @@ export class MyGPIO {
let containers = await Container.find({});
for (let c of containers) {
try {
if (c.sensorType) {
if (c.sensorType && !c.sensorProxy) {
await MyGPIO.setup(c.sensorPin1, GPIO.DIR_IN);
await MyGPIO.setup(c.sensorPin2, GPIO.DIR_IN);
}
await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT);
await MyGPIO.write(c.pumpPin, false);
if( c.pumpPin && !c.pumpProxy )
{
await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT);
await MyGPIO.write(c.pumpPin, false);
}
} catch (e) {
}
}

View File

@ -1,11 +1,13 @@
import {IContainer} from "./database/IContainer";
import {SensorType} from "./SensorType";
import {HX711} from "./HX711";
import debug from "debug";
import {ArduinoProxyPayload} from "./ArduinoProxyPayload";
import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType";
import {ArduinoProxy} from "./ArduinoProxy";
import Container from "./database/Container";
import {HCSR04} from "hc-sr04";
const HX711 = require("pi-hx711");
const log = debug("itender:sensor");
@ -31,7 +33,7 @@ export class SensorHelper {
container.rawData = val.data.value;
} else {
let sensor = new HX711(container.sensorPin1, container.sensorPin2);
container.rawData = sensor.measure();
container.rawData = await sensor.readRaw();
}
} catch (e) {
log("Sensor (Weight cell) of container " + container._id + " is broken or has malfunction - Removing it!");
@ -42,9 +44,9 @@ export class SensorHelper {
} else if (container.sensorType == SensorType.ULTRASOUND) {
try {
// V2: Measure weight
let sensor = new HX711(container.sensorPin1, container.sensorPin2);
let sensor = new HCSR04(container.sensorPin1, container.sensorPin2);
container.rawData = sensor.measure();
// container.rawData = sensor.measure(); ToDo
} catch (e) {
log("Sensor (Ultrasound) of container " + container._id + " is broken or has malfunction - Removing it!");

View File

@ -14,6 +14,7 @@ export const ContainerSchema = new Mongoose.Schema<IContainer>({
sensorDelta: Number, // V2: Now sensorDelta - Differenz, welche beim Einstellen der Zutat aus Gewicht(Sensor) - Volumen errechnet wird
sensorTare: Number, // V2: Now sensorTare
sensorProxy: {type: Boolean, default: false},
pumpProxy: { type: Boolean, default: false },
filled: Number,
enabled: {type: Boolean, default: false},
});

View File

@ -19,9 +19,18 @@ export interface IContainer extends mongoose.Document {
* HX711 CLOCK-Pin
*/
sensorPin2: number;
/**
* Is the arduino used as proxy for the sensor?
*/
sensorProxy: boolean
rawData: number;
pumpPin: number;
/**
* Is the arduino used as proxy for the pump?
*/
pumpProxy: boolean
filled: number;
enabled: boolean;
}

View File

@ -2,13 +2,15 @@
"entryPoints": [
"src/main.ts",
"src/iTender.ts",
"src/Mixer.ts",
"src/ArduinoProxy.ts",
"src/web/main.ts",
"src/WebsocketApp.ts",
"src/App.ts",
"src/routes/ws/websocketRoute.ts"
],
"out": "docs/",
"readme": "README.md",
"name": "iTender Documentation",
"readme": "DOCME.md",
"name": "iTender internal Code Docs",
"tsconfig": "./tsconfig.json"
}

View File

@ -2466,6 +2466,13 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
pi-hx711@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pi-hx711/-/pi-hx711-1.2.0.tgz#804f954f8c397c4442304118a95dda679fa94d24"
integrity sha512-HuoMIVo+T1wf8jig/VODiE9XYCEBgSfavxLrtG9SF6l8fQQPr618ri3mSQB8oCAoYrNiYA1hEXoH+GdtlKN3Ow==
dependencies:
pigpio "^3.3.1"
picocolors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
@ -2476,6 +2483,14 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pigpio@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/pigpio/-/pigpio-3.3.1.tgz#fc31885ea2bfb335cccb80b9d78b443fcfe56b90"
integrity sha512-z7J55K14IwWkA+oW5JHzWcgwThFAuJ7IzV3A2//yRm4jJ2DTU0DHIy91DB0siOi12rvvlrIhRetEuAo0ztF/vQ==
dependencies:
bindings "^1.5.0"
nan "^2.14.2"
pkg-dir@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"