Closed sam43054 closed 3 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
can you tell me how to know lora's CR, BW and SF ?
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.
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
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 .
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.
@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?
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 .
@AdamJGodzik Very interesting. Thanks for your discovery! :D
@AdamJGodzik, Thank you very much!
@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 ......
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.
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.
Interesting topic.
Extending on @stafil 's comment above, the proper parameters to use for
setSignalBandwidth(...)
can be deduced from the implementation of the function src/LoRa.cppI 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 above250E3
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.
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?
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
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
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 !
@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
@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:
Thanks Regards
Hello @yodapuces63
I've published my testings about radio transmissions between my Ra01 and My E32-433 modules. If it could help you.
Best regards :)
Hi @ZeSanglier
Thanks for your detailed and clear document.
Best regards
Great ! thank you As i still have communication trouble, this will help me Regards
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
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
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
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];
}
@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.
Thanks.
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.
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;
}
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;
}
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(" ");
}
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 !?
my OWN crypting algo
Unless you have a couple of PhDs in maths and cryptography, do not roll your own crypto. Use AES.
:-) Very simple, but not easy to uncrypt :-)
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.
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.
@Kongduino I have found articles already that made them connect to each other.
@yodapuces63 What are your settings(Airrates etc.) on TTGO and E32, and how did you set them?
Hello As the E95 (E32 in a box) use a configuration tool from EByte, I use it and setup the default proposal:
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.
@zbx-sadman are the settings for transmitting and receiving packets different? or Is it possible to use the same settings for both?
Air rate value used on E32 side, LoRa settings used on TTGO (naked SX1276) side.
@zbx-sadman for example, I want to send and receive message from TTGO, are the Lora Settings same for both operations?
Yes, of course. You need no change LoRa settings after sending before recieve answer.
@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.
Very simple example for CDEByte E32 v8 & TTGO T3 v1.6.1 (Lora32).
cdebyte_example.ino
// 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
#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:
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?
How about the library for Ebyte E32 (LoRa_E32_Series_Library). Have you tried using it?
No, i did not use it never
@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 can you try using it?
Unfortunately, this lib not interesting for me.
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