Millis mit 3600000UL klappt nicht

Hallo miteinander,

ich habe folgende Hardware im Einsatz

  • Arduino Uno V3
  • Adafruit Motorshield V2
  • 3 Wasserpumpen

Die ersten 2 Wasserpumpen sollen im Stundentackt für 1 Minute lang Strom bekommen.
Die dritte Wasserpumpe läuft alle 3 Sekunden für nur wenige Millisekunden lang.

Jedoch starten die 2 Wasserpumpen erst gar nicht.
Wenn ich jedoch den Takt von 1 Stunde auf bsw. 10 Minuten reduziere klappt es.

Hat jemand einen Tipp woran das liegen kann?

#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
Adafruit_DCMotor *myMotor2 = AFMS.getMotor(2);
Adafruit_DCMotor *myMotor3 = AFMS.getMotor(3);

class Flasher
{
  // Class Member Variables
  // These are initialized at startup
  long MotorOnTime;     // milliseconds of on-time
  long MotorOffTime;    // milliseconds of off-time
  int MotorSpeed; // milliseconds of off-time
  Adafruit_DCMotor *motor;

  // These maintain the current state
  int MotorState;                 // MotorState used to set the Motor
  unsigned long previousMillis;   // will store last time Motor was updated

  // Constructor - creates a Flasher 
  // and initializes the member variables and state
  public:
  Flasher(Adafruit_DCMotor *p_motor)
  {
      MotorState = 0;
      previousMillis = 0;
      // Set the speed to start, from 0 (off) to 255 (max speed)
      motor = p_motor;
  }

  void Update(long on, long off, int m_speed)
  {
      MotorOnTime = on;
      MotorOffTime = off;
      MotorSpeed = m_speed; 
      motor->setSpeed(MotorSpeed);
    // check to see if it's time to change the state of the LED
    unsigned long currentMillis = millis();
     
    if((MotorState == 1) && (currentMillis - previousMillis >= MotorOnTime))
    {
      MotorState = 0;  // Turn it off
      previousMillis = currentMillis;  // Remember the time
      Serial.println(MotorOnTime);
      motor->run(FORWARD);
    }
    else if ((MotorState == 0) && (currentMillis - previousMillis >= MotorOffTime))
    {
      MotorState = 1;  // turn it on
      previousMillis = currentMillis;   // Remember the time
      Serial.println(MotorOffTime);
      motor->run(RELEASE);
    }
  }
};

Flasher pumpe1(myMotor);
Flasher pumpe2(myMotor2);
Flasher pumpe3(myMotor3);

void setup()
{
  Serial.begin(9600);
  Serial.println("Adafruit Motorshield v2 - DC Motor test!");

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
}

void loop()
{
  pumpe1.Update(3600000UL,60000,255);
  pumpe2.Update(3600000UL,60000,255);
  pumpe3.Update(3000,200,50);
}

mich springt nichts an (außer die permanenten Parameterübergaben, die es wohl kaum braucht, aber auch nicht die Ursache sein werden).

Wie kannst du sicher sein, dass dein Sketch überhaupt die Stunde durchläuft und nicht schon vorher z.B. wegen einer kurzen Stromschwankung einen Reset durchführt?

Daher nur mal so auf Verdacht:
Serial.print Ausgaben ergänzen
auf einem Display die aktuellen Millis und previous Millis ausgeben lassen.

Hi

Erwartest Du Negativ-Laufzeiten?
Wenn nicht, änder das LONG in UNSIGNED LONG für die Zeiten.

LONG (auf Uno/Nano) = 31 Bit, max 2147483647
Du möchtest darin aber 3600000000 speichern - passt nicht.
Denke, der Kompiler müsste Dir dazu eine Warnung auswerfen - in den Einstellungen dafür die ausführlichen Warnungen beim Kompilieren und Hochladen anklicken.
Erst bei UNSIGNED hast Du die 32 Bit, was den Wertebereich nach oben verdoppelt - Da passen dann auch die 3,6 Mrd rein.

... hatte Da 3 Nullen zu viel 'gezählt' - mit nur 3,6 Mio sollte auch LONG passen
MfG

noiasca:
Daher nur mal so auf Verdacht:
Serial.print Ausgaben ergänzen
auf einem Display die aktuellen Millis und previous Millis ausgeben lassen.

an welcher Stelle meinst du das?
ich gebe doch mit Serial.println(MotorOnTime); und Serial.println(MotorOffTime); die Millis aus.

naja aber nur dann, wenn die Bedingung erfüllt ist.
Du suchst ja jetzt einen Grund, warum du da nicht reinkommst, also solltest die Ausgaben so machen, dass sich die laufend aktualsieren so dass du es auch siehst oder?

Meiner Meinung kannst Du die Variable "MotorState" nicht für 3 Motoren verwenden. Jeder Motor braucht seine. Das gleiche gilt für "previousMillis".

Die dritte Wasserpumpe läuft alle 3 Sekunden für nur wenige Millisekunden lang.

Meiner Meinung ist das Utopie.Kein Motor läuft in so kurzer Zeit an.

void Update(long on, long off, int m_speed)
  {
      MotorOnTime = on;
      MotorOffTime = off;
      MotorSpeed = m_speed;

Wieso Kopierst Du die Variablen um? Wieso schreibst Du die Variablen nicht gleich in die Funktion?

void Update(long MotorOnTime, long MotorOffTime, int  MotorSpeed)
  {

Grüße Uwe

Meiner Meinung kannst Du die Variable "MotorState" nicht für 3 Motoren verwenden. Jeder Motor braucht seine. Das gleiche gilt für "previousMillis".

Hat ihm doch.
(soweit ich das erkennen kann)

Bei dem Rest stimme ich dir schon zu.
Die Klasse könnte man noch gut entschlacken.....

@combie

Hat ihm doch.
(soweit ich das erkennen kann)

Jetzt verstehe ich Dich nicht.
Uwe

Jetzt verstehe ich Dich nicht.

Dann will ich mal versuchen, dem entgegen zu wirken......

"MotorState" und "previousMillis" sind private Instanzeigenschaften.
Stehen also für jeden Motor unabhängig zur Verfügung.

Da kommt sich nichts ins Gehege.

So ich das sehe.

aha
Danke
Uwe

Habe da mal ein bisschen drüber gefegt...
Versucht, möglichst viel unverändert zu übernehmen.
Also: Da lässt sich noch einiges verbessern.

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include <CombieTypeMangling.h>

using namespace Combie::Millis;

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
Adafruit_DCMotor *myMotor2 = AFMS.getMotor(2);
Adafruit_DCMotor *myMotor3 = AFMS.getMotor(3);

class Flasher
{
   private:
    // Class Member Variables
    // These are initialized at startup
    unsigned long MotorOnTime;     // milliseconds of on-time
    unsigned long MotorOffTime;    // milliseconds of off-time
    unsigned int  MotorSpeed; 
    Adafruit_DCMotor *motor;

    // These maintain the current state
    enum MotorState {EIN,LAUFZEIT,AUS,WARTEZEIT};
    MotorState motorState;                 // MotorState used to set the Motor
    unsigned long timestamp;   // will store last time Motor was updated

    // Constructor - creates a Flasher
    // and initializes the member variables and state
  public:
    Flasher(Adafruit_DCMotor *p_motor):motorState(EIN),motor(p_motor),timestamp(0){}

    void set(const unsigned long on, const unsigned long off, const unsigned int m_speed)
    {
      MotorOnTime = on;
      MotorOffTime = off;
      MotorSpeed = m_speed;
      motor->setSpeed(MotorSpeed);
    }
    
    void run()
    {
      // check to see if it's time to change the state of the LED
      unsigned long currentMillis = millis();
      switch(motorState)
      {
        case EIN:       timestamp = currentMillis;  // Remember the time
                        Serial.println(MotorOnTime);
                        motor->run(FORWARD);
                        motorState = LAUFZEIT;
                        break;

        case LAUFZEIT:  if(currentMillis - timestamp >= MotorOnTime)
                        {  
                          motorState = AUS;
                        }
                        break;
                       
        case AUS:       timestamp = currentMillis;  // Remember the time
                        Serial.println(MotorOffTime);
                        motor->run(RELEASE);
                        motorState = WARTEZEIT;
                        break;

        case WARTEZEIT: if(currentMillis - timestamp >= MotorOffTime)
                        {  
                           motorState = EIN;
                        }
                        break;
      }
    }
};

Flasher pumpe1(myMotor);
Flasher pumpe2(myMotor2);
Flasher pumpe3(myMotor3);

void setup()
{
  Serial.begin(9600);
  Serial.println("Adafruit Motorshield v2 - DC Motor test!");

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz

  pumpe1.set( 1_hr,   1_min, 255);
  pumpe2.set( 1_hr,   1_min, 255);
  pumpe3.set( 3_sec, 200_ms,   50);
  
  /*
  // testdaten
  pumpe1.set(2_sec,  1.5_sec, 255);
  pumpe2.set(3_sec,    4_sec, 255);
  pumpe3.set(5_sec, 2.22_sec,  50);
  */  
}

void loop()
{
  pumpe1.run();
  pumpe2.run();
  pumpe3.run();
}

CombieTypeMangling.zip (4.44 KB)