Hallo Community.
Ich sitze jetzt schon seit Tagen und Wochen an diesem Problem und komme einfach nicht weiter.
Ich habe einen riesigen Code geschrieben und dieser funktioniert auch einwandfrei, bis auf eine Funktion.
Prinzipiell geht es darum, für eine automatisierte EpoxiHarz-Mischvorrichtung vorher die Gewichts- Unter- und Obergrenze des Harzbades einzustellen in das später hinein gefördert wird, sowie die Volumenanteile der beiden Komponenten. All das wird ins EEPROM gespeichert und nachher wieder abgerufen. Nach diesen Werten werden dann die zwei Pumpen über PWM gesteuert.
Der Code funktioniert mit mehreren Stati. In jedem Status wird eine Aufgabe ausgeführt und dann über einen button der Status geändert oder er erhöht sich selber über ein "status++". Über die buttons kann man in höhere und niedrigere Stati springen. Die Werte werden über ein Poti eingestellt und dann mit den buttons bestätigt.
Es geht mir nur um eine Sache: Zum auswählen der Harzbad Unter- und Obergrenzen habe ich einen Filter eingeführt, der nur Vielfache Werte von 25 auf dem Display anzeigt, da eine höhere Genauigkeit stören würde:
int WertUG = Poti / 2; //Einführung Rohwert UG
if (WertUG % 25 == 0) { //UG in 25er Schrittweite (filter)
Wert_filterUG = WertUG;
}
Im Status 7 wird dann "Wert_filterUG" auf dem LCD angezeigt und kann mit dem Poti eingestellt werden. Ein Druck auf den button erhöht den Status, wo der letzte Wert dann ins EEPROM gespeichert wird:
if (status == 7) { //Harzbad UG einstellen über Poti (Wert_filterUG)
lcd.setCursor(0, 0);
lcd.print("Harzbad Untergr.");
lcd.setCursor(0, 1);
lcd.print(Wert_filterUG);
lcd.print(" g");
if (Wert_filterUG < 1000) {
lcd.setCursor(5, 1);
lcd.print(" ");
}
if (Wert_filterUG < 100) {
lcd.setCursor(4, 1);
lcd.print(" ");
}
if (Wert_filterUG < 10) {
lcd.setCursor(3, 1);
lcd.print(" ");
}
}
Das Problem: Wenn man am Poti dreht, hängen die Werte komplett hinterher. Es dauert mehrere Sekunden bis sich der Wert ändert und dann ist man auf einmal von 100 auf 500 gesprungen und es ist fast unmöglich einen Wunschwert einzustellen. Es macht mich einfach sehr unglücklich, da der Rest alles läuft. Ohne den Filter ändern sich die Werte flüssig.
Ich habe auch mal den oberen Code in jeden Status eingefügt und komischerweise Funktioniert der Filter total flüssig in allen Stati kleiner 3!
Es muss also irgendwo eine Stelle geben, die ab Status 3 den Arduino verlangsamt oder so.
Ich habe ab Status 3 blinkende Displays in den Code eingebaut, die funktionieren aber mit "millis()" und sollten nichts verlangsamen. Auch als ich das Blinken raus genommen habe, hat es nicht besser geklappt.
Ich habe auch schon die Baudrate in beide Richtungen angepasst, ohne Erfolg.
Wenn ich kleinere Teiler als 25 nehme, läuft es immer flüssiger.
Ich werde unten meinen Code einfügen, bis zum Status 7. Ist trotzdem eine Menge, weil das ganze Setup und die Bedingungen davor mit drin sind. Es tut mir Leid wenn euch dann der Kopf glüht. Danach geht es noch weiter bis Status 21, aber da läuft alles und da ist auch nirgends Status 3 erwähnt.
Ich bin total am Verzweifeln und möchte das Projekt einfach nicht so unperfekt abgeben... Vielleicht könnt ihr mir ja sagen, woran es liegt dass dieser Filter so seltsam hält. Vielen Dank euch!
#include <EEPROM.h> //Libraries
#include <HX711_ADC.h>
#include <LiquidCrystal.h>
#include <TM1637Display.h>
#include <inttypes.h>
#define CLK1 26 //define small display pins für alle 3 Displays; small display1
#define DIO1 27
#define CLK2 22 //small display 2
#define DIO2 23
#define CLK3 24 //small display 3
#define DIO3 25
const uint8_t lo[] = {
//Blink-Anzeige "LO", wenn Vorratsbehälter unter bestimmter Grenze
SEG_D | SEG_E | SEG_F, // L
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
0x00,
0x00,
};
const uint8_t auff[] = {
//Blink-Anzeige "AUFF", wenn die Pumpen arbeiten
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // U
SEG_A | SEG_E | SEG_F | SEG_G, // F
SEG_A | SEG_E | SEG_F | SEG_G, // F
};
const int button1Pin = 10; //button Pins
const int button2Pin = 9;
const int HX711_dout_1 = 39; //Zelle1 HX711 dout pin
const int HX711_sck_1 = 38; //Zelle1 HX711 sck pin
const int HX711_dout_2 = 37; //Zelle2 HX711 dout pin
const int HX711_sck_2 = 36; //Zelle2 HX711 sck pin
const int HX711_dout_3 = 35; //Zelle3 HX711 dout pin
const int HX711_sck_3 = 34; //Zelle3 HX711 sck pin
const int potPin = A0; //Poti Pin
const int rs = 52, en = 50, d4 = 48, d5 = 46, d6 = 44, d7 = 42; //LCD Pins
const int pump1 = 3; //Pumpen Pins
const int pump2 = 4;
HX711_ADC LoadCell_1(HX711_dout_1, HX711_sck_1); //HX711 1 Harzbad
HX711_ADC LoadCell_2(HX711_dout_2, HX711_sck_2); //HX711 2 Harz
HX711_ADC LoadCell_3(HX711_dout_3, HX711_sck_3); //HX711 3 Haerter
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //LCD-Display erstellen
TM1637Display display1(CLK1, DIO1); //SmallDisplay1 erstellen
TM1637Display display2(CLK2, DIO2); //SmallDisplay2 erstellen
TM1637Display display3(CLK3, DIO3); //SmallDisplay3 erstellen
const int calVal_eepromAdress_1 = 0; // EEPROM adress for calibration value load cell 1 (4 bytes); Adressen müssen mind. 4 Stellen auseinander liegen
const int calVal_eepromAdress_2 = 4; // EEPROM adress for calibration value load cell 2 (4 bytes)
const int calVal_eepromAdress_3 = 8; // EEPROM adress for calibration value load cell 3 (4 bytes)
unsigned long t = 0; //Variablen
int button1 = 0;
int button2 = 0;
int status = 0;
int extra = 0;
int neu = 0;
int pumprate1 = 0;
int pumprate2 = 0;
bool Auffuellvorgang{ false }; //Auffüllvorgang ist nicht aktiviert
float WertHarz; //vol. Anteil Harz
int WertHarz_address = 150; //EEPROM address for WertHarz
float PumpHarz; //Pumpenverhältnis Harz
int PumpHarz_address = 154; //EEPROM address
float WertHaert; //vol. Anteil Haert
int WertHaert_address = 160; //EEPROM address for WertHaert
float PumpHaert; //Pumpenverhältnis Haert
int PumpHaert_address = 164; //EEPROM address
int Wert_filterUG; //UG in 25er Schrittweite
float UG;
int UG_address = 120; // EEPROM adress for UG
int Wert_filterOG; //OG in 25er Schrittweite
float OG;
int OG_address = 124; //EEPROM address for OG
unsigned long previousMillisHB = 0; //Harzbad Zeiten für Blink-Anzeige
const long intervalHB = 2340;
const long intervalHB2 = 11700;
unsigned long previousMillisBlink = 0; //Harz und Härter Zeiten für Blink-Anzeige
const long intervalBlink = 3900;
const long intervalBlink2 = 7800;
unsigned long previousMillisTare = 0; //Tare Zeiten für Tare ohne delay
const long intervalTare = 23400;
const long intervalTare2 = 39000;
const long intervalTare3 = 39780;
bool istGesetzt = false; //bool Variable für Tare
bool istGesetzt2 = false; //bool Variable für Tare2
void setup() {
TCCR2B = TCCR2B & 0b11111000 | 0x02; Timer2 (pin 9&10) von 490 auf 3900Hz ändern
pinMode(button1Pin, INPUT); //Pin Modes
pinMode(button2Pin, INPUT);
pinMode(pump1, OUTPUT);
pinMode(pump2, OUTPUT);
Serial.begin(57600);
Serial.print("status: ");
Serial.println(status);
float calibrationValue_1; // calibration value load cell 1
float calibrationValue_2; // calibration value load cell 2
float calibrationValue_3; // calibration value load cell 3
EEPROM.get(calVal_eepromAdress_1, calibrationValue_1); //calibration values aus EEPROM holen (vorher generiert)
EEPROM.get(calVal_eepromAdress_2, calibrationValue_2);
EEPROM.get(calVal_eepromAdress_3, calibrationValue_3);
LoadCell_1.begin(); //Wägezellen starten
LoadCell_2.begin();
LoadCell_3.begin();
unsigned long stabilizingtime = 15600; // higher time = higher tare preciscion
boolean _tare = true; //false = no tare in next step
byte loadcell_1_rdy = 0;
byte loadcell_2_rdy = 0;
byte loadcell_3_rdy = 0;
while ((loadcell_1_rdy + loadcell_2_rdy + loadcell_3_rdy) < 3) { //run startup, stabilization and tare, all modules simultaniously
if (!loadcell_1_rdy) loadcell_1_rdy = LoadCell_1.startMultiple(stabilizingtime, _tare);
if (!loadcell_2_rdy) loadcell_2_rdy = LoadCell_2.startMultiple(stabilizingtime, _tare);
if (!loadcell_3_rdy) loadcell_3_rdy = LoadCell_3.startMultiple(stabilizingtime, _tare);
}
LoadCell_1.setCalFactor(calibrationValue_1); // user set calibration value (float)
LoadCell_2.setCalFactor(calibrationValue_2); // user set calibration value (float)
LoadCell_3.setCalFactor(calibrationValue_3); // user set calibration value (float)
Serial.println("Startup is complete");
lcd.begin(16, 2);
lcd.print("Startup complete");
lcd.setCursor(0, 1);
lcd.print("press button1");
display1.clear();
display2.clear();
display3.clear();
}
void loop() {
static boolean newDataReady = 0;
const int serialPrintInterval = 3900;
if (LoadCell_1.update()) newDataReady = true; //check for new data Waegezellen
LoadCell_2.update();
LoadCell_3.update();
display1.setBrightness(4); //SmallDisplays anschalten
display2.setBrightness(4);
display3.setBrightness(4);
// Fuellstandsanzeige Harzbad Normalzustand
int HB;
if (status >= 3) {
HB = LoadCell_1.getData();
if (LoadCell_1.getData() < 0) {
HB = 0;
}
}
// Fuellstandsanzeige Harzbad Auffüllvorgang mit Blink
if ((status == 20 || status == 21) && (pumprate1 > 0 || pumprate2 > 0)) { //Blink wenn mindestens eine der beiden Pumpen arbeitet und auffüllt
unsigned long currentMillisHB = millis();
if (LoadCell_1.getData() < 0) {
HB = 0;
}
if (currentMillisHB - previousMillisHB < intervalHB) { //Zeige den Vektor "auff" an
display1.setSegments(auff);
}
if (currentMillisHB - previousMillisHB >= intervalHB) { //Zeige den Wert "Wägezelle" HB an
display1.showNumberDec(HB, false, 4, 0);
}
if (currentMillisHB - previousMillisHB >= intervalHB2) { //Reset den Wert von Millis
previousMillisHB = currentMillisHB;
}
} else if (status >= 3) { //Außerhalb von Status 20/21 nur HB anzeigen
display1.showNumberDec(HB, false, 4, 0);
}
// Fuellstandsanzeige Harz mit Blink
int HARZ = LoadCell_2.getData();
if (status >= 3) {
unsigned long currentMillisBlink = millis();
if (LoadCell_2.getData() < 0) {
HARZ = 0;
}
if (LoadCell_2.getData() >= 100) { //Wenn HARZ > 100g, nur HARZ anzeigen
display2.showNumberDec(HARZ, false, 4, 0);
}
if (LoadCell_2.getData() < 100) { //Wenn HARZ < 100g, Anzeige mit Blink
if (currentMillisBlink - previousMillisBlink < intervalBlink) {
display2.setSegments(lo);
}
if (currentMillisBlink - previousMillisBlink >= intervalBlink) {
display2.showNumberDec(HARZ, false, 4, 0);
}
if (currentMillisBlink - previousMillisBlink >= intervalBlink2) {
previousMillisBlink = currentMillisBlink;
}
}
}
// Fuellstandsanzeige Haerter mit Blink
int HAERT = LoadCell_3.getData();
if (status >= 3) {
unsigned long currentMillisBlink = millis();
if (LoadCell_3.getData() < 0) {
HAERT = 0;
}
if (LoadCell_3.getData() >= 100) { //Wenn HAERT > 100g, nur HAERT anzeigen
display3.showNumberDec(HAERT, false, 4, 0);
}
if (LoadCell_3.getData() < 100) { //Wenn HAERT < 100g, Anzeige mit Blink
if (currentMillisBlink - previousMillisBlink < intervalBlink) {
display3.setSegments(lo);
}
if (currentMillisBlink - previousMillisBlink >= intervalBlink) {
display3.showNumberDec(HAERT, false, 4, 0);
}
if (currentMillisBlink - previousMillisBlink >= intervalBlink2) {
previousMillisBlink = currentMillisBlink;
}
}
}
///////////////////////////////////////////////////////////////////// Funktion der Buttons
button1 = digitalRead(button1Pin); //Einführung Buttons
button2 = digitalRead(button2Pin);
if (button1 == HIGH && extra == 0) {
delay(3900);
status++;
Serial.print("status: ");
Serial.println(status);
lcd.clear();
} else if (button2 == HIGH) {
delay(3900);
switch (status) {
case 9:
case 8:
status = 7;
break;
case 10:
case 11:
status = 9;
break;
case 12:
case 13:
case 14:
status = 11;
break;
case 15:
case 16:
case 17:
case 18:
case 19:
status = 14;
break;
case 20:
extra++;
Serial.print("extra: ");
Serial.println(extra);
break;
case 21:
pumprate1 = PumpHarz * 2.55;
pumprate2 = PumpHaert * 2.55;
analogWrite(pump1, pumprate1);
analogWrite(pump2, pumprate2);
status = 20;
extra = 0;
neu = 0;
break;
}
Serial.print("status: ");
Serial.println(status);
lcd.clear();
}
if (button1 == HIGH && status == 20 && extra > 0 && extra <= 3) {
delay(3900);
neu++;
Serial.print("neu: ");
Serial.println(neu);
lcd.clear();
}
if (button2 == HIGH && status == 20 && neu > 0) {
delay(3900);
neu = 0;
extra--;
Serial.print("neu: ");
Serial.println(neu);
lcd.clear();
}
/////////////////////////////////////////////////////////////////////////////////////////
int Poti = analogRead(potPin); //Einführung Poti
int FoerderHarz = Poti / 17; //Einführung Fördergeschwindigkeit Harz beim Aufbauen
int FoerderHaert = Poti / 17; //Einführung Fördergeschwindigkeit Harz beim Aufbauen
int AntHarz = Poti / 6.82; //Einführung Anteil Harz, mit Poti festlegen (0-150 Volumenanteile)
if (AntHarz > 150) {
AntHarz = 150;
}
int AntHaert = Poti / 6.82; //Einführung Anteil Haert, mit Poti festlegen (0-150 Volumenanteile)
if (AntHaert > 150) {
AntHaert = 150;
}
int WertUG = Poti / 2; //Einführung Rohwert UG
if (WertUG % 25 == 0) { //UG in 25er Schrittweite (filter)
Wert_filterUG = WertUG;
}
int WertOG = Poti / 2 + 400; //Einführung Rohwert OG
if (WertOG % 25 == 0) { //OG in 25er Schrittweite (filter)
Wert_filterOG = WertOG;
}
///////////////////////////////////////////////////////////////////////////////// Beginn Programm
if (status == 1) { //System aufbauen
lcd.setCursor(0, 0);
lcd.print("System");
lcd.setCursor(0, 1);
lcd.print("aufbauen");
}
if (status == 2) { //Tare alle Wägezellen
unsigned long currentMillisTare = millis();
lcd.setCursor(0, 0);
lcd.print("System tare...");
if (currentMillisTare - previousMillisTare < intervalTare) {
LoadCell_1.tareNoDelay();
LoadCell_2.tareNoDelay();
LoadCell_3.tareNoDelay();
}
if (currentMillisTare - previousMillisTare >= intervalTare && currentMillisTare - previousMillisTare < intervalTare2) {
lcd.setCursor(0, 1);
lcd.print("done");
}
if (currentMillisTare - previousMillisTare >= intervalTare2 && currentMillisTare - previousMillisTare < intervalTare3) {
lcd.clear();
status++; //AUTOWECHSEL
}
if (currentMillisTare >= intervalTare3 && istGesetzt == false) { //Millis-Wert einmalig speichern, danach wird "istGesetzt" nurnoch =true bleiben
previousMillisTare = millis();
istGesetzt = true;
}
}
if (status == 3) { //Harz und Haerter auffüllen
lcd.setCursor(0, 0);
lcd.print("Harz&Haert auff.");
lcd.setCursor(0, 1);
lcd.print("...");
if (LoadCell_1.getData() >= 100 && LoadCell_2.getData() >= 100) {
lcd.setCursor(0, 3);
lcd.print("done");
delay(23400);
lcd.clear();
status++;
}
}
if (status == 4) { //Harz vorfoerdern
lcd.setCursor(0, 0);
lcd.print("Harz vorfoerdern");
lcd.setCursor(0, 1);
lcd.print("adjust then b1");
analogWrite(pump1, FoerderHarz);
}
if (status == 5) { //Haerter vorfoerdern
analogWrite(pump1, 0);
lcd.setCursor(0, 0);
lcd.print("Haerter vorfoerd");
lcd.setCursor(0, 1);
lcd.print("adjust then b1");
analogWrite(pump2, FoerderHaert);
}
if (status == 6) { //Tare alle Zellen
analogWrite(pump1, 0);
analogWrite(pump2, 0);
unsigned long currentMillisTare = millis();
lcd.setCursor(0, 0);
lcd.print("System tare...");
if (currentMillisTare - previousMillisTare < intervalTare) {
LoadCell_1.tareNoDelay();
LoadCell_2.tareNoDelay();
LoadCell_3.tareNoDelay();
}
if (currentMillisTare - previousMillisTare >= intervalTare && currentMillisTare - previousMillisTare < intervalTare2) {
lcd.setCursor(0, 1);
lcd.print("done");
}
if (currentMillisTare - previousMillisTare >= intervalTare2 && currentMillisTare - previousMillisTare < intervalTare3) {
lcd.clear();
status++; //AUTOWECHSEL
}
if (currentMillisTare >= intervalTare3 && istGesetzt2 == false) { //Millis-Wert einmalig speichern, danach wird "istGesetzt2" nurnoch =true bleiben
previousMillisTare = millis();
istGesetzt2 = true;
}
}
if (status == 7) { //Harzbad UG einstellen über Poti (Wert_filterUG)
lcd.setCursor(0, 0);
lcd.print("Harzbad Untergr.");
lcd.setCursor(0, 1);
lcd.print(Wert_filterUG);
lcd.print(" g");
if (Wert_filterUG < 1000) {
lcd.setCursor(5, 1);
lcd.print(" ");
}
if (Wert_filterUG < 100) {
lcd.setCursor(4, 1);
lcd.print(" ");
}
if (Wert_filterUG < 10) {
lcd.setCursor(3, 1);
lcd.print(" ");
}
}
Danke dass du bis hierher gelesen hast