Propleme bei Düngepumpe

Hallo,

ich bin gerade daran mit meinen bescheiden Programmierkenntnisse eine kleine Düngepumpe für mein Aquarium zu bauen. Ich bin auch schon recht weit, nur habe ich jetzt ein kleines Problem mit der Steuerung. Immer wenn ich den die Düngepumpe (über TIP122) schalte, haut es mir kurzeitig immer wieder die Uhrzeit zusammen (sie Bild im Anhang), was zu einem kurzen Aussetzer der Pumpe führt. Wenn die Pumpe nicht geschalten ist kommt es nicht zu diesem Zeitfehler. Ich hoffe ihr könnt mir helfen und verflucht mich nicht für meine Programmierung.

Vielen Dank im voraus

Johannes

P.s. Ich habe gerade nur eine Diode an den Ausgang gehängt und da läuft der Code ohne Fehler. Also gehe ich mal davon aus das in meiner Schaltung was nicht stimmt. Hab an Base einen 1k Ohm Widerstand am collector eine 1N4007 Diode

#include "LCD4Bit_mod.h"
#include "Wire.h"
#include <DS18B20.h>

int dosierpumpe1 = 2;                                   // Düngepumpe 1 an Pin 2

int duengemenge1 = 10;                                  // Düngemenge Pumpe 1 in ml

int duengedauer1 = duengemenge1 * 3 ;                   // Berechnung der Laufzeit Pumpe 1

long duengezeit1 = 194200;                               // Düngezeitpunkt 1  hhmmss



char buffer[20] = "";                                    // Speicherbereich für Datenkonvertierung

LCD4Bit_mod lcd = LCD4Bit_mod(2);                        // LCD-Display
DS18B20_List ds18b20(5);                                 // DS18B20 an Pin 5

#define wassertemperatur 0x899A                          // DS18B20 Adresse
#define DS3232_I2C_ADDRESS 0x68                          // I2C Adresse

/****************************************************************************************************
 * Konvertierung BCD-kodierter Dezimalzahl
 */
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

/****************************************************************************************************
 * Zeit und Datum aus DS1307 auslesen und konvertieren
 */
void getDateDs1307(int date[])
{
  Wire.beginTransmission(DS3232_I2C_ADDRESS);         // I2C-Kommunikation im Schreibmodus starten
  Wire.write(0x00);                                   // Registerzeiger auf 0 setzen
  Wire.endTransmission();                             // I2C-Kommunikation beenden
  Wire.requestFrom(DS3232_I2C_ADDRESS, 7);            // I2C-Kommunikation im Lesemodus starten

  date[ 0 ] = bcdToDec(Wire.read() & 0x7f);        // Sekunden
  date[ 1 ] = bcdToDec(Wire.read());               // Minuten
  date[ 2 ] = bcdToDec(Wire.read() & 0x3f);        // Stunden
  date[ 3 ] = bcdToDec(Wire.read());               // Wochentag
  date[ 4 ] = bcdToDec(Wire.read());               // Tag
  date[ 5 ] = bcdToDec(Wire.read());               // Monat
  date[ 6 ] = bcdToDec(Wire.read());               // Jahr
}

/****************************************************************************************************
 */
void setup() {
  Serial.begin(9600);
  Wire.begin();                                    // I2C-Bus einrichten

  lcd.init();                                      // LCD-Anzeige initialisieren
  lcd.clear();
  lcd.printIn( "DS1307 - Uhr" );


  pinMode(dosierpumpe1, OUTPUT);                       // Digitaler Pin 2 als Ausgang
}
/****************************************************************************************************
 */
void loop() {

  int datum[ 7 ];
  char str[30] ;
  long Stunde = datum[2];
  long uhrzeit = Stunde * 10000 + datum[1] * 100 + datum[0];


  getDateDs1307( datum );                            // Datum und Uhrzeit aus DS1307 holen
  ds18b20.update();                                  // Temperatur aus DS18B20 holen

   // Schalten der Düngepumpen
  
  if (uhrzeit < duengezeit1 ) {
 digitalWrite( dosierpumpe1, LOW);
  }
  else if ( uhrzeit > duengezeit1 + duengedauer1) {
    digitalWrite( dosierpumpe1, LOW);
  }
  else {
    digitalWrite(dosierpumpe1, HIGH);

  }


  // Anzeige im LCD
  
  sprintf( str, "%02d-%02d   %02d:%02d:%02d",
           datum[4], datum[5],
           datum[2], datum[1], datum[0] );
  lcd.cursorTo( 1, 0 );
  lcd.printIn( str );


  // Anzeige im Serial Monitor
  
  sprintf( str, "Temp", dosierpumpe1);
  lcd.cursorTo( 2, 0 );
  lcd.printIn( str );


  Serial.println(uhrzeit);
   float T_wasser=ds18b20.get_temp_by_id(wassertemperatur);
  Serial.print("Wassertemperatur: ");
  print_temperature(T_wasser);
  Serial.println("C");
  
  delay(1000);
}

Bitte die Schaltung.
Grüße Uwe

P.s. Ich habe gerade nur eine Diode an den Ausgang gehängt und da läuft der Code ohne Fehler. Also gehe ich mal davon aus das in meiner Schaltung was nicht stimmt. Hab an Base einen 1k Ohm Widerstand am collector eine 1N4007 Diode

Und um genau das herauszufinden benötigen wir ein Schaltbild, ohne dem dem wir im Trüben fischen.

Ich denke, das war die fehlende Freilaufdiode.

Hallo,

die Freilaufdiode habe ich die ganze zeit dran gehabt. Ich habe gerade das ganze nur mit einer einzigen kleinen LED probiert. Und wenn ich nur diese LED statt dem Transistor schalte gibt es keine Probleme.

Auf dem Bildern jetzt nicht zu sehen aber das Rote und das Schwarze Kabel führen zur Pumpe. Oben links zu sehen Eingang des Netzteils.

Gruß Johannes

IMG_3996.JPG

IMG_3997.JPG

IMG_3998.JPG

Eine LED verbraucht erstens nicht so viel Strom wie eine Pumpe. Und zweitens verhalten sich induktive Lasten generell völlig anders.

Ok und wie lässt sich dass umgehen? Ich schalte ja die Pumpe nicht direkt sondern eben den Transistor. Gibt es einen anderen Transistor mit dem sich die pumpe schalten lässt?

Grüße Johannes

Ich vermute einen Spannungseinbruch, wenn die.Pumpe anspringt. Wird der Ardu am selben Netzteil wie die Pumpe betrieben?

Ja wird es. Habe es gerade nochmal damit probiert den arduino per USB und die Pumpe mit dem 12V Netzteil zu betreiben. Der Fehler bleibt der selbe. Allerdings tritt das nicht beim Anlaufen der Pumpe sondern mitten im Fördervorgang auf.
Ich verwende diese Schlauchpumpe

Was zieht die Pumpe für Strom?

Ich habe jetzt 150mA gemessen.

Ok, das scheint nicht das Problem zu sein.

Ich würde es aber mal mit einem Darlington versuchen.

Ja denn muss ich erst bestellten. Hab da jetzt keinen da. Habe es gerade mit einem IRL3803 versucht. Selbes Problem

Der TIP12x ist ein Darlington...

Der Strom sollte eigentlich reichen. Vor allem wenn du sagst, dass es nicht am Anlaufstrom liegt. Einen größeren Kondensator (mehrere 100 µF) könnte man trotzdem mal probieren.

Elektromagnetische Störungen durch die Pumpe sind noch eine Möglichkeit.

Ist der Motor der Pumpe entstört? Mal in jede Zuleitung eine Drossel und direkt am Motor 100nF parallel zu diesem. Evtl. einen Widerstand an der Basis des Darlington-Transistors. Letze Idee: Motorkreis mittels Optokoppler oder Relais vollkommen vom Arduino trennen ...

HotSystems:
Ok, das scheint nicht das Problem zu sein.

Ich würde es aber mal mit einem Darlington versuchen.

der verwendete TIP122 ist ein Darlington.

Evtl. einen Widerstand an der Basis des Darlington-Transistors.

Da ist ja schon einer.

Aber der Vorschlag einen 0,1µ Kondensators an den Klemmen/Anschlüssen ds Motors wäre einen Versuch wert.

Einen fehlende Freilaufdiode macht sich erst beim Abschalten des Motors bemerkbar.

Grüße Uwe

Also die Kondensatoren scheinen die Lösung zu sein. Vielen Dank an aller Vorschläge freu

uwefed:
der verwendete TIP122 ist ein Darlington.
Da ist ja schon einer.

Aah, ok, danke. :smiley:

Hallo,

ich hätte da jetzt noch eine Frage zu meinem Projekt. Ich habe den RTC DS1307 gegen einen DS3231 getauscht da dieser ja genauer sein soll. Das ging auch problemlos ohne den Code zu ändern. Allerdings würde ich jetzt noch den intigrierten Temperatursensor verwenden und habe allerdings keine Ahnung wie ich an die Daten kommen soll. Könnt ihr mir helfen?

#include "LCD4Bit_mod.h"
#include "Wire.h"
#include <DS18B20.h>

int dosierpumpe1 = 10;                                   // Düngepumpe 1 an Pin 10

int duengemenge1 = 9;                                    // Düngemenge Pumpe 1 in ml

int duengedauer1 = duengemenge1 * 1.7;                   // Berechnung der Laufzeit Pumpe 1

long duengezeit1 = 100000;                               // Düngezeitpunkt 1  hhmmss

int motorPin = 2;                                        // Lüfter an Pin 6
float threshold = 30;                                    // Schalttemperatur für Lüfter (30 Grad Celsius)
float hysterese = 0.5;                                     // Hysterese Wert (0.5 Grad Celsius)

char buffer[20] = "";                                    // Speicherbereich für Datenkonvertierung

LCD4Bit_mod lcd = LCD4Bit_mod(2);                        // LCD-Display
DS18B20_List ds18b20(9);                                 // DS18B20 an Pin 9

#define wassertemperatur 0x899A                          // DS18B20 Adresse
#define DS3231_I2C_ADDRESS 0x68                          // I2C Adresse

/****************************************************************************************************
 * Konvertierung BCD-kodierter Dezimalzahl
 */
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

/****************************************************************************************************
 * Zeit und Datum aus DS1307 auslesen und konvertieren
 */
void getDateDs3231(int date[])
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);         // I2C-Kommunikation im Schreibmodus starten
  Wire.write(0x00);                                   // Registerzeiger auf 0 setzen
  Wire.endTransmission();                             // I2C-Kommunikation beenden
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);            // I2C-Kommunikation im Lesemodus starten

  date[ 0 ] = bcdToDec(Wire.read() & 0x7f);        // Sekunden
  date[ 1 ] = bcdToDec(Wire.read());               // Minuten
  date[ 2 ] = bcdToDec(Wire.read() & 0x3f);        // Stunden
  date[ 3 ] = bcdToDec(Wire.read());               // Wochentag
  date[ 4 ] = bcdToDec(Wire.read());               // Tag
  date[ 5 ] = bcdToDec(Wire.read());               // Monat
  date[ 6 ] = bcdToDec(Wire.read());               // Jahr
}

/****************************************************************************************************
 */
void setup() {
  Serial.begin(9600);
  Wire.begin();                                    // I2C-Bus einrichten

  lcd.init();                                      // LCD-Anzeige initialisieren
  lcd.clear();
  lcd.printIn( "DS1307 - Uhr" );


  pinMode(dosierpumpe1, OUTPUT);                       // Digitaler Pin 10 als Ausgang
  pinMode(motorPin, OUTPUT);                           // Digitaler Pin 2 als Ausgang
}
/****************************************************************************************************
 */
void loop() {

  int datum[ 7 ];
  char str[30] ;
  long Stunde = datum[2];
  long uhrzeit = Stunde * 10000 + datum[1] * 100 + datum[0];
  getDateDs3231( datum );                            // Datum und Uhrzeit aus DS1307 holen
  ds18b20.update();                                  // Temperatur aus DS18B20 holen
  float T_wasser = ds18b20.get_temp_by_id(wassertemperatur);

  // Schalten der Düngepumpen

  if (uhrzeit < duengezeit1 )
    digitalWrite( dosierpumpe1, LOW);
  else if ( uhrzeit > duengezeit1 + duengedauer1)
    digitalWrite( dosierpumpe1, LOW);
  else
    digitalWrite(dosierpumpe1, HIGH);

  // Schalten des Lüfters

  if (T_wasser > (threshold + hysterese))
    digitalWrite(motorPin, HIGH);
  else if (T_wasser < (threshold - hysterese))
    digitalWrite(motorPin, LOW);


  // Anzeige im LCD

  sprintf( str, "%02d-%02d   %02d:%02d:%02d",
           datum[4], datum[5],
           datum[2], datum[1], datum[0] );
  lcd.cursorTo( 1, 0 );
  lcd.printIn( str );


  // Anzeige im Serial Monitor

  sprintf( str, "Temp", dosierpumpe1);
  lcd.cursorTo( 2, 0 );
  lcd.printIn( str );


  Serial.println(uhrzeit);
  Serial.print("Wassertemperatur: ");
  Serial.print(T_wasser);
  Serial.println("C");
  
  delay(1000);
}

Schau dir halt mal das Datenblatt an:

Auf Seite 11 siehst du unten die zwei Temperatur-Register 0x11 und 0x12. Siehe auch Seite 15

Oder du verwendest eine fertige Library:

Oder du nimmst nur die entsprechende Funktion daraus und passt die an:

int temperature()
{
    union int16_byte {
        int i;
        byte b[2];
    } rtcTemp;
    
    rtcTemp.b[0] = readRTC(TEMP_LSB);
    rtcTemp.b[1] = readRTC(TEMP_MSB);
    return rtcTemp.i >> 6;
}

EDIT: Bessere Lib und Funktion gefunden

Also so anpassen dass statt readRTC() (das ist eine andere Funktion in der Library) jeweils der Inhalt des entsprechenden Registers für LSB und MSB genommen wird.

Das liefert dann die Temperatur als int in 0.25° Schritten

So ganz bin ich da noch nicht durchgestiegen, liegt aber einfach daran dass für mich als Neuling das an vielen Stellen des Codes immer nach Banhof klingt xD. Also Tschuldigung wenn ich jetzt noch mal paar doof Fragen stelle.

Aber im Moment erschließt sich mir aus dem von dir gepostetn Code nicht so genau was der Controller da tut.

Weil es wird ja die variable "temperatur" definiert. Dann bei byte ein array mit zwei "stellen" (MSB und LSB vermutlich?). In rtcTemp.b[0] wird der LSB und in [1] der MSB geschriebe.

Aber wie kommt jetzt die zahl in meine definierte Variable temperatur?