Skocz do zawartości

Komunikacja radiowa - nadajnik Silicon Labs Si4010


Pomocna odpowiedź

Napisano

Dzień dobry,

Z problemem borykam się już długi czas, ale utknąłem i obawiam się że moja wiedza jest po prostu niewystarczająca, by wszystko zrozumieć - szukam pomocy.

Usiłuję skomunikować ze sobą nadajnik Silicon Labs

Si4010 oraz wariometr Flymaster GPS SD

(jego odbiornik to Si4355

) za pomocą sygnału radiowego. Chcę wysłać odczyt temperatury z zewnętrznego czujnika (termometru zamontowanego na szycie powłoki balonu na ogrzane powietrze). Urządzenie nie pokazuje sygnału nadajnika w swoim interfejsie najprawdopodobniej z powodu niepoprawnego sygnału.

Sygnał, który muszę wysłać został mi opisany tak:

[PREAMBLE][PREAMBLE][PACK_ID][DATA][CRC]

 

4 bytes for preamble + 2 for syncword + 2 for datatype and ID + 2 data + 1 for CRC

(w pierwszej linijce producent najwyraźniej zapomniał wpisać syncword)

Wydaje mi się, że 80% tego sygnału mam przygotowane poprawnie, ale nie rozumiem funkcji generującej sumę kontrolną CRC.

Od producenta wariometru dostałem skrawki kodu które mają mi pomóc:

RF CODE

Kod nadajnika jest dostępny na GitLab - plik keyfob_demo_2_main.c. Jest to zmodyfikowany przykład kodu nadajnika wysyłającego numer naciśniętego przycisku.

A więc po kolei to, co udało mi się zrobić na podstawie wskazań z RF CODE:

PREAMBLE = 0xAA

4 bajty PREAMBLE = 0xAAAA 0xAAAA

SYNCWORD = 0xD42D

PACKID = 0x1FFF

Wartości powyżej na podstawie przykładowego kodu od producenta

void FmInvertEndian(UINT16 *pwLittleEndian)
{
UINT8 hold;
UINT8 *ptr;
ptr = (UINT8*) pwLittleEndian;
hold = ptr[1];
ptr[1] = ptr[0];
ptr[0] = hold;
}

#define RF_Preamble         0xAAAA
#define RF_SyncroWord      0xD42D

// i16PacketType - sensor type 
// i16ID - serial number
// TAS packet type is 5 (0x5)

void InitRFPackage(UINT16 i16PacketType, UINT16 i16ID) // InitRFPackage(5,i16ID)
{
   UINT8 *tmp;
   // Set Preamble and SyncroWord
  g_aRFPAcket[PREAMBLE_1] = RF_Preamble; // 0xAAAA
  g_aRFPAcket[PREAMBLE_2] = RF_Preamble; // 0xAAAA
  g_aRFPAcket[SYNCWORD_1]  = RF_SyncroWord; // 0xD42D

  g_aRFPAcket[PACK_ID] = i16PacketType & 0x7; // 0x5 & 0x7 -> 0x5



  i16ID &= 0x1FFF;
  FmInvertEndian(&i16ID);
  tmp = (UINT8*) &i16ID;
  tmp[0] >>= 3;

  g_aRFPAcket[PACK_ID] |=i16ID; // 0x5 |= 0x1FFF -> 0x1FFF
}

DATA = 0xAAAA (przykładowa wartość temperatury, nie mam pojęcia jak zostanie odczytana w urządzeniu)

CRC - 0x00 - placeholder, bo nie wiem jak jest obliczana zarówno w przykładowym kodzie od producenta wariometru jak i w kodzie z którego korzystam

void FillRFPacket()
{
   UINT8   i8DataIndex;
   UINT16  ai16TempBuff[2]; // maximum size of array is 3 (0,1,2)
   UINT8   *ptri8;


   InitRFPackage(5,g_i16SerialNumber);


   ptri8= (UINT8*)  (g_aRFPAcket + HDRSIZE ); // co to jest HDRSIZE?


   ai16TempBuff[0] = g_aRFPAcket[PACK_ID]; // = 0x1FFF
   // ai16TempBuff = [0x1FFF]
   for(i8DataIndex=0; i8DataIndex < g_i16BufferIndex; i8DataIndex++) // co to jest g_i16BufferIndex?
   {
        ai16TempBuff[1] = g_aRFBuffer[i8DataIndex];
        memcpy(ptri8,  (UINT8*) (ai16TempBuff+1), sizeof(UINT16)  );
        ptri8 += sizeof(UINT16);

        *ptri8 = calculate_CRC((UINT8*) ai16TempBuff,(2*sizeof(UINT16)));
        ptri8++;

   }

}

UINT8 calculate_CRC(UINT8 *ptrTemp,UINT8 i8Lenght)
{
  UINT8 i8CRC=0,i8;

  for(i8 = 0; i8 < i8Lenght; i8++)  // Last byte is CRC byte
  {
     i8CRC ^= ptrTemp[i8];
  }
  return(i8CRC);
}

---

Oraz kod odpowiadający za przygotowanie sygnału do wysłania:

void PutOnRFBuffer(UINT16 i16ValueToSend)
{
   if(g_i16BufferIndex>RF_BUFFER_SIZE) return;

   g_aRFBuffer[g_i16BufferIndex]=i16ValueToSend;
   g_i16BufferIndex++;

}

// Prepare data to be sent

#define THERMISTOR_ID_MASK        0xC000      // thermistor data id
void PrepareToSend(UINT16 i16DataType, UINT16 i16DataValue)
{
   // Mask Data
   i16DataValue &= 0x3FFF;	// clean mask
   i16DataValue |= THERMISTOR_ID_MASK;
   PutOnRFBuffer(i16DataValue);
}

Podsumowując, z tego co rozumiem ramka sygnału powinna wyglądać tak:

0xAAAA 0xAAAA 0xD42D 0x1FFF 0xAAAA 0x00

Przekształcając to na kod, który napisałem przerabiając przykładowy program od Silicon Labs:

void vPacketAssemble (void)
{ 
 BYTE i;

 pbFrameHead = abFrame ;
 bFrameSize = bFrameSize_c;


 for (i=0;i<bPreambleSize_c;i++) // bPreambleSize_c = 4
 {
abFrame[i] = bPreamble;
 }

abFrame[bFrameSize_c - 9] = bSync1_c;   // 0x2D
abFrame[bFrameSize_c - 8] = bSync2_c;   // 0xD4
       abFrame[bFrameSize_c - 7] = 0x5;        // TAS packet type
       abFrame[bFrameSize_c - 6] = 0x1F;       // example ID
       abFrame[bFrameSize_c - 5] = 0xFF;       // example ID
       abFrame[bFrameSize_c - 4] = 0xAA;       // example data
abFrame[bFrameSize_c - 3] = 0xAA;       // example data
abFrame[bFrameSize_c - 2] = 0;	       //CRC, see function vCalculateCrc below
abFrame[bFrameSize_c - 1] = 0;	       //CRC, see function vCalculateCrc below

vCalculateCrc();

 return;
}
//--------------------------------------------------------------
//Calculate CRC and write in the frame buffer
//Bit pattern used (1)1000 0000 0000 0101, X16+X15+X2+1
void vCalculateCrc(void)
{
       BYTE i,j;
       WORD wCrc;
       wCrc = 0xffff;
       for(j = bPayloadStartIndex_c;j<bPayloadStartIndex_c + bPayloadSize_c;j++)
       {
               wCrc = wCrc ^ ((WORD)abFrame[j]<<8);

               for (i = 8; i != 0; i--)
               {
                       if (wCrc & 0x8000)
                       {
                      wCrc = (wCrc << 1) ^ 0x8005;
                       }
                       else
              {
                               wCrc <<= 1;
                       }
               }
       }
 //-----------------------------------------------------------------
 //Write CRC in frame
 abFrame[bFrameSize_c - 2] = ((BYTE*)&wCrc)[0];
 abFrame[bFrameSize_c - 1] = ((BYTE*)&wCrc)[1];
 return;
}

---

Wysyłam to, ale niestety żadne wykryte urządzenie nie pojawia w odbiorniku. Nie bardzo wiem co może być przyczyną.

PS. Jestem również w stanie "odpłacić się" finansowo lub lotem balonem dla jednej osoby w Krakowie za dokończenie rozwiązania i poprawne skomunikowanie urządzeń. Mieszkam w Krakowie, posiadam devkit Silicon Labs oraz wariometr.

  • 2 tygodnie później...

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...