2 Arduino Mega ueber serial Verbinden

Hallo Zusammen

Vieleicht kann mir ja mal Jemand helfen

Ich moechte 2 Mega ueber Serial1 Verbinden

und vom ersten zum zweiten einen string senden beim ersten geht das ueber serialprint1
wie kann Ich aber den String auf dem 2 Empfangen

Habe jetzt den einen Mega 15 Meter vom Display (Parallel) instaliert das Klappt
wenn Ich aber ein 2 Display dabei schalte bleibt das zweite dunkel

Waere nett wenn mir jemand helfen koennte

bye juergen

Sketch? Was heißt Parallel installiert bei dir?

Alternativ kannst du auch I2C für die Kommunikation zwischen den beiden Megas nutzen.

Deine Konfiguration ist nicht klar. Kannst Du bitte besser erklären?. Grüße Uwe

Hallo Zusammen

Hallo sschultewolter

Parallel installiert heist

LiquidCrystal lcd(22, 23, 24, 25, 26, 27);
LiquidCrystal lcd1(22, 28, 24, 25, 26, 27);

Gibt es Beispiele fuer I2C 2 Mega und DS1307

Hallo uwefed

Der mega ist fuer meine Heizungssteuerung + Haussteuerung
nun moechte Ich Die ein und ausgaenge ueber Strings zum zweiten uebertragen
und die Strings dann ueber den Mega 2 auf den Lcd ausgeben

bye juergen

Hoi Juergen,

Du hast für die LCDs jeweils 2 Kabel an einem Pin ?
Das wird so nichts...du musst ANDERE Pins für das 2. LCD definieren

A.R.Ty:
Hoi Juergen,

Du hast für die LCDs jeweils 2 Kabel an einem Pin ?
Das wird so nichts...du musst ANDERE Pins für das 2. LCD definieren

Da die Pins des Displays ja Eingänge sind spricht im ersten Moment nichts gegen das Paralellschalten von 2 (Gleichen) LCD-Modulen.
Für die Hintergrundbeleuchtung würde ich wegen des höheren Stroms für jedes Display je 1 Transistor verwenden.

Funktioniert das 2. Display wenn Du das erste entfernst?

Bei einem Mega ist natürlch die bessere Lösung für das 2. Display nochmals 6/7 Pins zu benutzen.

Grüße Uwe

Da die Pins des Displays ja Eingänge sind spricht im ersten Moment nichts gegen das Paralellschalten von 2 (Gleichen) LCD-Modulen.

Joa, aber dann hat er ja nicht 2 Stück 4x20 sondern "1" Stück 4x40 - weisst ja, wie die Dinger funktionieren.

Deswegen

Bei einem Mega ist natürlch die bessere Lösung für das 2. Display nochmals 6/7 Pins zu benutzen.

hatte ich dies

Das wird so nichts...du musst ANDERE Pins für das 2. LCD definieren

getastet

Hallo zusammen

Hallo uwefed

Hatte habe eine Anschluss platine fuer die LCD aud der Platine war ein fehler
die Anzeige klappte danach war aber nicht das was Ich wollte

Ich moechte die megas ueber seriel Verbinden das klappt auch schon nun mein Problem

Ich bekomme ueber seriel einen String empfangeneDaten mit dem inhalt "73.1,54.1,42.2,44.1,36.8,85.0,46.4"
wie bekomme Ich den in ein charArray

Ein kleines Beispiel waere sehr nett

bye juergen

Den Code von jurs hier:
http://forum.arduino.cc//index.php?topic=194811.msg1439191#msg1439191

Du brauchst nur die receiveBuffer() Methode! Nicht den Rest. Die ruft man immer wieder in loop() auf solange sie NULL zurückgibt. Wenn was anderes kommt, ist der string fertig eingelesen.

Danach strtok() verwenden um an die einzelnen Werte zu kommen:

juergen01:
Ich bekomme ueber seriel einen String empfangeneDaten mit dem inhalt "73.1,54.1,42.2,44.1,36.8,85.0,46.4"
wie bekomme Ich den in ein charArray

Ein kleines Beispiel waere sehr nett

Falls Du am Ende jedes Datensatzes noch ein CR oder CRLF als Zeilenende-Trennzeichen sendest, so wie es beispielsweise der Serielle Monitor bei entsprechender Einstellung macht, siehe zum Beispiel Funktion "char* receiveBuffer()" in meinem Beitrag
http://forum.arduino.cc//index.php?topic=194811.msg1439191#msg1439191

In Einzelbestandteile Zerlegen und die Zahlen aus dem Char-Array in Gleitkommavariablen umwandeln brauchst Du nicht?

Hallo zusammen

Hallo jurs

wie rufe Ich das Char-Array auf "receiveBuffer()"
und wo kann Ich die groesse des Char-Array aendern

bye juergen

juergen01:
wie rufe Ich das Char-Array auf "receiveBuffer()"
und wo kann Ich die groesse des Char-Array aendern

Die Größe des Char-Array ist innerhalb der Funktion statisch deklariert, siehe:

 static char lineBuffer[25]; // Maximale Zeilenlänge festlegen

Für längere Zeilen müßte man mehr als 25 deklarieren.

Und beim Aufrufen wird der Rückgabewert der Funktion als Char-Pointer an eine als Char-Pointer deklarierte Variable zugewiesen. Z.B.:

char* zeile;

An diesen Char-Ponter wird dann der Rückgabewert zugewiesen und auf NULL vergleichen:

zeile=receiveBuffer();
if (zeile==NULL) ...

Wenn der Rückgabewert NULL ist, wurde noch keine vollständige Zeile empfangen.
Und wenn der Char-Pointer ungleich NULL ist, dann weist er immer auf das Char-Array innerhalb der Funktion.
Und danach kannst Du "zeile" praktisch wie ein char-Array selbst verwenden, also z.B. mit zeile[0], zeile[1], zeile[2] auf die einzelnen Zeichen im Array zugreifen, die Zeile mit Serial.println(zeile) ausgeben oder Funktionen aufrufen, die einen Charpointer als Funktionsparameter erwarten, z.B. die AVR-Stringfunktionen aus der Library avr-libc: <string.h>: Strings

Hallo zusammen

Hallo jurs
Habe jetzt ein CRLF mit gesendet
Als ausgabe aus dem Serialmonitor bekomme Ich jetzt

57.0
60.3
48.5
51.4
41.7
62.3
42.4

aber nach receiveBuffer() bekomme Ich in zeile[1] bis zeile[7] nur ein zeichen

zeile=receiveBuffer(); wenn ich das so eingebe bekomme Ich
was not declared in this scope
dann habe meine deklaration
char* zeile;
aber nach receiveBuffer() bekomme Ich in zeile[1] bis zeile[7] nur ein zeichen

Dann noch kann man die einzelnen Werte immer an der gleichen stelle im Char-Array einlesen

bye juergen

juergen01:
aber nach receiveBuffer() bekomme Ich in zeile[1] bis zeile[7] nur ein zeichen

Ja, "zeile[index]" ist immer genau ein Zeichen und "zeile" ist ein Zeiger (Char-Pointer) auf eine gesamte Zeile.

juergen01:
zeile=receiveBuffer(); wenn ich das so eingebe bekomme Ich
was not declared in this scope
dann habe meine deklaration
char* zeile;

Ja, jede Variable muss VOR der ersten Verwendung deklariert werden.
Wobei es freigestellt ist, die Variable getrennt zu deklarieren und dann zu verwenden:

  char* zeile;  // Deklaration
  zeile=receiveBuffer(); // Verwendung im Programm

Oder beides in einem Einzeiler zu machen:

  char* zeile=receiveBuffer(); // Deklaration und Verwendung im Programm

juergen01:
Dann noch kann man die einzelnen Werte immer an der gleichen stelle im Char-Array einlesen

Du kannst alles mögliche machen.
Je nachdem, wie Du es brauchst.

Wenn Du aus dem Char-Array beispielsweise Gleitkommazahlen herausziehen und an "float" Variablen zuweisen wolltest, würdest Du beispielsweise den Char-Pointer auf den Anfang der gewünschten Zahl im Char-Array zeigen lassen und die Library-Funktion "atof" (steht für "Array to float") aufrufen. Z.B.

float f=atof(zeile); // Deklariere Gleitkommazahl f und weise die Zahl zu, die ab Anfang von "zeile" im Char-Array steht.

Wichtig ist dabei immer die Prüfung darauf, ob "zeile" überhaupt gültig ist. Ich verwende nur zwei Zuweisungen für "zeile", die Variable ist entweder "NULL", und das bedeutet, es wurde über die serielle Schnittstelle noch keine gültige Zeile mit allen Werten empfangen. Oder "zeile" ist ungleich NULL, was bedeutet, dass dieser Char-Pointer auf das in der Funktion receiveBuffer() deklarierte Char-Array zeigt.

In der loop-Funktion hast Du also zwei Möglichkeiten, die Prüfung zu machen und die loop am Laufen zu halten.

  1. Möglichkeit: Prüfen auf NULL und wenn NULL, dann die loop abbrechen und neu starten, indem die loop-Funktion vorzeitig mit "return" verlassen wird.
void loop()
{
  char* zeile=receiveBuffer();
  if (zeile==NULL) return;  // loop vorzeitig verlassen (loop wird direkt danach automatisch neu aufgerufen)
  // Der nachfolgende Code wird nur ausgeführt, wenn etwas anderes als NULL zurückgeliefert wurde
 // Den auszuführenden Code zur Behandlung von "zeile" hier einfügen
}

Oder Du machst einen Codeblock, der nur ausgeführt wird, wenn ein Pointer ungleich NULL ("!NULL") zurückgeliefert wurde:

void loop()
{
  char* zeile=receiveBuffer();
  if (zeile!=NULL)  // es wurde gerade eine Zeile vollständig empfangen
  {
    // Den auszuführenden Code zur Behandlung von "zeile" hier einfügen
  }
  // weiteren in der loop auszuführenden Code hier einfügen
}

Was soll denn nun insgesamt mit der Zeile genau gemacht werden, nachdem sie empfangen wurde?

Hallo zusammen

Hallo jurs

Was soll denn nun insgesamt mit der Zeile genau gemacht werden, nachdem sie empfangen wurde?

Ich moechte die Daten die ueber seriel kommen auf ein LCD ausgeben da die
Endfernung zwischen LCD Mega ueber 20 Meter ist.
Ich will die Daten nur anzeigen

bye juergen

juergen01:
Ich moechte die Daten die ueber seriel kommen auf ein LCD ausgeben

#include <LiquidCrystal.h>
#include "Wire.h"

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // Sainsmart LCD keypad shield

void setup()
{
  Serial.begin(9600);
 // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  lcd.print("LCD Ready.");
}


char* receiveBuffer()
#define ZEILENTRENNZEICHEN 13   // 13 ist Steuerzeichen CR (Carriage Return)
{
  static char lineBuffer[41]; // Maximale Zeilenlänge festlegen
  static byte counter=0;
  char c;
  if (Serial.available()==0) return NULL; // Nullpointer zurück
  if (counter==0) memset(lineBuffer,0,sizeof(lineBuffer));// Puffer vor Benutzung löschen
  c=Serial.read();
  if (c==ZEILENTRENNZEICHEN)
  {
    counter=0;
    return lineBuffer;
  }
  else if (c>=32) // kein Steuerzeichen?
  {
    lineBuffer[counter]=c; // Zeichen im Zeilenpuffer einfügen
    if (counter<sizeof(lineBuffer)-2) counter++;
  }
  return NULL;
}



void serialTask()
{
  char* zeile=receiveBuffer();
  if (zeile==NULL) return; // nix empfangen, nix zu tun, zurück
//  Serial.println(zeile);  // Kommentarzeichen an Zeilenanfang entfernen, um Zeile auf Serial auszugeben
  lcd.clear(); // jetzt wurde eine Zeile empfangen, LCD löschen
  // vier mit Komma getrennte Parameter aus der Zeile abtrennen,
  // dann aufs LCD ausgeben
  char* param; // Char-Pointer für einen Parameter deklarieren
  param=strtok(zeile,","); // Ersten Parameter holen
  lcd.print(param);  // Ersten Parameter aufs LCD
  lcd.setCursor(8,0); // Schreibmarke auf dem LCD versetzen
  param=strtok(NULL,","); // nächsten Parameter holen
  lcd.print(param);  // nächsten Parameter aufs LCD
  lcd.setCursor(0,1);
  param=strtok(NULL,",");
  lcd.print(param);
  lcd.setCursor(8,1);
  param=strtok(NULL,",");
  lcd.print(param);
}

void loop()
{
  serialTask();  
}

Hallo zusammen

Hallo jurs

So klappt es ja aber auf dem LCD werden die Werte nur
in der oberen lincken ecke geschrieben

und Ich moechte die Werte gerne auch im void loop() haben

um sie auf serial auszugeben
die Werte kommen auf serial1
wenn Ich void serialTask() in int serialTask() aendere bekomme
Ich eine Fehlermeldung

bye juergen

juergen01:
So klappt es ja aber auf dem LCD werden die Werte nur
in der oberen lincken ecke geschrieben

Funktioniert lcd.setCursor() auf Deinem Display nicht?
Oder hast Du den Demosketch nicht richtig angepaßt (so wie gepostet ist der Quellcode für ein LCD mit 2 Zeilen a 16 Zeichen)?

Normalerweise sollten vier Werte in zwei Zeilen des LCD-Displays geschrieben werden, schön auf zwei Zeilen verteilt und je Zeile immer ein Wert linksbündig und ein Wert ab Mitte der Zeile beginnend ausgegeben.

juergen01:
und Ich moechte die Werte gerne auch im void loop() haben
um sie auf serial auszugeben

Haha, Du bist gut. Kannst Du Dich daran erinnern, dass ich vorhin gefragt habe "Was soll denn nun insgesamt mit der Zeile genau gemacht werden, nachdem sie empfangen wurde?" und Du hast darauf geantwortet:

juergen01:
Ich moechte die Daten die ueber seriel kommen auf ein LCD ausgeben

Genau das habe ich als Code gepostet. Passend für ein LCD-Keypad-Shield, aber leicht anpassbar auf andere LCDs.

Wenn es Dir nur darum geht, irgendwas in die loop()-Funktion reinzubekommen, das ich der Übersichtlichkeit wegen in eine extra Funktion geschrieben habe, damit die loop()-Funktion übersichtlich bleibt: Du kannst den gesamten Funktionsrumpf aus "serialTask()" herausschneiden und in die loop() hineinkopieren.

Wenn Du es anders hättest haben wollen, dann hättest Du genau das als Antwort auf meine Reply #13 von vorhin ja schreiben können.

Wenn Du es jetzt doch wieder anders haben möchtest, als Du es auf ausdrückliche Nachfrage beschrieben hast ("Ich moechte die Daten die ueber seriel kommen auf ein LCD ausgeben"), wie es verarbeitet werden soll, dann mal zu und in die Tasten gegriffen: Die Funktion "receiveBuffer()" empfängt zeilenweise von der seriellen Schnittstelle, und beispielsweise die Funktion "strtok()" der AVR-Library kann Dir die Zeile an bestimmten Trennzeichen wie dem Komma in seine Einzelteile zerlegen.

Und dann machst Du mit den zerlegten Einzelteilen der Zeile das, was in Deinem Sketch notwenig ist. Auf LCD ausgeben. In der loop() verwenden. Auf Serial ausgeben. Und eventuell sogar in Gleitkommazahlen umwandeln. Ich kann nicht hellsehen.

Hallo zusammen

Hallo jurs

Deine Antwort hat mir nicht sehr gefallen
auch das haha gefaellt mir nicht sehr

Hier mein veraenderter sketch

#include <LiquidCrystal.h>
#include "Wire.h"

LiquidCrystal lcd(22, 23, 24, 28, 26, 27); // Sainsmart LCD keypad shield

void setup()
{
Serial.begin(9600);
Serial1.begin(9600);
// set up the LCD's number of columns and rows:
lcd.begin(20, 4);
lcd.print("LCD Ready.");
}

char* receiveBuffer()
#define ZEILENTRENNZEICHEN 13 // 13 ist Steuerzeichen CR (Carriage Return)
{
static char lineBuffer[41]; // Maximale Zeilenlänge festlegen
static byte counter=0;
char c;
if (Serial1.available()==0) return NULL; // Nullpointer zurück
if (counter==0) memset(lineBuffer,0,sizeof(lineBuffer));// Puffer vor Benutzung löschen
c=Serial1.read();
if (c==ZEILENTRENNZEICHEN)
{
counter=0;
return lineBuffer;
}
else if (c>=32) // kein Steuerzeichen?
{
lineBuffer[counter]=c; // Zeichen im Zeilenpuffer einfügen
if (counter<sizeof(lineBuffer)-2) counter++;
}
return NULL;
}

void serialTask()
{
char* zeile=receiveBuffer();
if (zeile==NULL) return; // nix empfangen, nix zu tun, zurück
// Serial.println(zeile); // Kommentarzeichen an Zeilenanfang entfernen, um Zeile auf Serial auszugeben
lcd.clear(); // jetzt wurde eine Zeile empfangen, LCD löschen
// vier mit Komma getrennte Parameter aus der Zeile abtrennen,
// dann aufs LCD ausgeben
char* param; // Char-Pointer für einen Parameter deklarieren
param=strtok(zeile,","); // Ersten Parameter holen
lcd.print(param); // Ersten Parameter aufs LCD
Serial.println(param);
lcd.setCursor(8,0); // Schreibmarke auf dem LCD versetzen
param=strtok(NULL,","); // nächsten Parameter holen
lcd.print(param); // nächsten Parameter aufs LCD
// Serial.println(param);
lcd.setCursor(0,1);
param=strtok(NULL,",");
lcd.print(param);
lcd.setCursor(8,1);
param=strtok(NULL,",");
lcd.print(param);
}

void loop()
{
serialTask();
//delay(100);
// Serial.println(param);
}

bye juergen