Skocz do zawartości

Komunikacja radiowa - nadajnik Silicon Labs Si4010


blockchain

Pomocna odpowiedź

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.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.