PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 2 Prozessoren koppeln?



darxon69
13.03.2008, 07:32
Hallo Leute.

ich habe derzeit ein projekt in der Planung bei dem ich 2 Module miteinander verbinden möchte. eine Handsteuerbox mit Controller (Display3000) und eine Basisstation in der eine weiterer Controller sitzt, der Motoransteuerung, USB,Netzwerk usw. bearbeitet.
Meine Frage ist nun, mit welchem Verfahren man am elegantesten mit wenigen Leitungen beide Controller so verbindet, dass sie miteinander kommunizieren können. Sie sollen untereinander Daten und Steuerbefehle austauschen, wobei beide gleichberechtigt sein können, also kein Master-Slave. Ich habe mir schon mal Gedanken gemacht, ob man es über I2C macht. Da gehen ja mehrere Master am Bus und es wird ja auch bei einigen RN-Boards zwischen Haupt- und Coprozessor verwendet.
Dann wäre ja noch RS232. Da muss ich vielleicht noch dazu sagen, daß das Verbindungskabel zwischen beiden Modulen etwa 2m lang ist. Bei RS232 wollt eich allerdings keinen MAX232 zur Pegelanpassung verwenden, sondern direkt die Controllerausgänge miteinander verbinden. Die Frage ist nun, ob man über die Entfernung dann keine Probleme bekommt.
Kurz gefragt, wie würdet ihr das Ganze lösen und warum?

Reeper
13.03.2008, 10:41
Zu den 2m kann ich leider nichts sagen (ob danach nochwas brauchbares ankommt, selber arbeite ich mit 0,5m).

Bei meinen Bot habe ich das mit den Usarts gelöst - funktioniert tadellos.
Wenn du eh nur 2 Controller verwenden willst, biedet dies sich ja gerade an.

Falls weitere µC dazu kommen, muss einer der Master sein (hängen ja alle auf der selben Leitung und haben nur je 1x txd und rxd) und die Daten wieder senden.

Hier mal eine Möglichkeit mit einem Atmega 162 (2xUsart) und einem Atmega 32:

Atmega 162 -> USART0 -> Empfang von PC-Signalen

ISR(USART0_RXC_vect)
{
char rec_buffer0;
rec_buffer0 = UDR0; // speichere UDR0-Wert in temp
data0[a]=rec_buffer0;
if (rec_buffer0=='#')
{
switch (data0[0])
{
case 'B': string_senden1(data0); // String gleich Slave_Controller übermitteln
break;

case 'A': switch (data0[1])
{
case 'L': switch (data0[2]) //------------Lüfter----------
{
case '1': PORTB |= (1<<0);
break;
case '0': PORTB &=~(1<<0);
break;
}
break;

case 'Q': data0[a]='\0'; //------------Servo_1---------
serv1=atoi(&data0[2]);
s1=1;
break;

case 'W': data0[a]='\0'; //------------Servo_2----------
serv2=atoi(&data0[2]);
s2=1;
break;

}
break;
}
strcpy(data0,"");
a=-1;
}
a++;
}

Atmega 162 -> USART1 -> Verbindung mit anderen µC (egal ob Slave oder nicht)

ISR(USART1_RXC_vect)
{
char rec_buffer1;
rec_buffer1 = UDR1; // speichere UDR1-Wert in temp
data1[b]=rec_buffer1;
if (rec_buffer1=='#')
{
//-----------------------------------------------------
if (data1[0]=='€')
{
strcpy(fehler,&data1[1]);
strcpy(data1,fehler);
b=b-1;
}
//-----------------------------------------------------
switch (data1[0])
{
case 'B': switch (data1[1])
{
case 'V': string_senden0(data1); // Spannungswert
data1[b]='\0';
strcpy(spannung,&data1[2]);
rxd_V=1;
break;

case 'S': string_senden0(data1); // Warnung
break;

case 'T': string_senden0(data1); // Temperaturwert
switch (data1[2])
{
case '1': data1[b]='\0';
strcpy(temp1,&data1[3]);
rxd_T1=1;
break;
case '2': data1[b]='\0';
strcpy(temp2,&data1[3]);
rxd_T2=1;
break;
}
break;

case 'X': slave1=0;
break;
}
break;
}
strcpy(data1,"");
b=-1; // Zeichen '\0' weg
}
b++;
}

Atmega 32:

ISR(USART_RXC_vect)
{
char temp;
temp = UDR; // speichere UDR-Wert in temp
data[a]=temp;
if (temp=='#')
{
//----------receive_str_edit------------------
data[a]='\0'; // '#' weg
if (data[0]=='B')
{
switch (data[1])
{
case 'G': go=1;
break;

case 'L': switch (data[2])
{
case '0': PORTC &=~(1<<5);
break;
case '1': PORTC |= (1<<5);
break;
}
break;

case 'M': manual=0;
switch (data[2])
{
case '1': PORTB |= (1<<0)|(1<<4); //-----vorwaerts------
PORTB &=~((1<<1)|(1<<2));
break;
case '2': PORTB |= (1<<1)|(1<<2); //-----rueckwaerts------
PORTB &=~((1<<0)|(1<<4));
break;
case '3': PORTB |= (1<<2)|(1<<4); //-----links------
PORTB &=~((1<<0)|(1<<1));
break;
case '4': PORTB |= (1<<0)|(1<<1); //-----rechts------
PORTB &=~((1<<2)|(1<<4));
break;
case '5': PORTB |= (1<<0)|(1<<1)|(1<<2)|(1<<4); //-----stopp------
break;
}
OCR1A=255;
OCR1B=255;
stop_manual=0;
manual=1;
break;

case 'P': PWM=atoi(&data[3]);
switch (data[2])
{
case 'A': OCR1A=PWM;
OCR1B=PWM;
break;
case 'R': OCR1A=PWM;
break;
case 'L': OCR1B=PWM;
break;
}
break;

case 'Z': switch (data[2])
{
case 'Q': OCR1B=0;
break;
case 'E': OCR1A=0;
break;
}
break;
}
}
strcpy(data,"");
//----------receive_str_edit------------------
a=-1;
}
a++;
}


Funktionsbeispiel:

1. Zeichen== Ziel µC
2. und folgende Zeichen== beliebige Unterteilung
letztes Zeichen == '#'

Beispiel:
PC -> "AL1#" (Licht an -> Befehl für µC A)
"BM1#" (Motoren_vorwaerts -> Befehl an µC B)
Alle µC sind quasi gleichwertig.
Bei mehreren µC fragt der Atmega 162 alle nacheinander ab und wird zum Master, bei nur 2 µC ist dies irrelevant.
Es kann also auch ein Slave (B) zu einem Slave (C) Daten problemlos über den Master (A) versenden.


Zur Hardware:
Meine µC sind alle seperat per ISP zu erreichen und auch seperat über RS232 zu flashen (per Schalter -jeder µC hat einen - lege ich die RXD und TXD Leitung entweder zum MAX323 oder über Kreuz zum anderen µC).

Verwende ich ohne Probleme bei meinem Bot:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=33059&start=0

Gruß Stefan

darxon69
13.03.2008, 13:04
Danke für die Anregungen. Ist natürlich eine einfache und saubere Sache und da es eh nur 2 Controller sind, kann ich mich damit anfreunden. Die Baudraten auf RS232 sollten iegentlch auch ausreichend schnell sein.
Das Problem mit der Länge dürfte auch nicht weiter bestehen, da auf dem einen Controllerboard ein MAX232 drauf ist.