www.blafusel.de


  Home  |   Privat  |   Impressum  |   Bücher  |   Computer  |   Mikrocontroller  |   Misc  |   OBD  |   Forum
Aktuelle Zeit: Mittwoch 24. April 2024, 09:10

Alle Zeiten sind UTC + 1 Stunde




Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Sonntag 20. August 2006, 11:00 
Hallo!

Ich habe versucht, nach der KW1281 Protokollbeschreibung unter Linux mit einem einfachen Programm Verbindung zum Motorsteuergerät aufzunehmen.

Bei fest eingestellter Baudrate von 9600 bekomme ich nach dem Senden des 5baud-7O1 Adressbytes die erwarteten sync und keyword bytes, dann schickt das Motorsteuergerät die vier ASCII Blöcke, die ich jeweils mit einem ACK Block quittieren kann (Blöcke 1 bis 8). Dann beginnt der ACK Block Schlagabtausch (Blöcke 9 bis 12).

Block 13 vom Steuergerät zu empfangen gelingt jedoch nicht mehr; wenn ich die eingehenden Bytes jeweils mit dem Komplement quittiere kann ich ca. 6 mal die Folge 0x03 0x0a empfangen und dann kommt nichts mehr.

Die Kommunikation unter VAG-COM 409.1 via wine funktioniert problemlos. Hier ist mein Testprogramm: Mache ich vielleicht einen trivialen Fehler?

Code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>

#include <linux/termios.h>

int fd;
int counter;   /* kw1281 protocol block counter */

/* manually set serial lines */

static void _set_bit(int bit)
{
   int flags;

   ioctl (fd, TIOCMGET, &flags);
   if (bit) {
      ioctl (fd, TIOCCBRK, 0);
      flags &= ~TIOCM_RTS;
   } else {
      ioctl (fd, TIOCSBRK, 0);
      flags |= TIOCM_RTS;
   }
   ioctl (fd, TIOCMSET, &flags);
}

/* receive one byte and acknowledge it */

unsigned char kw1281_recv_byte_ack()
{
   unsigned char c, d;

   read (fd, &c, 1);
   d = 0xff-c;
   usleep (10000);
   write (fd, &d, 1);
   read (fd, &d, 1);
   if (0xff-c != d)
      printf ("kw1281_recv_byte_ack: echo error (0x%02x != 0x%02x)\n", 0xff-c, d);
   return c;
}

/* send one byte and wait for acknowledgement */

void kw1281_send_byte_ack(unsigned char c)
{
   unsigned char d;
   int in;

   usleep (10000);
   write (fd, &c, 1);
   read (fd, &d, 1);
   if (c != d)
      printf ("kw1281_send_byte_ack: echo error (0x%02x0x%02x != 0x%02x)\n", c, d);
   read (fd, &d, 1);
   if (0xff-c != d)
      printf ("kw1281_send_byte_ack: ack error (0x%02x != 0x%02x)\n", 0xff-c, d);
}

/* write 7O1 address byte at 5 baud and wait for sync/keyword bytes */

void kw1281_init(int address)
{
   int i, p, flags;
   unsigned char c;

   int out,in;

   /* prepare to send (clear dtr and rts) */
   ioctl (fd, TIOCMGET, &flags);
   flags &= ~(TIOCM_DTR | TIOCM_RTS);
   ioctl (fd, TIOCMSET, &flags);
   usleep (200000);

   _set_bit (0);      /* start bit */
   usleep (200000);   /* 5 baud */
   p = 1;
   for (i=0; i<7; i++) {   /* address bits, lsb first */
      int bit = (address >> i) & 0x1;
      _set_bit (bit);
      p = p ^ bit;
      usleep (200000);
   }
   _set_bit (p);      /* odd parity */
   usleep (200000);
   _set_bit (1);      /* stop bit */
   usleep (200000);

   /* set dtr */
   ioctl (fd, TIOCMGET, &flags);
   flags |= TIOCM_DTR;
   ioctl (fd, TIOCMSET, &flags);

   /* read bogus values, if any */
   ioctl(fd, FIONREAD, &in);
   while (in--) {
      read (fd, &c, 1);
      printf ("ignore 0x%02x\n", c);
   }

   read (fd, &c, 1);
   if (c != 0x55)
      printf ("kw1281_init: sync error (0x55 != 0x%02x)\n", c);

   read (fd, &c, 1);
   if (c != 0x01)
      printf ("kw1281_init: keyword error (0x01 != 0x%02x)\n", c);

   c = kw1281_recv_byte_ack ();
   if (c != 0x8a)
      printf ("kw1281_init: keyword error (0x8a != 0x%02x)\n", c);

   counter = 1;
}

/* receive a complete block */

void kw1281_recv_block()
{
   int i;
   unsigned char c, l, t;
   char buf[256];

   /* block length */
   l = kw1281_recv_byte_ack();

   c = kw1281_recv_byte_ack();
   if (c != counter) {
      printf ("counter error (%d != %d)\n", counter, c);

      printf ("IN   OUT\t(block dump)\n");
      printf ("0x%02x\n", l);
      printf ("     0x%02x\n", 0xff-l);
      printf ("0x%02x\n", c);
      printf ("     0x%02x\n", 0xff-c);
      while (1) {
         c = kw1281_recv_byte_ack();
         printf ("0x%02x\n", c);
         printf ("     0x%02x\n", 0xff-c);
   }   }

   t = kw1281_recv_byte_ack();
   switch (t) {
      case 0xf6:
         printf ("got ASCII block %d\n", counter);
         break;
      case 0x09:
         printf ("got ACK block %d\n", counter);
         break;
      default:
         printf ("block title: 0x%02x (block %d)\n", t, counter);
   }
   l -= 2;

   i = 0;
   while (--l) {
      c = kw1281_recv_byte_ack();
      buf[i++] = c;
      printf ("0x%02x ", c);
   }
   buf[i] = 0;
   if (t == 0xf6)
      printf ("= \"%s\"\n", buf);
   else
      printf ("\n");

   /* read block end */
   read (fd, &c, 1);
   if (c != 0x03)
      printf ("block end error (0x03 != 0x%02x)\n", c);

   counter++;
}

/* send an ACK block */

void kw1281_send_ack() {
   unsigned char c;

   printf ("send ACK block %d\n", counter);

   /* block length */
   kw1281_send_byte_ack (0x03);

   kw1281_send_byte_ack (counter++);

   /* ack command */
   kw1281_send_byte_ack (0x09);

   /* block end */
   c = 0x03;
   usleep (10000);
   write (fd, &c, 1);
   read (fd, &c, 1);
   if (c != 0x03)
      printf ("echo error (0x03 != 0x%02x)\n", c);
}


int main(int arc, unsigned char *argv[]) {

   unsigned char c;
   struct termios oldtio, newtio;
   struct sigaction saio;

   fd = open ("/dev/ttyS0", O_SYNC | O_RDWR | O_NOCTTY);
   if (fd < 0) {
      exit(-1);
   }

   tcgetattr (fd, &oldtio);

   newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
   newtio.c_iflag =  IGNPAR | ICRNL;
   newtio.c_oflag = 0;
   newtio.c_cc[VMIN] = 1;
   newtio.c_cc[VTIME] = 0;
   tcflush (fd, TCIFLUSH);
   tcsetattr (fd, TCSANOW, &newtio);

   printf ("init\n");   /* ECU: 0x01, INSTR: 0x17 */
   kw1281_init (0x01);      /* send 5baud address, read sync byte + key word */

   printf ("receive blocks\n");
   kw1281_recv_block ();   /* controller ID */
   kw1281_send_ack ();

   kw1281_recv_block ();   /* component # */
   kw1281_send_ack ();

   kw1281_recv_block ();   /* software coding */
   kw1281_send_ack ();

   kw1281_recv_block ();   /* dealer part # */
   kw1281_send_ack ();

   printf ("main loop\n");
   while (1) {
      kw1281_recv_block ();
      usleep (100000);
      kw1281_send_ack ();
   }

   /* tcsetattr (fd, TCSANOW, &oldtio); */
}


grusz
Philipp


Nach oben
  
 
 Betreff des Beitrags:
BeitragVerfasst: Montag 21. August 2006, 06:08 
Offline
Administrator
Benutzeravatar

Registriert: Mittwoch 6. Oktober 2004, 09:52
Beiträge: 2122
Schau mal hier: http://www.blafusel.de/misc/obd2_kw1281.html#11
Du machst es genau so wie ich - falsch. Vor allem bei
Code:
/* read block end */


Vermutlich stresst Du die ECU schon vorher zu sehr - gerade bei 9600Bd. Also etwas langsamer angehen mit den ACKs. Hängt vermutlich auch vom System ab. Ein µC ist halt schnell, weiß nicht, was Unix da macht. Aber Pausen sind immer gut. Sonst sieht der Code ja gut aus und wenn es bis dahin schon klappt, dann wird es so was ärgerlich triviales sein.

Vielleicht macht die ECU aber auch nach ein paar ACKs dicht. Kenne ich zwar nicht so, aber die Hersteller sind ja manchmal phantasievoll. Also vielleicht keine Zeit vertrödeln, sondern irgendwann mal Daten abfragen. Im Zweifellsfall immer wieder den Fehlerspeicher auslesen.


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Donnerstag 24. August 2006, 09:30 
Danke für die Tips! Leider hilft mir das noch nicht weiter :(

Ich warte vor dem Senden der ACKs in der Schleife 100ms, aber die Verbindung bricht reproduzierbar bei Block 13 vom ECU zusammen. Das gleiche passiert, wenn ich die ACKs durch group reading Befehle ersetze. Ich erhalte einen Messwertblock 11, aber statt Block 13 lese ich wieder nur 0x03 0x0a 0x03 0x0a usw.

Florian hat geschrieben:
Schau mal hier: http://www.blafusel.de/misc/obd2_kw1281.html#11
Du machst es genau so wie ich - falsch. Vor allem bei
Code:
/* read block end */


Das habe ich nicht ganz verstanden. Ich warte vor jedem write() etwa 10ms (bei 20ms bricht die Verbindung ab). Mache ich beim /* read block end */ noch etwas anderes falsch?


Nach oben
  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 25. August 2006, 07:50 
Offline
Administrator
Benutzeravatar

Registriert: Mittwoch 6. Oktober 2004, 09:52
Beiträge: 2122
Es wird IMHO am Timing liegen - wo auch immer. Natürlich kann auch an der ECU was falsch sein. Aber wenn Du Daten empfängst und dann ein Fehler auftritt, ist der Code ja schon mal OK.

Bei dem Kommentar hatte ich einen Wartezyklus übersehen.


Nach oben
 Profil  
 
 Betreff des Beitrags: huhu
BeitragVerfasst: Mittwoch 9. Januar 2008, 21:24 
hey philip, wie weit bist du denn nun gekommen? timing in den griff bekommen?

.martin


Nach oben
  
 
BeitragVerfasst: Donnerstag 25. Februar 2010, 14:08 
Ich kann den Fehler hier bestätigen. Benutze zwar 10400 baud, aber ansonsten nur eine leicht abgeänderte Version deines Codes. Auch hier bekomme ich nach Block 13 nur noch 0x0f und 0x0a abwechsent.
Initialisierung, ASCII Bytes und das erste Group Reading funktionieren aber problemlos.

Gibts jemanden der das in den Griff bekommen hat, bzw weiß wo ran es liegt?


Nach oben
  
 
BeitragVerfasst: Donnerstag 25. Februar 2010, 19:11 
hab den fehler:

newtio.c_iflag = IGNPAR; // ICRNL provokes bogus replys after block 12


ICRNL muss raus, dann klappts auch nach block 12.


Nach oben
  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 34 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de