Forum: Mikrocontroller und Digitale Elektronik Problem beim SENT Signal, Message werden nicht richtig ausgelesen ATxmega256a3


von Mido (Gast)



Lesenswert?

Hallo liebe Freunde,

ich habe ein Impulsförmiges SENT Signal (Single Edge Nibble Transmission 
Siehe Bild)  zu analysieren und durch eine serielle Schnittstelle aufm 
PC Messwerte anzuzeigen.

Das impulsförmige Signal enthält verschiedene Message, diese können 
richtig oder falsch übertragen werden. Durch die Checksumme wird gegeben 
ob ein Message korrekt übertragen wurde oder nicht.


(ein Nibble ist 4 Bit groß und fängt bei fallender Flanke an und endet 
bei der nächsten fallenden Flanke also 0 und 1 Impuls)

Ein Message Enthält 9 Nibble (siehe Bild):

1- Synchronization (4 bit)
2- Status & Communication (4 bit)
3- Data 1  (4 bit)
4- Data 2  (4 bit)
5- Data 3  (4 bit)
6- Data 4  (4 bit)
7- Data 5  (4 bit)
8- Data 6  (4 bit)
9- Checksum (4 bit)

Zuerst muss der µC den Synchronisation Bereich finden, dass bei jeder 
fallenden Flanke ein Interrupt ausgelöst wird und die Zeit zwischen zwei 
fallenden Flanken misst und verglichen wird. Wenn der Synchronisation 
Bereich gefunden ist, müssen dann die nächsten 8 Perioden (oder Nibble) 
gespeichert werden, also nur 8 Werte müssen gespeichert. Mithilfe der 
Cheksumme kann man sicherstellen, ob die Daten richtig übertragen wurden 
oder nicht.

Das Problem jetzt:

Ich weiß ganz genau, dass mein Signal 5 Message enthält (kein reelles 
Signal aber nur zum Testen), 4 richtige Message mit richtig berechneter 
Checksumme und 1 falsches Message.

Das Signal sieht dann so aus:

Msg1Richtig_IFG_Msg2Richtig_IFG_Msg3Richtig_IFG_Msg4Falsch_IFG_MSG5Richt 
ig_IFG_

IFG= Inter frame Gape

Dieses Signal wiederholt sich dann immer wie die o. g. Reihenfolge.
Der Code soll dann nur die 4 richtig übertragenen Message ausgeben,
d. h. es sollen die Dezimalwerte von jedem Nibble (insgesamt 8 
Dezimalwerte) seriell ausgegeben.

und so muss es z. B. aussehen:

Msg1     5 6 7 8 3 1 4 5
Msg2     5 3 6 2 0 6 5 2
Msg3     7 9 0 2 3 7 8 8
Msg5     3 3 1 3 4 5 5 6

Diese Reihenfolge soll eigentlich wiederholt werden, wenn alles richtig 
gemacht wird. Weil nur die 4 Message richtig sind.



Msg1     5 6 7 8 3 1 4 5
Msg2     5 3 6 2 0 6 5 2
Msg3     7 9 0 2 3 7 8 8
Msg5     3 3 1 3 4 5 5 6

Msg1     5 6 7 8 3 1 4 5
Msg2     5 3 6 2 0 6 5 2
Msg3     7 9 0 2 3 7 8 8
Msg5     3 3 1 3 4 5 5 6

Msg1     5 6 7 8 3 1 4 5
Msg2     5 3 6 2 0 6 5 2
Msg3     7 9 0 2 3 7 8 8
Msg5     3 3 1 3 4 5 5 6

Msg1     5 6 7 8 3 1 4 5
Msg2     5 3 6 2 0 6 5 2
Msg3     7 9 0 2 3 7 8 8
Msg5     3 3 1 3 4 5 5 6

usw..



Was mein Code ausgibt ist leider was anders :(

die Message-Werte werden bei mir in dieser Form ausgegeben:


Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5

Msg3     7 9 0 2 3 7 8 8
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg5     3 3 1 3 4 5 5 6
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5
Msg1     5 6 7 8 3 1 4 5



Die Reihenfolge stimmt in meinem Code irgendwie nicht :(

und hier ist mein Code:





int x=0;
int i;
int n=0;
int checksum, checksum16;
int tempCs=0;
int clock_tick;
int perioden_dauer;
float const ticks= 0.0179;  //   1/56
int nibble_anzahl=8;
int nibble_lengthinticks[8];
float messwerte_interrupt[8];

int druck [3];
int tepmeratur [3];
uint8_t messwerte_Druck [255];
uint8_t messwerte_Temperatur[255];
int messwerte_checksum;
float const zeit_in_us= 0.0167;       // 0,0167= 1/60 (prescaler=1)
bool synchronisiert_b = false;
bool  message_complete_b= false;
bool message_succeeded = false;
bool zaehler = false;
bool interrupt=false;
int sync_clk_tick =56;
int nibble_min;
int nibble_max;
int sync_min= 10080;     // 168 �s
int sync_max = 12000;    //200 �s
//int sync_max_1= 231;
int n_nibble = 0;
int Abweichung=10;
float nibble_in_tick;
uint8_t  message[8]; //Werte in diesem Array reichen von 0 bis 15
int messwerte[8];
uint8_t value;
uint8_t value1;






****************************************

ISR (TCC0_OVF_vect)
{



if (interrupt)
{

TCC0.CNT=0 ;


}
}


****************************************


void zaehler_auswerten(void)
{


  if (PORTC.PIN3CTRL==PORT_ISC_FALLING_gc)

  {

    perioden_dauer = TCC0.CNT;

    TCC0.CNT= 0;
    zaehler=true;


  }


}

****************************************


ISR(PORTC_INT0_vect) // interrupt fuer I/O Port
{
  cli();




  zaehler_auswerten();
  interrupt=true;


  if (perioden_dauer >= sync_min && perioden_dauer <= sync_max)       // 
synchronization and Communication

  {

    synchronisiert_b = true;
    clock_tick = perioden_dauer*ticks;

    n_nibble = 0;
  }



  sei();
}



****************************************


void messwerte_vergleich(void)
{



  if(synchronisiert_b  && zaehler) 
// synchronisiert ?

        {

    nibble_min=12*clock_tick;
    nibble_max=27*clock_tick;


     if((perioden_dauer >= nibble_min && perioden_dauer <= nibble_max))
// zeit entspricht einer nibble Periode ?

  {
      messwerte[n_nibble] =  perioden_dauer;
      n_nibble++;
      zaehler=false;

    }
    if (n_nibble >= nibble_anzahl)                                 // 
ein message soll nicht laenger als 9 nibble sein
    {

      n_nibble = 0;
      message_complete_b = true;

    }
  }

  else
  {

    synchronisiert_b = false;

  }
}



************************************************





void messwerte_auswerten(void)
{
  int i;
  for(i = 0; i< nibble_anzahl; i++)
  {
    message[i] =  round ((messwerte[i]-nibble_min)/clock_tick);  // 
Nibblewert in dezimalzahlen zwischen 0..15 speichern
  }

}


************************************************



int checksum_legacy()
{
  checksum=5;
  for (i=1;i<nibble_anzahl-1;i++)
  {
    tempCs=message[i]+(checksum*16);
    checksum=CRC4legacy_table[tempCs];
  }
  // checksum with an extra "0" value
  /*tempCs=checksum*16;
  checksum=CRC4legacy_table[tempCs+1];*/
  return checksum;
}


************************************************


int checksum_recomended()
{
  checksum16=5;
  for (i=1;i<nibble_anzahl-1;i++)
  {
    //checksum16= bitxor((message[i]),(CRC4Recom_table(checksum16+1)));
    checksum16= (message[i])^(CRC4Recom_table[checksum16]);
  }
  checksum16= 0 ^ CRC4Recom_table[checksum16];

  return checksum16;
}


//********************************************************************** 
************************************************************************ 
************



/* output value when system is idle */
void SetIdleValue(void)
{
  if(Port == SER_PORT_AO0)
  {
    /* set AO0 */
    DACB.CH0DATA = IdleValue & 0x0FFF;  // limit output to 4095
  }
  else
  {
    int Port_bm;
    if(Port == SER_PORT_DO0)
    {
      Port_bm = PIN2_bm;
    }
    else
    {
      Port_bm = PIN3_bm;
    }

    if(IdleValue == 0)
    {
      PORTA.OUTCLR = Port_bm;
    }
    else
    {
      PORTA.OUTSET = Port_bm;
    }
  }
}







int main (void)
{

  sei();

  /* set system clock -> also change F_CPU definition in SENT2SERIAL.h! 
*/
  funct_clock_init_PLL_60M();                // clock initialization 60 
MHz

  funct_DACB_single0_enable(DAC_REFSEL_AVCC_gc);      // initialize DAC 
with internal Vcc    OR

  uart_InitUsartDriver();                  // initialize RS232 
communication


  IdleValue  = DEFAULT_IDLE_VAL;              // analog output -> 5 V 
(max.: 0x0FFF, 12 bit)
  Port    = SER_PORT_AO0;                // set analog output as idle 
port
  errorOut  = true;                         // turn off error messages 
by default
  debugOut  = true;                      // turn off debug messages by 
default



  if (debugOut)
  {
    uart_send_string(version);
    // send version number via RS232
    uart_send_string("\nSignalgenerator laeuft\n");
  }

  uart_send_string("\nSignalgenerator wurde initialisiert\n");

  func_glob_interrupt();
  funct_timer0_init();


  uart_send_string("\nENDE INITIALISIERUNGEN\n");




  /* main loop */



  while(1)
  {


    uart_StateMachine();

    if(synchronisiert_b && zaehler)
    {
      //uart_send_string("\nSignalgenerator Synchronisiert\n");

      messwerte_vergleich();
      if(message_complete_b)
      {
        zaehler=false;
        messwerte_auswerten();

        checksum_recomended();
        //uart_send_string("\n message_complete\n");


         //uart_send_data(message,8);
        if(checksum16==message[8])


        {

          //uart_send_string("\nMESSAGES Succeeded ON:\n");
          uart_send_string("\n-");
            uart_send_data(message,8);




        }else
        {
          //uart_send_string("\nERROR Message ON:\n");
          //uart_send_data(message, 8);


        }
      }
    }
  }
  return 0;
}






Es könnte vielleicht sein dass während der µC die Messwerte speichert 
und ausgibt, werden schon die nächsten Message verpasst.

Oder vielleicht haben die Datentyp einen Einfluss auf den Code, ich 
meine jetzt mit float, integer, unint8, unint16 usw. ...

Es muss auch sicher gestellt werden, dass das gespeicherte Message 
direkt ausgegeben wird.

Hat jemand vielleicht eine Idee wie man den Code korrigiert, ich stehe 
seit eine Woche aufm Schlauch und komme nicht voran.



Anbei findet ihr den Code im Text Datei.






Danke euch im Voraus

von Ahmed M. (mido)


Lesenswert?

Hat jemand vielleicht eine Idee !!

von Rudolph R. (rudolph)


Lesenswert?

SENT ist ziemlich exotisch.
Ich konnte noch keine Bauteile finden die ich wirklich auch kaufen 
könnte, wobei die Suche auch durch den Namen behindert wird.

Woher kommt überhaupt das Signal und warum bist Du so sicher, dass es 
genau so kodiert ist wie Du es beschreibst?

von Anja (Gast)


Lesenswert?

Hallo,

Sent ist sehr zeitkritisch.
Ich würde dabei keine Subroutine verwenden um den Pin zu pollen
sondern in einer interrupt-Routine die Zeitstempel der CCP-Unit in einen 
Ringpuffer schreiben und dann im Hauptprogramm auswerten.

Die Synchronisation ist kein "Nibble" sondern die Zeitbasis mit der der 
Sender Sendet. Sent hat auf der Senderseite sehr große Toleranzen. Der 
Empfänger muß aus der Synchronisation die tatsächliche tick-Breite 
bestimmen und auch bei den empfangenen Nibbles "verrechnen"

Gruß Anja

von Ahmed M. (mido)


Lesenswert?

Rudolph R. schrieb:
> SENT ist ziemlich exotisch.
> Ich konnte noch keine Bauteile finden die ich wirklich auch kaufen
> könnte, wobei die Suche auch durch den Namen behindert wird.
>
> Woher kommt überhaupt das Signal und warum bist Du so sicher, dass es
> genau so kodiert ist wie Du es beschreibst?



Hallo Rudolph,

das Signal kommt eigentlich von einem SENT Druck und Temperatur Sensor.
Da ich kein Sensor verfüge, habe ich selber ein SENT Signal 
nachprogrammiert, klingt komisch aber es war nur zum testen.
Wenn es so richtig funktioniert dann sollte auch beim SENT Sensor auch 
funktionieren.

von Ahmed M. (mido)


Lesenswert?

Anja schrieb:

Danke Anja für deine Antwort,

> Ich würde dabei keine Subroutine verwenden um den Pin zu pollen
> sondern in einer interrupt-Routine die Zeitstempel der CCP-Unit in     einen 
Ringpuffer schreiben und dann im Hauptprogramm auswerten.

Ich habe leider nicht so gut verstanden was du genau meinst, kannst du 
bitte bezüglich meinem Code konkreter erklären !!


> Die Synchronisation ist kein "Nibble" sondern die Zeitbasis mit der der
> Sender Sendet. Sent hat auf der Senderseite sehr große Toleranzen. Der
> Empfänger muß aus der Synchronisation die tatsächliche tick-Breite
> bestimmen und auch bei den empfangenen Nibbles "verrechnen"
>
> Gruß Anja

genau die Synchronisation wird auch nicht am PC angezeigt, dadurch wird 
nur die Tick Länge ausgerechnet und für die weiteren "Nibble" benutzt. 
Daher ist auch die Tick Länge keine konstante sonder sie variiert 
zwischen 3 µs und 90 µs.

von Ahmed M. (mido)


Lesenswert?

Hat jemand noch vielleicht eine Idee ??

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.