Hi,
in meinem derzeitigen Projekt verwende ich 2 Arduino Nano`s, die über eine Serielle verbindung miteinender Kommunizieren. Beim ersten Nano über die Hardwareserial, beim zweiten Nano über ein Softwareserial (Siehe Bild). Um trotzdem die Möglichkeit eines Interrupts zu haben, wird eine 3. Leitung vom 1. Nano (Pin A5) zum 2. Nano (Pin 3) geführt, die vor dem Übertragen auf LOW gezogen wird.
Der 2. Nano erhält seine Daten (in Form eines struct) über die Hardwareserial. Diese werden gemeinsam mit anderen Daten in ein Struct geschrieben, welches dann auf Anfrage des 1. Nano`s über das Softwareserial übertragen werden.
Die Anfrage des 1. Nano an den 2. Nano erfolgt über das Senden einer Zahl (0-5). Am 2. wird dann die Anfrage über eine switch statement abgearbeitet.
Mein Problem: Das ganze läuft nur 2x. Beim 3. Mal kann der empfangene char nicht mehr korrekt abgespeichert werden.
Kann es also sein, dass ich zuviel RAM benötige? Gibt es Verbesserungsvorschläge für den untenstehenden Code?
Code (switch statement gekürzt, steht überall das gleiche nur mit anderen structs):
enum dataNeeded {
RTData,
vescOptData,
gpsRTData,
btData,
fsrData,
batData
};
SoftwareSerial softSerial(4, 5);
void serialISR();
uint8_t recRequest;
void setup() {
Serial.begin(9600);
softSerial.begin(19200);
//Interrupt on change@Pin D3
attachInterrupt(digitalPinToInterrupt(3), serialISR, CHANGE);
}
// the loop function runs over and over again until power down or reset
void loop() {
//softSerial.print(charToSend);
}
void serialISR() {
Serial.println(F("in ISR"));
if (softSerial.available() > 1) {
recRequest = Serial.read();
}
requestHandler((char)recRequest);
}
void requestHandler(char receivedNumber) {
Serial.println(F("In requestHandler")); //Serial.println(receivedNumber);
switch (receivedNumber) { //Select which data is requested and copy the requested data into char Array and pass it to send function
case RTData:
char rtDat[sizeof(RtData) + 1];
memcpy(&rtDat, &RtData, sizeof(DataRT));
sendCharArray(rtDat);
break;
default:
Serial.println(F("reqHandler failure!"));
break;
}
}
void sendCharArray(char arrayToSend[]) {
for (int i = 0; i < sizeof(arrayToSend); i++) {
softSerial.print(arrayToSend[i]);
}
Serial.println("CharArray Sent");
delete(arrayToSend);
}
Befürchte nur, dass das bei mir nicht Möglich ist, da da bereits andere Daten abgefragt werden (Hab an dem Nano noch ein GPS und einen ADC über I²C hängen). Sollte dann, während gerade andere Daten abgefragt werden, die Anfrage vom 1. Nano kommen, kann ich die nicht bearbeiten. Deshalb der Interrupt.
Es funktioniert ja 2x ohne Probleme. Beim dritten Mal scheitert es dann
Daas liegt nicht am RAM, sondern an deiner Vorstellung von ISR.
Interrupts dienen nicht zum Parallel Ausführen verschiedener Tasks, sondern um sehr hardwarenah mit wenigen Maschinenbefehlen auf Ereignisse zu reagieren. Als kleine Software-Erweiterung zu Timern und anderen Hardware-Komponenten.
Serial.print in einer ISR "funktioniert" für 64 Buchstaben. Es funktioniert also nicht!
Deine Beschreibung ist sehr lückenhaft Da Du nur einen Teilaspekt Deines Projekts beleuchtest. Der Fehler kann überall liegen.
soweit ich mich erinnere kann die software serial nicht >9600
Um trotzdem die Möglichkeit eines Interrupts zu haben, wird eine 3. Leitung vom 1. Nano (Pin A5) zum 2. Nano (Pin 3) geführt, die vor dem Übertragen auf LOW gezogen wird.
Die serielle Schnittstelle ist sehr langsam. Bei deinen Baudraten im Bereich von hunderten 100µs bis 1ms. Ein Zeichen braucht 1 / Baudrate * 10 Sekunden. Da braucht man keine Interrupts wenn loop() vernünftig programmiert ist und nicht blockiert. Außerdem haben die Serial Klassen intern einen Puffer den man nur schnell genug leeren muss.
Leider funktioniert das mit empfangen der Anfrage nicht (auch nicht mit einem if(Serial.available()) in der main loop). Habe es gelöst indem der Nano 2 einfach in 500ms Abständen selbstständig schickt und der Nano 1 diese in der serialEvent() Funktion bearbeitet (sprich in ein char[] aufnimmt und dann mit memcpy() in das struct schreibt).
Wird sicher nicht das letzte Problem an diesem Projekt sein, werdet ziemlich sicher noch ein paar Themen von mir in diesem Forum sehen
Dann schau Dir mal union an. Da kann das char[] und das Struct den gleichen Speicher gemeinsam nutzen und Du musst nichts umkopieren und kannst direkt zugreifen.
Tommy56:
Dann schau Dir mal union an. Da kann das char[] und das Struct den gleichen Speicher gemeinsam nutzen und Du musst nichts umkopieren und kannst direkt zugreifen.
Gruß Tommy
Mal schauen. Da ich die Daten als struct bekomme (library), müsste ich die dann nur einmal umkopieren. Schau ich mir morgen mal genauer an!
Tommy56:
Dann schau Dir mal union an. Da kann das char[] und das Struct den gleichen Speicher gemeinsam nutzen und Du musst nichts umkopieren und kannst direkt zugreifen.
Gruß Tommy
Hab mir das mal angesehen. Möglich ist das schon. Erlaubt ist es allerdings weder in C noch in C++, daher für mich leider nicht geeignet.