From 3457b76938926e956d938d78d9b6856e9b60d112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Ryb=C3=A1rsky?= Date: Sun, 27 Apr 2025 01:43:55 +0200 Subject: [PATCH] get mostly one directional comms working --- .vscode/settings.json | 2 +- dependencies.lock | 2 +- main/components/packets.h | 33 ++++ main/components/radio.c | 340 +++++++++++++++++++++++++++++++------- main/components/radio.h | 2 + main/components/sensors.c | 24 ++- main/hw/ccs811.c | 2 - main/hw/ina260.c | 6 +- main/hw/mcp3550.c | 80 ++++++--- main/hw/mcp3550.h | 2 - main/hw/sx1262.c | 2 + main/main.c | 4 +- 12 files changed, 402 insertions(+), 97 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c1a9e7a..34e25be 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "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.openOcdConfigs": [ "board/esp32s3-builtin.cfg" diff --git a/dependencies.lock b/dependencies.lock index 20bbb23..2a59adb 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -2,7 +2,7 @@ dependencies: idf: source: type: idf - version: 5.4.1 + version: 5.5.0 k0i05/esp_bme680: component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8 dependencies: diff --git a/main/components/packets.h b/main/components/packets.h index 7448f63..f027309 100644 --- a/main/components/packets.h +++ b/main/components/packets.h @@ -2,8 +2,20 @@ #define PACKETS_STRUCTS #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)) { + char syncPhrase[10]; uint32_t packetIndex; uint8_t packetType; uint32_t missionTimer; @@ -44,6 +56,15 @@ typedef struct __attribute__((packed)) uint8_t gas_range; 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 uint32_t time_seconds; // Seconds since start of day int32_t latitude_centi_degrees; // Latitude * 10,000 @@ -73,6 +94,7 @@ typedef struct __attribute__((packed)) typedef struct __attribute__((packed)) { + char syncPhrase[10]; uint32_t packetIndex; uint8_t packetType; } UplinkPacket; @@ -85,4 +107,15 @@ typedef struct __attribute__((packed)) uint16_t servoB; } SystemControlPacket; +typedef struct __attribute__((packed)) +{ + uint8_t PingData[20]; +} PingPacket; + +typedef struct __attribute__((packed)) +{ + uint32_t packetIndex; + uint32_t crc32Checksum; +} ACKPacket; + #endif \ No newline at end of file diff --git a/main/components/radio.c b/main/components/radio.c index 2d8b613..b32816e 100644 --- a/main/components/radio.c +++ b/main/components/radio.c @@ -5,104 +5,330 @@ #include "esp_log.h" #include "string.h" #include "esp_timer.h" - -const char *msg = "Testing 123 test why is this not on air"; +#include "esp_rom_crc.h" #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; 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(); + 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"); - float tcxoVoltage = 2.2; // use TCXO - bool useRegulatorLDO = true; // use DCDC + LDO + LoRaDebugPrint(false); - // LoRaDebugPrint(true); 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) { vTaskDelay(1); } } - uint8_t spreadingFactor = 7; + uint8_t spreadingFactor = 6; uint8_t bandwidth = SX126X_LORA_BW_250_0; uint8_t codingRate = SX126X_LORA_CR_4_8; uint16_t preambleLength = 8; - uint8_t payloadLen = 0; bool crcOn = true; 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; - UplinkPacket uplinkPacket; - SystemControlPacket systemControlPacket; + LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn, invertIrq); +} - 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 (packetReadiness == 1) + if (xSemaphoreTake(loraRadioMutex, portMAX_DELAY) == pdTRUE) { - uint8_t downPacketSize = 0; - 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) + if (!LoRaSend(data, size, SX126x_TXMODE_SYNC)) { - ESP_LOGE(pcTaskGetName(NULL), "LoRaSend fail"); - } else { - packetReadiness = 0; + ESP_LOGW(TAG, "LoRaSend failed, retry %d", retry); + xSemaphoreGive(loraRadioMutex); + } + 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)); - if (rxLen > 0) + ESP_LOGE(TAG, "Failed to send packet after %d retries", MAX_RETRIES); +} + +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; - GetPacketStatus(&rssi, &snr); - ESP_LOGI(pcTaskGetName(NULL), "rssi=%d[dBm] snr=%d[dB]", rssi, snr); +void process_uplink_packet(uint8_t *data, uint8_t len, uint64_t missionTimer) +{ + 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(); - if (lost != 0) - { - ESP_LOGW(pcTaskGetName(NULL), "%d packets lost", lost); - } - - end_time = esp_timer_get_time(); - elapsed = end_time - start_time; + int64_t end_time = esp_timer_get_time(); + int64_t elapsed = end_time - start_time; if (elapsed < interval_us) { vTaskDelay(pdMS_TO_TICKS((interval_us - elapsed) / 1000)); } } -} \ No newline at end of file +} + +// 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)); +// } +// } +// } diff --git a/main/components/radio.h b/main/components/radio.h index f7b9bcb..7c62101 100644 --- a/main/components/radio.h +++ b/main/components/radio.h @@ -12,8 +12,10 @@ #include "packets.h" void lora_comms_task(void *pvParameters); +void lora_receive_task(void *pvParameters); extern TelemetryPacket telemetryPacket; extern uint8_t packetReadiness; +extern SemaphoreHandle_t loraRadioMutex; #endif \ No newline at end of file diff --git a/main/components/sensors.c b/main/components/sensors.c index 6d5baa2..26aac80 100644 --- a/main/components/sensors.c +++ b/main/components/sensors.c @@ -122,7 +122,6 @@ void i2c_sensors_task(void *pvParameters) // task loop entry point for (;;) { - packetReadiness = 2; start_time = esp_timer_get_time(); // µs since boot // // handle sensor @@ -174,15 +173,15 @@ void i2c_sensors_task(void *pvParameters) float VREFVoltage = 2.5; - mics_adc_data_t ADCData; - memset(&ADCData, 0, sizeof(ADCData)); - //mics_adc_data_t ADCData = mcp3550_read_all(VREFVoltage); + // mics_adc_data_t ADCData; + // memset(&ADCData, 0, sizeof(ADCData)); + 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); mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_UVC, s_led_state); @@ -228,7 +227,16 @@ void i2c_sensors_task(void *pvParameters) telemetryPacket.gas_range = bmeData.raw_data.gas_range; telemetryPacket.heater_stable = bmeData.raw_data.heater_stable; 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.CO = ADCData.raw_co; telemetryPacket.NO2 = ADCData.raw_no2; diff --git a/main/hw/ccs811.c b/main/hw/ccs811.c index 64c15a4..37d4437 100644 --- a/main/hw/ccs811.c +++ b/main/hw/ccs811.c @@ -1,7 +1,5 @@ #include "ccs811.h" -#define CONFIG_FREERTOS_HZ 100 - i2c_device_config_t CCS811_DEV_CFG = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = CCS811_ADDRESS, diff --git a/main/hw/ina260.c b/main/hw/ina260.c index 3885861..e8a69e9 100644 --- a/main/hw/ina260.c +++ b/main/hw/ina260.c @@ -81,9 +81,7 @@ void ina260_printParams(uint16_t volt, uint16_t cur, uint16_t pow) float miliVolts = volt * 1.25; float miliAmps = cur * 1.25; float power = pow * 10; - cur *= 125; - ESP_LOGI(TAG_INA, "Current: %.3f mA (raw %d)", miliAmps, volt); - cur *= 125; - ESP_LOGI(TAG_INA, "Voltage: %.3f mV (raw %d)", miliVolts, cur); + ESP_LOGI(TAG_INA, "Current: %.3f mA (raw %d)", miliAmps, cur); + ESP_LOGI(TAG_INA, "Voltage: %.3f mV (raw %d)", miliVolts, volt); ESP_LOGI(TAG_INA, "Power: %.3f mW (raw %d)", power, pow); } \ No newline at end of file diff --git a/main/hw/mcp3550.c b/main/hw/mcp3550.c index 91d20c3..bde1976 100644 --- a/main/hw/mcp3550.c +++ b/main/hw/mcp3550.c @@ -84,41 +84,81 @@ void mcp3550_spi_init() // 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) { - uint8_t rx_buf[4] = {0}; - uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000; + uint32_t data = 0; int64_t start = esp_timer_get_time(); + uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000; - // Start conversion - mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0); // CS LOW + // 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)) { 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 + vTaskDelay(pdMS_TO_TICKS(10)); // Wait 1 tick (e.g., 1ms) } - // 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; + // Clock out 25 bits + for (int i = 0; i < 25; i++) { + gpio_set_level(MCP3550_SCK_GPIO, 1); + esp_rom_delay_us(5); // small delay to simulate clock high + data = (data << 1) | gpio_get_level(MCP3550_MISO_GPIO); + gpio_set_level(MCP3550_SCK_GPIO, 0); + esp_rom_delay_us(5); // small delay to simulate clock low } - // Extract 22-bit result - uint32_t raw = ((rx_buf[0] & 0x3F) << 16) | (rx_buf[1] << 8) | rx_buf[2]; + mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 1); // CS HIGH + + // Extract 22-bit value (bits [23:2]) + uint32_t raw = (data >> 2) & 0x3FFFFF; // Sign-extend 22-bit value int32_t value = raw; diff --git a/main/hw/mcp3550.h b/main/hw/mcp3550.h index 7e8733f..db13947 100644 --- a/main/hw/mcp3550.h +++ b/main/hw/mcp3550.h @@ -7,8 +7,6 @@ #include "esp_log.h" #include "buscfg.h" -#define CONFIG_FREERTOS_HZ 100 - #define MCP3550_SPS 3.75f #define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms diff --git a/main/hw/sx1262.c b/main/hw/sx1262.c index 911a4d8..562bc43 100644 --- a/main/hw/sx1262.c +++ b/main/hw/sx1262.c @@ -262,6 +262,8 @@ void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, SX126X_IRQ_NONE //interrupts on DIO3 ); + + ESP_LOGI(TAG, "Almost done setting LoRa"); // Receive state no receive timeoout SetRx(0xFFFFFF); } diff --git a/main/main.c b/main/main.c index e4e8458..d973d63 100644 --- a/main/main.c +++ b/main/main.c @@ -30,11 +30,11 @@ #define TAG "cantest" -#define CONFIG_FREERTOS_HZ 100 - void app_main(void) { + ESP_LOGI("BOOT", "BRN Systems incorporated CanSat flight firmware build at %s %s", __DATE__, __TIME__); + /* instantiate i2c master bus 0 */ ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));