Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
sam43054 opened this issue Nov 16, 2018 · 55 comments
Closed

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

sam43054 opened this issue Nov 16, 2018 · 55 comments

Comments

@sam43054
Copy link

sam43054 commented Nov 16, 2018

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

  • Can a E19 and E32 module talk to each other? is it even possible?
  • Or can I get 292.96875 any closer to 300.0000
  • Or is there additional settings to tweak the AirRate?
  • Can you set BW to an 'unsupported' rate of 128 with lora.h ?
  • Or is there some other reason I might be getting a garbled character string (that I don't get when I used between two E19s)
@sam43054 sam43054 changed the title Ebyte E32 talking to an Ebyte E19 ? AirRate Queston --- Ebyte E32 talking to an Ebyte E19 ? Nov 16, 2018
@stafil
Copy link

stafil commented Nov 26, 2018

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
Copy link

ada1s1h commented Feb 25, 2019

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

@PRO2XY
Copy link

PRO2XY commented Apr 24, 2019

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
Copy link

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
Copy link

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
Copy link

SimpleRomb commented Feb 1, 2021

@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
Copy link

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
Copy link
Collaborator

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

@SimpleRomb
Copy link

@AdamJGodzik,
Thank you very much!

@al1fch
Copy link

al1fch commented Feb 11, 2021

@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
Copy link

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
Copy link

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
Copy link

xg590 commented Jun 15, 2021

Interesting topic.

@baarratia
Copy link

baarratia commented Aug 19, 2021

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
Copy link

karfam commented Jan 7, 2022

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
Copy link

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
Copy link

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
Copy link

ZeSanglier commented Jan 15, 2023

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
Copy link

@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
Copy link

@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
Copy link

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
Copy link

al1fch commented Feb 12, 2023

Hi @ZeSanglier

Thanks for your detailed and clear document.

Best regards

@yodapuces63
Copy link

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

@yodapuces63
Copy link

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
Copy link

ZeSanglier commented Feb 15, 2023

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
Copy link

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
Copy link
Contributor

zbx-sadman commented Aug 15, 2023

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
Copy link
Contributor

zbx-sadman commented Aug 16, 2023

@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
Copy link

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
Copy link

yodapuces63 commented Sep 12, 2023

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
Copy link

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
Copy link

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
Copy link

Kongduino commented Sep 13, 2023

my OWN crypting algo

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

@yodapuces63
Copy link

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

@Edgineer10
Copy link

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
Copy link

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
Copy link

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

@Edgineer10
Copy link

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

@yodapuces63
Copy link

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

  • Air rate : 2.4k
  • address: 16h1234
  • Channel: 11 (421Mhz)
    This module was used as "master" (sender) and send basic data (one s counter)
    Then with my "Salve" (receive) LoRa module (SX1278), I try many combinaison of BW/CF/CR (lots of time)
    I finally find the correct parameters:
  • BW: 500k
  • CF: 11
  • CR: 4/5
    But the data was "scramble" !
    Using the help of this github topics, i finally be able to decode (the OR and the key) the data. (see the nice table of zbx-sadman)
    Now, I am testing the transmitting distance. The "master" is near my PLC in the cave. The master had a good antenna (SMA and 17cm)
    For the receiver, starting with the small "spring" antenna, the max. distance was 50m, with very bad RSSI (-120dbm)
    I suspect the "cheap" antenna is tuned at bad frequency, so I remove the spring and solder just a "wire" of 17cm (433Mhz)
    RSSI become better (-60dbm) and the distance go to 300m
    Now, I fix the receiver at 70m and do a long test of send-receive and record the number of transmitting "error".

@zbx-sadman
Copy link
Contributor

zbx-sadman commented Sep 18, 2023

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
Copy link

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

@zbx-sadman
Copy link
Contributor

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

@Edgineer10
Copy link

Edgineer10 commented Sep 19, 2023

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

@zbx-sadman
Copy link
Contributor

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

@Edgineer10
Copy link

@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
Copy link
Contributor

zbx-sadman commented Sep 21, 2023

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
Copy link

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
Copy link
Contributor

zbx-sadman commented Sep 25, 2023

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

No, i did not use it never

@Edgineer10
Copy link

@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
Copy link
Contributor

zbx-sadman commented Sep 25, 2023

@zbx-sadman can you try using it?

Unfortunately, this lib not interesting for me.

@Edgineer10
Copy link

@zbx-sadman I would be happy if you could give it a try. I will try using that library as soon as the components arrive. How about the SetLdo function, did you do something different about that?

@zbx-sadman
Copy link
Contributor

How about the SetLdo function

The same content as in the function setLdoFlag() from the article https://blog.zesanglier.fr/2023/02/11/communiquer-entre-un-module-ebyte-e32-et-un-module-ra01-02-sx1278/

@Edgineer10
Copy link

@zbx-sadman what file should I paste it to? is it on the LoRa.h or LoRa.cpp?

@zbx-sadman
Copy link
Contributor

what file should I paste it to?

You can copy changes from this pull-request: d9914a2

@andremdaraujo
Copy link

Hi everyone!

I'm currently trying to establish LoRa communication between an E32-900T20D module and an STM32WL55JC1 (Nucleo board with that MCU that has an integrated LoRa radio). After doing some research I found this discussion, which helped me a lot!! The blog post from @ZeSanglier is also amazing.

I'm now testing transmission from the EBTYTE module to the STM32. Trying a test similar to what @ZeSanglier did, but I'm getting the following results:

E32 config:
ID: E32-900T20S/D
Version: 7393-1-14
Freq Now: 915.0MHz
Param Now: 0x0, 0x0, 0x19, 0x35, 0x40
9600 bps 8N1 (serial interface)
AirRate 2400
Power 20 dBm
FEC disable
Fixed mode disabled
WOR 250ms
IO mode PushPull
Address 0
Channel 53 (0x35)

  • Send "TEST" from E32 to STM32;
  • Raw data received by the STM32 (in hex): 44 35 30 C0 88 88 AB C9 77;
  • Data receive is consistent (if I repeat TX, I always get the same RX response).

From that response I'm assuming:

  • First byte is 0x40 + 4 (number of data bytes sent);
  • Second byte is E32 channel (0x35 = 53 for 915 MHz);
  • Third and forth bytes should be the E32 address (in my case, 00 00) - but they change according to the data transmitted;
  • 88 88 AB C9 should refer to "TEST", but notice the first and last bytes are no the same;
  • Last byte means the CRC/Checksum from what I understood.

So in my case it seems I don't have the fixed key that can be used to decrypt the data. Does anyone have an idea of what may be happening?

I'm documenting these results in detail on my repo: https://github.com/andremdaraujo/LoRaPingPong/blob/master/README.md - however, as of now, the results shown there refer to tests I've done using 868 MHz. But the result is analogous with 915 MHz.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests