Atmega 328P RS485.h Library

Hallo zusammen,

Ich habe ein kleines Problem.
Ich habe mir eine Schaltung zusammengelötet und möchte über 2 Atmega328p mit RS485 Bausteinen Kommunizieren.
Dies Funktioniert auch einwandfrei. Signale werden gesendet, ausgewertet und eine Antwort zurückgesendet.

Bei der Senderplatine verwende ich Alle Eingänge inkulsive Digital input 0+1.
Nun sobald die Kommunikation über RS485 erfolgreich verbunden wurde Schaltet es mir an der Senderplatine den Eingang D1 Hoch (Dies ist ja die Standart RX/TX Schnittstelle)

Das Programm sieht in etwa so aus:

#include <RS485.h>
#include <SoftwareSerial.h>

char Message[maxMsgLen+1] ;
char empfang[maxMsgLen + 4 + 1];

const int not_aus =  A0;
const int schlaffseil = A1;
const int kontaktleiste = A2;
const int auf_ab = A3;
const int links = A4;
const int fahren = 1;
const int drehmasch = 5;
const int drehbne = 6;
const int ausleger = 7;
const int teleskop = 9;
const int hacken = A5;

void setup()
{

	pinMode(not_aus, INPUT);
	pinMode(schlaffseil, INPUT);
	pinMode(kontaktleiste, INPUT);
	pinMode(auf_ab, INPUT);
	pinMode(links, INPUT);
	pinMode(fahren, INPUT);
	pinMode(drehmasch, INPUT);
	pinMode(drehbne, INPUT);
	pinMode(ausleger, INPUT);
	pinMode(teleskop, INPUT);
	pinMode(hacken, INPUT);

	Serial.begin(9600);
	Serial.println("System Startup - Sender");

	RS485_Begin(19200);
	{
		Serial.print("Sending:");
		Serial.println(message);
	}
	
}

Nun sobald ich Serial.beginn(9600); ausklammere, wird der Eingang D1 nicht mehr geschaltet.
Jedoch funktioniert dann auch die RS485 verbindung zum 2. Atmega328p nicht mehr.

Kann ich dies Umgehen sodass ich D1 als Eingang verwenden kann ohne das die Kommunikation diesen Eignang Schaltet?

Vielen Dank für die Antwort.

Bist Du sicher daß die RS485 bibliothek die Serialbibliothek braucht?
Wie sieht ein der Bibliothek beigelegtes Beispielprogramm aus?
Grüße Uwe

Die Libs die ich kenne, brauch man kein SoftSerial, dafür aber muss man die Pins angeben, TX/RX/EN.

Du hast in deinem Sketch Serial.begin drin womit ab dann auch Pin 0+1 genutzt werden und nicht mehr als normle Eingänge nutzbar sind. Wo hast du denn die RS485-Baustein dran? Du musst ja mindestens 3 Pins dafür haben. RX/TX/Flowcontrol . Da ist die im Sender noch nicht aufgefallen da du im Sketch die Pins noch nicht auswertest. Die IDE lässt es zu obwohl du sich gegenseitig "beeinflussenden Code" geschrieben hast. Also irgendwie Pins reduzieren oder einen anderen Atmega nehemen.
Gruß
DerDani

Ja meine lib braucht leider den Serial.Port (sobald ich diesen ausklammere, funktiniert die verbindung nicht mehr)

Kannst du mir bitte jenen Link mit der Rs485 Lib senden die keinen Serial.Port benötigt?

Ich habe den Rs485 an 2,3,4.

Danke

schnibli:
Ja meine lib braucht leider den Serial.Port (sobald ich diesen ausklammere, funktiniert die verbindung nicht mehr)
Kannst du mir bitte jenen Link mit der Rs485 Lib senden die keinen Serial.Port benötigt?
Ich habe den Rs485 an 2,3,4.

Wo hast du denn den Sketch her?

Du hast die Pins für SoftwareSerial nicht festgelegt und diese auch nicht gestartet.
Das ist sehr merkwürdig.

Das weis ich leider nicht mehr :s ....

im Void Loop sende ich mittels:
if(RS485_SendMessage(Message,fWrite,ENABLE_PIN))
{
Serial.print("Sending:");
Serial.println(message);
}

Nun Das Problem ist halt das ich dieses Problem erst nach dem Drucken der Platinen germekt habe. Daher währe ich froh wenn es eine RS485 ohne softwareSerial gäbe :s

Dies habe ich verwendet :slight_smile:

Hallo,

von den Funktionsnamen her sieht mir das bald danach aus ob die Lib eine von Nick Gammon ist.

Hier der Link zur Nick Lib, non_blocking …
http://www.gammon.com.au/forum/?id=11428
hier ist auch alles beschrieben was man ändern muß, ob software serial oder hardware serial.

Darauf basierend eine dritte Version/Beispiel wo der Master eine Antwort vom Slave erhält.

aktuelle Lib Version im Anhang, oder wartest noch einen Tag, dann stellt Nick bei sich eine aktuelle Version rein. Kleiner Bugfix, nichts generell schlimmes.

RS485_non_blocking.zip (3.66 KB)

Ich verstehe nicht ganz, wofür eine eigene RS-485 Bibliothek notwendig ist. Im einfachsten Fall schließt man Rx und Tx irgendeiner seriellen Schnittstelle an (soft/hard), und übertragt Daten über diese. Dabei macht es programmtechnisch keinen Unterschied, ob RS-232 oder RS-485 oder garkeine Treiber zwischen den seriellen Schnittstellen beider Geräte hängen.

Ich habe den Verdacht, daß Du hinter RS-485 irgendeine tolle Schnittstelle vermutest, die selbständig irgendwelche Übertragungen in einem raffinierten Format vornimmt. Das ist aber nicht der Fall. Wenn ein Programm mit direkter Verbinung zwischen Sender und Empfänger nicht funktioniert, dann funktioniert es auch mit RS-485 nicht.

Alternativ kann RS-485 auch für SPI oder sonst eine serielle Schnittstelle verwendet werden, braucht eben mehr Treiber-Module.

RS-485 könnte auch mit der IRremote Bibliothek benutzt werden, mit Übertragung per Kabel statt mit Infrarot. Dazu könnte man die IRremote Bibliothek auch modifizieren (Protokoll hinzufügen), um kürzere Datenpakete pro Zeichen oder mehrere Datenbytes pro Paket zu übertragen. Dann hättest Du eine weitere serielle Schnittstelle ohne Verwendung von Rx/Tx.

@Dr
Die Lib hat ne komplementär. Übertragung schon auf Software Seite. Diese macht die Übertragung Sicherere. Lies mal den Link dann sind deine Fragen beantwortet. Wenn man in beide Richtungen übertragen will muss man den En pin auch schalten.
Gruß
DerDani

Solange die Bibliothek SoftwareSerial benutzt, kann man das auch direkt für eine Punkt-zu-Punkt Verbindung benutzen. Was die Sicherheit betrifft, da ist mir AltSoftSerial lieber.

Schnibli handelt sich nur überlüssige Probleme mit der Half-Duplex (nicht komplementären) Übertragung und Multi-Master Fähigkeit ein, die er (bislang) garnicht braucht. Das alles macht eine Software-Lösung nur noch instablier und keinesfalls sicherer. Vielleicht wäre er besser dran, wenn er die Hardware-Schnittstelle für die Kommunikation benutzt, und SoftwareSerial für andere Zwecke, falls überhaupt notwendig.

Hallo,

Dr., wie volvodani schon schrieb, hat die Lib von Nick zwei Vorteile. Complementbildung und CRC Check. Kann man mit RS232 oder RS485 nutzen. Das ist egal. Da gebe ich dir recht. Wo ich dir nicht recht gebe ist das mit den Problemen. Weil die Lib läuft 1A. Nick hat 2 Bsp. Reiner Master mit reinem Slave und Rolling Master. Ich habe noch ein Zwischending mit festen Master und der/die Slaves antworteten.

Er kann ja ruhig Nicks erstes Bsp. nehmen mit non blocking Lib, den Code von Hardware Serial einbauen und fertig.
Oder er verzichtet auf die RS485 Bausteine und macht es auch ohne extra Lib. Ganz klassisch.

Hattest ihr in eurem Versuch keine Datenfehler bei der Kabellänge? Ihr habt nur die normale serielle verwendet? Ohne RS485 Bausteine.

DrDiettrich:
Ich verstehe nicht ganz, wofür eine eigene RS-485 Bibliothek notwendig ist. Im einfachsten Fall schließt man Rx und Tx irgendeiner seriellen Schnittstelle an (soft/hard), und übertragt Daten über diese. Dabei macht es programmtechnisch keinen Unterschied, ob RS-232 oder RS-485 oder garkeine Treiber zwischen den seriellen Schnittstellen beider Geräte hängen.

Nein. RS232 und Serial TTL unterscheiden sich nur duch die Spannungspegel. RS485 hat 2 Datenleitungen in eine richtung und funktioniert deshalb in Halbduplex. Senden nur in eine Richtung möglich. Entweder hin oder zurück.

Da braucht es einen "Richtungsregelung" sprich Sendeprotokoll.

Grüße Uwe

Man kann auch zwei RS-485 Treiber für zwei Signalleitungen nehmen, dann spart man sich die Probleme mit Half-Duplex.
Und eine Platine erst erstellen wenn alles funktioniert :-]
Von der Selbstzensur gestrichen :wink:

Eigentlich war D0 + D1 Reserve daher wurden die nie getestet :s.... (ich weis grosser Fehler)
Nun ist es so weit und die werden auch verwendet.

Ich komme mit der neuen Lib und dem Sample nicht ganz klar.

Und zwar habe ich meine message vorher so zusammengesetzt:

char Message[maxMsgLen+1] ;


	int var_fahrbefehl = 11;
	int var_not_aus = 0;
	int var_kontaktleiste = 0;
	int var_schlaffseil = 0;
	int var_links = 0;
	char message[20];

	itoa(var_not_aus, message, 10);
	strncat(message, ",", sizeof(message));
	strncat(message, itoa(var_kontaktleiste, buf, 10), sizeof(message));
	strncat(message, ",", sizeof(message));
	strncat(message, itoa(var_schlaffseil, buf, 10), sizeof(message));
	strncat(message, ",", sizeof(message));
	strncat(message, itoa(var_fahrbefehl, buf, 10), sizeof(message));
	strncat(message, ",", sizeof(message));
	strncat(message, itoa(var_links, buf, 10), sizeof(message));
	strcpy(Message,message);

Nun ist es ja kein char mehr daher habe ich ein bisschen mühe alles in ein byte Array zu schreiben, kann mir da jemand helfen?

const byte msg [] = "Hello world";


void loop ()
{
	myChannel.sendMsg (msg, sizeof (msg));
	delay (1000);
}  // end of loop

Hallo,

im Grunde must du dir das so vorstellen.
Dein char array "message" hat 20 Stellen. 0 bis 19, die 20. bleibt Null.
Ist für den unsichtbaren Nullterminator.

Jetzt mußt deine Variablen an die Indexsstellen 0..19 einspeichern.

ausführlich

message[0] = var_not_aus;
message[1] = kontaktleiste;
message[2] = schlaffseil;
message[3] = var_fahrbefehl;
message[4] = var_links;

und mach mal deine Variableninitialisierung mit byte statt int für diese.
Es können eh nur bytes (0...255) übertragen werden.
Wenn drüben Müll ankommt, gabs beim Sender einen Wertebereichüberlauf.
Bekommt man dann auch schneller mit.

das könntest du so übertragen. Ob du die Empfängeradresse benötigst weis ich nicht.

void sendMessage()
{ 
  digitalWrite(MAX485_EnablePin, HIGH);   // enable sending, disable receiving
  memset (&message, 0, sizeof message);   // Wird alles mit Nullen gefuellt
  message[0] = var_not_aus;
  message[1] = kontaktleiste;
  message[2] = schlaffseil;
  message[3] = var_fahrbefehl;
  message[4] = var_links; 
  myChannel.sendMsg ((byte*) &message, sizeof message); // Send my Message  
  Serial.flush();                       // warten auf komplette Übertragung
  digitalWrite(MAX485_EnablePin, LOW);  // enable receiving, disable sending 
}

Hallo so das hab ich nun kappiert.

Nun wie bring ich meine Atmegas zum Kommunizieren?
Ich habe die Library ins Projekt eingebunden und folgenden Code (zum test) auf jeweils einen Arduino geladen:

Sender:

#include <RS485_non_blocking.h>

size_t fWrite (const byte what)
{
  return Serial.write (what);  
}

RS485 myChannel (NULL, NULL, fWrite, 0);

void setup ()
{
  Serial.begin (115200);
  myChannel.begin ();
}  // end of setup

const byte msg [] = "Hello world";

void loop ()
{
  myChannel.sendMsg (msg, sizeof (msg));
  delay (1000);   
}  // end of loop

empfänger:

#include <RS485_non_blocking.h>

 int fAvailable ()
   {
   return Serial.available ();  
   }
 
 int fRead ()
   {
   return Serial.read ();  
   }
 

RS485 myChannel (fRead, fAvailable, NULL, 20);

void setup ()
  {
  Serial.begin (115200);
  myChannel.begin ();
  }  // end of setup

void loop ()
  {
  if (myChannel.update ())
    {
    Serial.write (myChannel.getData (), myChannel.getLength ()); 
    Serial.println ();
    }
  }  // end of loop

aber es kommt gar nichts an… wobei es mich hier wunder das ich die RX/TX/enabale pin nicht angeben muss…

Hast du ev ein einfaches Beispiel das Funkitoniert.?

Hallo,

hast du RS485 Chips schon dran und im Einsatz? Wenn nicht, brauchste dich um die Enable Pins nicht kümmern.
Hast du TX und RX überkreuz angeschlossen bei direkter Verbindung? Hatte ich auch erst falsch gemacht. :wink:
Mach erstmal Direktverbindung ohne RS485 Chip wenn möglich. Wenn das klappt, dann erst mit 485er. Vermeidet Fehler.

Du hast zwei UNOs? Dann hast du nur eine Hardware Serial. Darüber kommunizieren jetzt deine beiden Unos.
Du kannst jetzt nicht gleichzeitig dir auf diese eine Serial Ausgaben aufs Terminal ausgeben lassen. Geht nicht.

Deine Terminalausgaben am USB funktionieren nur über die Hardware Serial.
Deswegen mußte die Kommunikations über Software Serial machen.

Auf Nicks Seite direkt über Abschnitt "Master" steht das Bsp. für Software Serial.

Bekommste das alleine hin? Wenn nicht Bescheid geben.

Als Baudrate bitte 38400 verwenden. 115k hat mir zu viel Baudratenfehler. Hängt mit dem ungünstigen Teiler µC Takt zum Baudratentakt zusammen. Oder nimmst 250k Baudrate.

Hallo das war leider ein Schreibfehler.
Es sind 2 Selber gelötete Platinen, die vorhin Funktioniert haben. Nur brauche ich eben die Pings D0+D1 als Digital Input daher die Umstellung auf diese Version.

Ich Programiere mit Atmel Stduio mit dem IDE Plugin.

Nur sobald ich die SoftwareSerial.h importiere und “SoftwareSerial rs485 (2, 3); // receive pin, transmit pin” hinzufüge komt folgender Fehler:
Schweregrad Code Beschreibung Projekt Datei Zeile
Fehler undefined reference to `SoftwareSerial::~SoftwareSerial()’ sender008

Schweregrad Code Beschreibung Projekt Datei Zeile
Fehler undefined reference to `SoftwareSerial::SoftwareSerial(unsigned char, unsigned char, bool)’ sender008

Schweregrad Code Beschreibung Projekt Datei Zeile
Fehler ld returned 1 exit status sender008 collect2.exe 0

Das Programm siet so aus:

/*Begining of Auto generated code by Atmel studio */
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <RS485_protocol.h>
//Beginning of Auto generated function prototypes by Atmel Studio
void setup();
void loop();
//End of Auto generated function prototypes by Atmel Studio


SoftwareSerial rs485 (2, 3);  // receive pin, transmit pin

void setup() {
  // Open serial communications and wait for port to open:
 // Serial.begin(57600);
 
}

void loop() { // run over and over

}

Kann es sein das ich eine Falsche SoftwareSerial.h Library importiert habe:s

Hallo,

dein letztes Code Stück compiliert bei mir fehlerfrei.
Die Software Serial Lib ist die von der Arduino IDE. Sollte funktionieren.
Kompiliert ein Bsp. dieser Lib fehlerfrei?
Hast du an dieser Lib etwas geändert?

Die Arduino.h mußte nicht extra einbinden, wird automatisch gemacht.

Hast du auch die RS485 Chip an die neuen Pins gelötet? Die für Software Serial benutzt werden.

Ich habe in der Zwischenzeit ein Bsp. erstellt die bei mir mit 2 Megas über Software Serial funktioniert.
Ohne RS485 Chip mit Direktverbindung TX/RX über kreuz.

Edit:
kompiliere es bei dir mal testweise in der Arduino IDE. Wenn das klappt, dann hat Atmel Studio <> Plugin vielleicht irgendein kleines Problem.

NonBlocking_SoftSerial_001.zip (1.84 KB)