Arduino Due DAC mit Tasten selbst definieren

Hallo,
ich bin noch ziemlich neu was Arduino und alles drum herum angeht und ich dachte ich stelle meine Frage bzw Fragen mal hier in das Forum.
Also ich arbeite an einem folgenden Projekt:
Ich bin dran mit einem Arduino Due verschiedene DAC Outputs (verschiedene Spannungen) zu erzeugen. Das Ganze habe ich versucht mit einem 4x4 Keypad zu realisieren. Bis jetzt hat auch alles funktioniert sodass ich alle 16 Spannungen definieren konnte das sie auch richtig ausgegeben werden. Der nächste Schritt des Ganzen ist nicht mehr per Taste eine bestimmte Spannung auszugeben, sondern mit dem Keypad die Spannung vorzugeben. Meine Idee war es dazu ein Display (LCD 1602 Module) zu benutzen damit ich einsehen kann welche Spannung ich eintippe.
Jetzt stehe ich nur vor dem Großen Problem, dass ich nicht weiß wie ich das realisieren soll…
Muss ich dazu das Keypad an die Analogen Eingänge anschließen und kann ich dann in den Code einfach nur die Volt zahl schreiben oder brauche ich Grundsätzlich immer die Dezimalzahl damit der Arduino damit was anfangen kann?

Ich hoffe ich habe es verständlich genug erklärt und das mir jemand helfen kann^^

Was genau verstehst du unter Keypad ?
Bitte Link posten.

Wenn es ein Tastenfeld ist, dann gehört das an die "diigitale Seite" des Arduino. Damit willst du doch die Spannung vorgeben.
Also musst du das dem Arduino über die Pins mitteilen.

Hallo,
du kannst Dein Projekt basierend auf dem EVA-Prinzip umsetzen. Dafür zerlegst Du die Aufagenstellung in funktionale Blöcke, die einzeln gestestet und danach zum Gesamtprojekt zusammen geführt werden.
E = Eingabe ->>> Keypad, dafür gibt eine Menge Tutorials
V = Verabeitung ->>>
A = Ausgabe ->>> Anzeige, dafür gibt eine Menge Tutorials und DAC´s
Das ganze blockadefrei in einem Sketch umsetzen und Fertig ist Dein Projekt :slight_smile:

HotSystems:
Was genau verstehst du unter Keypad ?
Bitte Link posten.

Wenn es ein Tastenfeld ist, dann gehört das an die "diigitale Seite" des Arduino. Damit willst du doch die Spannung vorgeben.
Also musst du das dem Arduino über die Pins mitteilen.

Ich meine damit ein so ein Keypad: https://eckstein-shop.de/4x4-Matrix-Array-Keypad-8-pin-16-key-membranKeyboard-fuer-Arduino?curr=EUR&gclid=EAIaIQobChMIlvLwxL2T7wIVkdayCh07BwHaEAQYAyABEgIOW_D_BwE

paulpaulson:
Hallo,
du kannst Dein Projekt basierend auf dem EVA-Prinzip umsetzen. Dafür zerlegst Du die Aufagenstellung in funktionale Blöcke, die einzeln gestestet und danach zum Gesamtprojekt zusammen geführt werden.
E = Eingabe ->>> Keypad, dafür gibt eine Menge Tutorials
V = Verabeitung ->>>
A = Ausgabe ->>> Anzeige, dafür gibt eine Menge Tutorials und DAC´s
Das ganze blockadefrei in einem Sketch umsetzen und Fertig ist Dein Projekt :slight_smile:

Das irgendwie klingt das einfach.. aber ich weiß jetzt noch nicht genau wie ich anfangen soll :confused:
Könntest du mir das vielleicht anhand eines Beispiels das genauer erläutern? Das wäre echt super :slight_smile:
Aber schonmal danke für den Ansatz!^^

Muss ich dazu das Keypad an die Analogen Eingänge anschließen

es müssen halt freie Pins sein. die "Analogen" Eingänge können eben auch für Analog-Eingänge verwendet werden, ein "digitales" high/low können die aber auch unterscheiden.

und kann ich dann in den Code einfach nur die Volt zahl schreiben oder brauche ich Grundsätzlich immer die Dezimalzahl damit der Arduino damit was anfangen kann?

42!

du kannst
lcd.print("14.5 Volt");
schreiben wie auch
lcd.print(myDecimal);

noiasca:
es müssen halt freie Pins sein. die "Analogen" Eingänge können eben auch für Analog-Eingänge verwendet werden, ein "digitales" high/low können die aber auch unterscheiden.

42!

du kannst
lcd.print("14.5 Volt");
schreiben wie auch
lcd.print(myDecimal);

Also zu dem ersten Teil dann belasse ich es bei den Digitalen Eingängen.
zu dem anderen Teil übernimmt der DAC dann auch die Dezimalzahl? Also das wenn ich über das Keypad schreibe 1,5 und auf dem Display 1,5V steht, beim Ausgang des DAC auch 1,5V gemessen werden können?

zu dem anderen Teil übernimmt der DAC dann auch die Dezimalzahl? Also das wenn ich über das Keypad schreibe 1,5 und auf dem Display 1,5V steht, beim Ausgang des DAC auch 1,5V gemessen werden können?

Nicht von alleine - das musst Du schon so programmieren. Das ist aber möglich.

Fang doch erstmal damit an, die Ziffern von Deinem Keyboard einzulesen und auf der seriellen Schnittstelle (Monitor) auszugeben.
Hinweise:
Die verlinkte Tastatur hat keinen Dezimalpunkt.
Du musst Dir überlegen, wann das Ende der Eingabe festgestellt werden soll - vermutlich willst Du ja nicht für glatte 2V immer 2.00 eingeben wollen und eine Monstereingabe à la 3.1426926 ergibt m.E. eher wenig Sinn.

wno158:
Nicht von alleine - das musst Du schon so programmieren. Das ist aber möglich.

Fang doch erstmal damit an, die Ziffern von Deinem Keyboard einzulesen und auf der seriellen Schnittstelle (Monitor) auszugeben.
Hinweise:
Die verlinkte Tastatur hat keinen Dezimalpunkt.
Du musst Dir überlegen, wann das Ende der Eingabe festgestellt werden soll - vermutlich willst Du ja nicht für glatte 2V immer 2.00 eingeben wollen und eine Monstereingabe à la 3.1426926 ergibt m.E. eher wenig Sinn.

Das am Monitor auszugeben hab ich schon gemacht. Ich hatte ja das Projekt soweit das ich pro Taste eine andere Spannung ausgeben konnte.
Das ist der Code den ich mir zusammen gebastelt habe:

#include <Keypad.h>

int Ausgang = DAC0;
//int DAC0 = 66;
//int DAC1 = 67;                      vielleicht reicht auch nur ein Ausgang
//int value = analogRead(0);          //Sobald das hier aktiv ist funktioniert das Tastenfeld nicht mehr




//Keypad ==================================

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {52, 48, 44, 40}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {36, 32, 28, 24}; //connect to the column pinouts of the keypad
char Taste;
//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 
//=================================================================================




void setup() {   
Serial.begin(9600);      //öffne Serielle Kommunikation
analogWriteResolution(12);  //da es 12 bits sind muss es angegeben wird -> Standard Wert ist 8bits | Fehlermeldung weil nicht das richtige Board ausgewählt ist!!!
}

void loop() {

//Keypad Pfad =======================================
char  Taste = customKeypad.getKey();   //pressedKey entspricht der gedrückten Taste

if (Taste) {
    Serial.print("Die Taste "); 
    Serial.print(Taste);
    Serial.println();           //Teile uns am Serial Monitor die gedrückte Taste mit
     
        switch (Taste){            //das Programm soll verschiedene Sachen ausführen je nach dem welche Bedingung (Taste) gedrückt wird
           case '1':              //Taste 1
            //clearSpannung();
            analogWrite(Ausgang, 2700);
            //analogWrite(DAC1, 3722);
            Serial.println("Ausgangswert 4V");
            break;
           
          case '2':
          // clearSpannung();
           analogWrite(Ausgang, 2485); // Spannung beträgt 1,885V
           Serial.println("Ausgangswert 3,77V");
           break;
          
          case '3':
         //  clearSpannung();
           analogWrite(Ausgang, 2420);
           Serial.println("Ausgangswert 3,7V");
           break;

          case '4':
         //  clearSpannung();
           analogWrite(Ausgang, 2365);                       //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 3,627V");
           break;

          case '5':
         //  clearSpannung();
           analogWrite(Ausgang, 2284);
           Serial.println("Ausgangswert 3,552V");
           break;

          case '6':
         //  clearSpannung();
           analogWrite(Ausgang, 2272);                     //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 3,475V");
           break;

          case '7':
        //   clearSpannung();
           analogWrite(Ausgang, 2143);
           Serial.println("Ausgangswert 3,402V");
           break;

          case '8':
         //  clearSpannung();
           analogWrite(Ausgang, 2180);                    //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 3,327V");
           break;

          case '9':
        //   clearSpannung();
           analogWrite(Ausgang, 2049);                    //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 3,253V");
           break;

          case '*':                                 //Nr.10
       //    clearSpannung();
           analogWrite(Ausgang, 2085);                    //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 3,177V");
           break;

          case '0':                                 //Nr.11
       //    clearSpannung();
           analogWrite(Ausgang, 1957);                    //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 3,103V");
           break;

          case '#':                                 //Nr.12
         //  clearSpannung();
           analogWrite(Ausgang, 2818);
           Serial.println("Ausgangswert 3,028V");
           break;

          case 'A':                                 //Nr.13
      //     clearSpannung();
           analogWrite(Ausgang, 1587);                    //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 2,951V");
           break;

          case 'B':                                 //Nr.14
     //      clearSpannung();
           analogWrite(Ausgang, 1717);                    //ggf den Wert nochmal anpassen da sonst 2 Ausgänge benötigt werden um die richtige Spannung raus zu geben
           Serial.println("Ausgangswert 2,877V");
           break;

         case 'C':                                 //Nr.15
        //   clearSpannung();
           analogWrite(Ausgang, 2047);
           Serial.println("Ausgangswert 2,2V");
           break;

          case 'D':                                 //Nr.16
       //    clearSpannung();
           analogWrite(Ausgang, 1861);
           Serial.println("Ausgangswert 2V");
           break; 
        } 
}
}
void clearSpannung(){
  
  analogWrite(Ausgang, 0);
}

kleine Anmerkung vllt dazu.. ich habe noch vor dazu einen OP dran zu bauen damit ich auch wirklich die Spannung raus bekomme die ich brauche. Deshalb sind die Ausgangswerte nur halb so groß als das was er auf dem Monitor anzeigen soll.
ich weiß nur noch nicht ob das mit der If-Bedingung, Switch/case oder einer ganz anderen Sache programmiert werden soll oder kann

Hallo
funktioniert sowas ?

 analogWrite(Ausgang, 2700);

paulpaulson:
Hallo
funktioniert sowas ?

 analogWrite(Ausgang, 2700);

Ja. 'Ausgangs' ist ja definiert als DAC0 und die 2700 stellen dann die 2V da.
Der gesamte Code funktioniert
Mir stellt sich nur die Frage wie ich das halt so programmieren kann das ich nicht die Spannung selber vordefinieren muss wie in dem Code sondern durch die Eingabe des Keypads die Spannung selbst ändert.

Ah ja, danke!
Nun hast Du jetzt den Kontrollfluß "eine Taste -> eine Aktion (Spannung einstellen)".

Was (ich denke was) Du haben willst ist:
"Taste Taste Taste Ende" -> Umwandlung Tastenfolge in Spannungswert -> Aktion
Also würde ich erstmal die Analogausgabe abklemmen und die Tasten für die gewünschte Spannung nacheinander einlesen und umwandeln.

Was das "soll" angeht: Es gibt wie immer verschiedene Möglichkeiten. Die werden wohl meistens eine Kombination aus if und switch/case sein.

Du könntest mit jeder Ziffer, die eingegeben wird, eine interne Variable mitführen und die dann mit jeder neuen Ziffer mit 10 multiplizieren. Das ergibt bei Eingabe 1, 5, 2 dann für Variable intern die Folge 1, 110+5, (110+5)*10+2 = 152.

Andere (u.a. ich) würden wohl die Tasten nacheinander in ein Char-Array (Länge: maximaler Input+1) einlesen. Erst wenn die Eingabe erfolgreich abgeschlossen ist, geht es ans Umwandeln und Ausgeben.

Für den ersten Ansatz Löschtaste für die komplette Eingabe nicht vergessen, vielleicht später dann auch Löschen einzelner Ziffern einbauen.

Übrigens: Dein Code scheint mir für den Anfang funktional; allerdings siehst Du selbst, dass 16 Mal die Folge "clear / analogWrite / print" vorkommt - nur halt mit unterschiedlichen Werten. Das schreit nach einer Funktion. Die Wertezuordnung Taste -> Wert kann in Arrays erfolgen (Taste -> Index, Index -> Spannungswert).

skipzens:
Mir stellt sich nur die Frage wie ich das halt so programmieren kann das ich nicht die Spannung selber vordefinieren muss wie in dem Code sondern durch die Eingabe des Keypads die Spannung selbst ändert.

Ja das ist schon umfangreich. lies sehr aufmerksam was dir wno158 geschrieben hat.

Mach zunächst nur einen Sketch mit der reinen Tasteneingabe und der Testausgabe auf Serial.
Am besten fasst du das am Schluss alles in eine Funktion zusammen, die dir deinen neuen Wert zurückgibt.

Dann bekommst du auch einen Eindruck zur Usability, und ob du schlussendlich in zehntel Volt mit Vornullen arbeiten willst oder mit einem Komma und Enter, Löschen etc.

Schau dir auch die Beispiele der keypad Library noch mal genau an. Da sollte sich was finden wegen debounce und auch zu change state detection.

es könnten diese Methoden sein, aber ich mache nichts mit dieser lib...

customKeypad.setDebounceTime(20); // ?
customKeypad.setHoldTime(5); // ?

wno158:
Ah ja, danke!
Nun hast Du jetzt den Kontrollfluß "eine Taste -> eine Aktion (Spannung einstellen)".

Was (ich denke was) Du haben willst ist:
"Taste Taste Taste Ende" -> Umwandlung Tastenfolge in Spannungswert -> Aktion
Also würde ich erstmal die Analogausgabe abklemmen und die Tasten für die gewünschte Spannung nacheinander einlesen und umwandeln.

Was das "soll" angeht: Es gibt wie immer verschiedene Möglichkeiten. Die werden wohl meistens eine Kombination aus if und switch/case sein.

Du könntest mit jeder Ziffer, die eingegeben wird, eine interne Variable mitführen und die dann mit jeder neuen Ziffer mit 10 multiplizieren. Das ergibt bei Eingabe 1, 5, 2 dann für Variable intern die Folge 1, 110+5, (110+5)*10+2 = 152.

Andere (u.a. ich) würden wohl die Tasten nacheinander in ein Char-Array (Länge: maximaler Input+1) einlesen. Erst wenn die Eingabe erfolgreich abgeschlossen ist, geht es ans Umwandeln und Ausgeben.

Für den ersten Ansatz Löschtaste für die komplette Eingabe nicht vergessen, vielleicht später dann auch Löschen einzelner Ziffern einbauen.

Übrigens: Dein Code scheint mir für den Anfang funktional; allerdings siehst Du selbst, dass 16 Mal die Folge "clear / analogWrite / print" vorkommt - nur halt mit unterschiedlichen Werten. Das schreit nach einer Funktion. Die Wertezuordnung Taste -> Wert kann in Arrays erfolgen (Taste -> Index, Index -> Spannungswert).

Das mit den Variablen könnte ich mal versuchen.
Mit Array habe ich mich selbst noch nicht wirklich auseinander gesetzt ich habe mich versucht mal rein zu lesen allerdings mehr auch nicht aber dann werde ich mich da mal schlauer machen.
Ich muss schauen wie ich das alles einfacher in einer Funktion zusammen fassen könne.

Aber ich hab noch eine Frage:

Du könntest mit jeder Ziffer, die eingegeben wird, eine interne Variable mitführen und die dann mit jeder neuen Ziffer mit 10 multiplizieren. Das ergibt bei Eingabe 1, 5, 2 dann für Variable intern die Folge 1, 110+5, (110+5)*10+2 = 152.

Für was würde dann die 152 stehen? Ich steh da gerade ein bisschen aufm Schlauch

noiasca:
Ja das ist schon umfangreich. lies sehr aufmerksam was dir wno158 geschrieben hat.

Mach zunächst nur einen Sketch mit der reinen Tasteneingabe und der Testausgabe auf Serial.
Am besten fasst du das am Schluss alles in eine Funktion zusammen, die dir deinen neuen Wert zurückgibt.

Dann bekommst du auch einen Eindruck zur Usability, und ob du schlussendlich in zehntel Volt mit Vornullen arbeiten willst oder mit einem Komma und Enter, Löschen etc.

Schau dir auch die Beispiele der keypad Library noch mal genau an. Da sollte sich was finden wegen debounce und auch zu change state detection.

es könnten diese Methoden sein, aber ich mache nichts mit dieser lib...

customKeypad.setDebounceTime(20); // ?
customKeypad.setHoldTime(5); // ?

Die Befehle kenne ich noch gar nicht.. Dann werde ich mir das auch noch genauer anschauen.
An sich war der Plan das ich bis zur 3. nach Komma Stelle den Wert genau eingeben kann

Ich habe mir jetzt mal das mit dem Array angeschaut und so wie ich das sehe wird das (immer?) in einer for Schleife benutzt. In meinem Projekt würde das in einer For-Schleife doch gar nicht funktionieren da er ja nicht immer hoch/runter zählen soll, da ja eine x beliebige Taste gedrückt werden kann die dann Ausgegeben wird (oder habe ich hier einen Denk-Fehler?)

Die 152 ist erstmal nur die eingegebene Ziffernfolge. Ob du das als 152, 15.2, 1.52 oder gar als 0.152V interpretierst musst Du selbst entscheiden oder durch eine festzulegende "Komma-Taste" passend einrichten.

wno158:
Die 152 ist erstmal nur die eingegebene Ziffernfolge. Ob du das als 152, 15.2, 1.52 oder gar als 0.152V interpretierst musst Du selbst entscheiden oder durch eine festzulegende "Komma-Taste" passend einrichten.

Ich hatte mir überlegt bei dem Keypad die Taste "*" als Komma zu nehmen und "#" als Löschtaste

Prima. Dann kannst du ab Eingabe von * die Anzahl Nachkommastellen mitzählen und hinterher den Wert passend skalieren.
Es fehlt dann noch die Ende-Taste - du musst ja wissen, wann die Eingabe fertig ist.

skipzens:
Ich hatte mir überlegt bei dem Keypad die Taste "*" als Komma zu nehmen und "#" als Löschtaste

ICH würde das Komma nicht mit einpreisen in die Tastatur, sondern nur in der Anzeige verwenden.

Wie Du auf auf die Vor- und Nachkommastellen kommst, ist im folgenden Code dargestellt. (Hier mit 2VK/2NK)
Zur Anzeige dann die Zahl Vorkomma, das komma ansich und dann die Zahl Nachkomma.
Dann kannst Du ganz bequem mit der Ganzzahl rechnen und brauchst keine Zeichenketten/float Umstände.

int zahl = 0;
int lastzahl = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start..."));
}

void loop() {
  if (Serial.available() > 0)
  {
    char zeichen = Serial.read();
    if (isDigit(zeichen))
    {
      Serial.print(F("Digit erkannt: "));
      Serial.println(zeichen);
      if (zahl > 999)// zahl ist schon 4stellig?
      {
        zahl = zahl - (zahl / 1000) * 1000; // mache erste Stelle weg
      }
      zahl = zahl * 10 + (zeichen - 48); // Stelle hinzufügen und Ziffer addieren
      Serial.println(F("Neue Zahl: "));
      Serial.println(zahl);

    }
    if (zahl != lastzahl)
    {
      if (zahl > 0)
      {
        Serial.println(F("Trennung Vor- und Nachkomma"));
        if (zahl > 99)
        {
          Serial.print(F("Vorkomma: "));
          Serial.println((zahl - zahl % 100) / 100);
        }
        Serial.print(F("Nachkomma: "));
        Serial.println(zahl % 100);
        lastzahl = zahl;
      }
    }
  }
}

Anstelle is(Digit) kannst Du später in einer switch/case verwenden, indem Du prüfst, ob das Zeichen 0..9 ist.
Dafür einen case und alles abgedeckt.
Dann einen case für zeichen löschen (von hinten nach vorne) und einen case fürs bestätigen der Ziffer.
Das wars.