Arduino - Programmierung

  • Seite 9 von 10
22.07.2023 22:45
avatar  Montre
#121
avatar

Ja danke. Arduino unterstützt nur C-Konstrukte, kein C++.


 Antworten

 Beitrag melden
22.07.2023 22:54
avatar  Montre
#122
avatar

Ich habe Graham meinen kompakteren Code gepostet.


 Antworten

 Beitrag melden
25.07.2023 21:25 (zuletzt bearbeitet: 25.07.2023 21:36)
avatar  Montre
#123
avatar

Zitat von Montre im Beitrag #121
Ja danke. Arduino unterstützt nur C-Konstrukte, kein C++.

Die Arduino-Doku ist diesbezgl. etwas sparsam ausgelegt. Tatsächlich werden Klassen unterstützt. Jede Lib ist prinzipiell eine Klasse.
Im Libaries-Verzeichnis muss man ein Verzeichnis mit dem Namen der Klasse erzeugen und dort seine Klasse (.cpp und .h) reinkopieren.

Die Startdatei mit setup() und loop() suggeriert, dass der Code nur Code ohne Objekte unterstützt. Aber es geht doch mehr.
Die Erkenntnis stammt aus dieser Datei.

Das eröffnet nämlich ganz neue Möglichkeiten, weil man eine plattformunabhängige Klasse erstellen kann, die dann mit einem RaspPi- und Arduino-Layer ergänzt wird. Zumindest sollte man das mal untersuchen. Das wird sich für den normalen User rätselhaft anhören, aber die Entwickler verstehen, was ich meine.


 Antworten

 Beitrag melden
25.07.2023 22:30
#124
avatar

Meinst di Objektorientierte Programmierung? Das geht mit den Arduino c. Schau mal hier für ein Beispiel https://werner.rothschopf.net/202003_ard...frelais_oop.htm

Ich selbst habe es noch nicht genutzt. Wobei die Vorteile schon praktisch sein könnten. Beispiel ich nutze in vielen Projekten ein Display, dann wäre ein Display Objekt welches ich ohne viel Aufwand in jedem Programm nutzen könnte ganz praktisch. Dann muss ich die Grundlagen nur einmal schreiben.

Auch bei einem Midi Projekt könnte ja jede Taste ein Objekt Taste() sein, welches dann alle Informationen wie Midicode, Zustände und so weiter enthält. Der Nachteil wäre dann aber vermutlich beim ersten mal sehr viel Mehrarbeit und wie es sich auf die Geschwindigkeit auswirkt müsste man testen.


 Antworten

 Beitrag melden
26.07.2023 00:21 (zuletzt bearbeitet: 26.07.2023 00:25)
avatar  Montre
#125
avatar

Zitat von Christian_Hofmann im Beitrag #124
Meinst di Objektorientierte Programmierung? Das geht mit den Arduino c. Schau mal hier für ein Beispiel https://werner.rothschopf.net/202003_ard...frelais_oop.htm

Genau. Das ist doch ne saubere Sache.

Zitat von Christian_Hofmann im Beitrag #124
Beispiel ich nutze in vielen Projekten ein Display, dann wäre ein Display Objekt welches ich ohne viel Aufwand in jedem Programm nutzen könnte ganz praktisch. Dann muss ich die Grundlagen nur einmal schreiben.

So ist es. Man versteht es auch leichter, wenn die Komplexität zu nimmt. Das merken die Leute auch selber, wenn sie für den nächsten Schritt immer länger überlegen müssen.

Zitat von Christian_Hofmann im Beitrag #124
Der Nachteil wäre dann aber vermutlich beim ersten mal sehr viel Mehrarbeit und wie es sich auf die Geschwindigkeit auswirkt müsste man testen.

Der Vorteil kann so immens größer sein, dass es dann im Ganzen dann doch lohnend ist, übersichtlich zu arbeiten. Wir reden hier aber nicht um 100-Zeilen-Progrämmchen. Da braucht man keine Objektorientierung.

Aber dem erwähnten 5000-Zeilen-Programm hätte das sicher gut getan. Schleifen ist das eine, was eigentlich jeder geübte Coder automatisch anwendet (aber nicht die allumfassende Lösung darstellt), aber auch ggf. die Hardware mit ihren Pins zu abstrahieren, oder auch ein Manual als Objekt zu benutzen, hätte der Verständlichkeit des Codes gut getan, weil es sich wiederholenden Code vermeidet. Aber wem erzähl ich das - du weißt es ja. Und die, die wenig Ahnung haben, die können es nicht und wollen es auch nicht. Da hackt man lieber 5000 Zeilen rein, ohne wenn und aber. Das der Code funktioniert, kann gut sein und will ich nicht in Frage stellen, aber das Fehler drin sind, ist nicht so leicht auszuschließen. Da muss dann jeder Anwender selbst 5000 Zeilen prüfen, ob das alles richtig umgesetzt ist ist. Und das ist dann schon nicht mehr so dolle.

Und wenn du die Performance in Frage stellst, dann dürftest du keine einzige Lib verwenden. Das sind nämlich alles Klassen


 Antworten

 Beitrag melden
26.07.2023 09:55
avatar  Montre
#126
avatar

...und Python solltest du auch nicht verwenden


 Antworten

 Beitrag melden
26.07.2023 12:33 (zuletzt bearbeitet: 26.07.2023 12:35)
#127
avatar

Nach im Vergleich DUE und Pico sollte das dann unterm Strich egal sein. Sofern man Python auf dem Pico nimmt, dann macht die CPU mit 133 Mhz im Vergleich zu 84 Mhz das ganze wohl wieder gut. Aber Spaß beiseite. Arduino c auf dem Pico ist recht gefährlich, man muss die Geschwindigkeit manuell teilweise reduzieren (Pausen oder runtertakten). Sonst laufen die Programme zu schnell was Probleme bei z.B Takt auf den Pins führt.

Wozu ich allerdings nichts finden konnte ist diese Frage:
Der Arduino DUE und Pico haben ja einen Prozessor mit zwei Kernen. Python selbst kann seine Aufgaben auf mehrere Kerne verteilen. Da muss man selbst nicht viel machen, kann es jedoch mit Threads (schweres Thema) noch optimieren.

Aber wie sieht es beim Arduino aus? Das erstellte Programm müsste doch bestimmt auch entsprechend auf Multithreading ausgelegt sein? Ein gewöhnliches Programm ohne manuelle Anpassung dürfte doch nur einen Kern nutzen. Weiß da jemand etwas genaueres?


 Antworten

 Beitrag melden
26.07.2023 14:32
#128
So

Dafür brauchst du Arduino Cracks, die sich meines Wissens nur um Arduino Forum tummeln.


 Antworten

 Beitrag melden
26.07.2023 15:04
#129
avatar

Also ist im Grunde die Erwähnung der zwei Kerne ein Marketing Gag, der den meisten nicht viel nutzen wird :)

Ich frage mich inwieweit der Compiler überhaupt support bietet. Es wird dann vermutlich auf Assembler hinauslaufen. Da sind wir Anfänger aber wohl raus :)


 Antworten

 Beitrag melden
26.07.2023 15:30
avatar  Montre
#130
avatar

Die Frage ist nicht Multithreading sondern Multicore. Ich denke mal, dass das genauso easy ist, wie beim Pico.
Schau mal hier.


 Antworten

 Beitrag melden
27.12.2023 12:44
#131
So

Zitat von Montre im Beitrag #27
@Brassmann
Wenn Dir die Optimierung deines Codes zu schwierig ist, dann kann ich Tipps geben.
z.B. lässt sich die Zeile 150 bis 157 durch eine Schleife ersetzen:

1
2
 
  for(int i=0; i < 8; i++)
pinMode(row1+i*2, INPUT);
 



Die Konstanten row2 bis row8 und col2 bis vol8 kannst Du löschen, wenn alles durch kompakte Schleifen nach gezeigtem Muster ersetzt wurden. Dann hast Du auch ungefähr 200 Zeilen weniger Code.




Durch ein neues Erweiterungsprojekt bei mir kam ich wieder an einer Diodenmatrix-Abfrage vorbei. Meine momentane Lösung bzw. momentaner Code auf Arduino Due war trotz der hier diskutierten Änderungen und Verbesserungen immer noch fehlerhaft, sprich bei bestimmten Akkorden erklangen weitere, nicht gedrückte Töne.

Ich habe daher mit einem SX1509 herumprobiert, das Ergebnis war jedoch negativ. Das passt vielleicht zu einer Tastermatrix, z.B. Pistons, aber nicht zu Manualen. Warum? Bei meinen Tests war es nicht möglich, mehr als einen MIDI-Befehl gleichzeitig zu senden. Auch für den Einsatz von Registertastern oder Pistons könnte dieser Fakt hinderlich sein, wenn man mal mehr als eine Taste zugleich drücken will.

Also zurück zum "altmodischen" Weg und die Matrix per Arduino-Code scannen. Ich habe ein paar Verschlankungen vorgenommen und nun einen Code ohne die verbliebenen Fehler. Wenn man die Rows für mehrere Manuale gemeinsam aktiv schaltet, kann man mit einem Arduino Due oder Mega locker 5 Manuale plus Pedal scannen. Mit dem Midi-Flush Befehl habe ich hin und her experimentiert und ihn weiterhin drin gelassen.

Hier der Code, ohne Gewähr, falls ihn jemand verwenden oder adaptieren will.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 

// Name: Arduino Mega Midi Controller Mega side.
// Created: May 10, 2021
// Last Edited: Mar 26, 2022
// Author: Larason2
// Acknowledgements: Bald Engineer, Amanda Ghassaei, jeffb42, GrumpyMike, John Main, Ghost, RIP Tutorial, Arduino tutorials.
// Includes Midi Through, wiring for pistons, improved debounce.
 
//für Arduino Due und MIDIUSB-Bibliothek angepasst
 
#include "MIDIUSB.h"
 

 
//###############Diodenmatrix-Variablen##############################
//Amount of Rows and Columns
const int rows = 8;
const int cols = 8;
 
//Entprellen der Tasten
unsigned long Delay = 10; //in Millisekunden
unsigned long DelayMikro = 10; //in Mikrosekunden, 10 ging so recht und schlecht
 
//MIDI Kanal
int midichannel = 3; //das ergibt Kanal 4 für das 3. Manual
//####################################################################
 

 
//Setup Key Data Arrays
byte keysA[rows][cols] = { {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1},
};
 
//Setup Key Press Arrays
byte lastA[rows][cols];
 

//deckungsgleich zum Tasten-Array die MIDI-Codes für NoteOn/Off
uint8_t keyToMidiMap[rows][cols] = { 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75,
76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95, 96, 97, 98, 99,
};
 

 
//Entprellen der Tasten
unsigned long BounceAOn[rows][cols];
unsigned long BounceAOff[rows][cols];
 

//row-Pins
uint8_t rowpin[rows] = {22, 24, 26, 28, 30, 32, 34, 36};
 
//col-Pins
uint8_t colpin[cols] = {23, 25, 27, 29, 31, 33, 35, 37};
 

/** Funktionen für MIDI *****************************************************/
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
delayMicroseconds(300);
MidiUSB.flush();
}
 
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
delayMicroseconds(300);
MidiUSB.flush();
}
 
void sendControlChange (byte channel, byte controller, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, controller, value};
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
 
/****************************************************************************/
 

void setup() {

for (int i = 0; i <= 7; i++) {
pinMode(rowpin[i], INPUT);
pinMode(colpin[i], INPUT);
}

}
 
void loop() {

for (int i = 0; i <= 7; i++) {
pinMode(colpin[i], INPUT_PULLUP);
}
 
delayMicroseconds(DelayMikro);
 
for (int i = 0; i <= 7; i++) {
pinMode(rowpin[i], OUTPUT);
digitalWrite(rowpin[i], LOW);
delayMicroseconds(DelayMikro);
 
for (int j = 0; j <= 7; j++) {
keysA[i][j] = digitalRead(colpin[j]);
delayMicroseconds(DelayMikro);
}
 
pinMode(rowpin[i], INPUT);
delayMicroseconds(DelayMikro);
}
 
for (int i = 0; i <= 7; i++) {
pinMode(colpin[i], INPUT);
}
 
delayMicroseconds(DelayMikro);
 

//gedrückte Tasten als MIDI-Befehle senden
for (int i = 0; i <= 7; i++) {
 
for (int j = 0; j <= 7; j++) {
 
if (keysA[i][j] == LOW && lastA[i][j] == HIGH && ((millis() - BounceAOn[i][j]) > Delay)) {
noteOn(midichannel, keyToMidiMap[i][j], 127);
lastA[i][j] = keysA[i][j];
BounceAOff[i][j] = millis();
}
if (keysA[i][j] == HIGH && lastA[i][j] == LOW && ((millis() - BounceAOff[i][j]) > Delay)) {
noteOff(midichannel, keyToMidiMap[i][j], 0);
lastA[i][j] = keysA[i][j];
BounceAOn[i][j] = millis();
}
}
}
}
 
 



 Antworten

 Beitrag melden
31.12.2023 02:10
#132
avatar

Dein Code für die Matrix ist gut. Ich habe es damals ja selbst ähnlich gelöst. Aber inzwischen mache ich das auch nicht mehr, da es doch Recht aufwändig ist und spätestens wenn man noch entprellen will wird es nicht leichter. Ich nutze inzwischen Keypad https://www.arduino.cc/reference/en/libraries/keypad/

Im Prinzip eine fertige Lösung eigentlich für Tastenfelder, aber das ist ja auch nur eine Matrix. Ich übergebe also nur die Zeilenleser und Zeilenschreiber und Frage dann ab ob es ein Ereignis gab. Das sind dann vielleicht vier Zeilen Code. Natürlich ist das nicht ganz so flexibel, aber für einen Schalter oder Manual Taste reicht es in den meisten Fällen aus.


 Antworten

 Beitrag melden
31.12.2023 07:44
#133
So

An der Keypad Bibliothek bin ich auch vorbei gekommen. Da habe ich allerdings irgendwo gelesen, dass hier nur bis zu 8 gleichzeitige Tastendrücke verarbeitet werden. Daher habe ich die verworfen, wollte mich nicht einschränken, auch wenn man nur selten 8 Töne und mehr spielt.


 Antworten

 Beitrag melden
31.12.2023 09:07
#134
So

Hab mir die Keypad Bibliothek grad angeschaut. Es sind 10 statt 8 Tasten gleichzeitig. Aber weniger Code ist das auch nicht, als eine Schleifen-gesteuerte Abfrage. Höchstens das Entprellen könnte einfacher sein. Wobei ich das über Code bei mir gelöst und damit bislang keine Prellprobleme habe. Hier habe ich eine Gummimatten-Kontaktierung. In Zukunft hab ich Reedkontakte, das Prellverhalten derer kenne ich nicht.


 Antworten

 Beitrag melden
31.12.2023 12:46
avatar  Montre
#135
avatar

Zitat von Brassmann im Beitrag #134
Aber weniger Code ist das auch nicht

Das spielt keine Rolle. Da ist halt jemand, der Fehler entfernt, optimiert bzw. den Code pflegt. Diese Arbeit erspart man sich in diesem Fall.


 Antworten

 Beitrag melden
Bereits Mitglied?
Jetzt anmelden!
Mitglied werden?
Jetzt registrieren!