Forum: Mikrocontroller und Digitale Elektronik Modbus RTU Slave fuer AVR


von Juergen G. (jup)


Angehängte Dateien:

Lesenswert?

Im Beitrag Beitrag "Modbus RTU Slave Protolollstack"

ging es um die Implementierung von Modbus auf einem AVR, ich hatte da 
angeboten meinen Code zu posten, wenn sich jemand findet der diesen Code 
in eine representable Form bringt.

Es kamen immer wieder Anfragen per PM somit mache ich einen neuen Thread 
auf und poste mal den RTU Slave Teil meiner Implementation.

Dieser Code basiert auf der UART Implementation von P.Fleury, mit 
einigen Anpassungen um die Lib modbus-faehig zu machen.

Der Modbus code ist auch irgenwo abgeschrieben, ich erinnere mich an 
zwei quellen, eine davon war freemodbus.
Freemodbus war mir aber zu gross fuer einen uC somit hab ich Ihn auf das 
notwendigste zusammengekuerzt.

Im aktuellen Code sind auch einige Modbus Funktionen auskommentiert, 
zBsp.  READ_INPUT_STATUS, das ist aber ziehmlich das selbe wie 
READ_COIL_STATUS nur mit anderem Address-Bereich

FORCE_MULTIPLE_COILS
PRESET_MULTIPLE_REGISTERS
Hab ich auch nicht fertig implementiert da es in meinen Anwendungen nie 
gebraucht wurde und ich auch keine Modbus-Geraete habe die danach 
gefragt haben.


Also dann probiert mal ob Ihr mit dem Code was anfangen koennt.
Fragen an mich hier im Forum, nicht per PM, das gleiche gilt fuer 
Verbesserungen, somit haben alle was davon.

Ju

von Juergen G. (jup)


Lesenswert?

Nochmal an Alle, Fragen bitte hier im Thread posten, nicht per PM.
PM's kann nur ich lesen, die Posts jeder den es interessiert.

Die Frage nach den Bus Treibern.

Obiger code basiert auf der UART Lib von P.Fleury.

Peters Lib wurde insoweit angepasst, das sie mit RS232 und mit RS485 
funkioniert. Es muss nur die entsprechende init routine im main 
aufgerufen werden.

Bei Verwendung von RS485 ist ein zusaetzlicher Pin am AVR zum senden 
notwendig. Als Bustreiber sollte alles gehen was dem entsprechenden 
Standard unterstuetzt.

ju

von flo (Gast)


Lesenswert?

Hi,

leider mangelt es mir da noch an Verständnis....

1. Wie kann man z.B. einem bestimmten Holding einen Wert zuweisen?
2. Wie kann ich einen bestimmten Holding auslesen?

Ist die Datei BSP_Modbus ein Beispiel?
Was soll hier passieren?

Gruß Flo

von Juergen G. (jup)


Lesenswert?

> Ist die Datei BSP_Modbus ein Beispiel?

Ja, das ist ein Slave er bekommt seine Adresse
aus der Datei JG_Modbus.h

#define SLAVE_ID  11

in diesem Beispiel

Die Holdingregister sind in dem Array

int16_t actProfileData[MAX_WordAddress];

und die Coil Register in

int8_t systemBits[MaxActionBytes];

untergebracht, beide in der BSP_Modbus_main.c deklariert und in der 
JG_Modbus.c referenziert.

Da kannst Du entsprechend Werte zuweisen.

Der Slave ist in einer Endlosschleife.
Wenn ueber den UART eine Anfrage vom Master kommt und diese vom Slave 
als ordentliches Modbus Datagramm erkannt wird, wird diese Anfrage vom 
Slave beantwortet.
Die Validation ist ein Zusammenspiel von UART RX ISR und Timer2 um die 
Timeouts und Pausen zu erkennen, danach wird die Checksum und der Inhalt 
der Daten von den eigentlichen Modbus Funktionen ueberprueft und 
beantwortet.

Der Slave lauft soweit stumm und beantwortet die Anfragen die vom Master 
kommen.

Wenn ein Master ein Holdingregister schreibt, dann findet sich das 
Resultat an der entsprechenden Stelle im Array 
actProfileData[WordAddress]
Wenn der Master ein Holdingregister liest, bekommt er den Wert der an
actProfileData[WordAddress] steht.

Das gleiche gilt fuer die Coil Register respektive das Array

systemBits[MaxActionBytes]

hier wird jede Coil-Register Adresse durch ein Bit representiert.

Ein Fallstrick ist hier, das die meisten Modbus Master bei 1 anfangen zu 
zaehlen und die entsprechende Array Position dann Adresse-1 ist.

>
> 1. Wie kann man z.B. einem bestimmten Holding einen Wert zuweisen?

ist somit glaube ich geklaert


> 2. Wie kann ich einen bestimmten Holding auslesen?
>

Du kannst das nicht, das kann nur ein Modbus Master der ein 
entsprechendes Datagramm generiert. Da gibts einige Programme die sogar 
frei sind, frag mich aber nicht welche das sind.

Wenn Du HTerm verwendest und Deinen AVR ueber den UART an Deinen PC 
haengst, kannst Du Datagramme in HEX eintippen und sie dem AVR senden, 
er wird Dir antworten.


> Ist die Datei BSP_Modbus ein Beispiel?
> Was soll hier passieren?
>
Ist glaub ich auch weiter oben schon beantwortet.


Ju

von flo (Gast)


Lesenswert?

Hallo,

habe nun mal folgendes gemacht:


Diese Defines für den Atmega16 angepasst:

#define RS485_CPort  DDRD
#define RS485_Port  PORTD
#define RS485_Pin  PIND
#define RS485_Send  PD1
#define RS485_PSend  PIN1

Ansonsten habe ich nix verändert. Nun versuche ich über Modbus Poll auf 
den Slvae Atmega16 zuzugreifen. Getaktet wird der Controller mit 8Mhz 
mit dem internen Quarz.

In Poll eingestellt:
Baudrate: 9600
8 Datenbits
Parität: keine
1 Stopbit

Modus: RTU

Mein USB Com Adapter blinkt bei TX, sprich da wird was gesendet nur auf 
dem Board tut sich nix.

Als Polldefinition habe ich Holding Funktion 3 angegeben von 3 - 11 
lesen und die Slave ID 11.

Als Fehler kommt Timeout.

Gruß Florian

von Juergen G. (jup)


Lesenswert?

Modbus RTU ist zeitabhaengig, die Pausen muessen exakt eingehalten 
werden, sonst wird das Paket nicht als gueltig erkannt.

Die Timer in meinem Beispiel sind glaube ich fuer einen 16MHz Crystal 
konfiguriert. Da also mal als erstes ansetzen und deinen Timer so 
konfigurieren das er der Zeit von einem Bit Deiner serial Uebertragung 
entspricht.

Mit dem internen RC vom Atmel und einem zeitkritischen Serial Protokoll 
zu arbeiten ist auch keine glueckliche Wahl.

Klemm an Deinen AVR mal einen 16MHz Crystal und dessen C's dran, dann 
sollte es mit dem Beispiel code klappen.
Ist glaube ich fuer den Einstieg das beste, spaeter wenn Du ein paar 
Erfolgserlebnisse hast, kannst Du immer noch mit dem RC vom AVR 
experimentieren.

Ju

von flo (Gast)


Lesenswert?

Hab jetzt mal den 16Mhz Quarz in Bewegung gesetzt.
Allerdings bekomme ich nur Timeout.....

Hab an deinem Code nur auf PD1 geändert, da dies am Atmega16 der TxD Pin 
ist....

Ansonsten ist alles unverändert... mal schauen ob es an der Hardware 
liegt.

da verwende ich die hier:

http://www.sedu-board.de/

Gruß Flo

von flo (Gast)


Lesenswert?

Mit was für einem Controller hast du bei deinem Beispiel gearbeitet?

Gruß Flo

von Juergen G. (jup)


Lesenswert?

flo schrieb:
> Mit was für einem Controller hast du bei deinem Beispiel gearbeitet?
>
> Gruß Flo

Die Entwicklung war auf einem m644, weil der 2 UARTs hat, der BSP Code 
lauft auf einem m32, sollte also Pin kompatibel zu Deinem m16 sein.

Zu dem von Dir geaenderten Pin.
Ich weiss nicht was Du da wo geaendert hast, es ist aber normalerweise 
keine Aenderung noetig wenn Du mit RS232 an den PC gehst.

Die Definitionen

RS485_CPort
RS485_Port
RS485_Send

und deren Verwendung sind nur da wenn Du mit RS485 arbeitest, da gibt es 
einen Send_Enable Pin am Bus Treiber der vor dem senden auf High gesetzt 
werden muss.
RS232 hat das nicht.
Wenn Du obige definition auf deinen TX pin geaendert hast, dann kann das 
nicht funktionieren.

Ju

von flo (Gast)


Lesenswert?

Hi,

ich nutze natürlich den RS485 Mode der wird doch auch im Beispiel 
genutzt.

Der RTS mit dem wird die Richtung normalerweise beim Modbus dann 
bestimmt.
Diesen hab ich auch auf einen Pin gelegt.

Zunächst hatte ich hier noch nen Denkfehler drin.
Aber der von dir angesprochene RS485_CPort liegt auf PD7 bei mir.
Das scheint auch so zu passen.

Nur bekomm ich leider nur Timeout.....

Ich werd jetzt mal das Beispiel von freemodbus org testen.

Gruß Flo

von flo (Gast)


Lesenswert?

Hi Ju,

irgendwie komme ich da nicht weiter:

Hardware - Sedu Board:

Atmega16

Ich habe einen USB zu RS485 Wandler am PC dran.
In deinem Beispiel steht auch, dass das Beispiel für RS485 ist.

Der CPort ist bei mir jetzt PD6 hab das nochmal durchgemessen, das passt 
jetzt eigentlich so. Bei dir war dieser Pin auf PD5 was ja eigentlich 
egal ist und halt nur wegen der Beschaltung ist.

Als Antwort bekomme ich immer Read error : break --> Write error : 
break.
Vielleicht liegt es auch an den Einstellungen in Modbus Poll?

Auch an der Slave ID oder Baudrate habe ich nix geaendert.

Kannst du mir vielleicht mal eine funktionierende Version kompilieren, 
die mit dem Sedu Board laufen sollte

Gruss Florian

von Juergen G. (jup)


Lesenswert?

@flo

Ich kenne das SEDU board nicht und habe auf der o.g. Seite auf die 
Schnelle keinen Schaltplan gefunden.
Kannst Du mir den Link zum Schaltplan posten.

Auf der Seite steht was von einem FT232, von einem Bus Treiber und 
Jumpern.

Vielleicht solltest Du mal direkt an Deinem uC messen ob da was ankommt 
und das das was der uC sendet auch bis zu Deinem PC durchkommt.

Ist die Baudrate richtig eingestellt?

ju

von Juergen G. (jup)


Lesenswert?

Zum Besseren Verstaendniss der Definitionen in meinem Beispiel

RS485_CPort  => Das DDR Register
RS485_Port   => Der Port
RS485_Send   => der Ausgangs Pin des PORT

Ju

von flo (Gast)


Lesenswert?

Ich nutze nicht den FT232 der auf dem Sedu Board ist!

Folgende Topologie:

PC mit USB---> Wandler auf RS485 ---> SN75176 --> RX-TX am Atemga16

Auf dem Sedu Board wird der Jumper auf Software gesetzt und die Jumper 
für Tx und Rx werden gesetzt.

An PD6 kann die Richtung wenn auf Software gejumpert ist geändert 
werden.

Leider kann ich in Modbus Poll einstellen was ich will ich bekomme 
ständig Timeout oder Read und Write Error.

Habe die Belegung am Stecker mehrmals überprüft, dass sollte passen.

Welche Einstellungen müssen gemacht werden, damit die Kommunikation 
funktioniert?

Gruß Florian

von flo (Gast)


Lesenswert?

Hier noch der direkte Link zu den Unterlagen:

http://www.sedu-board.de/docs/SEDU-Board_Datenblatt.pdf

Gruß Flo

von Juergen G. (jup)


Lesenswert?

Fuer die Kommunikation im Beispiel ist
Baud    9600
Bits    8
StopBit 1

voreingestellt.

Hast Du schon mal eine ganz normale serielle Komunikation ueber RS485 
zwischen Deinem PC und dem uC probiert, ohne Modbus.

Ich weiss nicht wie Dein USB/RS485 Adapter funktioniert.

Vielleicht versuchst Du es einfach mal mit dem FT232 vom SEDU Board und 
RS232.

Da faellt mir gerade ein, es gab mal das Problem, das einige Modbus Poll 
Programme nicht mit virtuellen COM Ports arbeiten.
Ist das Windows mit dem du werkelst?

Ju

von flo (Gast)


Lesenswert?

Hi,

Naja RS232 bringt mich nicht wirklich weiter, da ich eben über den PC 
auch auf mehrere Slaves zugreifen will. Der FT232 ist direkt 
onboard.....

Ich werde mal noch versuchen im Auschlussverfahren zu schauen wo es 
hängt.... evtl. mal einen anderen USB zu RS485 Converter nehmen....
Da ich oft mit Adaptern zu tun hab ist es mir auch bekannt, dass es da 
ab und an zu Problemen kommt.

Ansonsten muss ich halt auch mal noch eine andere Hardware nehmen.....

Gruß Flo

von flo (Gast)


Lesenswert?

Mit welchem Tool hast du den ganzen Code überprüft?

Vielleicht kannst du mir ja auch mal eine compilierte Version anhängen. 
Vielleicht läuft da was schief.... Einzige Änderung im Code wäre ja die 
oben angesprochene mit PD6 als RS485_send.

Der Adapter blinkt in jedem Fall und es wird mir auch angezeigt, dass 
auf TxD was ausgegeben wird aber eben keine Antwort kommt. Dadurch 
entsteht ein Time Out.

Baud 9600
Bists 8
Stop Bit 1
Parität: Ohne ?

Inputs:
Slave ID: 11
Functions Code: 4
Startadress: 0
Quantity: 10

Das sollte doch hinhauen oder....von den Konfigurationen

Gruß Flo

von Juergen G. (jup)


Lesenswert?

Startadress: 0
und
Functions Code: 4

geht in die Hose,

Wie weiter oben schon geschrieben, Modbus faengt
bei 1 an zu zaehlen

und Funktionscode 4 ist READ_INPUT_REGISTERS

will also Input Register lesen die im Beispiel nicht verwendet werden.
Das Beispiel liest und schreibt Holding Register und Coils.


Im Beispiel sind

  actProfileData[IDX_DW_Debug01] = 101;
  actProfileData[IDX_DW_Debug02] = 102;
  actProfileData[IDX_DW_Debug03] = 103;

Holding Register und haben die angegebenen Werte.
die Positionen im Array sind

IDX_DW_Debug01  35
IDX_DW_Debug02  36
IDX_DW_Debug03  37

Somit musst Du modpoll mit

Slave ID: 11
Functions Code: 3
Startadress: 36
Quantity: 3

aufrufen und solltest 101, 102 und 103 zurueck bekommen.


Ju

von flo (Gast)


Lesenswert?

Hi,

ja inputs wird nicht unterstützt....
aber ich bekomme auch keinen Holding zum laufen.

Slave ID: 11
Functions Code: 3
Startadress: 36
Quantity: 3

Ergebnis: TimeOut

Baud 9600
Bists 8
Stop Bit 1
Parität: Ohne ?

Ja ich werkle mit Windwos.... aber der RS485 Adpater gibt auch saubere 
Signale aus, dass sieht man am TxD Pin... nur kommt nix zurück?!
Die Antwort fehlt.

Komme hier auf keinen wirklich grünen Zweig....

Hast du am verlinkten Schaltplan irgendwas gesehen was es sein könnte, 
dass die Funktion nicht gewährleistet ist?

Werde mir wohl doch einen anderen AVR schnappen und einen Bustreiber 
dran bauen und dann mit dem USB --> RS485 Adapter nochmal versuchen.... 
wird aber noch bisschen dauern, da ich da sicher nicht alle teile parat 
habe.... :)

Gruß Flo

von Hauke H. (hauke112)


Lesenswert?

Hi,
habe beim stöbern im Internet den Beispiel Code gefunden und habe 
festgestellt das er recht übersichtlich ist.
Allerdings bekomme ich den Modbus Slave nicht zum laufen, vielleicht 
kann mir ja jemand helfen oder hat eine Idee wodran es liegen könnte. 
Ich benutze ein Stk500 mit einem Atmega32. Habe einen externen Quarz mit 
16Mhz angeschlossen.
Als Bustreiber verwende ich einen Max487. RE/ und DE des Bustreibers 
habe ich mit PD5 des Stk500 verbunden. RO und DI sind mit PD0 und PD1 
(RX und TX) verbunden.
Nun Versuche ich mit Hilfe von Modbus Poll die Holding Register 
auszulesen.
Allerdings bekomme ich immer ein Read Error:Break condition.
Habe in Modbus Poll folgende einstellungen vorgenommen:

Connection: Serial Port
- 9600 Baud
- 8 Data Bits
- None Parity
- 1 Stop Bit

Read Write Definition:
Slave ID 11
Function:03
Address: 36
Quantity:3
Scan Rate 1000 ms

Über eine gute Idee oder anmerkung wo mein fehler liegen könnte würde 
ich mich freuen.

Gruß Hauke

von Juergen G. (jup)


Lesenswert?

Hallo Hauke,

die Einstellungen von Modbus Poll sind OK.

Ich tippe auf ein Hardware Problem.
Kannst Du die Signale zum Max487 verfolgen?

Und die Signal A und B (oder + und -) auf der RS485 Leitung.
Evtl vertauscht.

Gruss
Ju

[edit]

check auch die PD0 und PD1 Verbindung zwischen Atmega und MAX

RO sollte auf RXD und DI auf TXD sein.

[noch ein edit]

und an die RE/ und DE Pins des Max sollte ein PullUP oder PullDown hin

von Hauke H. (hauke112)


Angehängte Dateien:

Lesenswert?

Hallo Juergen,
erstma recht vielen dank fuer deine schnelle Antwort.
Habe die Leitungen zwischen dem Atmega und dem MAX nochmals verfolgt.
Die Verdrahtung ist wie du oben geschrieben hast.
Habe das Signal am RXD des Atmegas mal mit einem Oszi aufgezeichnet und 
im Anhnag gepostet.
Zusätzlich habe ich ´RE/ und DE des MAX mit einem 2k2 Widerstand auf GND 
gelegt.
Allerdings bekomme ich immer noch keine Antwort vom ATmega bin langsam 
ein wenig am verzweifeln.
Muss ich vielleicht irgendwelche Fuse Bits setzten? Nutze seit neustem 
AVR Studio 5,  habe nur unter Tools --> AVR Pogramming --> Fuses ---> 
SUT_CKSEL die Fuses auf EXTHIFXTALRES_1KCK_64MS gesetzt. Vielleicht habe 
ich da auch einen Fehler gemacht?

Über weitere Anregungen, wo ich noch nach fehlern suche könnte würde ich 
mich freuen. Wie gesagt bin bei diesem Projekt ein wenig am verzweifeln.

Danke schon mal im vorraus

Gruß Hauke

von Juergen G. (jup)


Lesenswert?

Fuses, uff, lass mich mal nachdenken.

Ich meine wenn die Clock fuses richtig gesetzt sind, also so das Dein 
Atmega mit dem 16MHz Cristal auch mit 16MHz rennt sollte es gut sein.
Allerdings hat der AtMega32 auch noch die JTag Fuse, diese betreffen 
aber nur den PortC.

AVR Studio hab ich keine Ahnung, bei mir stehen die

lfuse auf 0xFF
hfuse auf 0xD9

Ju

von Hauke H. (hauke112)


Lesenswert?

Moin,

ok die waren richtig gesetzt.
Am code habe ich nichts geändert.
Vielleicht sonst noch eine Idee, wo sich ein Fehler eingeschlichen haben 
könnte?

Gruß Hauke

von Juergen G. (jup)


Lesenswert?

Wenn das soweit alles OK ist, hilft nur zu untersuchen an welchem Punkt 
die Komunikation aussteigt.

Ich gehe davon aus dass Du den Code 
http://www.mikrocontroller.net/attachment/113765/BSP_Modbus.zip 
verwendest.

Als erstes:
rufe den modpoll mal so auf das nur nach einem Word gefragt wird

Also

Connection: Serial Port
- 9600 Baud
- 8 Data Bits
- None Parity
- 1 Stop Bit

Read Write Definition:
Slave ID 11
Function:03
Address: 36
Quantity:1

und im main()
1
if (uart0_status.status == RS_FrameComplete) {
2
   if (UART_RxHead) {    
3
      modbus_processSlaveFrame((uint8_t*) UART_RxBuf, UART_RxHead);
4
   }
5
   uart_flush();
6
   uart0_status.status = RS_Wait;
7
}

wackelst Du an den entsprechenden Stellen mal an einem Pin des uC's um 
zu sehen welcher Teil der Bedingungen erfuellt ist.

Wenn Du siehst das
modbus_processSlaveFrame()
aufgerufen wird dann etwas tiefer gehen und im File JG_Modbus.c

am Ende des Files in der Funktion modbus_processSlaveFrame()
1
void modbus_processSlaveFrame(uint8_t *query, int query_length) {
2
  uint8_t cnt = 0;
3
4
  if (check_crc16(query, query_length) == query_length) {
5
    modbus_slave_manage(query, query_length);
6
  } else {
7
    for (cnt = 0; cnt < UART_RX_BUFFER_SIZE; cnt++) {
8
      query[cnt] = 0;
9
    }
10
  }
11
}

sehen ob der CRC Check durchgeht. Ich hatte schon modpoll Programme die 
einen eigenen CRC Key verwendeten.

Wenn der CRC check durchgeht, im selben File in der Funktion

modbus_slave_manage()
1
  switch (sft.function) {
2
        ...
3
        }

sehen mit welcher Funktionsnummer der modpoll tatsaechlich daherkommt.

Ich hatte es schon, das der Master eigentlich mit
03  READ_HOLDING_REGISTERS

daherkommen sollte

tatsaechlich kam er aber mit

04 READ_INPUT_REGISTERS

daher.


und da in meinem Code nicht alle Funktions Nummern komplett 
implementiert sind kann es da unter Umstaenden zu Missverstaendnissen 
kommen.

Gruss Ju

von Hauke H. (hauke112)


Lesenswert?

Moin,

schön dank für die Anregungen.
Habe den Fehler nun auf dem STK500 festgestellt. Den Grund dafür kenne 
ich aber nicht. Habe die Schaltung nochmal auf einem extra Board 
aufgebaut und nun funktioniert es.
Allerdings bekomme ich immer nur ein bis 2 Antworten. Den Fehler hierfür 
habe ich in der Sende Empfangs Umschaltung festgestellt. Also PD5 bleibt 
auf hight Pegel stehen und Schaltet nicht wieder zurück aul low.

Wenn du hier zu noch eine idee hättest wäre ich dir echt dankbar.

Gruß Hauke

von Juergen G. (jup)


Lesenswert?

Freut mich das es jetzt klappt.

Ich kann mir nicht vorstellen warum das mit dem zurueckschalten in den 
Empfangsmodus nicht tut.
Wenn es einmal tut sollte es immer tun, da es per ISR gemacht wird. Wenn 
kein bit mehr zu senden ist geht der Pin Low.

im File Modbus_uart.c
1
ISR(USART0_TX_vect) {
2
3
  if (is485) {
4
    RS485_Port &= ~(1<<RS485_Send);
5
  }
6
}

von Hauke H. (hauke112)


Angehängte Dateien:

Lesenswert?

Moin,

der Code scheint so weit zu passen.
Habe das Signal an RE/ und DE mal mit dem osi aufgezeichnet.
Nehme ich die Betriebsspannung vom Atmega weg und steck sie wieder ran 
bekomme ich immer einmal eine Antwort und wie vermutet schaltet der PD5 
nach dem senden nicht wieder ab.

Gruß Hauke

von Juergen G. (jup)


Lesenswert?

Laeuft der Compiler im AVR Studio fehlerfrei durch wenn Du erst ein
"make clean" und dann ein make machst?

von Hauke H. (hauke112)


Lesenswert?

Wenn der Compiler auf speed otimiert ist habe ich keinen Fehler beim 
Compilieren, auch wenn ich vorher auf Build -->  clean gehe.
Stelle ich allerding ein das nicht optimiert werden soll bekomme ich den 
Fehler undefined reference to 'setBitValForSysBit' nehme ich allerdings 
das inline vor der funktion weg, so ist auch der Fehler verschwunden.

von Juergen G. (jup)


Lesenswert?

Das ist soweit OK, lass das inline besser dort und compilire das es 
damit lauft.
Ich wollte wissen ob der Compiler evtl. irgendwelche Definitionen 
vermisst und folglich nicht die TX ISR anspringt.

Da das aber in Ordnung ist, ist irgendwo anders der Wurm drin.

Es sieht so aus als ob der Atmega noch etwas zum senden hat, dein Master 
es aber nicht haben will.

Gruss
Ju

von Hauke H. (hauke112)


Angehängte Dateien:

Lesenswert?

Habe den Signal verlauf von PD5 nochmal aufgezeichnet, so wie es 
aussieht scheint der Atmega nach dem ersten senden den PD5 PIN wieder 
auf low zu setzen.
Allerdings wird der PIN dann nach dem zweiten senden nicht wieder 
zurückgesetzt.
Vielleicht eine Idee woran es liegen könnte?

von Juergen G. (jup)


Lesenswert?

Der einzigste Punkt im ganzen Code wo der RS485_Send (PD5) auf high 
gesetzt wird ist im File

Modbus_uart.c

in der Function

uart_putc()

bevor gesendet wird, und wenn alle Bytes raus sind wird er in der  ISR 
USART0_TX_vect wieder auf Low gesetzt.

Wenn Du keinerlei Aenderungen am code gemacht hast sollte dieser Pin nur 
zum senden High sein.

Durchsuch mal Deinen Code ob Du diesen Pin nicht zufaellig als irgend 
einen indikator fuer debug zwecke nimmst oder Du uart_putc() irgendwo 
anders noch aufrufst.

Dein Oszi zeigt das der Pin etwa 800ms nach dem er nach dem senden 
abgeschaltet wurde wieder auf High geht. Das ist zu lange um eine 
Antwort auf ein Packet zu sein.

Das erste High kommt gleich nach der Anfrage, das zweite High kommt 1s 
nach der ersten Anfrage.

Das sieht aus als ob Dein modpoll 2 mal fragt, die zweite Antwort jedoch 
ignoriert.

Rufe mal Dein modpoll so auf, dass er nur einen Versuch macht.

Ju

von Hauke H. (hauke112)


Lesenswert?

Moin,
habe es seit langem mal wieder geschafft am Projekt zu basteln. Habe 
einen zweiten Slave aufgebaut und einen Wago Buskoppler als MAster 
eingesetzt.
Nach der Pause habe ich den auch den kleinen Fehler im Code gefunden und 
zwar in der Modbus_uart.h im Teil wo der Atmega32 definiert wird steht:
#define TXCIE  TXEN das TXEN habe ich nun durch TXCIE ersetzt und es 
funktioniert.
Nochmals vielen dank für deine Hilfe.
Gruß Hauke

von Uwe Z. (uwe_z)


Lesenswert?

Danke für den Kode!

Ich habe ein Testprogramm auf einem ATmega48 fast ohne Probleme zum 
Laufen bekommen.

Ein erster Vorschlag zur Verbesserung besteht darin, die Interruptrate 
aus der gesetzten Baudrate abzuleiten:
1
void initInterrupts(void) 
2
{
3
    // TC2 used for Modbus Timeout
4
    //   CTC mode 32 prescaler
5
    // one interrupt per bit length
6
    // baudrate is F_CPU / (16*UBRRx) 
7
    //   UBRRx < 500 for common baudrates and F_CPU=8MHz
8
    // 
9
    // call initInterrupts() after baudrate init!
10
  TCCR2A  = (1 << WGM21) | (0 << WGM20);
11
  TCCR2B  = (1 << WGM22) 
12
            | (0 << CS22) | (1 << CS21) | (1 << CS20);
13
  OCR2A   = UBRR0 >> 1;
14
  TIMSK2 |= (1<<OCIE2A);
15
}

Gruß aus Uppsala,

   Uwe.

von vilex (Gast)


Lesenswert?

danke für code!

von sla (Gast)


Lesenswert?

..bei der Abfrage der Coils bzw. Inputs wird eine falsche Anzahl von 
Daten Bytes zurück gesendet.
Der Fehler scheint durch die Aufsummierung der Datenmenge + Startadresse 
in der for{} Schleife zu entstehen, da die Variable ic mit 0 und nicht 
mit der Startadresse beginnt, sollte hier die Datenmenge reichen!

geänderter Code:

static int response_io_status(sft_t *sft, uint8_t *stab,
                uint8_t *response, int offset) {
  uint8_t sBit = sft->address;
  uint8_t startByte = (uint8_t)(sBit / 8);
  uint8_t nOBytes = (uint8_t)(sft->nb / 8) + ((sft->nb % 8)?1:0);
  //uint8_t bytesToThread = nOBytes + ((sft->address % 8)?1:0);
  uint8_t ic;
  uint8_t destByte = 0, intermByte = 0;

  for (ic = 0; ic < nOBytes; ic++){
    // getting the first byte where we have to get Bit's from
..

von Frank (Gast)


Lesenswert?

Hallo zusammen,
ich habe das ganze mal probiert und komme leider nicht weiter.
Ich bin so vorgegangen:

-Neues Projekt im AVR Studio erstellt (Atmega16)

-Dateien dem Projekt hinzugefügt.

-F_CPU auf 10MHZ gesetzt in den Projekteigenschaften.

-Timereinstellungen angepasst:
void initInterrupts(void) {


  // TC2 used for Modbus Timeout and sysSec Counter

  TCCR2 |= ((1<<CS21)); //Prescaler auf 8 setzten
  OCR2 = 116;  //Wert vorladen
  TIMSK |= (1<<OCIE2);

}

In der Beispieldatei auf RS232 umgestellt.
  rs323_init(UART_BAUD_SELECT(9600,F_CPU));
statt
  rs485_init(UART_BAUD_SELECT(9600,F_CPU));

Compilieren erzeugt keine Fehler und läuft sauber durch. Die Fuses sind 
auf externen Quarz gesetzt. JTAG ist aus.

Das Board hängt direkt über RS232 am Rechner dran (MAX232 dazwischen)
Hardwareaufbau funktioniert mit einfachem Sende/Antworte Programm. Denke 
daran liegt es nicht.

Hab ich irgendwas noch übersehen?

Besten Dank
F.

von Frank (Gast)


Lesenswert?

Ich frage über Modbus Poll die SlaveID 11 und Adresse 36 ab. Bekomme 
abwechselnd Write Error und Read Error: Framing Error.

F.

von Frank (Gast)


Lesenswert?

Hat sich erledigt, in Modbus Poll war noch die Parität auf Even 
eingestellt...

Sehr vielen Dank an Juergen!

von Bernd (Gast)


Lesenswert?

Juergen G. schrieb:
> Modbus RTU ist zeitabhaengig, die Pausen muessen exakt eingehalten
> werden, sonst wird das Paket nicht als gueltig erkannt.
>
> Die Timer in meinem Beispiel sind glaube ich fuer einen 16MHz Crystal
> konfiguriert. Da also mal als erstes ansetzen und deinen Timer so
> konfigurieren das er der Zeit von einem Bit Deiner serial Uebertragung
> entspricht.

Hallo,

ich weiß, dass es ein alter Thread ist, aber ich habe eine Frage zur 
Bitzeit.
Wie ist die zu verstehen? Nach meiner Rechnung passen die Einstellungen 
nicht zusammen, es funktioniert aber...

Ich habe das Beispiel erfolgreich auf einem AT90CAN als RS232 Variante 
mit 9600 Baud und externen 16 MHz laufen. Vielen Dank für das kurze 
Beispiel!

Timer zwei ist auf Prescaler 8 gestellt und wird mit 32 vorgeladen.
Macht nach meiner Rechnung 16MHz/8=2MHz.
(1/2MHz)*32=16us

9600 Baud (in bits per second laut Datenblatt) ist 1/9600=104us.

Irgendwo muss ich da etwas falsch verstehen.

von Bernd (Gast)


Lesenswert?

In der Datei JG_Modbus.c muss in der Funktion modbus_slave_manage() ein 
"break" entfernt werden. Es verhindert den Zusammenbau einer gültigen 
Nachricht und liefert nur FF FF als Antwort. Das richtige break ist 
schon da.
1
  case FC_PRESET_SINGLE_REGISTER:
2
3
    data = (query[offset + 3] << 8) + query[offset + 4];
4
5
    if (sft.address >= MAX_WordAddress) {
6
7
      resp_length = response_exception(&sft, ILLEGAL_DATA_ADDRESS,
8
          response);
9
    } else {
10
11
      if ((sft.address < MAX_WordAddress)){
12
        actProfileData[sft.address] = data;
13
        break;  // <<<< remove this break; it breaks before a proper response could be built
14
      }
15
16
      memcpy(response, query, query_length);
17
      resp_length = query_length;
18
    }
19
    break;
20
  case FC_FORCE_MULTIPLE_COILS:
21
     //...

von Christian Beinig (Gast)


Lesenswert?

Hallo,
hätte hier noch etwas: https://github.com/mbs38/yaMBSiavr

Eine Implementierung, die auch die Function Codes "Force Multiple Coils" 
und "Force Multiple Registers" unterstützt. Allerdings muss man ihr die 
verschiedenen Baudraten noch per Hand beibringen, da sie nicht auf 
Fleurys Library basiert. Dafür ist die Lib recht gut kommentiert.

Dabei ist auch ein Beispiel für den Atmega88, das bei mir zu 2,9k 
kompilliert.

Vielleicht nützt das ja jemandem :)

CB

von Max B. (maxmb) Benutzerseite


Lesenswert?

Hallo Christian,

die genannte Implementierung stammt von mir. Danke für die Blumen. Ich 
hab die Verlinkung hier mal als Anlass genommen mal ein Release zu 
machen und ein paar Sachen sauberer reinzuschreiben und so. Falls es 
jemand brauchen kann:

https://sourceforge.net/projects/yambsiavr/

von Gorden H. (gordenh)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche seit einigen Tagen meinen ATMega644PA den Modbus 
beizubringen. Ich plane ein derzeit ein Projekt mit dem ATMega und einem 
Siemens OP177.. die Kommunikation läuft deshalb zwangsweise über den 
Modbus.
Nun versuche ich schon einige Tage mich durch diverse Beispiele zu 
wuseln um einen funktionierenden Code hinzubekommen.
Ich arbeite derzeit mit einem Pollin Evaluation Board und einem USB zu 
RS485-Adapter. Habe jetzt den ATMega mit TX/RX und Richtungspin an einen 
MAX485 angeschlossen und diesen mit dem USB->RS485 Adapter verbunden.

Leider bekomme ich über Modbus Poll nur ein TimeOut.
Angehängt habe ich meine beiden Projekte mit den jeweiligen Beispielen.

ModbusPoll:
Baudrate je nach Bsp. 9600 oder 38400
8 Bit Daten
1 Stoppbit
keine Parity
keine Flowcontrol

von Max B. (maxmb) Benutzerseite


Lesenswert?

Hallo Gorden,

ich hab mir MB-yaMBSiavr.zip angeschaut.
Dein Timer sorgt bei 16Mhz, und Prescaler 8 für einen Interrupt alle 
128µs, anstatt alle 102,5µs wie im Beispiel. Daher solltest du in der 
yaMBSiavr.h in den Zeilen

#define modbusInterFrameDelayReceiveStart 16
#define modbusInterFrameDelayReceiveEnd 18
#define modbusInterCharTimeout 7

die Werte auf 14, 15 und 6 ändern, damit das wieder passt.
Das sollte allerdings nicht der Grund gewesen sein, warum es nicht 
funktioniert :P

Aber:
Du weißt, dass der UART1 verwendet wird und nicht UART0?
In Modbuspoll hast du auch die richtige Device Adresse (hier 1) und auch 
nur die im Beispiel vorhandenen Register/Coils oder was auch immer 
ausgewählt?

Viele Grüße, M

: Bearbeitet durch User
von Gorden H. (gordenh)


Lesenswert?

Hi Max,

danke für die schneller Antwort, und sorry dass ich dich zuerst per PN 
angeschrieben hab und dann das hier noch gepostet habe.

Zur Sache: Erstmal danke für die Einstellungsanpassung.

Auf die Gefahr hin, dass ich jetzt (jetzt erst recht wo ich es noch 
schreibe) gesteinigt werde: der ATMega644PA hat ja zwei USARTS und kein 
UART.. nun ist in der Library doch alles so angepasst, dass die 
Adressierung hinhaut, gibt ja auch beim Kompilieren keine Fehler.. 
soweit so gut.
Da du sagst dass USART1 benutzt wird:
USART1 geht laut Datenblatt auf den PORTD dementsprechend habe ich die 
PORTD PIN 0 und 1 (RX/TX) auch an den MAX485 angeschlossen.. sollte also 
auch passen.

Das Modbus Poll-Programm hab ich entsprechend der in deinem Beispiel 
definierten Holdingregister eingestellt.. also 0..3, sollte diese 
Adresse falsch sein, sollte ich doch aber Read/Write-Error bekommen und 
kein plumpes Timeout oder?

Slaveadresse 1 ist soweit auch definiert und die entsprechenden 
Einstellungen wie oben zusätzlich habe ich den USB-COM-Anschluss genauso 
eingestellt, falls das nicht eh schon das modbus poll programm macht.

Ich werde gegen 18 Uhr nochmal die angepassten Daten einspeisen und dann 
testen. Es könnte auch sein, dass mein MAX485 irgendeinen defekt. Die 
Pegel an A/B ändern sich jedenfalls nicht wenn ich Polle, aber ich messe 
auch nur mit einem Multimeter, habe leider kein Oszi zuhause, wenn ich 
das mal im Labor teste, was müsste ich da "ungefähr" auf dem Oszi sehen?

von Max B. (maxmb) Benutzerseite


Lesenswert?

Gorden H. schrieb:
> PORTD PIN 0 und 1 (RX/TX)

Nope. PD2 und PD3 sind es.

Und das wird dann noch mit dem TXenable/RXdisable kollidieren. In der 
yaMBSiavr.h steht:

/*
* Definitions for transceiver enable pin.
*/
#define TRANSCEIVER_ENABLE_PORT PORTD
#define TRANSCEIVER_ENABLE_PIN 2
#define TRANSCEIVER_ENABLE_PORT_DDR DDRD

Das musst du dann noch auf irgendeinen anderen freien Pin deiner Wahl 
umkonfigurieren und die beiden RXdisable/TXenable pins des MAX485 da 
dran anschließen.

M

: Bearbeitet durch User
von Gorden H. (gordenh)


Lesenswert?

So ich bin jetzt wieder am Objekt. Danke für die Lesenachhilfe, manchmal 
ist man einfach zu blind :(.

Habe jetzt folgenden Aufbau:
1
ATMega        MAX485      USB->RS485-Adapter 
2
             ________
3
PD2        1|RO   Vcc|8     5V 
4
            |        |
5
PD7        2|/RE    B|7     485- 
6
            |        |
7
PD7        3|DE     A|6     485+ 
8
            |        |
9
PD3        4|DI   GND|5     GND verbunden mit Board GND
10
            |________|
11
12
Vcc und GND hängt noch ein 10µF
13
Muss an  PD7 ein Pullup/down Widerstand sein?

Habe den Pin in der yaMBSiavr.h entsprechend angepasst auf 7.
Somit sollte der HW-Aufbau jetzt ja endlich auch richtig sein 
(hoffentlich)

Leider bekomme ich über den Modbuspoll weiterhin nur ein Timeout.
Im Ruhezustand (USB-RS485 angeschlossen und verbunden mit dem Board, 
aber kein Modbuspoll) messe ich jeweils gegen GND:

RO: 4,90 V
DI: 4,90 V
A:  0,30 V
B:  0,17 V

Wenn ich mit Modbuspoll polle genauso. Sind die Pegel an A/B nicht 
irgendwie zu niedrig, bzw. die an PD 2/3 zu hoch? Irgendwie hab ich das 
Gefühl, dass sich alle beteiligten Geräte gegen mich verschworen haben.

von m.n. (Gast)


Lesenswert?

Gorden H. schrieb:
> und diesen mit dem USB->RS485 Adapter verbunden.

Könnte es sein, daß Dir dieser Adapter das Timing verdirbt?

von Gorden H. (gordenh)


Lesenswert?

m.n. schrieb:
> Könnte es sein, daß Dir dieser Adapter das Timing verdirbt?

Kann gut sein, leider habe ich keine reine Serielle Schnittstelle mehr 
in den PCs/Laptops, bin deshalb auf einen USB-Adapter angewiesen zum 
Testen.

Link zum Adapter:
http://www.digitus.info/mx/produkte/zubehoer/adapter-und-konverter/r-usb-seriell-adapter-usb-20-da-70157/
"Datenblatt" leider nicht viel Infos
http://datasheet.digitus.info/de/4016032307433.html

von Max B. (maxmb) Benutzerseite


Lesenswert?

Gorden H. schrieb:
> Muss an  PD7 ein Pullup/down Widerstand sein?

nein.

Gorden H. schrieb:
> RO: 4,90 V
> DI: 4,90 V
> A:  0,30 V
> B:  0,17 V

Ist völlig normal. Hast halt keine Bias-Schaltung gebaut für den Bus..
http://www.ni.com/images/support/us/bias.gif
Dürfte aber trotzdem funktionieren.

Der Adapter müsste theoretisch gehen.

Nimm mal HTERM oder so und schick mal ne Modbus Message per Hand. Vorher 
in yambsiavr.c einfach die crc funktion so verändern, dass sie immer 
0x1234 liefert. Dafür musst du nur out=0x1234 einkommentieren.

Dann einfach mal 01 03 00 00 00 03 34 12 hinschicken. Dann müsste was 
zurückkommen...

Ansonsten mal mit nem zweiten seriell->usb wandler mal direkt auf den RO 
vom MAX485 hängen und gucken was da so kommt. Da sollte das gleiche 
ankommen. Wenn das schon nicht der Fall ist naja ne... ^^

von Gorden H. (gordenh)


Lesenswert?

Huhu,

zum HTerm:

Port COM4 (ist der USB 485 adapter) Data 8 Stop 1 Parity None und kein 
CTS Flow Control...

Wenn ich Connecte sehe ich keine CTS DSR RI DCD LED - aber sind 
vielleicht eh nie an bei der Hardware..

Wenn ich jetzt "01 03 00 00 00 03 34 12" sende über "HEX" und dann Enter 
so dass es im Transmitted steht... habe also das Gesendet(?), erhalte 
aber nichts zurück.. :(

Einen zweiten USB/Serielladapter habe ich leider nicht rumfliegen, der 
hier war schon eine Neuanschaffung für den Zweck.

: Bearbeitet durch User
von Max B. (maxmb) Benutzerseite


Lesenswert?

Gorden H. schrieb:
> Wenn ich jetzt "01 03 00 00 00 03 34 12" sende über "HEX" und dann Enter
> so dass es im Transmitted steht... habe also das Gesendet(?), erhalte
> aber nichts zurück.. :(
Dann hast du es gesendet.

Ansonsten halt (Speicher-)Oszi an RO halten. So richtig gut sehen ob was 
Vernünftiges kommt kann man dann mit Hirnschmalz+Speicheroszi oder nem 
weiteren FTDI Ding:

> Einen zweiten USB/Serielladapter habe ich leider nicht rumfliegen, der
> hier war schon eine Neuanschaffung für den Zweck.
Dann würde ich noch einen zweiten anschaffen. Kann man immer brauchen. 
Kostenpunkt unter 5 Euro bei ebay.

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Max B. schrieb:
> Dann würde ich noch einen zweiten anschaffen.

Aus Erfahrung: um Digitus mache ich schon seit vielen Jahren einen 
weiten Bogen.

von Max B. (maxmb) Benutzerseite


Lesenswert?

m.n. schrieb:
> Max B. schrieb:
>> Dann würde ich noch einen zweiten anschaffen.
>
> Aus Erfahrung: um Digitus mache ich schon seit vielen Jahren einen
> weiten Bogen.

Ich meinte irgendein Board mit einem TF232 drauf...

von m.n. (Gast)


Lesenswert?

Max B. schrieb:
> TF232

?
Ich lerne gerne dazu.

von Gorden H. (gordenh)


Lesenswert?

Also um das ganze nochmal abzurunden.. am Code liegt es dann wohl nicht 
mehr? und Hardware ist soweit auch ok. dann besorg ich mir wohl nochmal 
nen neuen Max485 da bei dem den ich hab nicht zu 100% klar ist, ob er 
überhaupt noch ganz funktionabel ist.
Das Problem ist, dass ich mit der ganzen Sache schon unter Zeitdruck 
stehe, da tut quasi jeder Tag an dem ich nicht weiter komme weh :/

Aber trotzdem nochmal ein großes Danke an euch, dass ihr mich soweit an 
die Hand genommen habt. Bin nur leider grad an dem Punkt wo ich 
überlegen muss, ob ich die RS485/Modbus-Sache begrabe und stattdessen 
auf ein herkömmliches 0815-LCD+Matrixtastertur downgrade, was ich direkt 
oder über einen zweiten µC anspreche.

: Bearbeitet durch User
von Gorden H. (gordenh)


Lesenswert?

Hi, vielleicht würde das als Ersatz für meinen blanken max485 dienen um 
den fehlerhaften maxi auszuschließen. hoffe der Link geht so.
http://www.segor.de/#Q=RS485-TTLModul&M=1
Der Direktlink geht leider nicht. Einmal auf neuer Katalog gehen dann 
nach RS485 suchen, dann taucht das RS485 TTl Modul auf.

Und zusätzlich nochmal einen anderen USB RS485 Wandler meinst du?

: Bearbeitet durch User
von jup (Gast)


Lesenswert?

Einfach mal so gefragt.

Wie lang sind denn Deine Leitungen zwischen den beiden "Endgeraeten"
sind die Leitungen verdrillt
hast Du Abschluss R's dran?

wenn die Leitungen kurz sind und keine R's dran sind, haben es die Max 
schwer da was richtiges zu erkennen.

Das Du einen Max gegrillt hast sehe ich eher als unwarscheinlich an. Die 
MAX sind meiner Erfahrung nach sehr robust, da brauchs schon einiges um 
die kaputt zu machen.

Ju

von Gorden H. (gordenh)


Lesenswert?

In der Tat sind die Leitungen zur Zeit zum Testen sehr kurz, nur ein 
paar Zentimeter um genau zu sein. Hätte nicht gedacht, dass sich das 
noch negativ auswirken könnte.

 Was für einen Abschlusswiderstand würdest du empfehlen, habe jetzt 
zwischen 100 und 120 Ohm gelesen die ich dann am Max an den A/B 
anschließe, und das gleiche am USB-RS485 Wandler?

Zum Grillen: Das Siemens OP177 hat eine serielle Schnittstelle mit SubD9 
Buchse. Das Pinout ist abweichend zum RS422/485 und zusätzlich ist auf 
einem Pin auch noch +24V. Das hab ich aber quasi in meiner Naivität in 
den Anfängen nicht überprüft, deshalb kann es sein, dass der MAX 
(welcher ineinem rs458/rs232 Adapter verbaut war gegrillt wurde, habe 
den jetzt quasi ausgebaut um mir die RS232/485 Wandlung als Fehlerquelle 
zu sparen, und den ATMega direkt über RS485 kommunizieren zu lassen.

von m.n. (Gast)


Lesenswert?

Gorden H. schrieb:
> Bin nur leider grad an dem Punkt wo ich
> überlegen muss, ob ich die RS485/Modbus-Sache begrabe und stattdessen
> auf ein herkömmliches 0815-LCD+Matrixtastertur downgrade, was ich direkt
> oder über einen zweiten µC anspreche.

Ich kenn weder das Siemens Gerät noch Deine Anforderungen. Aber wenn 
eine Lösung mit eigenem µC reichen würde, würde ich das vermutlich so 
machen. Falls es noch woanders klemmt, hast Du größeren Spielraum bei 
der Anpassung.

m.n. schrieb:
> Max B. schrieb:
>> TF232
>
> ?

Offensichlich ein unkorrigierter Tippfehler, aber auch zu TF232 gibt es 
etliche Treffer bei der Suche.
Aktuell möchte hier jemand ein 433mhz-Signal über Antenne empfangen. 
Wieviel km Länge muß diese wohl haben?

von Gorden H. (gordenh)


Lesenswert?

Die Angabe des Siemens-Gerätes war auch nur der Vollständigkeit halber.

Sinn ist halt eine Visualisierung von Füllständen von eingegrabenen 
Tanks. Diese sollen dann befüllt/entleert werden können bzw. der 
Gartenteich und die Rasensprenger durch diese Tanks gespeist werden. Mit 
einem kleinen 2 Zeilen Display wäre das mühselig. Die HMI würde da schon 
viel Comfort bieten zur Auswahl von Ventilen etc., und ich kann diese 
halt gut selbst Projektieren aus Erfahrung.

von Max B. (maxmb) Benutzerseite


Lesenswert?

m.n. schrieb:
> Max B. schrieb:
>> TF232
>
> ?
> Ich lerne gerne dazu.

Sorry. FTDI FT232 war gemeint.

Gorden H. schrieb:
> Hi, vielleicht würde das als Ersatz für meinen blanken max485 dienen um
> den fehlerhaften maxi auszuschließen. hoffe der Link geht so.
> http://www.segor.de/#Q=RS485-TTLModul&M=1
> Der Direktlink geht leider nicht. Einmal auf neuer Katalog gehen dann
> nach RS485 suchen, dann taucht das RS485 TTl Modul auf.
>
Kannste machen. Kannst auch wenns drängt einfach zu Conrad oder so gehen 
und einen max481, max485 oder ähnlich verlangen.

> Und zusätzlich nochmal einen anderen USB RS485 Wandler meinst du?
USB zu UART auf TTL Pegel. Sowas kann man zum Testen eben auch ohne 
MAXxxx an den Atmel hängen.

jup schrieb:
> Wie lang sind denn Deine Leitungen zwischen den beiden "Endgeraeten"
> sind die Leitungen verdrillt
> hast Du Abschluss R's dran?

Bei der Baudrate und Kabellänge ist Verdrilltheit und 
Reflektionsfreiheit durch Abschluss mit Sicherheit egal. Das Biasing 
mitsamt einem Widerstand in der Mitte des Teilers sollte man aber auf 
jeden Fall machen, da es ja vorkommen kann, dass keiner der auf dem Bus 
vorhandenen Treiber gerade nicht hochohmig ist.

jup schrieb:
> Das Du einen Max gegrillt hast sehe ich eher als unwarscheinlich an. Die
> MAX sind meiner Erfahrung nach sehr robust, da brauchs schon einiges um
> die kaputt zu machen.

Kommt drauf an. RS485 Spec verlangt, dass man +-12V anlegen kann, ohne, 
dass etwas kaputtgeht. Nicht jedoch 24V. Damit habe ich auch schon mal 
um die 20 MAX481 auf einem Bus auf einen Schlag gegrillt...

Es gibt natürlich zB. sowas wie MAX13442E, an den man sogar +-80V 
anlegen kann :P

Gorden H. schrieb:
> Zum Grillen: Das Siemens OP177 hat eine serielle Schnittstelle mit SubD9
> Buchse. Das Pinout ist abweichend zum RS422/485 und zusätzlich ist auf
> einem Pin auch noch +24V.

Sicher, dass das Ding Modbus spricht? Hab das nicht direkt finden 
können.

von Gorden H. (gordenh)


Lesenswert?

Max B. schrieb:

> Gorden H. schrieb:
>> Zum Grillen: Das Siemens OP177 hat eine serielle Schnittstelle mit SubD9
>> Buchse. Das Pinout ist abweichend zum RS422/485 und zusätzlich ist auf
>> einem Pin auch noch +24V.
>
> Sicher, dass das Ding Modbus spricht? Hab das nicht direkt finden
> können.

https://cache.industry.siemens.com/dl/files/461/21084461/att_82592/v1/hmi_tp177a_tp177b_op177b_operating_instructions_en_US_en-US.pdf

Lt. Datenblatt Seite 29 Spricht es Modbus unter Verwendung eines 
Siemens-Adapters. Meine Herangehensweise war bisher die: solange die 
Kommunikation zwischen PC und ATMega über RS485 und Modbus nicht 
funktioniert, will ich es erst gar nicht am Panel versuchen, weil das 
Gerät auch keinerlei Debug-Funktionen bietet um zu überprüfen ob 
überhaupt was passiert. Das einzige was man sich anzeigen lassen kann, 
ist ob der anzuzeigende Wert gelesen wird (wenn keine Kommunikation 
werden nur "####" angezeigt sonst halt der Wert).


Aber vermutlich werde ich mal parallel als Notlösung mit einem kleinen 
Display anfangen, vielleicht mit einem zweiten µController für 
Matrixtastatur und LCD. eine Kommunikation ATTiny<->Atmega oder 
Atmega<->Atmega sollte ja hoffentlich für mich hinzubekommen sein.

von Max B. (maxmb) Benutzerseite


Lesenswert?

Gorden H. schrieb:
>> Sicher, dass das Ding Modbus spricht? Hab das nicht direkt finden
>> können.
>
> 
https://cache.industry.siemens.com/dl/files/461/21084461/att_82592/v1/hmi_tp177a_tp177b_op177b_operating_instructions_en_US_en-US.pdf
>
> Lt. Datenblatt Seite 29 Spricht es Modbus unter Verwendung eines
> Siemens-Adapters.

Aha. Da steht nicht, dass das Ding Modbus-Master sein kann. Hört sich 
für mich mehr so an, als würde es ein Client für eine der in dem 
Tabellenfeld daneben aufgeführten SPSen sein.

Gorden H. schrieb:
> Aber vermutlich werde ich mal parallel als Notlösung mit einem kleinen
> Display anfangen, vielleicht mit einem zweiten µController für
> Matrixtastatur und LCD. eine Kommunikation ATTiny<->Atmega oder
> Atmega<->Atmega sollte ja hoffentlich für mich hinzubekommen sein.

Kannste prinzipiell auch Modbus für nehmen.

von Mathias O. (m-obi)


Lesenswert?

Also ich nutze für Modbus am AVR (ATmega88 und ATtiny841) immer 
freemodbus.
Sowohl für RTU als auch TCP. Funktioniert super.
http://www.freemodbus.org/

Für den PC nimm ich libmodbus. Z.B. für ein Modbus-Tester, der mir dann 
verschiedene Funktionen nacheinander durchtestet. Also 
selbstgeschriebene Programme.
http://libmodbus.org/

Und als USB/RS485-Adapter den 
http://www.amazon.de/In-Circuit-901-274-USB-RS485-Adapter-Blau-Gr%C3%BCn/dp/B00I9H0998
Der hat die Bias-Schaltung auch schon mitdrin.

Wenn das Panel ein Client/Master ist. Dann muss der AVR natürlich 
Server/Slave sein.

: Bearbeitet durch User
von Max B. (maxmb) Benutzerseite


Lesenswert?

Mathias O. schrieb:
> Also ich nutze für Modbus am AVR (ATmega88 und ATtiny841) immer
> freemodbus.
> Sowohl für RTU als auch TCP. Funktioniert super.
> http://www.freemodbus.org/

Hab ich auch schon benutzt. Habe dann dennoch eine eigene 
Implementierung speziell für den AVR geschrieben, weil ich es auch auf 
einem in einem Gerät bereits vorhandenen attiny2313 laufen lassen wollte 
- dafür ist freemodbus aber zu bloated.

Mathias O. schrieb:
> Für den PC nimm ich libmodbus. Z.B. für ein Modbus-Tester, der mir dann
> verschiedene Funktionen nacheinander durchtestet. Also
> selbstgeschriebene Programme.
> http://libmodbus.org/
Schöner ist natürlich eine fertige GUI zum Testen. Ich hab auch immer 
einfach python script geschrieben mit pymodbus dahinter.

Hast du eine nette GUI zur Hand?

von John Doe Mueller (Gast)


Lesenswert?

@maxmb:

http://en.radzio.dxp.pl/modbus-master-simulator/

funktioniert gut zum Testen.

von Tim Grunolf (Gast)


Lesenswert?

Ja tut es. Stürzt allerdings sehr gerne ab und verliert manchmal Pakete 
wenn man es benutzt um mal richtig Durchsatz zu machen. Habe mir dann 
doch ein paar kleine Skripte mit modpoll geschrieben - zumindest für die 
Performance-Tests :)

von Hans Günther (Gast)


Lesenswert?

Hallo,
kann mir jemand sagen wie man diese Library 
https://github.com/mbs38/yaMBSiavr) bei Atmel Studio 7 einbindet?

HG

von Hirnsauce (Gast)


Lesenswert?

Hans Günther schrieb:
> kann mir jemand sagen wie man diese Library
> https://github.com/mbs38/yaMBSiavr) bei Atmel Studio 7 einbindet?

Einfach die .h und die .c Datei per Drag&Drop rechts in den 
Library-Explorer von AS7 ziehen. Im code dann #include "yambsiavr.h" e 
voila :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.