Multitasking Project Problem

Hallo liebe leute, ich habe ein kleines problem mit meinem project den ich als Non block code programmieren will, was eigentlich ganz gut läuft bis jetzt.

Mein Project besteht aus:

Mega 2560. soll eventuell später auf Due umgerüstet werden, wenn speed zu langsam.

5x Nema 17 (4x 17HS24-2104S) (1x 17HS19-2004S1)
1x Nema 23 (23HS2430 3A)

5x Referenzschalter
5X Digital Lichtsensor ( eBay-Artikelnummer:25271261173)
1x DS18B20 Digitaler Temperaturfühler 1-Wire
1x DHT22 Digital Humidity AM2302

1x Nextion 7" Enhanced (NX8048K070_011C)

Nun aber zu mein eigentlichen problem.

Alle stepper laufen in eine einzelne schleife.

for(int x = 0; x < 9000000; x++){  
    States();
If(Sensor1 == LOW and Sensor2 == Low){
if(x<1000){
stepper1 mach was
stepper2 mach auch was
}
if(x>1000)
mach was anderes
}
Und so weiter...

Das funzioniert soweit alles.

States(); Hier wird abgefragt was für ein status die sensoren haben.

void States(){
  
     StartButtonState = digitalRead(StartButton);
   UebergabeRefButtonState = digitalRead(UebergabeRefButton);
   HuelsRefButtonState = digitalRead(HuelsRefButton);
   StopfRefButtonState = digitalRead(StopfRefButton);
   NotHaltButtonState = digitalRead(NotHaltButton);
   QuantiRefButtonState = digitalRead(QuantiRefButton);
RollRefButtonState = digitalRead(RollRefButton);
   
   HuelsSensorState = digitalRead(HuelsSensor);
   HuelsSTSensorState = digitalRead(HuelsSTSensor);
   TabackOSensorState = digitalRead(TabackOSensor);
   HuelsUbergabeState = digitalRead(HuelsUbergabeSensor);
   TabackUSensorState = digitalRead(TabackUSensor); 
}

Problem:

um im display was anzeigen zu können also ob sensor 1 aktiv oder nicht oder die temperatur etc, mößte ich in States();
noch volgendes hinzufühen.

// Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);


    Serial.print("Humidity.txt=");
Serial.print("\"");
Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print("%");
Serial.print("\"");
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);

 Serial.print("Temperature.txt=");
Serial.print("\"");
  Serial.print(F("Taback Temperature: "));
  Serial.print(t);
  Serial.print("*C");
Serial.print("\"");
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);

nur 2 von viele, jedoch reicht das aus das die stepper auf 1x mit 1000nstel speed laufen, alles wird super langsam, was mache ich da falsch?

Liegt es an die Libraries?
Geladen sind:

#include <Nextion.h>
#include <NexButton.h>
#include <NexVariable.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include "DHT.h"
#include <Stepper.h>

naja, hast du dir ja eh schon als Kommmentar geschrieben:

// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)

einer (oder alle drei) deiner Zugriffe wird dich ausbremsen.

Das funzioniert soweit alles.

Nööö…

for(int x = 0; x < 9000000; x++)

Wie soll denn x, auf deinem Mega, jemals so groß werden?

// Sensor readings may also be up to 2 seconds ‘old’ (its a very slow sensor)

Das habe ich so übernommen frage ist ob man die librari einfach so verändern kann. Das es mich nicht mehr abbremmst?

for(int x = 0; x < 9000000; x++)
Das wahr ein beiapiel so groß muss es natürlich nicht werden

seby1302:
for(int x = 0; x < 9000000; x++)
Das wahr ein beiapiel so groß muss es natürlich nicht werden

So groß kann es überhaupt nicht werden. Schaue Dir mal den Maximalwert für int an.

Gruß Tommy

Hi

  1. int geht von -32768 bis 32767
  2. Du brauchst hier KEINE negativen Zahlen
  3. Du willst Dir überlegen, welchen Datentyp Du Wo brauchst - int ist zwar Standard - aber leider zu 90% der falsche Typ!
    Wenn Du tausend Male die Sekunde Deine Sensoren ausliest, Die Das nur alle zwei Sekunden haben wollen, könnte Das schon ‘etwas’ bremsend wirken.
    Allgemein sind ‘wartende Schleifen’ keine wirklich gute Idee - einzige Ausnahme: Der Arduino soll NUR warten - dann ist’s durchaus ein probates Mittel.
    Spätestens in einer Woche willst Du aber, daß der Arduino WÄHREND des Warten aber noch was Sinnvolles treibt - und spätestens dann fällt Dir die wartende Schleife auf die Füße.
    Ergo: Mach’s von Anfang an richtig, ist besser für die Füße!

MfG

Ergo: Mach’s von Anfang an richtig, ist besser für die Füße!

Du meinst also die schleife ganz weg lassen? ok hatte ich auch schon dran gedacht, aber wie zähle ich dann die schritte die die einzelne stepper treiben?

Long stepper4count=0;

void Loop(){
 if(stepper4count<1200 ){
stepper4count++;
    digitalWrite(en4Pin, LOW); 
    digitalWrite(dir4Pin,LOW);
   
    time_a4 = micros();
    digitalWrite(step4Pin, HIGH);                       
    while(micros() - time_a4 < 50){
    }
    
    time_b4 = micros();
    digitalWrite(step4Pin, LOW);
    while(micros() - time_b4 < 50){
    }
    
 }else if(stepper4count == 1200 ){
   digitalWrite(en4Pin, HIGH);  
stepper4count=0;
   }
}

könnte das so gehen? wobei die while ist auch eine schleifen…

Hi

while(micros() - time_a4 < 50){}

Sieht wie eine blockierende Schleife aus - ok, nur 50ns, aber die Zeit rennt der Arduino hier im Kreis - nix mit IR-Fernbedienung oder sonst einem Kram.

Du möchtest NICHT, wenn noch keine 1200 Schritte gemacht wurden, den nächsten Schritt auslösen!
Du möchtest eher prüfen, ob die Zeit für den nächsten Step bereits gekommen ist!
Sowohl AN, wie auch AUS-schalten sind einzelne Vorgänge - Du hast beide (blockierende) While-Schleifen am Stück.
Du kannst gerne per micros() prüfen, ob Deine ON-Time (50ns) vorbei ist - bei positiver Prüfuńg den Ausgang abschalten und auf das Ende dieser OFF-Time warten.
Nur in einem der Fälle ist ein Schritt beendet und Du darfst also auch nur 1x die ‘stepper4count’ runter zählen.
Und auch: Bei 0 eben keine neuen Steps mehr auslösen.

MALE Dir haarklein auf, WAS WANN passieren soll - dann nur noch den Kram genau so programmieren und sich wundern, wo man überall Mist gedacht hat :wink:

MfG

Gennau so schauts aus, ich hab mir alles überdacht und habe mir deshalb eine steppercontoll.h gebastelt, oder ehr gesagt bin ich noch dabei.

void RollStepper(int EN, int DIR, int SPEED){
  if(EN == LOW){
  digitalWrite(dir6Pin, DIR); 
  digitalWrite(en6Pin, LOW);   // Enable
   

    time_a6 = micros();
      digitalWrite(step6Pin, HIGH);                       
    while(micros() - time_a6 < SPEED){
    }

    time_b6 = micros();
     digitalWrite(step6Pin, LOW);
    while(micros() - time_b6 < SPEED){
    }
  }else if(EN == HIGH){
    digitalWrite(en6Pin, HIGH);  //Disable
  }
}

funzioniert auch gan gut soweit.

if blabla
RollStepper(LOW,LOW,100);// Enabled, Vorwerts, 100 Speed

else if blabla 2
RollStepper(LOW,High,100);// Enabled, Rückwerts, 100 Speed

else

RollStepper(High,0,0);// Disabled

Jetzt bin ich am überlegen ob es nicht sinn voll währe die steps die er machen soll zu übergeben

RollStepper(LOW,LOW,100,6400);// Enabled, Vorwerts, 100 Speed, 6400 schritte???

Was meint ihr da zu.

Ich habe nähmlich ein problem:

If(sensor1 == low)

mach 1000 stritten, nun wird aber bei 900 schrtitte der sensor high und es geht nicht mehr weiter logich ^^

Du hast da ja immer noch Warteschleifen mit while drinne.

Ich habe es bereits geändert es läuft ohne for oder while schleife
Allerdings es reicht wenn ich die sensoren auswerte und es läuft wie vor auch eventuel minimal schneller heist Stadt 10 Minuten für 1000 steps macht er die in 9,5 Minuten :confused:

void RollStepper(int EN, int DIR, int SPEED, int STEPS){
  if(EN == LOW and RollSteperCount < STEPS){
  digitalWrite(dir6Pin, DIR); 
  digitalWrite(en6Pin, LOW);   // Enable
  RollSteperCount++; 

    time_a6 = micros();                            
    if(micros() - time_a6 < SPEED){
    digitalWrite(step6Pin, HIGH);
    }

    time_b6 = micros();  
    if(micros() - time_b6 < SPEED){
    digitalWrite(step6Pin, LOW);
    }
  }else if(EN == HIGH){
    digitalWrite(en6Pin, HIGH);  //Disable
  }
}

P.s ich meine wenn ich die am Display sende:

  if (HuelsSensorState == HIGH ) {
  Serial.print("HuelsSensor.txt=");
Serial.print("\"");
Serial.print("Huelsen Vorrats Voll");
Serial.print("\"");
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
  }else{
Serial.print("HuelsSensor.txt=");
Serial.print("\"");
Serial.print("Huelsen Vorrats Leer");
Serial.print("\"");
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
  }

es sind ja 5 + nothalt Status = 6 mit jeden weiterem wird er immer langsamer, ohne die läuft er bereits sehr gut, mit dem Arduino due sollte das schon gehen, allerdings wird selbst der noch Schwierigkeit haben mit dem senden der sensoren status.

EDIT:

Da es warscheinlich nicht anders gehen wird, dachte ich mir diese eventuell zeitversetzt zu überprüfen weiß aber nicht ganz ob es richtig so ist?

SensorTimer = millis();                        
    if(SensorTimer - millis() > 1000){
     Serial.print("t0.txt=" ); //erste sensor aktuelisieren
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
}


SensorTimer2 = millis();                        
    if(SensorTimer2 - millis() > 2000){
     Serial.print("t1.txt=" ); //zweitesensor aktuelisieren
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
}

//und so wieter?

SensorTimer2 = millis();
if(SensorTimer2 - millis() > 2000){

Schon mal auf dem Papier nachgerechtet, was dabei raus kommt?

Wenn ich es kapieren würde würd ich nicht so doof fragen, oder aber das teil wird dann so larm das ich kein unterschied merke, in zwischen bin ich voll verwiert….

wie wärs richtig?!

ich hab probiet:

if(millis() - SensorTimer2 > 2000)){ // rennt aber aktuelisiert nicht.
if(millis() - SensorTimer2 < 2000)){ // aktuelisiert aber die bewegungen kannst du mit mikroskop sehen :confused: .

das da oben gennau so wahr ein versuch

postmaster-ino:
Hi

while(micros() - time_a4 < 50){}

Sieht wie eine blockierende Schleife aus - ok, nur 50ns, aber die Zeit rennt der Arduino hier im Kreis - nix mit IR-Fernbedienung oder sonst einem Kram.

Du möchtest NICHT, wenn noch keine 1200 Schritte gemacht wurden, den nächsten Schritt auslösen!
Du möchtest eher prüfen, ob die Zeit für den nächsten Step bereits gekommen ist!
Sowohl AN, wie auch AUS-schalten sind einzelne Vorgänge - Du hast beide (blockierende) While-Schleifen am Stück.
Du kannst gerne per micros() prüfen, ob Deine ON-Time (50ns) vorbei ist - bei positiver Prüfuńg den Ausgang abschalten und auf das Ende dieser OFF-Time warten.
Nur in einem der Fälle ist ein Schritt beendet und Du darfst also auch nur 1x die ‘stepper4count’ runter zählen.
Und auch: Bei 0 eben keine neuen Steps mehr auslösen.

MALE Dir haarklein auf, WAS WANN passieren soll - dann nur noch den Kram genau so programmieren und sich wundern, wo man überall Mist gedacht hat :wink:

MfG

Wenn Du es zusammenbringst mit einem Controller mit 62ns Zykluszeit Pausen im ns bereich aufzulösen dann Erklährs mir und wir werden reich.

Realistischer ist wenn man statt nano (10^-9) mykro (10^-6) schreibt also 50µs.
Grüße Uwe

seby1302:
if(millis() - SensorTimer2 > 2000)){ // rennt aber aktuelisiert nicht.

Wird in deinen Zusammenhang NIE wahr

seby1302:
if(millis() - SensorTimer2 < 2000)){ // aktuelisiert aber die bewegungen kannst du mit mikroskop sehen

Ist in deinen Zusammenhang IMMER wahr

ok es wäre dann nett wen mir eklären könntest wie ich das dann mache, es soll z.b alle x Sekunden 1x kurz die Commandos am Display senden.

ich hab gestern was gelsen das der bei 9600 Baud nur 1000 characters pro secunde kann?

Wenn das so ist sollte ich dann lieber um ändern auf 11520 Baud und als variable versenden und dann in nextion auswerten in etwa.

if (HuelsSensorState == HIGH ) {
Serial.print("n1.val=");   
Serial.print(1); 
Serial.write(0xff);  
Serial.write(0xff);
Serial.write(0xff);
}else{
Serial.print("n1.val=");   
Serial.print(0); 
Serial.write(0xff);  
Serial.write(0xff);
Serial.write(0xff);
}

anstelle von

Serial.print("HuelsSensor.txt=");
Serial.print("\"");
Serial.print("Huelsen Vorrats Voll");
Serial.print("\"");
Serial.write(0xff);
Serial.write(0xff);
Serial.write(0xff);
}

Kann das einer bestätigen? mein englich ist nicht so gut weiß nicht ob es richtig verstanden habe. :confused:

Und noch etwas was ich nicht ganz verstehe, bei den Arduino due stand Achtung! Logical current 3.3v Versorgung ist weiterhin 5-7v
sind die 3,3v logical current nun die spannung die die pins maximal ausgeben können? oder vertragen?

Meine Endschaltern etc werden mit 5v betrieben verträgt er die oder muss ich die dann an 3,3v klemmen, die 5v commen aus dem Netzteil mit vorwiderstand. Ziehen den Arduino also nix ab, nur der bekommt die 5v bei 20ma meine ich wahren das.

die die pins maximal ausgeben können? oder vertragen?

ja

Wieso glaubst du das nicht, was du liest?
Keiner von uns kann mehr wissen, als im Datenblatt steht.

seby1302:
Und noch etwas was ich nicht ganz verstehe, bei den Arduino due stand Achtung! Logical current 3.3v Versorgung ist weiterhin 5-7v
sind die 3,3v logical current nun die spannung die die pins maximal ausgeben können? oder vertragen?

"Logical current 3.3v" ist Quatsch, denn Strom in Ampere und Spannung in Volt.

Auf der Arduino-Seite steht verständlicher Text:

Warning: Unlike most Arduino boards, the Arduino Due board runs at 3.3V. The maximum voltage that the I/O pins can tolerate is 3.3V. Applying voltages higher than 3.3V to any I/O pin could damage the board.

Die Pins können maximal 3,3 V Spannung ausgeben und vertragen.

Endschalter werden gerne mit 24 V betrieben und über Optokoppler auf die für den µC tauglichen Spannungen gebracht.

Ok dann werd ich die auf 3,3 um Polen was ich nicht verstanden hatte wahr ob es die nur ausgeben kann oder nur vertragen oder beides ^^

Jedenfals tickt er bei 115200 Bauds Minimum doppelt so schnell, werde erstmal das ganze in variablem um schreiben, und im Nextion auswerten, dann nochmal schauen was mit den kürzeren Kommandos passiert ob es mit dem Duo Ausreichend schnell ist.

seby1302:
Ok dann werd ich die auf 3,3 um Polen was ich nicht verstanden hatte wahr ob es die nur ausgeben kann oder nur vertragen oder beides ^^

Ich habe einen Teensy 3.2, der nur 3,3 V Spannung ausgeben kann, wohl aber 5 V Spannung an den digitalen Pins verträgt. Das scheint aber eine Ausnahme zu sein.

Grundsätzlich solltest Du nur etwas zum Display schicken, wenn sich ein Wert ändert. Dazu kannst Du einen Merker setzen, der nach dem Schreiben gleich gelöscht wird:

  if (Displayaktualisieren) {
    Displayaktualisieren = false;
    if (HuelsSensorState) {
      Serial.print("n1.val=");
      Serial.print(1);
      Serial.write(0xff);
      Serial.write(0xff);
      Serial.write(0xff);
    } else {
      Serial.print("n1.val=");
      Serial.print(0);
      Serial.write(0xff);
      Serial.write(0xff);
      Serial.write(0xff);
    }
  }

Eine andere Möglichkeit wäre, die Änderung auszuwerten:

if (aktuellHuelsSensorState != altHuelsSensorState) {...}