Code Hilfe / Verbesserung

Hallo Arduino Gemeinde.

Zuerst möchte ich mich mal eben vorstellen.
Ich bin der Sesto bin 37 Jahre alt und Elektroniker im Stromerzeugungsbereich :).

Nun habe ich vor ein paar Wochen angefangen mit dem Arduino eine Steuerung für die LEGO Eisenbahn meiner Kinder zu Programmieren.

Im ersten abschnitt geht es darum mit dem Arduiono über Relais die weichen zu steuern.
Dafür verwende ich Folgendes Programm aus dem Anhang.

Nun habe ich 2 Probleme:

  1. Die Relais werden beim starten des Arduino eingeschalten sollten aber aus sein.
  2. Beim abfragen der Touchfunktion wird das Relais entweder an oder ausgeschalten,
    ich würde es aber gerne so haben das beim drücken das Relais gezogen wird und nach x Sekunden
    wieder zurückgeschalten wird.

Würde mich freuen wenn ihr mir bei der Lösung der Probleme helfen könntet :wink:

Beste Grüße
Acul

sketch_jul02b.ino.ino (8.22 KB)

Würde mich freuen wenn ihr mir bei der Lösung der Probleme helfen könntet

Die Chancen stehen gut!
Nur leider sehe ich keinen Anhang.

nun aber hoffe ich :slight_smile:

  1. Die Relais werden beim starten des Arduino eingeschalten sollten aber aus sein.

Das hängt von deinen Relais-Modulen ab. Du hast wahrscheinlich "ActiveLow" .
Dann setze sie in setup() gleich in Grundstellung

digitalWrite(relais1, HIGH);
pinMode(relais1, OUTPUT);

Noch eleganter (Geschmackssache) ist es, wenn du eigene logische Zustände definierst

const boolean AUS = HIGH;
const boolean EIN = LOW;
...
   digitalWrite(relais1, AUS);
  1. Beim abfragen der Touchfunktion wird das Relais entweder an oder ausgeschalten,
    ich würde es aber gerne so haben das beim drücken das Relais gezogen wird und nach x Sekunden
    wieder zurückgeschalten wird.

...und während das eine Relais noch an ist, soll man schon das nächste anstupsen können. Stimmts?

Dann ist delay() tabu. und du musst dir für jedes Relais merken, wann es eingeschaltet wurde und entsprechend bei Ablauf ausschalten. ( Das mit millis() - prev > dauer aus BlinkWithoutDelay verstehen und anpassen...)

Hallo Michael.

Danke für deine antworten .
Teil eins habe ich angepasst und funktioniert nun super.

Teil 2 ist noch etwas Knobelig :wink: aber ich arbeite daran.

Eine weitere frage habe ich noch zur Technik des ARDUINO ansich.
Ist es möglich mit dem ARDUINO MEGA etwas direkt also ohne RELAIS zu Schalten das
mit 6V betrieben wird ? Das würde mit die Verkabelung erleichtern.

Es müssen über 6V sein, 5v sind leider zu wenig.

Statt eines Relais kann man bei Gleichstrom einen Transistor nehmen.
Meist ist auch neben der Spannung die erforderliche Stromstärke das Problem.
Ein Arduino direkt kann nicht mal ein 5V Relais schalten. Schau dir dein Relais-Board an. Da ist vermutlich ein Transistor und ein Optokoppler mit drauf.

Bis 100 mA passt ein beliebiger NPN Schalttransistor, ab 1A braucht es einen "Logik Level" MOSFET.
Dazwischen ist es "Geschmackssache" ( MOSFET sind einfacher und bisschen teurer, bei NPN muss man genau schauen, und die 4ct Dinger tun es auch nicht)

Das RELAISboard würde ich am liebsten nicht verwenden auch wenn es jetzt noch im Code implementiert ist und ich damit die ersten versuche starte.
Auf dem Relaisboard ist natürlich ein Optokoppler um beide Schaltbereiche Galvanisch zu trennen.

Verstehe der Arduino ist nur führ sehr geringe ströme ausgelegt.

Möglich währe also auch eine schaltung über Optokoppler die dann 6v schalten ?
Die Relais sind mir einfach zu klobig ;(

Kommt darauf an was du schalten willst. Es kommt nicht nur auf die Spannung, sondern auch auf den Strom an.

Galvanische Trennung ist nicht immer unbedingt nötig. Man kann wie gesagt auch Transistoren direkt ansteuern.

Und "sehr gering" ist etwas untertrieben. 40mA gehen an einem Ausgang schon, wobei es besser ist sich auf weniger zu beschränken

Geschalten werden 8 Magneten wenn alles fertig aufgebaut ist.

Wie ich gerade gemerkt habe ist eine Spannung von 7 Volt besser als 6Volt
Beschrieben ist der magnet mit 1,75 A

Dann nimm nen MOSFet, der macht Dir das Leben leichter und bei den Strömen brauchst Du Dir auch über Wäre keine großen Gedanken zu machen.

Aber mach Dir Gedanken zur Stromversorgung!

Was meinst du damit genau Klaus ?

Ich möchte Den Arduino das 7 Zoll TFT und die Magneten zusammen über ein 7 - 12V Netzteil betreiben.
Da die Magneten ja nicht alle 8 zur gleichen zeit geschalten werden, ich denke höchstens 4 sind auf einmal gleichzeitig in betrieb, sollte es ein gutes Netzteil mit 3A tun.

Ich habe gerade nochmals über den MOSFET gelesen.

Somit würde ich den Arduino zum schalten des Gates verwenden der dann Sorce und Drain schaltet "wie" eine Relais ind so den Elektrischen fluss schliest. Verstanden!

Hallo Gemeinde.

Nun brauche ich nochmals bitte eure Hilfe.

Ich habe dank dieser Anleitung:
http://forum.arduino.cc/index.php?topic=354263.msg2443077#msg2443077
Verstanden wie Ein-Ausschalten mittels eines Timers funktioniert.

Nur bekomme ich es nicht in mein Programm eingefügt.
Ich habe durch das TFT ein if abfrage die den Touch abfragt ob auf einen bestimmten bereich geklickt wird.

// If we press "WEICHE X"
if ((x>=20) && (x<=150) && (y>=40) && (y<=80)) {
drawRoundRect(20, 40, 150, 80); // Rahmen um den bereich
R1_timestore = millis(); // aufschreiben der zeit - Starten des Timers
if(staterelais1 == LOW){ // wenn das Relais aus ist
staterelais1 = HIGH; // schalte es ein
delay(100); // Kurz warten
digitalWrite(relais1,staterelais1); // abspeichern der Zustände
}
else {
if (millis() - 5000 > R1_timestore) { //vergleichen der aufgeschriebenen zeit mit der aktuellen
digitalWrite(relais1,staterelais1); //abspeichern der Zustände
staterelais1 = LOW; //Relais auf Low setzen
}

So sieht der betreffende Code nun aus. ich habe dahinter meine Überlegungen geschrieben

Jedoch schaltet der arduino nun nicht mal mehr das Relais ein.
Wo habe ich noch den Denkfehler ?

Versuche mal diese Variante:

if ((x >= 20) && (x <= 150) && (y >= 40) && (y <= 80)) {
  drawRoundRect(20, 40, 150, 80);                                // Rahmen um den bereich
  R1_timestore = millis();                                            // aufschreiben der zeit - Starten des Timers
  if (staterelais1 == LOW) {                                         // wenn das Relais aus ist
    staterelais1 = HIGH;                                               // abspeichern der Zustände
    delay(100);                                                           // Kurz warten (warum?)
    digitalWrite(relais1, staterelais1);                              // Relais einschalten
  }
} else {
  if (millis() - R1_timestore > 5000) {     //vergleichen der aufgeschriebenen zeit mit der aktuellen
    staterelais1 = LOW;                           //abspeichern der Zustände
    digitalWrite(relais1, staterelais1);        //Relais ausschalten
  }
}

Funktioniert leider auch nicht.

Das Relais Schaltet nicht ein.

Hier mal der Komplette Code:

#include <UTFT.h> 
#include <URTouch.h>

UTFT    myGLCD(SSD1289,38,39,40,41);
URTouch  myTouch( 6, 5, 4, 3, 2);

extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

int x, y;
int VddRelais = 17;

char currentPage, selectedUnit;

unsigned long R1_timestore;

const int relais1 = 8;

int staterelais1 = HIGH;

// ====== Custom Funtions ======
// drawHomeScreen - Custom Function
void drawHomeScreen() {
  // Title
  //myGLCD.setBackColor(0,0,0); // Sets the background color of the area where the text will be printed to black
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(BigFont); // Sets font to big
  myGLCD.print("LegoCity Weichen", CENTER, 10); // Prints the string on the screen
  myGLCD.setColor(255, 0, 0); // Sets color to red
  myGLCD.drawLine(0,32,319,32); // Draws the red line
  
  // Button - WEICHE 1
  myGLCD.setColor(16, 167, 103);
  myGLCD.fillRoundRect (20, 40, 150, 80); 
  myGLCD.setColor(255, 255, 255); 
  myGLCD.drawRoundRect (20, 40, 150, 80); 
  myGLCD.setFont(BigFont); 
  myGLCD.setBackColor(16, 167, 103); 
  myGLCD.print("WEICHE 1", 21, 52); 
}

// Highlights the button when pressed
void drawRoundRect(int x1, int y1, int x2, int y2) {
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (x1, y1, x2, y2);

}

void setup() {
   myGLCD.InitLCD();
   myGLCD.clrScr();
   myTouch.InitTouch();
   myTouch.setPrecision(PREC_MEDIUM);
   
   digitalWrite(relais1,HIGH);

   pinMode(relais1, OUTPUT);

   pinMode(VddRelais, OUTPUT);
   digitalWrite(VddRelais, HIGH);

    drawHomeScreen();  // Draws the Home Screen
  currentPage = '0'; // Indicates that we are at Home Screen

}

void loop() {
  
  if (currentPage == '0') {
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x=myTouch.getX(); // X coordinate where the screen has been pressed
      y=myTouch.getY(); // Y coordinates where the screen has been pressed
      
      // If we press  "WEICHE X"
      if ((x>=20) && (x<=150) && (y>=40) && (y<=80)) {
        drawRoundRect(20, 40, 150, 80); 
        R1_timestore = millis();
        if(staterelais1 == LOW){
          staterelais1 = HIGH;
          // delay(100);
          digitalWrite(relais1,staterelais1);       
        }
          else {
          if (millis() - R1_timestore > 5000) {
           staterelais1 = LOW;
           digitalWrite(relais1,staterelais1);
          }
        }
      }
    }
  }
}

versuch es mal so:

#define Aus HIGH
#define An LOW

#include <UTFT.h>
#include <URTouch.h>

UTFT    myGLCD(SSD1289,38,39,40,41);
URTouch  myTouch( 6, 5, 4, 3, 2);

extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];

int x, y;
int VddRelais = 17;

char currentPage, selectedUnit;

unsigned long R1_timestore;

const int relais1 = 8;

int staterelais1 = HIGH;

// ====== Custom Funtions ======
// drawHomeScreen - Custom Function
void drawHomeScreen() {
  // Title
  //myGLCD.setBackColor(0,0,0); // Sets the background color of the area where the text will be printed to black
  myGLCD.setColor(255, 255, 255); // Sets color to white
  myGLCD.setFont(BigFont); // Sets font to big
  myGLCD.print("LegoCity Weichen", CENTER, 10); // Prints the string on the screen
  myGLCD.setColor(255, 0, 0); // Sets color to red
  myGLCD.drawLine(0,32,319,32); // Draws the red line
 
  // Button - WEICHE 1
  myGLCD.setColor(16, 167, 103);
  myGLCD.fillRoundRect (20, 40, 150, 80);
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (20, 40, 150, 80);
  myGLCD.setFont(BigFont);
  myGLCD.setBackColor(16, 167, 103);
  myGLCD.print("WEICHE 1", 21, 52);
}

// Highlights the button when pressed
void drawRoundRect(int x1, int y1, int x2, int y2) {
  myGLCD.setColor(255, 0, 0);
  myGLCD.drawRoundRect (x1, y1, x2, y2);
  while (myTouch.dataAvailable())
    myTouch.read();
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRoundRect (x1, y1, x2, y2);

}

void setup() {
   myGLCD.InitLCD();
   myGLCD.clrScr();
   myTouch.InitTouch();
   myTouch.setPrecision(PREC_MEDIUM);
   
   digitalWrite(relais1,HIGH);

   pinMode(relais1, OUTPUT);

   pinMode(VddRelais, OUTPUT);
   digitalWrite(VddRelais, HIGH);

    drawHomeScreen();  // Draws the Home Screen
  currentPage = '0'; // Indicates that we are at Home Screen

}

void loop() {
 
  if (currentPage == '0') {
    if (myTouch.dataAvailable()) {
      myTouch.read();
      x=myTouch.getX(); // X coordinate where the screen has been pressed
      y=myTouch.getY(); // Y coordinates where the screen has been pressed
     
      // If we press  "WEICHE X"
      if ((x>=20) && (x<=150) && (y>=40) && (y<=80)) {
        drawRoundRect(20, 40, 150, 80);
        R1_timestore = millis();
        if(staterelais1 == Aus){
          staterelais1 = An;
          // delay(100);
          digitalWrite(relais1,staterelais1);       
        }
          else {
          if (millis() - R1_timestore > 5000) {
           staterelais1 = Aus;
           digitalWrite(relais1,staterelais1);
          }
        }
      }
    }
  }
}

Was bringt die definition
#define Aus HIGH
#define An LOW
genau ?

Nun lässt sich das Relais einschalten per druck auf das Touch Feld jedoch schaltet es danach nicht mehr aus, nicht auf wiederholten Touch oder auch nicht automatisch nach den gewünschten 5sek.

Was bringt die definition
#define Aus HIGH
#define An LOW
genau ?

überall wo Aus steht wird HIGH eingesetzt
überall wo An steht wird LOW eingesetzt
da du active Low Relais verwendest, mußt du die Logik negieren

Okay das habe ich verstanden.
im original Code bei dem bis zu 16 Relais geschalten werden habe ich umgedacht und LOW als HIGH angesehen.

Hast du evtl noch einen Lösungs vorschlag ?

Nun lässt sich das Relais einschalten per druck auf das Touch Feld jedoch schaltet es danach nicht mehr aus, nicht auf wiederholten Touch oder auch nicht automatisch nach den gewünschten 5sek.

du solltest dir deine geschweiften Klammern mal ansehen, da ist der Hund begraben.