Skip to content
Snippets Groups Projects
Commit 5d2de00d authored by Philipp Markwardt's avatar Philipp Markwardt :tram:
Browse files

feat: raw send and receive

add a dumb transceiver function to send or receive
generic payload

- use terminal `SEND FROM 22 TO 11 DATA 0x01 0x04..`
- use flag `STATION_FEATURE` and `REPEATER_FEATURE`
  to build a station transciver or repeater
- all received data will printed as `RECV FROM 33...`
- all send data will be printed as `SEND FROM 33...`
parent 9f30d992
Branches
No related tags found
No related merge requests found
......@@ -18,3 +18,6 @@ monitor_speed = 115200
lib_deps =
SPI
mikem/RadioHead@^1.120
# use REPEATER_FEATURE to build a repeater node
build_flags = -D STATION_FEATURE
......@@ -59,7 +59,18 @@
#define REPEATER_ADDRESS 11
// serial buffer for formatted printing
static char strXBuf[128] = {
#define MAX_MESSAGE_SIZE 128
#define MAX_SERIAL_BUFFER_SIZE 200
#define MAX_LORA_PAYLOAD_SIZE 32
static char strXBuf[MAX_MESSAGE_SIZE] = {
0,
};
static char serial_buffer[MAX_SERIAL_BUFFER_SIZE] = {
0,
};
static char serial_data_buffer[MAX_SERIAL_BUFFER_SIZE] = {
0,
};
......@@ -68,10 +79,16 @@ unsigned long loop_start_millis;
uint32_t msg_count;
// Buffer for incoming LoRa messages
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
uint8_t lora_payload_buf[MAX_LORA_PAYLOAD_SIZE];
// This variable will be overwritten by the received message length.
uint8_t lora_payload_len = sizeof(lora_payload_buf);
uint8_t keep_from_address;
// Serial communication
uint8_t received_number_of_bytes;
uint8_t current_payload_byte;
// RadioHead instance
static RH_RF95 rf95(RFM95_PIN_CS, RFM95_PIN_INT);
......@@ -83,8 +100,14 @@ void setup()
// Initialize Serial Monitor
Serial.begin(115200);
// Debug Print
Serial.println("REPEATER Starting Up...");
// Debug Print
#ifdef REPEATER_FEATURE
Serial.print("REPEATER Starting Up... ");
#endif
#ifdef STATION_FEATURE
Serial.print("STATION Starting Up... ");
#endif
// Initialize RFM95
// First Reset the RFM95
......@@ -118,42 +141,62 @@ void setup()
loop_start_millis = 0;
msg_count = 0;
keep_from_address = 0;
current_payload_byte = 0;
Serial.println("REPEATER Ready");
Serial.println("Ready");
}
// Print the current message in RF95 buffer
// Note to print a prefix ('RAW', 'FORWARD', 'RECEIVE'...) in code
// before calling this function
void print_message_from_buffer_to_serial()
void print_received_lora_message()
{
// =========================================================================
// Receiver Part
//
// Just receive the message and print it to serial
// =========================================================================
// Print TO and FROM Adress
sprintf(strXBuf, "TO %d FROM %d DATA", rf95.headerTo(), rf95.headerFrom());
sprintf(strXBuf, "RECV FROM %d TO %d DATA", rf95.headerFrom(), rf95.headerTo());
Serial.print(strXBuf);
// print the raw data in 0x00 hex format
for (uint8_t i = 0; i < len; i++)
for (uint8_t i = 0; i < lora_payload_len; i++)
{
sprintf(strXBuf, " 0x%02x", buf[i]);
sprintf(strXBuf, " 0x%02x", lora_payload_buf[i]);
Serial.print(strXBuf);
}
Serial.println();
// reset buffer
memset(lora_payload_buf, 0, sizeof(lora_payload_buf));
}
void send_message()
void send_lora_message(uint8_t from, uint8_t to)
{
Serial.print("SEND ");
print_message_from_buffer_to_serial();
sprintf(strXBuf, "SEND FROM %d TO %d DATA", from, to);
Serial.print(strXBuf);
for (uint8_t i = 0; i < lora_payload_len; i++)
{
sprintf(strXBuf, " 0x%02x", lora_payload_buf[i]);
Serial.print(strXBuf);
}
Serial.println();
// Transmit a message via LoRa
// send package with message count
rf95.send(buf, len);
rf95.setHeaderFrom(from);
rf95.setHeaderTo(to);
rf95.send(lora_payload_buf, lora_payload_len);
rf95.waitPacketSent();
}
void loop()
void lora_cycle_check()
{
loop_start_millis = millis();
// Check if a message is available, if called the first time
// the available() function will also enable the receiver
......@@ -164,14 +207,17 @@ void loop()
}
// Read the message into the buffer
if (!rf95.recv(buf, &len))
if (!rf95.recv(lora_payload_buf, &lora_payload_len))
{
return;
}
// Always print the message to serial (For Debugging or Logging)
Serial.print("RECV ");
print_message_from_buffer_to_serial();
print_received_lora_message();
}
void repeater_cycle_check()
{
// Stage 1. If the package is not from Station but from any other address
// Forward the message to the STATION. As the RFID packet format has
......@@ -186,22 +232,19 @@ void loop()
// Keep the original sender address for later
keep_from_address = rf95.headerFrom();
// Set the FROM and TO address for the repeater and forward the message
// to the station
rf95.setHeaderFrom(REPEATER_ADDRESS);
rf95.setHeaderTo(STATION_ADDRESS);
send_message();
// Send the message to the station
send_lora_message(REPEATER_ADDRESS, STATION_ADDRESS);
// Stage 2. We expect the station to send and ACK back to the sender
// We will wait max 2000ms for the ACK.
if (!rf95.waitAvailableTimeout(2000))
{
Serial.println("NOACK");
Serial.println("ERR NOACK");
return;
}
// Read the ACK into the buffer
if (!rf95.recv(buf, &len))
if (!rf95.recv(lora_payload_buf, &lora_payload_len))
{
return;
}
......@@ -209,17 +252,103 @@ void loop()
// Check if this is the ACK we expect
if (rf95.headerFrom() != STATION_ADDRESS || rf95.headerTo() != REPEATER_ADDRESS)
{
Serial.println("WRONGACK");
Serial.println("ERR WRONGACK");
return;
}
// Send ACK back to the original sender. As the repater ist explicit
// "contaced", we also set the FROM address to the repeater address.
rf95.setHeaderFrom(STATION_ADDRESS);
rf95.setHeaderTo(keep_from_address);
send_message();
send_lora_message(STATION_ADDRESS, keep_from_address);
Serial.print("ACK ");
print_message_from_buffer_to_serial();
print_received_lora_message();
}
// Check if a serial message is available and in correct
// format. Then send the message via LoRa.
void station_cycle_check()
}
\ No newline at end of file
// check if there is a new char in Serial received
{
if (Serial.available())
{
// Expected Serial Command. Example:
// `SEND FROM 11 TO 10 DATA 0x00 0x00 ....`
// Reset serial buffer
memset(serial_buffer, 0, sizeof(serial_buffer));
received_number_of_bytes = Serial.readBytesUntil('\n', serial_buffer, sizeof(serial_buffer));
// Check if the command is valid
if (received_number_of_bytes < 4)
{
Serial.println("ERR INVALIDCOMMAND");
return;
}
uint8_t address_from = 0;
uint8_t address_to = 0;
uint8_t readable_variables = 0;
// Parse the Serial Command
readable_variables = sscanf(serial_buffer, "SEND FROM %hhd TO %hhd DATA %[^\t\n]\n", &address_from, &address_to, serial_data_buffer);
// Check if the command is valid
if (readable_variables != 3)
{
Serial.println("ERR INVALIDCOMMAND");
return;
}
// Payload to send from `0xf1 0x03 ...` to byte array
current_payload_byte = 0;
for (u_int8_t i = 0; i < sizeof(serial_data_buffer); i++)
{
// check if space
if (serial_data_buffer[i] == ' ')
{
continue;
}
// check if end of string
if (serial_data_buffer[i] == '\0')
{
break;
}
// check if 0x
if (serial_data_buffer[i] == '0' && serial_data_buffer[i + 1] == 'x')
{
// If maximum payload size is reached, stop
if (current_payload_byte >= RH_RF95_MAX_MESSAGE_LEN)
{
break;
}
// convert hex to byte
if (sscanf(&serial_data_buffer[i], "0x%hhx", &lora_payload_buf[current_payload_byte]))
{
current_payload_byte++;
};
}
}
// Set the FROM and TO address for the station and send the message via lora
send_lora_message(address_from, address_to);
}
}
void loop()
{
loop_start_millis = millis();
lora_cycle_check();
#ifdef REPEATER_FEATURE
repeater_cycle_check();
#endif
#ifdef STATION_FEATURE
station_cycle_check();
#endif
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment