get mostly one directional comms working
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"C_Cpp.intelliSenseEngine": "default",
|
"C_Cpp.intelliSenseEngine": "default",
|
||||||
"idf.espIdfPath": "/home/bruno/esp/v5.4.1/esp-idf",
|
"idf.espIdfPath": "/home/bruno/esp/master/esp-idf",
|
||||||
"idf.pythonInstallPath": "/usr/bin/python",
|
"idf.pythonInstallPath": "/usr/bin/python",
|
||||||
"idf.openOcdConfigs": [
|
"idf.openOcdConfigs": [
|
||||||
"board/esp32s3-builtin.cfg"
|
"board/esp32s3-builtin.cfg"
|
||||||
|
@@ -2,7 +2,7 @@ dependencies:
|
|||||||
idf:
|
idf:
|
||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
version: 5.4.1
|
version: 5.5.0
|
||||||
k0i05/esp_bme680:
|
k0i05/esp_bme680:
|
||||||
component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8
|
component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@@ -2,8 +2,20 @@
|
|||||||
#define PACKETS_STRUCTS
|
#define PACKETS_STRUCTS
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
|
||||||
|
#define UplinkSync "PlechHore"
|
||||||
|
#define DownlinkSync "PlechDole"
|
||||||
|
|
||||||
|
#define UplinkPacketType_SystemControl 0
|
||||||
|
#define UplinkPacketType_Ping 1
|
||||||
|
#define UplinkPacketType_ACK 255
|
||||||
|
|
||||||
|
#define DownlinkPacketType_Telemetry 0
|
||||||
|
#define DownlinkPacketType_Ping 1
|
||||||
|
#define DownlinkPacketType_ACK 255
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
{
|
{
|
||||||
|
char syncPhrase[10];
|
||||||
uint32_t packetIndex;
|
uint32_t packetIndex;
|
||||||
uint8_t packetType;
|
uint8_t packetType;
|
||||||
uint32_t missionTimer;
|
uint32_t missionTimer;
|
||||||
@@ -44,6 +56,15 @@ typedef struct __attribute__((packed))
|
|||||||
uint8_t gas_range;
|
uint8_t gas_range;
|
||||||
uint8_t gas_index;
|
uint8_t gas_index;
|
||||||
|
|
||||||
|
float air_temperature; /*!< air temperature in degrees celsius */
|
||||||
|
float relative_humidity; /*!< relative humidity in percent */
|
||||||
|
float barometric_pressure; /*!< barometric pressure in hecto-pascal */
|
||||||
|
float gas_resistance; /*!< gas resistance in ohms */
|
||||||
|
uint16_t iaq_score; /*!< air quality index (0..500) */
|
||||||
|
float temperature_score;
|
||||||
|
float humidity_score;
|
||||||
|
float gas_score;
|
||||||
|
|
||||||
// GPS DATA
|
// GPS DATA
|
||||||
uint32_t time_seconds; // Seconds since start of day
|
uint32_t time_seconds; // Seconds since start of day
|
||||||
int32_t latitude_centi_degrees; // Latitude * 10,000
|
int32_t latitude_centi_degrees; // Latitude * 10,000
|
||||||
@@ -73,6 +94,7 @@ typedef struct __attribute__((packed))
|
|||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
{
|
{
|
||||||
|
char syncPhrase[10];
|
||||||
uint32_t packetIndex;
|
uint32_t packetIndex;
|
||||||
uint8_t packetType;
|
uint8_t packetType;
|
||||||
} UplinkPacket;
|
} UplinkPacket;
|
||||||
@@ -85,4 +107,15 @@ typedef struct __attribute__((packed))
|
|||||||
uint16_t servoB;
|
uint16_t servoB;
|
||||||
} SystemControlPacket;
|
} SystemControlPacket;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
uint8_t PingData[20];
|
||||||
|
} PingPacket;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
uint32_t packetIndex;
|
||||||
|
uint32_t crc32Checksum;
|
||||||
|
} ACKPacket;
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -5,100 +5,280 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
#include "esp_rom_crc.h"
|
||||||
const char *msg = "Testing 123 test why is this not on air";
|
|
||||||
|
|
||||||
#define TAG "LoRa"
|
#define TAG "LoRa"
|
||||||
|
|
||||||
uint32_t packetIndex = 0;
|
#define ACK_TIMEOUT_MS 500 // Wait 300ms for ACK
|
||||||
|
#define MAX_RETRIES 3
|
||||||
|
|
||||||
|
uint32_t packetIndexTX = 0;
|
||||||
|
uint32_t packetIndexRX = 0;
|
||||||
|
|
||||||
TelemetryPacket telemetryPacket;
|
TelemetryPacket telemetryPacket;
|
||||||
uint8_t packetReadiness = 0;
|
uint8_t packetReadiness = 0;
|
||||||
|
|
||||||
void lora_comms_task(void *pvParameters)
|
volatile bool ackReceived = false;
|
||||||
|
uint32_t lastAckIndex = 0;
|
||||||
|
|
||||||
|
SemaphoreHandle_t loraRadioMutex;
|
||||||
|
|
||||||
|
void setup_lora(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
const int64_t interval_us = 100000; // 100 ms
|
|
||||||
int64_t start_time, end_time, elapsed;
|
|
||||||
LoRaInit();
|
LoRaInit();
|
||||||
|
|
||||||
int8_t txPowerInDbm = 20;
|
int8_t txPowerInDbm = 20;
|
||||||
|
uint32_t frequencyInHz = 869525000;
|
||||||
|
float tcxoVoltage = 2.2;
|
||||||
|
bool useRegulatorLDO = true;
|
||||||
|
|
||||||
uint32_t frequencyInHz = 0;
|
|
||||||
frequencyInHz = 869525000;
|
|
||||||
ESP_LOGW(TAG, "Enable TCXO");
|
ESP_LOGW(TAG, "Enable TCXO");
|
||||||
float tcxoVoltage = 2.2; // use TCXO
|
LoRaDebugPrint(false);
|
||||||
bool useRegulatorLDO = true; // use DCDC + LDO
|
|
||||||
|
|
||||||
// LoRaDebugPrint(true);
|
|
||||||
if (LoRaBegin(frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO) != 0)
|
if (LoRaBegin(frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO) != 0)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Does not recognize the module");
|
ESP_LOGE(TAG, "LoRa module not recognized. Halting.");
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t spreadingFactor = 7;
|
uint8_t spreadingFactor = 6;
|
||||||
uint8_t bandwidth = SX126X_LORA_BW_250_0;
|
uint8_t bandwidth = SX126X_LORA_BW_250_0;
|
||||||
uint8_t codingRate = SX126X_LORA_CR_4_8;
|
uint8_t codingRate = SX126X_LORA_CR_4_8;
|
||||||
uint16_t preambleLength = 8;
|
uint16_t preambleLength = 8;
|
||||||
uint8_t payloadLen = 0;
|
|
||||||
bool crcOn = true;
|
bool crcOn = true;
|
||||||
bool invertIrq = false;
|
bool invertIrq = false;
|
||||||
LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, payloadLen, crcOn, invertIrq);
|
|
||||||
uint8_t bufIn[256]; // Maximum Payload size of SX1261/62/68 is 255
|
|
||||||
uint8_t bufOut[256]; // Maximum Payload size of SX1261/62/68 is 255
|
|
||||||
|
|
||||||
DownBoundPacket downboundPacket;
|
LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn, invertIrq);
|
||||||
UplinkPacket uplinkPacket;
|
}
|
||||||
SystemControlPacket systemControlPacket;
|
|
||||||
|
|
||||||
while (1)
|
static void prepare_downbound_packet(DownBoundPacket *packet, uint8_t type, uint64_t missionTimer)
|
||||||
|
{
|
||||||
|
memset(packet, 0, sizeof(DownBoundPacket));
|
||||||
|
packet->missionTimer = missionTimer;
|
||||||
|
packet->packetIndex = packetIndexTX++;
|
||||||
|
ESP_LOGI(TAG_RADIO, "Sending downbound packet with index %ld", packetIndexTX - 1);
|
||||||
|
packet->packetType = type;
|
||||||
|
strcpy(packet->syncPhrase, "PlechDole");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_packet_with_retries(uint8_t *data, uint16_t size)
|
||||||
|
{
|
||||||
|
for (int retry = 0; retry <= MAX_RETRIES; retry++)
|
||||||
{
|
{
|
||||||
start_time = esp_timer_get_time(); // µs since boot
|
if (xSemaphoreTake(loraRadioMutex, portMAX_DELAY) == pdTRUE)
|
||||||
if (packetReadiness == 1)
|
|
||||||
{
|
{
|
||||||
uint8_t downPacketSize = 0;
|
if (!LoRaSend(data, size, SX126x_TXMODE_SYNC))
|
||||||
memset(bufOut, 0, sizeof(bufOut));
|
|
||||||
downboundPacket.missionTimer = start_time;
|
|
||||||
downboundPacket.packetIndex = packetIndex++;
|
|
||||||
downboundPacket.packetType = 1;
|
|
||||||
|
|
||||||
memcpy(bufOut, &downboundPacket, sizeof(downboundPacket));
|
|
||||||
downPacketSize += sizeof(downboundPacket);
|
|
||||||
memcpy(((uint8_t *)bufOut) + downPacketSize, &telemetryPacket, sizeof(telemetryPacket));
|
|
||||||
downPacketSize += sizeof(telemetryPacket);
|
|
||||||
|
|
||||||
ESP_LOGI(pcTaskGetName(NULL), "%d byte packet sent...", downPacketSize);
|
|
||||||
|
|
||||||
// Wait for transmission to complete
|
|
||||||
if (LoRaSend(bufOut, downPacketSize, SX126x_TXMODE_SYNC) == false)
|
|
||||||
{
|
{
|
||||||
ESP_LOGE(pcTaskGetName(NULL), "LoRaSend fail");
|
ESP_LOGW(TAG, "LoRaSend failed, retry %d", retry);
|
||||||
} else {
|
xSemaphoreGive(loraRadioMutex);
|
||||||
packetReadiness = 0;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "%d byte packet sent (attempt %d)", size, retry + 1);
|
||||||
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
|
||||||
|
// Wait for ACK
|
||||||
|
ackReceived = false;
|
||||||
|
uint64_t start_wait = esp_timer_get_time();
|
||||||
|
while ((esp_timer_get_time() - start_wait) < (ACK_TIMEOUT_MS * 1000))
|
||||||
|
{
|
||||||
|
if (ackReceived)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "ACK received for packet.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGW(TAG, "ACK timeout, retrying...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t rxLen = LoRaReceive(bufIn, sizeof(bufIn));
|
ESP_LOGE(TAG, "Failed to send packet after %d retries", MAX_RETRIES);
|
||||||
if (rxLen > 0)
|
}
|
||||||
|
|
||||||
|
void prepare_and_send_telemetry(uint64_t missionTimer)
|
||||||
|
{
|
||||||
|
uint8_t bufOut[256] = {0};
|
||||||
|
|
||||||
|
DownBoundPacket downboundPacket;
|
||||||
|
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_Telemetry, missionTimer);
|
||||||
|
|
||||||
|
uint16_t offset = 0;
|
||||||
|
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
||||||
|
offset += sizeof(downboundPacket);
|
||||||
|
memcpy(bufOut + offset, &telemetryPacket, sizeof(telemetryPacket));
|
||||||
|
offset += sizeof(telemetryPacket);
|
||||||
|
|
||||||
|
send_packet_with_retries(bufOut, offset);
|
||||||
|
packetReadiness = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_and_send_ack(uint32_t ackIndex, uint32_t crc32Checksum, uint64_t missionTimer)
|
||||||
|
{
|
||||||
|
uint8_t bufOut[256] = {0};
|
||||||
|
|
||||||
|
DownBoundPacket downboundPacket;
|
||||||
|
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_ACK, missionTimer);
|
||||||
|
|
||||||
|
ACKPacket ackPacket = {
|
||||||
|
.packetIndex = ackIndex,
|
||||||
|
.crc32Checksum = crc32Checksum,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16_t offset = 0;
|
||||||
|
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
||||||
|
offset += sizeof(downboundPacket);
|
||||||
|
memcpy(bufOut + offset, &ackPacket, sizeof(ackPacket));
|
||||||
|
offset += sizeof(ackPacket);
|
||||||
|
|
||||||
|
if (xSemaphoreTake(loraRadioMutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
if (!LoRaSend(bufOut, offset, SX126x_TXMODE_SYNC))
|
||||||
{
|
{
|
||||||
ESP_LOGI(pcTaskGetName(NULL), "%d byte packet received:[%.*s]", rxLen, rxLen, bufIn);
|
ESP_LOGE(TAG, "Failed to send ACK");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "%d byte ACK sent", offset);
|
||||||
|
}
|
||||||
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int8_t rssi, snr;
|
void process_uplink_packet(uint8_t *data, uint8_t len, uint64_t missionTimer)
|
||||||
GetPacketStatus(&rssi, &snr);
|
{
|
||||||
ESP_LOGI(pcTaskGetName(NULL), "rssi=%d[dBm] snr=%d[dB]", rssi, snr);
|
if (len < sizeof(UplinkPacket))
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Uplink packet too small: %d bytes", len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UplinkPacket uplinkPacket;
|
||||||
|
memcpy(&uplinkPacket, data, sizeof(UplinkPacket));
|
||||||
|
|
||||||
|
if (strcmp(UplinkSync, uplinkPacket.syncPhrase) != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Invalid sync phrase");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Got uplink packet of type %d, index %d", uplinkPacket.packetType, uplinkPacket.packetIndex);
|
||||||
|
|
||||||
|
uint8_t payloadRXLen = len - sizeof(UplinkPacket);
|
||||||
|
|
||||||
|
if (uplinkPacket.packetType == UplinkPacketType_ACK)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Received ACK for packet %d", uplinkPacket.packetIndex);
|
||||||
|
ackReceived = true;
|
||||||
|
lastAckIndex = uplinkPacket.packetIndex;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uplinkPacket.packetIndex == packetIndexRX + 1)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Packet arrived in correct order");
|
||||||
|
packetIndexRX = uplinkPacket.packetIndex;
|
||||||
|
|
||||||
|
uint32_t crc = esp_rom_crc32_le(0, data + sizeof(UplinkPacket), payloadRXLen);
|
||||||
|
build_and_send_ack(packetIndexRX, crc, missionTimer);
|
||||||
|
|
||||||
|
switch (uplinkPacket.packetType)
|
||||||
|
{
|
||||||
|
case UplinkPacketType_SystemControl:
|
||||||
|
if (payloadRXLen == sizeof(SystemControlPacket))
|
||||||
|
{
|
||||||
|
SystemControlPacket sysCtrl;
|
||||||
|
memcpy(&sysCtrl, data + sizeof(UplinkPacket), sizeof(SystemControlPacket));
|
||||||
|
// TODO: Process sysCtrl
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "SystemControlPacket size mismatch");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UplinkPacketType_Ping:
|
||||||
|
// TODO: handle Ping
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGW(TAG, "Unknown uplink packet type %d", uplinkPacket.packetType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (uplinkPacket.packetIndex > packetIndexRX + 1)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Skipped %d packets", uplinkPacket.packetIndex - (packetIndexRX + 1));
|
||||||
|
packetIndexRX = uplinkPacket.packetIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Duplicate packet: %d", (packetIndexRX + 1) - uplinkPacket.packetIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lora_receive_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "lora_receive_task started");
|
||||||
|
uint8_t bufIn[256];
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Wait to take the semaphore before accessing LoRa
|
||||||
|
if (xSemaphoreTake(loraRadioMutex, 0) == pdTRUE)
|
||||||
|
{
|
||||||
|
uint8_t rxLen = LoRaReceive(bufIn, sizeof(bufIn));
|
||||||
|
if (rxLen > 0)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "%d byte packet received", rxLen);
|
||||||
|
process_uplink_packet(bufIn, rxLen, esp_timer_get_time());
|
||||||
|
int8_t rssi, snr;
|
||||||
|
GetPacketStatus(&rssi, &snr);
|
||||||
|
ESP_LOGI(TAG, "rssi=%d[dBm], snr=%d[dB]", rssi, snr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the semaphore when done with LoRa RX
|
||||||
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10)); // Delay to prevent busy-waiting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lora_comms_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "lora_comms_task started");
|
||||||
|
// Initialize the semaphore for radio access (binary semaphore, 1 = available)
|
||||||
|
loraRadioMutex = xSemaphoreCreateMutex();
|
||||||
|
xSemaphoreGive(loraRadioMutex); // Set semaphore as available
|
||||||
|
|
||||||
|
const int64_t interval_us = 400000; // 400 ms
|
||||||
|
|
||||||
|
setup_lora();
|
||||||
|
xTaskCreate(
|
||||||
|
lora_receive_task,
|
||||||
|
"LoraReceiveTask",
|
||||||
|
8192,
|
||||||
|
NULL,
|
||||||
|
(tskIDLE_PRIORITY + 2),
|
||||||
|
NULL);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int64_t start_time = esp_timer_get_time();
|
||||||
|
|
||||||
|
if (packetReadiness)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Preparing telemetry");
|
||||||
|
|
||||||
|
prepare_and_send_telemetry(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lost = GetPacketLost();
|
int64_t end_time = esp_timer_get_time();
|
||||||
if (lost != 0)
|
int64_t elapsed = end_time - start_time;
|
||||||
{
|
|
||||||
ESP_LOGW(pcTaskGetName(NULL), "%d packets lost", lost);
|
|
||||||
}
|
|
||||||
|
|
||||||
end_time = esp_timer_get_time();
|
|
||||||
elapsed = end_time - start_time;
|
|
||||||
|
|
||||||
if (elapsed < interval_us)
|
if (elapsed < interval_us)
|
||||||
{
|
{
|
||||||
@@ -106,3 +286,49 @@ void lora_comms_task(void *pvParameters)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void lora_comms_task(void *pvParameters)
|
||||||
|
// {
|
||||||
|
// const int64_t interval_us = 400000; // 100 ms
|
||||||
|
// int64_t start_time, end_time, elapsed;
|
||||||
|
|
||||||
|
// setup_lora();
|
||||||
|
|
||||||
|
// uint8_t bufIn[256];
|
||||||
|
|
||||||
|
// while (1)
|
||||||
|
// {
|
||||||
|
// start_time = esp_timer_get_time();
|
||||||
|
|
||||||
|
// if (packetReadiness)
|
||||||
|
// {
|
||||||
|
// ESP_LOGI(TAG, "Preparing telemetry");
|
||||||
|
// prepare_and_send_telemetry(start_time);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uint8_t rxLen = LoRaReceive(bufIn, sizeof(bufIn));
|
||||||
|
// if (rxLen > 0)
|
||||||
|
// {
|
||||||
|
// ESP_LOGI(TAG, "%d byte packet received", rxLen);
|
||||||
|
// process_uplink_packet(bufIn, rxLen, start_time);
|
||||||
|
|
||||||
|
// int8_t rssi, snr;
|
||||||
|
// GetPacketStatus(&rssi, &snr);
|
||||||
|
// ESP_LOGI(TAG, "rssi=%d[dBm], snr=%d[dB]", rssi, snr);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int lost = GetPacketLost();
|
||||||
|
// if (lost != 0)
|
||||||
|
// {
|
||||||
|
// ESP_LOGW(TAG, "%d packets lost", lost);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// end_time = esp_timer_get_time();
|
||||||
|
// elapsed = end_time - start_time;
|
||||||
|
|
||||||
|
// if (elapsed < interval_us)
|
||||||
|
// {
|
||||||
|
// vTaskDelay(pdMS_TO_TICKS((interval_us - elapsed) / 1000));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@@ -12,8 +12,10 @@
|
|||||||
#include "packets.h"
|
#include "packets.h"
|
||||||
|
|
||||||
void lora_comms_task(void *pvParameters);
|
void lora_comms_task(void *pvParameters);
|
||||||
|
void lora_receive_task(void *pvParameters);
|
||||||
|
|
||||||
extern TelemetryPacket telemetryPacket;
|
extern TelemetryPacket telemetryPacket;
|
||||||
extern uint8_t packetReadiness;
|
extern uint8_t packetReadiness;
|
||||||
|
extern SemaphoreHandle_t loraRadioMutex;
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -122,7 +122,6 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
// task loop entry point
|
// task loop entry point
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
packetReadiness = 2;
|
|
||||||
start_time = esp_timer_get_time(); // µs since boot
|
start_time = esp_timer_get_time(); // µs since boot
|
||||||
//
|
//
|
||||||
// handle sensor
|
// handle sensor
|
||||||
@@ -174,15 +173,15 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
|
|
||||||
float VREFVoltage = 2.5;
|
float VREFVoltage = 2.5;
|
||||||
|
|
||||||
mics_adc_data_t ADCData;
|
// mics_adc_data_t ADCData;
|
||||||
memset(&ADCData, 0, sizeof(ADCData));
|
// memset(&ADCData, 0, sizeof(ADCData));
|
||||||
//mics_adc_data_t ADCData = mcp3550_read_all(VREFVoltage);
|
mics_adc_data_t ADCData = mcp3550_read_all(VREFVoltage);
|
||||||
|
|
||||||
//log_mics_adc_values(&ADCData);
|
log_mics_adc_values(&ADCData);
|
||||||
|
|
||||||
int32_t nh3val = mcp3550_read(MCP_CS_ADC_NH3);
|
//int32_t nh3val = mcp3550_read(MCP_CS_ADC_NH3);
|
||||||
|
|
||||||
ESP_LOGI(TAG_BME, "MICS NH3: %ld -> %fV", nh3val, mcp3550_to_voltage(nh3val, VREFVoltage));
|
//ESP_LOGI(TAG_BME, "MICS NH3: %ld -> %fV", nh3val, mcp3550_to_voltage(nh3val, VREFVoltage));
|
||||||
|
|
||||||
//gpio_set_level(BLINK_GPIO, s_led_state);
|
//gpio_set_level(BLINK_GPIO, s_led_state);
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_UVC, s_led_state);
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_UVC, s_led_state);
|
||||||
@@ -229,6 +228,15 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
telemetryPacket.heater_stable = bmeData.raw_data.heater_stable;
|
telemetryPacket.heater_stable = bmeData.raw_data.heater_stable;
|
||||||
telemetryPacket.gas_valid = bmeData.raw_data.gas_valid;
|
telemetryPacket.gas_valid = bmeData.raw_data.gas_valid;
|
||||||
|
|
||||||
|
telemetryPacket.air_temperature = bmeData.air_temperature;
|
||||||
|
telemetryPacket.relative_humidity = bmeData.relative_humidity;
|
||||||
|
telemetryPacket.barometric_pressure = bmeData.barometric_pressure;
|
||||||
|
telemetryPacket.gas_resistance = bmeData.gas_resistance;
|
||||||
|
telemetryPacket.iaq_score = bmeData.iaq_score;
|
||||||
|
telemetryPacket.temperature_score = bmeData.temperature_score;
|
||||||
|
telemetryPacket.humidity_score = bmeData.humidity_score;
|
||||||
|
telemetryPacket.gas_score = bmeData.gas_score;
|
||||||
|
|
||||||
telemetryPacket.NH3 = ADCData.raw_nh3;
|
telemetryPacket.NH3 = ADCData.raw_nh3;
|
||||||
telemetryPacket.CO = ADCData.raw_co;
|
telemetryPacket.CO = ADCData.raw_co;
|
||||||
telemetryPacket.NO2 = ADCData.raw_no2;
|
telemetryPacket.NO2 = ADCData.raw_no2;
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
#include "ccs811.h"
|
#include "ccs811.h"
|
||||||
|
|
||||||
#define CONFIG_FREERTOS_HZ 100
|
|
||||||
|
|
||||||
i2c_device_config_t CCS811_DEV_CFG = {
|
i2c_device_config_t CCS811_DEV_CFG = {
|
||||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||||
.device_address = CCS811_ADDRESS,
|
.device_address = CCS811_ADDRESS,
|
||||||
|
@@ -81,9 +81,7 @@ void ina260_printParams(uint16_t volt, uint16_t cur, uint16_t pow)
|
|||||||
float miliVolts = volt * 1.25;
|
float miliVolts = volt * 1.25;
|
||||||
float miliAmps = cur * 1.25;
|
float miliAmps = cur * 1.25;
|
||||||
float power = pow * 10;
|
float power = pow * 10;
|
||||||
cur *= 125;
|
ESP_LOGI(TAG_INA, "Current: %.3f mA (raw %d)", miliAmps, cur);
|
||||||
ESP_LOGI(TAG_INA, "Current: %.3f mA (raw %d)", miliAmps, volt);
|
ESP_LOGI(TAG_INA, "Voltage: %.3f mV (raw %d)", miliVolts, volt);
|
||||||
cur *= 125;
|
|
||||||
ESP_LOGI(TAG_INA, "Voltage: %.3f mV (raw %d)", miliVolts, cur);
|
|
||||||
ESP_LOGI(TAG_INA, "Power: %.3f mW (raw %d)", power, pow);
|
ESP_LOGI(TAG_INA, "Power: %.3f mW (raw %d)", power, pow);
|
||||||
}
|
}
|
@@ -84,41 +84,81 @@ void mcp3550_spi_init()
|
|||||||
// return value;
|
// return value;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// int32_t mcp3550_read(uint8_t cs_pin)
|
||||||
|
// {
|
||||||
|
// uint8_t rx_buf[4] = {0};
|
||||||
|
// uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000;
|
||||||
|
// int64_t start = esp_timer_get_time();
|
||||||
|
|
||||||
|
// // Start conversion
|
||||||
|
// mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0); // CS LOW
|
||||||
|
|
||||||
|
// // Wait until MISO/SDO goes LOW = DR ready
|
||||||
|
// while (gpio_get_level(MCP3550_MISO_GPIO)) {
|
||||||
|
// if ((esp_timer_get_time() - start) > timeout_us) {
|
||||||
|
// ESP_LOGW(TAG_MICS, "Timeout waiting for MISO=0 on CS %u", cs_pin);
|
||||||
|
// mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH
|
||||||
|
// return INT32_MIN;
|
||||||
|
// }
|
||||||
|
// esp_rom_delay_us(10); // micro delay
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Data is ready, do full SPI read
|
||||||
|
// spi_transaction_t trans = {
|
||||||
|
// .length = 25, // 25 bits
|
||||||
|
// .rx_buffer = rx_buf,
|
||||||
|
// };
|
||||||
|
// esp_err_t err = spi_device_transmit(mcp3550_handle, &trans);
|
||||||
|
|
||||||
|
// mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH to start next conversion
|
||||||
|
|
||||||
|
// if (err != ESP_OK) {
|
||||||
|
// ESP_LOGE(TAG_MICS, "SPI transmit failed");
|
||||||
|
// return INT32_MIN;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Extract 22-bit result
|
||||||
|
// uint32_t raw = ((rx_buf[0] & 0x3F) << 16) | (rx_buf[1] << 8) | rx_buf[2];
|
||||||
|
|
||||||
|
// // Sign-extend 22-bit value
|
||||||
|
// int32_t value = raw;
|
||||||
|
// if (value & (1 << 21)) value |= 0xFFC00000;
|
||||||
|
|
||||||
|
// return value;
|
||||||
|
// }
|
||||||
|
|
||||||
int32_t mcp3550_read(uint8_t cs_pin)
|
int32_t mcp3550_read(uint8_t cs_pin)
|
||||||
{
|
{
|
||||||
uint8_t rx_buf[4] = {0};
|
uint32_t data = 0;
|
||||||
uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000;
|
|
||||||
int64_t start = esp_timer_get_time();
|
int64_t start = esp_timer_get_time();
|
||||||
|
uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000;
|
||||||
|
|
||||||
// Start conversion
|
// CS LOW
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0); // CS LOW
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0);
|
||||||
|
|
||||||
// Wait until MISO/SDO goes LOW = DR ready
|
// Wait for DR (MISO LOW)
|
||||||
while (gpio_get_level(MCP3550_MISO_GPIO)) {
|
while (gpio_get_level(MCP3550_MISO_GPIO)) {
|
||||||
if ((esp_timer_get_time() - start) > timeout_us) {
|
if ((esp_timer_get_time() - start) > timeout_us) {
|
||||||
ESP_LOGW(TAG_MICS, "Timeout waiting for MISO=0 on CS %u", cs_pin);
|
ESP_LOGW(TAG_MICS, "Timeout waiting for MISO=0 on CS %u", cs_pin);
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH
|
||||||
return INT32_MIN;
|
return INT32_MIN;
|
||||||
}
|
}
|
||||||
esp_rom_delay_us(10); // micro delay
|
vTaskDelay(pdMS_TO_TICKS(10)); // Wait 1 tick (e.g., 1ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data is ready, do full SPI read
|
// Clock out 25 bits
|
||||||
spi_transaction_t trans = {
|
for (int i = 0; i < 25; i++) {
|
||||||
.length = 25, // 25 bits
|
gpio_set_level(MCP3550_SCK_GPIO, 1);
|
||||||
.rx_buffer = rx_buf,
|
esp_rom_delay_us(5); // small delay to simulate clock high
|
||||||
};
|
data = (data << 1) | gpio_get_level(MCP3550_MISO_GPIO);
|
||||||
esp_err_t err = spi_device_transmit(mcp3550_handle, &trans);
|
gpio_set_level(MCP3550_SCK_GPIO, 0);
|
||||||
|
esp_rom_delay_us(5); // small delay to simulate clock low
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH to start next conversion
|
|
||||||
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG_MICS, "SPI transmit failed");
|
|
||||||
return INT32_MIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract 22-bit result
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH
|
||||||
uint32_t raw = ((rx_buf[0] & 0x3F) << 16) | (rx_buf[1] << 8) | rx_buf[2];
|
|
||||||
|
// Extract 22-bit value (bits [23:2])
|
||||||
|
uint32_t raw = (data >> 2) & 0x3FFFFF;
|
||||||
|
|
||||||
// Sign-extend 22-bit value
|
// Sign-extend 22-bit value
|
||||||
int32_t value = raw;
|
int32_t value = raw;
|
||||||
|
@@ -7,8 +7,6 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "buscfg.h"
|
#include "buscfg.h"
|
||||||
|
|
||||||
#define CONFIG_FREERTOS_HZ 100
|
|
||||||
|
|
||||||
#define MCP3550_SPS 3.75f
|
#define MCP3550_SPS 3.75f
|
||||||
#define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms
|
#define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms
|
||||||
|
|
||||||
|
@@ -262,6 +262,8 @@ void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate,
|
|||||||
SX126X_IRQ_NONE //interrupts on DIO3
|
SX126X_IRQ_NONE //interrupts on DIO3
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Almost done setting LoRa");
|
||||||
// Receive state no receive timeoout
|
// Receive state no receive timeoout
|
||||||
SetRx(0xFFFFFF);
|
SetRx(0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
@@ -30,11 +30,11 @@
|
|||||||
|
|
||||||
#define TAG "cantest"
|
#define TAG "cantest"
|
||||||
|
|
||||||
#define CONFIG_FREERTOS_HZ 100
|
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
ESP_LOGI("BOOT", "BRN Systems incorporated CanSat flight firmware build at %s %s", __DATE__, __TIME__);
|
||||||
|
|
||||||
/* instantiate i2c master bus 0 */
|
/* instantiate i2c master bus 0 */
|
||||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));
|
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user