sandeepmistry / arduino-LoRa

An Arduino library for sending and receiving data using LoRa radios.
MIT License
1.68k stars 634 forks source link

AirRate Queston --- Ebyte E32 talking to an Ebyte E19 ? #203

Closed sam43054 closed 3 years ago

sam43054 commented 5 years ago

My exploration into LoRa Radios has gotten me into experimenting with different modules, Now I am trying to see if I can get them to work with each other.

I go two (E19 module) SparkFun SparkX SAMD21 Pro RF 1W Radios using sandeepmistry Lora.h to talk with each other beautifully

I recently got some LoRa modules from ebyte https://www.ebay.com/itm/Ebyte-E32-915T30D-8km-1W-915M-SX1278-SX1276-915MHz-Long-Range-UART-LoRa-Module/192492725802?hash=item2cd175e62a:rk:1:pf:0

These E32s are UART not SPI modules so I know I cant use them with LoRa.h and an Arduino. However since they are both SX1276 so I should be able to use a UART E32 and send a message and receive it on a E19 module ?

So here is my question The UART E32 Has AirRate options of 0.3 or 1.2 or 2.4 or 4.8 or 9.6 or 19.2 kbps

So I found a AirRate Calculator http://www.rfwireless-world.com/calculators/LoRa-Data-Rate-Calculator.html

For the example of 300 or (0.3 kbps) it supposedly the equivalent of 125 bandwidth, code rate 4 to 5, and Spread Spectrum of 12 But in the Calculator above it amounts to a AirRate of "292.96875000000006" not an even 0.3 kbps

And when I send a message from a E32 to a E19 I get a garbled character string

Playing around with the Calculator the only way I could match 300 with the Calculator was to enter 128 BW , 4 to 5, 12 Spread

So before going any further I wanted to ask some clarifying questions

stafil commented 5 years ago

Hi, my module is E32-ttl-100

0.3kbps - SF: 12 BW: 7 CR: 1 1.2kbps - SF: 11 BW: 8 CR: 1 2.4kbps - SF: 11 BW: 9 CR: 1 4.8kbps - SF: 8 BW: 8 CR: 2

packet is crypted ... my packet crypted is: byte s[] = {0x55, 0x66, 0x69, 0x56, 0x55, 0x55, 0x55, 0x55, 0x9a, 0x56, 0x96, 0xa5, 0x96, 0x66, 0x96, 0x66, 0x96, 0x69, 0x95, 0xa6, 0x57, 0x89};

Frequency: 433MHz Addres: 0 chanell: 24 AirRate: 2.4kbps message is: Hello

ada1s1h commented 5 years ago

can you tell me how to know lora's CR, BW and SF ?

PRO2XY commented 5 years ago

Extending on @stafil 's comment above, the proper parameters to use for setSignalBandwidth(...) can be deduced from the implementation of the function src/LoRa.cpp

I successfully received packets sent from E32 on E19 using the default parameters on E32, and the following settings on E19:

    LoRa.setSpreadingFactor(11);
    LoRa.setSignalBandwidth(251E3);
    LoRa.setCodingRate4(1);

Note that 251E3 is only a way to get the library to use BW: 9. You can use any value above 250E3 to do the same.

However, as noted by @stafil and also in the datasheet, the data packet is encrypted, and the decryption algorithm has not been shared with the public by CD-EByte.

masood-alam commented 5 years ago

can you tell me how to know lora's CR, BW and SF ?

I did it by sniffing SPI signals with USBee AX PRO analyzer

AdamJGodzik commented 3 years ago

packet is crypted ... my packet crypted is: byte s[] = {0x55, 0x66, 0x69, 0x56, 0x55, 0x55, 0x55, 0x55, 0x9a, 0x56, 0x96, 0xa5, 0x96, 0x66, 0x96, 0x66, 0x96, 0x69, 0x95, 0xa6, 0x57, 0x89}; E32 works also with generic SX1276 like RFM95 . The decryption is simple : 1.Each pair of characters ( nibbles) decrypt to 1 byte (but last 4 chars which is the packet CRC and the look up is below: // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x55,0x56,0x59,0x5A,0x65,0x66,0x69,0x6A,0x95,0x96,0x99,0x9A,0xA5,0xA6,0xA9,0xAA So decoding the above we have: [05][61][00][00][B1][9C][95][95][96][8D] [57][89] First byte is the number of bytes being transmitted . Second is fixed to the first .

3/4 is the address [0,0]

5 to 9 contains data "Hello" - it is scrambled with key 0xF9 ( 0xF9 is for 5 bytes -keys depends on the data length and varies per each , to decrypt data byte need to use : data = key ^ byte ) Then there is one byte of the check sum following with crc .

In summary E32 sends twice as data as needed and some operations like check sum or CRC just duplicate the SA1276 job.

SimpleRomb commented 3 years ago

@AdamJGodzik, could you please explain in detail? I do not understand how did you get this values: [05][61][00][00][B1][9C][95][95][96][8D] [57][89] Maybe a little of code for example?

AdamJGodzik commented 3 years ago

First of all - I did the evaluation of E32-868T30D more than year ago. My recommendation was not to use it because it is not efficient in term of Lora communication . I don't have code but just sending known content and receiving it on RFM95 I was able to understand the frame structure . This post I found recently by chance and I was not sure anybody needs such info . If you are interested you can use my evaluation.

The packet structure is : Bytes 0, 1 - number of message bytes sent ( up to 58 bytes) Bytes 2,3 - contains key index to decrypt the message content Bytes 4,5 - high address of the packet Bytes 6,7 – low address of the packet Bytes 8,9 to byte N-6 ,N –5 are the coded message bytes . Bytes N-4, N-3 contains check sum Bytes N-2 ,N-1 is very likely some CRC In following example: The message is: Hello Packed received on RFM95 is: byte s[] = {0x55, 0x66, 0x69, 0x56, 0x55, 0x55, 0x55, 0x55, 0x9a, 0x56, 0x96, 0xa5, 0x96, 0x66, 0x96, 0x66, 0x96, 0x69, 0x95, 0xa6, 0x57, 0x89}; Conversion table : ( T-table : 0x55,0x56,0x59,0x5A,0x65,0x66,0x69,0x6A,0x95,0x96,0x99,0x9A,0xA5,0xA6,0xA9,0xAA ) Bytes 0-1 0x55, 0x66 are decoded with the T-table into bytes (0x00 ) & (0x05) then two bytes are converted into one byte which is [high nibble=0][low nibble=0x05] -> 0x05 . Each of the following pairs but the last are converted the same way and we have : [05][61][00][00][B1][9C][95][95][96][8D] [57][89] Length is 5: Key index is 0x62 High address is 0 Low address is zero. Key is ‘H’^0xB1 = 0xF9 ( it is different for each message length but if you know first byte you can easily decode it ) SO we have : B1^0xF9 -> ‘H’ 9C^0xF9 -> ‘e’ 95^0xF9 -> ‘l’ 95^0xF9 -> ‘l’ 96^0xF9 ->’o’ [8D] is the check sum of following bytes [05][61][00][00][B1][9C][95][95][96]
[57][89] - is CRC or something – not needed for reception only for sending . Hope it explains all .

IoTThinks commented 3 years ago

@AdamJGodzik Very interesting. Thanks for your discovery! :D

SimpleRomb commented 3 years ago

@AdamJGodzik, Thank you very much!

al1fch commented 3 years ago

@AdamJGodzik, Thank you very much for your discovery !!

What's the purpose of Key index in this scheme ?

Here is a test whis FEC disabled ( other params from default) My E32 are E32-868T20D version 1.3, other side : ESP32 + SX1276

Without FEC no nibles to decode and assemble , received message is 10 bytes only : 05 F0 00 00 C2 EF E6 E6 E5 A9 , where key is H ^ 0xC2 = 0x8A Decrypted message is Hello + CS

whis 5 bytes messages key is the same for my 4 E32-868T20D key depends on message size : 1 2 3 4 5 6 7 8 9 10 ...... 0x69, 0x71, 0x7A, 0x82, 0x8A, 0x92, 0x9A, 0xA2, 0xAA, 0XB2 ......

AdamJGodzik commented 3 years ago

Key index is the entry index into 256 table to select actual key - instead of hacking it each time. Keys are length dependent but it may be different for other devices the E32-868T30D I was using. CRC has following parameters: Algorithm :KERMIT , Check:0x2189 , Poly:0x1021 ,Init:0x99C0 ,RefIn:true ,RefOut:true , XorOut:0x0000 with the msb first and lsb follows as the last byte in the frame.

ZeSanglier commented 3 years ago

Thank you everyone for your explanations.

Currently, I'm trying a communication between an E32-433T30D1B module and a RA-01 module (SX1278, 433Mh) With FEC disabled, it's like @al1fch explains it but with some differences. I sent "TEST" in transparent mode (among other tests), then RA-01 received :

44 17 00 00 E7 F6 E0 E7 01

It seems 44 is the message size + 0x40 (with "TEST-TEST" message, it's 49) 17 is the channel 00 00 is the address E7 F6 E0 E7 the message encrypted with B3 key (E7^B3=54=T, F6^B3=45=E...) 01 is the checksum, looks like checkSum 8 2s Complement.

I tried messages with different lengths and with my module the key is always B3.

xg590 commented 3 years ago

Interesting topic.

baarratia commented 3 years ago

Extending on @stafil 's comment above, the proper parameters to use for setSignalBandwidth(...) can be deduced from the implementation of the function src/LoRa.cpp

I successfully received packets sent from E32 on E19 using the default parameters on E32, and the following settings on E19:

    LoRa.setSpreadingFactor(11);
    LoRa.setSignalBandwidth(251E3);
    LoRa.setCodingRate4(1);

Note that 251E3 is only a way to get the library to use BW: 9. You can use any value above 250E3 to do the same.

However, as noted by @stafil and also in the datasheet, the data packet is encrypted, and the decryption algorithm has not been shared with the public by CD-EByte.

Hi! I'm trying to communicate a TTGO T-beam V1.0 (915MHz) with an Ebyte E32 915T20D. I've tried setting the parameters (Spreading factor, Bandwidth, CR) mentioned above, but without luck. Anyone with some experience with this?

Thanks!

Edit: I've managed to send messages from the E32 to the T-beam, but not the other way around. Still struggling with how to send data to the E32... I think that I have to structure the message in an specific way or change the preamble length or something like that.

karfam commented 2 years ago

How did you manage to send from E32 to T-beam? Sync word? Is it possible for someone to share a simple snippet that works with tbeam as a receiver?

Emmanuel-FR commented 2 years ago

This is old but good ! I knew that these modules were not that great, but I did want to be able to use a RFM96 to receive the messages. And thanks also to stafil for the RF settings (btw the sync word is x012).

Basically, I just had to use your lookup table and figure out how this module parsed the data (58 bytes blocks except if it gets longer that 3 bytes...).

I found out that in my case the 15 bytes messages had a key of xDB and the 1 bytes ones a key of x69. I understand that they just have a lookup table.

I wonder why they made such a kludge to have a simple serial bridge,...

Cheers

yodapuces63 commented 1 year ago

Hi @ZeSanglier : I (try to) do exactly the same but with a eByte E49-400 => RA-01 I can not reach any success! The RA-01 is in receive state and this is the RA-01 settings: LoRa.begin(433E6) LoRa.setSpreadingFactor(11); // ranges 6-12,
LoRa.setSignalBandwidth(500000); // Bandwidth, LoRa.setCodingRate4(5); // Coding rate 4/: 5-8, LoRa.setPreambleLength(8); // Preamble length 6-65535, LoRa.enableCrc(); // CRC enable LoRa.setSyncWord(0x12); // ranges from 0-0xFF, default 0x12

The E49-400, send data avery 1s and is configured with : -address: 0xFFFF -chanel 0x2E (433Mhz) -air speed: 2.4kbps

I have try different setting around the above one, without success!

Can you see the difference with your project ? Thanks Marc LoRaSlave.txt

ZeSanglier commented 1 year ago

Hello,

My configuration for Ra-01 (SX1278) is LoRa.setSpreadingFactor(11); LoRa.setSignalBandwidth(500E3); LoRa.setCodingRate4(5);

but the eByte E32 uses SX1278 with LoRa modulation whereas the E49 uses GFSK modulation according the datasheet. The SX1278 seems to be able to use FSK/GFSK modulation with the right configuration but may be LoRa lib doesn't implement this... so datasheet will be your friend :)

Good luck for your project !

yodapuces63 commented 1 year ago

@ZeSanglier Thanks a lots ! I thing, i will change tu the same type off module (E32-433T30D1B) Is it possible to share your code or the setting part for the eByte E32 and RA-01 ? Thanks

yodapuces63 commented 1 year ago

@ZeSanglier Hello I just received a new E32 I still try to send message to the RA-01, without success! I use you setup: LoRa.begin(433E6) LoRa.setSpreadingFactor(11);
LoRa.setSignalBandwidth(500E3);
LoRa.setCodingRate4(1);

But what is your -PreAmbleLength -Crc (enable/disable) -SyncWord

The setting of the E32: 2023-02-06_20-04-38

Thanks Regards

ZeSanglier commented 1 year ago

Hello @yodapuces63

I've published my testings about radio transmissions between my Ra01 and My E32-433 modules. If it could help you.

https://blog.zesanglier.fr/2023/02/11/communiquer-entre-un-module-ebyte-e32-et-un-module-ra01-02-sx1278/

Best regards :)

al1fch commented 1 year ago

Hi @ZeSanglier

Thanks for your detailed and clear document.

Best regards

yodapuces63 commented 1 year ago

Great ! thank you As i still have communication trouble, this will help me Regards

yodapuces63 commented 1 year ago

Hi ! Communication is working ! The "LoRa.setLdoFlag(true);" was the magic setup

Still have to find the "key" to extract data... The key "0xB3" with 4 bytes is working (great thanks to ZeSanglier for its tuto) But, Since i change the frequency and the address, the key "0cB3" do not work any more. May be the Key is related also to these parameters...? Still testing... Thanks Regards

ZeSanglier commented 1 year ago

Hi,

I tried to change the chan value. If I use the 0x18 chan, i've to set LoRa.begin(434E6) on Ra01 side.

And the XOR key change... 0xB2 with 0x18 chan, 0xB1 with 0x19 chan... it seems the key has a relation with the chan. If you do (sended value) XOR (received value), you will find the used key.

Regards

yodapuces63 commented 1 year ago

Hello Yes , the key change flowing the channel, but not the length of the data. Using XOR, i find the key All is ok now (send / receive) Thanks a lots for help Regards

Note: I use the eByte E95: industrial packing, DIN fix, RS485 comm, external antena and Modbus : Works fine 2023-02-24_08-30-57

zbx-sadman commented 1 year ago

A little bit key-related info. I have E32-900T20D and trying to use it with TTGO T3 v1.6.1

1) Key can be easy taken: we can send byte 0x00 in payload and receive key on remote instantly. 2) Key depend on channel. I checked all range and got result:

Chan Key
0x00 0x9A
0x01 0x99
0x02 0x98
0x03 0x9F
0x04 0x9E
0x05 0x9D
0x06 0x9C
0x07 0xA3
0x08 0xA2
0x09 0xA1
0x0A 0xA0
0x0B 0xA7
0x0C 0xA6
0x0D 0xA5
0x0E 0xA4
0x0F 0xAB
0x10 0xAA
0x11 0xA9
0x12 0xA8
0x13 0xAF
0x14 0xAE
0x15 0xAD
0x16 0xAC
0x17 0xB3
0x18 0xB2
0x19 0xB1
0x1A 0xB0
0x1B 0xB7
0x1C 0xB6
0x1D 0xB5
0x1E 0xB4
0x1F 0xBB
0x20 0xBA
0x21 0xB9
0x22 0xB8
0x23 0xBF
0x24 0xBE
0x25 0xBD
0x26 0xBC
0x27 0xC3
0x28 0xC2
0x29 0xC1
0x2A 0xC0
0x2B 0xC7
0x2C 0xC6
0x2D 0xC5
0x2E 0xC4
0x2F 0xCB
0x30 0xCA
0x31 0xC9
0x32 0xC8
0x33 0xCF
0x34 0xCE
0x35 0xCD
0x36 0xCC
0x37 0xD3
0x38 0xD2
0x39 0xD1
0x3A 0xD0
0x3B 0xD7
0x3C 0xD6
0x3D 0xD5
0x3E 0xD4
0x3F 0xDB
0x40 0xDA
0x41 0xD9
0x42 0xD8
0x43 0xDF
0x44 0xDE
0x45 0xDD

Seems a kind of logic exist on the key. Last key's byte forms by following code table:

Chan's 0xAB B-part Key's 0xCD D-part
0 A
1 9
2 8
3 F
4 E
5 D
6 C
7 3
8 2
9 1
A 0
B 7
C 6
D 5
E 4
F B

But i see no correlation with chan's 0xAB A-part, and Key's D-part. Seems this just range related values.

UPD: I've wrote simple key calculate function

uint8_t getCDEByteKey(const uint8_t _channelNo) {
  const uint8_t lsbTable[] = {0x0A, 0x09, 0x08, 0x0F, 0x0E, 0x0D, 0x0C, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0B};
  return ((_channelNo + 0x99) & 0xF0) | lsbTable[_channelNo & 0x0F];
}
zbx-sadman commented 1 year ago

@ZeSanglier , can you explain CRC-calculation for FEC case? I've testing as follows: 1) Set channel=06 , addr = 00 00, FEC = enable 2) Send from E32 array: 00 31 3) Catch on ESP32 side raw data: 65 59 55 69 55 55 55 55 96 A5 99 A6 69 AA 0B A1 4) Decode it in 'nibble-style': 42 06 00 00 9C AD 6F 10 5) Fetch key 9C, and decrypt 2 byte: 9C AD -> 00 31

Seems all ok, but i'm was stucked on CRC16 checking. Using https://www.lddgo.net/en/encrypt/crc in custom mode calculate CRC with 65 59 55 69 55 55 55 55 96 A5 99 A6 69 AA, and got 0B A1. It equal last two bytes of raw data. But nibble play give to me two bytes on the end: 6F 10, and it 'no-FEC case' checksum, and strange other byte.

image

Thanks.

Edgineer10 commented 1 year ago

Hello @ZeSanglier do you have a code snippet for decrypting the message from the Ebyte E32? I can see that there are a lot of conversions and decoding of the packets from the E32 to form the message.

yodapuces63 commented 1 year ago

Hello This is my "receive" function in the ESP32 !

You will find the "lora read", the "decode" and the "decrypt" The "decode" is for the E32 decoding The "decrypt" is MY crypting with a string key (for more strong crypting) In the LoRa Frame, I also add a "frame counter" to increase reliability of the data

//---Receive LoRa-----------------------------------------

bool Receive(){
  // Check for incoming LoRa packet
  uint8_t RecBuffer[20];                    //buffer LoRa
  uint8_t RecCrypt[20];                     //donnée cryptée
  uint8_t Len = LoRa.parsePacket();       //0 (rien):explicit mode (defaut), >0:implicit mode: nombre de byte, retour:nombre de bytes
  bool retour;                             //résultat de la fonction
  if (Len) {
    FrameCounter++;
    #ifdef OledDebug
    Oled.setPowerSave(0);                     //Display on
    DisplayOn = true;
    Oled.setCursor(0,0);
    Oled.printf("Frm %d  ",FrameCounter);
    #endif
    Serial.printf("Rec Cnt:%d Len:%d\n",FrameCounter,Len);
    #ifdef TelNetDebug
    TelNet.printf("Rec Cnt:%d Len:%d\n",FrameCounter,Len);
    #endif

    //read buffer LoRa
    int i = 0;
    while (LoRa.available() && (i<=19)) {
      RecBuffer[i] = LoRa.read();          //Lit 1 bytes
      Serial.print(RecBuffer[i],HEX);
      Serial.print(" ");
      i++;
    }
    Serial.println();

    //décode les donnees du module E95 avec la clef byte
    Serial.print("Decode: ");
    for(i = 4; i < (Len-1); ++i){
      RecCrypt[i-4] = RecBuffer[i] ^ 0xA7;           //la clef dépend de la frequence et de l'adresse (pas de la longueur)
      Serial.print(RecCrypt[i-4]);
      Serial.print(" ");
    }
    Serial.println();

    //décodage avec la clef de chiffrement
    Len = Len - 4;
    int j = 0; 
    byte KeySize = sizeof(KeyS);                                 
    for(uint8_t i = 0; i < (Len-1); ++i){
      RecData[i] = RecCrypt[i] ^ KeyS[j]; 
      j++;
      if (j == KeySize){j=0;}
      Serial.print(RecData[i]);
      Serial.print(" ");
    }

    FrameNumber = RecData[1] + 256*RecData[2];      //reconstruit le compteur dans la trame
    // Print received message data
    Serial.printf("Data Len:%d ad:%d frm:%d cmd:%d\n",Len,RecData[0],FrameNumber,RecData[3]);
    Serial.printf("RSSI: %d  SNR: %1.1f\n",LoRa.packetRssi(),LoRa.packetSnr());// Print packet/signal status including package RSSI and SNR
    #ifdef OledDebug
    Oled.setCursor(0,2);
    Oled.printf("%d: %d %00000d",Len,RecData[0],FrameNumber);
    Oled.setCursor(0,4);
    Oled.printf("L:%d  S:%1.1f ",LoRa.packetRssi(),LoRa.packetSnr());
    #endif
    #ifdef TelNetDebug
    TelNet.printf("Data Len:%d ad:%d frm:%d cmd:%d\n",Len,RecData[0],FrameNumber,RecData[3]);
    TelNet.printf("RSSI: %d  SNR: %1.1f\n",LoRa.packetRssi(),LoRa.packetSnr());
    #endif

    //Extrait les données ...
    #ifdef TelNetDebug
    TelNet.printf("frmp:%d\n",FrameNumberP);
    #endif
    if ((RecData[0] -128) == DevNum) {       //si la bonne adresse du module
      if (FrameNumber == (FrameNumberP+1)) {
        retour = true;
      }else{
        ComEr++;  //erreur dans la trame
        retour = false;
      }
      FrameNumberP = FrameNumber;
    }
  } else {
    retour = false;
  }
  return retour;
}

And this is the "SEND" function in the ESP32:

You will find the first byte needed for the E32 then the "coding" for the E32 then the "CRC" calculation

//---Send LoRa--------------------------------------------------------

void Send() {
  uint8_t Len = SendLen + 5;         //Longueur des data + l'entête (4) + le CRC (1)
  uint8_t SendBuffer[Len] = {0};
  //Configure l'entête  
  SendBuffer[0] = 0x40 + SendLen;   //+Longueur du message (sans header et sans le CRC)
  SendBuffer[1] = 0x0B;             //Chanel (11) : 421mhz
  SendBuffer[2] = 0x12;             //Adresse H
  SendBuffer[3] = 0x32;             //Adresse L

  //encode les donnees avec la key
  Serial.print("Send: ");
  for(uint8_t i = 0; i < SendLen; ++i){
    Serial.print(SendData[i]);
    Serial.print(" ");
    SendBuffer[i+4] = SendData[i] ^ 0xA7;           //la clef dépend de la frequence et de l'adresse (pas de la longueur)
  }
  Serial.println();

  //Calcule le CRC
  SendBuffer[Len-1] = Checksum(SendBuffer, Len);

  //Imprime le résultat
  Serial.print("Encod:");
  for(uint8_t i = 0; i < Len; ++i){
    Serial.print(SendBuffer[i], HEX);
    Serial.print(" ");
  }  
  Serial.println();
  Serial.println();

  LoRa.beginPacket();
  LoRa.write(SendBuffer, Len);
  LoRa.endPacket();
}
//---CheckSum coding----------------------------------------------------
uint8_t Checksum(uint8_t* buf, uint8_t s){
  uint32_t sum = 0;
  for(uint8_t i = 0; i < s; ++i){
    sum += buf[i];
  }
  sum = 0x100 - (sum & 0xFF);
  return (uint8_t)sum;
}
Edgineer10 commented 1 year ago

Hello @yodapuces63 what does this function do? Some instantiations and declarations are missing

//décodage avec la clef de chiffrement Len = Len - 4; int j = 0; byte KeySize = sizeof(KeyS);
for(uint8_t i = 0; i < (Len-1); ++i){ RecData[i] = RecCrypt[i] ^ KeyS[j]; j++; if (j == KeySize){j=0;} Serial.print(RecData[i]); Serial.print(" "); }

yodapuces63 commented 1 year ago

Hello This is my OWN crypting algo to increase secure on data It is not necessary for you

I use a "key" string to encrypt/uncrypt the data with a OR

The def is : char KeyS[] = "blablabla"; //crypt/uncrypt key de chiffrement uint8_t RecData[50]; //Receive data uncrypted uint8_t RecCrypt[20]; //data crypted received

But may be I will try also the AES lib !?

Kongduino commented 1 year ago

my OWN crypting algo

Unless you have a couple of PhDs in maths and cryptography, do not roll your own crypto. Use AES.

yodapuces63 commented 1 year ago

:-) Very simple, but not easy to uncrypt :-)

Edgineer10 commented 1 year ago

I will be using LilyGo TTGO Lora32 V2.1 and Ebyte E32-900T20D connected to mega. Some say they had make these modules communicates with each other. As soon as the product arrives, I will have them tested. For those who have tried please do guide and help me.

Kongduino commented 1 year ago

I will be using LilyGo TTGO Lora32 V2.1 and Ebyte E32-900T20D connected to mega. Some say they had make these modules communicates with each other. As soon as the product arrives, I will have them tested. For those who have tried please do guide and help me.

The problem with UART Ebyte modules is that their firmware is not compatible with regular LoRa modules. You cannot set the proper LoRa settings (SF/BW, and others) and they use an "air data rate" that has no meaning in LoRa – I have long believe they use FSK, not LoRa. So it's impossible to make them communicate with normal LoRa modules.

The only way to make them work is to get the non UART models, to use SPI, and drive them with the LoRa library.

Edgineer10 commented 1 year ago

@Kongduino I have found articles already that made them connect to each other.

Edgineer10 commented 1 year ago

@yodapuces63 What are your settings(Airrates etc.) on TTGO and E32, and how did you set them?

yodapuces63 commented 1 year ago

Hello As the E95 (E32 in a box) use a configuration tool from EByte, I use it and setup the default proposal:

zbx-sadman commented 1 year ago

E32-900T20D v8 AirRate to LoRa settings.

300 Bps : BW = 500000, SF = 11, CR4 = 6; 1200 Bps : BW = 500000, SF = 11, CR4 = 6; 2400 Bps: BW = 500000, SF = 11, CR4 = 5; 4800 Bps: BW = 250000, SF = 8, CR4 = 5; 9600 Bps: BW = 500000, SF = 8, CR4 = 5; 19200 Bps: BW = 500000, SF = 7, CR4 = 5.

Edgineer10 commented 1 year ago

@zbx-sadman are the settings for transmitting and receiving packets different? or Is it possible to use the same settings for both?

zbx-sadman commented 1 year ago

Air rate value used on E32 side, LoRa settings used on TTGO (naked SX1276) side.

Edgineer10 commented 1 year ago

@zbx-sadman for example, I want to send and receive message from TTGO, are the Lora Settings same for both operations?

zbx-sadman commented 1 year ago

Yes, of course. You need no change LoRa settings after sending before recieve answer.

Edgineer10 commented 1 year ago

@zbx-sadman I hope you can put your Lilygo TTGO and EBtye E32-9000T20D project so that I could have guide on the project that I am working on. Anyways, thank you for always answering my questions and expressing your insights here. I would love to know if there are other important things that would help me on this.

zbx-sadman commented 1 year ago

Very simple example for CDEByte E32 v8 & TTGO T3 v1.6.1 (Lora32).

cdebyte_example.ino

image

// Fixed mode transmission demo enable
//#define USE_FIXED_MODE

// UART's settings
#define UART_PORT_DEBUG                Serial
#define UART_PORT_LORA                 Serial2

constexpr uint32_t uartDebugSpeed    = 115200;
constexpr uint32_t uartE32Speed      = 9600;

// Push data to air every... ms
constexpr uint32_t reportInterval    = 2000;

// E32's M# pinns connected to,,,
constexpr uint8_t  configPinM0       = 5;
constexpr uint8_t  configPinM1       = 18;

// Target address here
constexpr uint16_t targetAddress     = 0x00FF;

// Radio channel: 862MHz + channel#
constexpr uint8_t  channelA          = 0x06;
constexpr uint8_t  channelB          = 0x07;

// E32 related stuff
#define E32_CMD_CONFIGURE              0xC2

#define UART_PARITY_8N1                B00000000
#define UART_BAUDRATE_9600_BPS         B00011000

#define AIR_DATARATE_300_BPS           B00000000
#define AIR_DATARATE_1200_BPS          B00000001
#define AIR_DATARATE_2400_BPS          B00000010
#define AIR_DATARATE_4800_BPS          B00000011
#define AIR_DATARATE_9600_BPS          B00000100
#define AIR_DATARATE_19200_BPS         B00000101

#define TRANSMISSION_MODE_FIXED        B10000000
#define TRANSMISSION_MODE_TRANSPARENT  B00000000

#define IO_DRIVE_PUSH_PULL             B01000000

#define WAKEUP_TIME_250MS              B00000000

#define FEC_SWITCH_OFF                 B00000000

#define TRANSMISSION_POWER_20DBM       B00000000

constexpr uint8_t getByteHi(const uint16_t _value) {
  return ((_value >> 0x08) & 0xFF);
}

constexpr uint8_t getByteLo(const uint16_t _value) {
  return (_value & 0xFF);
}

#if defined(USE_FIXED_MODE)
constexpr uint8_t e32Settings[] = {E32_CMD_CONFIGURE, getByteHi(targetAddress), getByteLo(targetAddress), (UART_PARITY_8N1 | UART_BAUDRATE_9600_BPS | AIR_DATARATE_2400_BPS), channelA, (TRANSMISSION_MODE_FIXED | IO_DRIVE_PUSH_PULL | WAKEUP_TIME_250MS | FEC_SWITCH_OFF | TRANSMISSION_POWER_20DBM)}; //
#else
constexpr uint8_t e32Settings[] = {E32_CMD_CONFIGURE, getByteHi(targetAddress), getByteLo(targetAddress), (UART_PARITY_8N1 | UART_BAUDRATE_9600_BPS | AIR_DATARATE_2400_BPS), channelA, (TRANSMISSION_MODE_TRANSPARENT | IO_DRIVE_PUSH_PULL | WAKEUP_TIME_250MS | FEC_SWITCH_OFF | TRANSMISSION_POWER_20DBM) };
#endif

void e32Configure(const uint8_t* _settings) {
  digitalWrite(configPinM0, HIGH);
  digitalWrite(configPinM1, HIGH);
  pinMode(configPinM0, OUTPUT);
  pinMode(configPinM1, OUTPUT);
  delay(5);
  UART_PORT_LORA.write(_settings, sizeof(e32Settings));
  // Wait for _settings bytes transmitted
  delay(50);
  digitalWrite(configPinM0, LOW);
  digitalWrite(configPinM1, LOW);
}

void setup() {
  UART_PORT_DEBUG.begin(uartDebugSpeed);
  UART_PORT_LORA.begin(uartE32Speed);
  UART_PORT_DEBUG.println("[*] System started");
  // Wait for E32 finished init
  delay(1000);
  e32Configure(e32Settings);
}

void loop() {
  static uint8_t payload;
  static uint32_t reportTimeLast;

#if defined(USE_FIXED_MODE)
  static bool flipFlop;
  // Fixed Mode: { addrHi, addrLo, channel, data, ...}
  uint8_t dataSend[0x03 + 0x01];
#else
  // Transparent Mode: { data, ...}
  uint8_t dataSend[0x01];
#endif
  uint8_t  messageSize = sizeof(dataSend);
  uint32_t nowTime;

  // ESP32 stuff
  delay(1);

  if (UART_PORT_LORA.available() > 0) {
    uint8_t cb = UART_PORT_LORA.read();
    UART_PORT_DEBUG.print("[<<] Recv: "); UART_PORT_DEBUG.print(" 0x"); UART_PORT_DEBUG.print(cb, HEX); UART_PORT_DEBUG.print(" '"); UART_PORT_DEBUG.print((char)cb); UART_PORT_DEBUG.println("'");
  }

  nowTime = millis();
  if (nowTime - reportTimeLast > reportInterval) {
    reportTimeLast = nowTime;

#if defined(USE_FIXED_MODE)
    dataSend[0x00] = getByteHi(targetAddress);
    dataSend[0x01] = getByteLo(targetAddress);
    // Hop channel example
    dataSend[0x02] = flipFlop ? channelA : channelB;
    flipFlop = !flipFlop;
#endif

    dataSend[messageSize - 0x01] = payload++;

    UART_PORT_LORA.write(dataSend, messageSize);
    UART_PORT_DEBUG.print("[>>] Sent: ");
    for (uint8_t i = 0x00; messageSize > i; i++) {
      UART_PORT_DEBUG.print(" 0x"); UART_PORT_DEBUG.print(dataSend[i], HEX);
    }
    UART_PORT_DEBUG.println();
  }
}

e32_companion_example.ino

image

#include <SPI.h>
#include <LoRa.h>

// UART's debug output speed
constexpr uint32_t uartDebugSpeed      = 115200;

// Send 'Hello' every ... ms
constexpr uint32_t helloInterval       = 5000;
constexpr uint8_t  helloPayload[]      = { 'H', 'e', 'l', 'l', 'o'};
// Radio channel: 862MHz + channel#
constexpr uint8_t  channelA            = 0x06;
// Target address here
constexpr uint8_t  targetAddress       = 0x00FF;

// E32's AirRate 2400Bps: BW = 500000, SF = 11, CR4 = 5
constexpr uint8_t  loraPreambleLength  = 8;
constexpr uint8_t  loraSyncWord        = 0x12;
constexpr uint8_t  loraSpreadingFactor = 11;
constexpr uint8_t  loraCodingRate4     = 5;
constexpr uint8_t  loraTxPower         = 10;
constexpr uint32_t loraSignalBandwidth = 500E3;
constexpr uint32_t loraFrequency       = 862E6 + 1E6 * channelA;

constexpr int8_t loraCsPin             = 18;
constexpr int8_t loraDio0Pin           = 26;
constexpr int8_t loraRstPin            = 23;

constexpr int8_t loraSclkPin           = 5;
constexpr int8_t loraMisoPin           = 19;
constexpr int8_t loraMosiPin           = 27;

#define arraySize(_array) ( sizeof(_array) / sizeof(_array[0x00]) )

constexpr uint8_t  getByteHi(const uint16_t _value) {
  return ((_value >> 0x08) & 0xFF);
}

constexpr uint8_t  getByteLo(const uint16_t _value) {
  return (_value & 0xFF);
}

uint8_t calcCDEByteChecksum(const uint8_t* _data, uint8_t _dataSize) {
  uint8_t checksum = 0x00;
  while (_dataSize--) {
    checksum += *_data++;
  }
  checksum = 0x100 - checksum;
  return checksum;
}

uint8_t getCDEByteKey(const uint8_t _channelNo) {
  const uint8_t lsbTable[] = {0x0A, 0x09, 0x08, 0x0F, 0x0E, 0x0D, 0x0C, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0B};
  return ((_channelNo + 0x99) & 0xF0) | lsbTable[_channelNo & 0x0F];
}

uint8_t encodePacket(uint8_t* _packetPayload, const uint16_t _targetAddress, const uint8_t _channelNo, const uint8_t* _data, const uint8_t _dataSize) {
  // Add header size
  uint8_t packetSize = 0x00;

  _packetPayload[packetSize++] = _dataSize + 0x40;
  _packetPayload[packetSize++] = _channelNo;
  _packetPayload[packetSize++] = getByteHi(_targetAddress);
  _packetPayload[packetSize++] = getByteLo(_targetAddress);

  uint8_t encryptKey = getCDEByteKey(_channelNo);

  for (uint8_t i = 0x00; _dataSize > i; i++) {
    _packetPayload[packetSize++] = _data[i] ^ encryptKey;
  }

  // Add checksum
  _packetPayload[packetSize] = calcCDEByteChecksum(_packetPayload, packetSize);
  packetSize++;

  return packetSize;
}

uint8_t decodePacket(uint8_t* _packetPayload, int _packetSize) {
  bool packetPayloadOk = false;
  uint8_t bufferWriteIdx = 0x00;

  packetPayloadOk = _packetPayload[_packetSize - 0x01] == calcCDEByteChecksum(_packetPayload, _packetSize - 0x01);

  for (uint8_t bufferReadIdx = 0x00; bufferReadIdx < _packetSize; bufferReadIdx++) {
    uint8_t currentByte = _packetPayload[bufferReadIdx];
    _packetPayload[bufferWriteIdx] = currentByte;
    if (_packetSize > bufferWriteIdx) {
      bufferWriteIdx++;
    }
  }
  return packetPayloadOk ? bufferWriteIdx : 0x00;
}

bool parsePacket(const uint8_t* _packetPayload, const int _packetSize) {
  const uint8_t  payloadSize = _packetPayload[0x00] - 0x040;
  const uint8_t  channelNo   = _packetPayload[0x01];
  const uint16_t targetAddress  = (_packetPayload[0x02] << 0x08) | _packetPayload[0x03];
  const uint8_t  encryptKey = _packetPayload[0x04];
  const uint8_t  encryptKeyCalc = getCDEByteKey(channelNo);

  printf("[*] Packet parsed: payloadSize = %d, channelNo = %02X, encryptKey = %02X | %02X, targetAddress = %04X, payload = ",
         payloadSize, channelNo, encryptKey, encryptKeyCalc, targetAddress);

  for (int i = 0; i < payloadSize; i++) {
    printf(" %02X", _packetPayload[i + 0x04] ^ encryptKeyCalc);
  }

  printf("\n");
  return true;
}

void setup() {
  Serial.begin(uartDebugSpeed);

  printf("[*] System started\n");
  SPI.begin(loraSclkPin, loraMisoPin, loraMosiPin);
  LoRa.setPins(loraCsPin, loraRstPin, loraDio0Pin);

  if (!LoRa.begin(loraFrequency)) {
    printf("[!] Error initializing LoRa protocol\n");
    while (true) {
      yield();
    }
  }

  printf("[*] LoRa settings BW = %06d, SF = %02d: ", loraSignalBandwidth, loraSpreadingFactor);
  LoRa.setPreambleLength(loraPreambleLength);
  LoRa.setTxPower(loraTxPower);
  LoRa.enableCrc();
  LoRa.setSyncWord(loraSyncWord);
  LoRa.setSignalBandwidth(loraSignalBandwidth);
  LoRa.setSpreadingFactor(loraSpreadingFactor);
  LoRa.setCodingRate4(loraCodingRate4);
  // !!! this is from library's add-on
  LoRa.setLdoFlagForced(true);
}

void loop() {
  static uint32_t helloTimeLast;
  uint8_t packetPayload[0x80]; // Header 4 byte + max payload 58 bytes + checksum 1 byte = 63 bytes. FEC coding: payload 63 * 2 + CRC 2 bute = 128 bytes
  uint32_t nowTime;;

  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    printf("\n[*] Received packet w/RSSI = %03d: ", LoRa.packetRssi());
    packetSize = (sizeof(packetPayload) > packetSize) ? packetSize : sizeof(packetPayload);
    for (uint8_t i = 0x00; packetSize > i; i++) {
      packetPayload[i] = LoRa.read();
      printf(" %02X", packetPayload[i]);
    }
    printf("\n");

    // Try to decode packet
    uint8_t decodedPacketSize = decodePacket(packetPayload, packetSize);
    if (decodedPacketSize) {
      parsePacket(packetPayload, decodedPacketSize);
    }
  }

  nowTime = millis();
  if (nowTime - helloTimeLast > helloInterval) {
    helloTimeLast = nowTime;
    uint8_t sendPacketSize = encodePacket(packetPayload, targetAddress, channelA, helloPayload, sizeof(helloPayload));
    printf("\n[*] Sending %02d bytes of data: ", sendPacketSize);
    for (uint8_t i = 0x00; sendPacketSize > i; i++) {
      printf(" %02X", packetPayload[i]);
    }
    printf("\n");

    LoRa.beginPacket();
    LoRa.write(packetPayload, sendPacketSize);
    LoRa.endPacket();
  }
}

Channel hopping on Fixed mode:

image

Edgineer10 commented 1 year ago

Hello @zbx-sadman , I can see that you have different method in your code. How about the library for Ebyte E32 (LoRa_E32_Series_Library). Have you tried using it?

zbx-sadman commented 1 year ago

How about the library for Ebyte E32 (LoRa_E32_Series_Library). Have you tried using it?

No, i did not use it never

Edgineer10 commented 1 year ago

@zbx-sadman can you try using it? I think that it will be helpful once you made it communicate using the LoRa_E32_Series_Library.

zbx-sadman commented 1 year ago

@zbx-sadman can you try using it?

Unfortunately, this lib not interesting for me.