Compare commits
7 Commits
3457b76938
...
main
Author | SHA1 | Date | |
---|---|---|---|
22d9f1f32a | |||
ee54abb663
|
|||
76eb216716
|
|||
c26e5e012c | |||
5ea05fa209 | |||
8b9e72ef71
|
|||
0c71409c30
|
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/master/esp-idf",
|
"idf.espIdfPath": "/home/bruno/esp/v5.4.1/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.5.0
|
version: 5.4.1
|
||||||
k0i05/esp_bme680:
|
k0i05/esp_bme680:
|
||||||
component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8
|
component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@@ -25,6 +25,8 @@ idf_component_register(SRCS
|
|||||||
"components/servocontroller.h"
|
"components/servocontroller.h"
|
||||||
"components/radio.c"
|
"components/radio.c"
|
||||||
"components/radio.h"
|
"components/radio.h"
|
||||||
|
"components/sdcard.c"
|
||||||
|
"components/sdcard.h"
|
||||||
"main.c"
|
"main.c"
|
||||||
|
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
@@ -15,80 +15,85 @@
|
|||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
{
|
{
|
||||||
char syncPhrase[10];
|
char syncPhrase[10]; //10
|
||||||
uint32_t packetIndex;
|
uint32_t packetIndex; //14
|
||||||
uint8_t packetType;
|
uint8_t packetType; //15
|
||||||
uint32_t missionTimer;
|
uint32_t missionTimer; //19
|
||||||
|
uint32_t CRCCheck;
|
||||||
} DownBoundPacket;
|
} DownBoundPacket;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
{
|
{
|
||||||
// MPU data
|
// MPU data
|
||||||
int16_t accelerationX;
|
int16_t accelerationX;//21
|
||||||
int16_t accelerationY;
|
int16_t accelerationY; //23
|
||||||
int16_t accelerationZ;
|
int16_t accelerationZ;//25
|
||||||
int16_t gyroX;
|
int16_t gyroX;//27
|
||||||
int16_t gyroY;
|
int16_t gyroY;//29
|
||||||
int16_t gyroZ;
|
int16_t gyroZ;//31
|
||||||
int16_t magnetX;
|
int16_t magnetX;//33
|
||||||
int16_t magnetY;
|
int16_t magnetY;//35
|
||||||
int16_t magnetZ;
|
int16_t magnetZ;//37
|
||||||
int16_t accelerometer_temperature;
|
int16_t accelerometer_temperature;//39
|
||||||
|
|
||||||
// CCS data
|
// CCS data
|
||||||
uint16_t eCO2;
|
uint16_t eCO2;//41
|
||||||
uint16_t tvoc;
|
uint16_t tvoc;//43
|
||||||
uint8_t currentCCS;
|
uint8_t currentCCS;//44
|
||||||
uint16_t rawCCSData;
|
uint16_t rawCCSData;//46
|
||||||
|
|
||||||
// INA data
|
// INA data
|
||||||
uint16_t volts;
|
uint16_t volts;//48
|
||||||
uint16_t current;
|
uint16_t current;//50
|
||||||
uint16_t power;
|
uint16_t power;//52
|
||||||
|
|
||||||
// BME DATA
|
// BME DATA
|
||||||
uint32_t temperature;
|
uint32_t temperature;//56
|
||||||
uint16_t humidity;
|
uint16_t humidity;//58
|
||||||
uint32_t pressure;
|
uint32_t pressure;//62
|
||||||
uint16_t gas;
|
uint16_t gas;//64
|
||||||
bool gas_valid;
|
bool gas_valid;//later
|
||||||
bool heater_stable;
|
bool heater_stable;//later
|
||||||
uint8_t gas_range;
|
uint8_t gas_range;//65
|
||||||
uint8_t gas_index;
|
uint8_t gas_index;//66
|
||||||
|
|
||||||
float air_temperature; /*!< air temperature in degrees celsius */
|
float air_temperature; /*!< air temperature in degrees celsius */ //70
|
||||||
float relative_humidity; /*!< relative humidity in percent */
|
float relative_humidity; /*!< relative humidity in percent */ //74
|
||||||
float barometric_pressure; /*!< barometric pressure in hecto-pascal */
|
float barometric_pressure; /*!< barometric pressure in hecto-pascal */ //78
|
||||||
float gas_resistance; /*!< gas resistance in ohms */
|
float gas_resistance; /*!< gas resistance in ohms */ //82
|
||||||
uint16_t iaq_score; /*!< air quality index (0..500) */
|
uint16_t iaq_score; /*!< air quality index (0..500) */ //84
|
||||||
float temperature_score;
|
float temperature_score; //88
|
||||||
float humidity_score;
|
float humidity_score; //92
|
||||||
float gas_score;
|
float gas_score; //96
|
||||||
|
|
||||||
// GPS DATA
|
// GPS DATA
|
||||||
uint32_t time_seconds; // Seconds since start of day
|
uint32_t time_seconds; // Seconds since start of day //100
|
||||||
int32_t latitude_centi_degrees; // Latitude * 10,000
|
int32_t latitude_centi_degrees; // Latitude * 10,000 //104
|
||||||
int32_t longitude_centi_degrees; // Longitude * 10,000
|
int32_t longitude_centi_degrees; // Longitude * 10,000 //108
|
||||||
int16_t altitude_centi_meters; // Altitude * 100
|
int16_t altitude_centi_meters; // Altitude * 100 //110
|
||||||
uint8_t fix_quality;
|
uint8_t fix_quality; //111
|
||||||
uint8_t num_satellites;
|
uint8_t num_satellites; //112
|
||||||
uint16_t date_yyddmm; // YYDDMM (from GPRMC)
|
uint16_t date_yyddmm; // YYDDMM (from GPRMC) //114
|
||||||
uint16_t speed_centi_knots; // Speed * 100 (from GPRMC)
|
uint16_t speed_centi_knots; // Speed * 100 (from GPRMC) //116
|
||||||
|
|
||||||
int32_t predicted_latitude_centi_degrees; // Latitude * 10,000
|
int32_t predicted_latitude_centi_degrees; // Latitude * 10,000 //120
|
||||||
int32_t predicted_longitude_centi_degrees; // Longitude * 10,000
|
int32_t predicted_longitude_centi_degrees; // Longitude * 10,000 //124
|
||||||
int16_t predicted_altitude_centi_meters; // Altitude * 100
|
int16_t predicted_altitude_centi_meters; // Altitude * 100 //126
|
||||||
|
|
||||||
// ADC DATA
|
// ADC DATA
|
||||||
int32_t NH3;
|
int32_t NH3; //130
|
||||||
int32_t CO;
|
int32_t CO; //134
|
||||||
int32_t NO2;
|
int32_t NO2; //138
|
||||||
int32_t UVC;
|
int32_t UVC; //142
|
||||||
|
|
||||||
int16_t currentServoA;
|
int16_t currentServoA; //144
|
||||||
int16_t targetServoA;
|
int16_t targetServoA; //146
|
||||||
int16_t currentServoB;
|
int16_t currentServoB; //148
|
||||||
int16_t targetServoB;
|
int16_t targetServoB; //150
|
||||||
|
|
||||||
|
uint8_t presentDevices;
|
||||||
|
|
||||||
|
uint8_t telemetryIndex; //151
|
||||||
|
|
||||||
} TelemetryPacket;
|
} TelemetryPacket;
|
||||||
|
|
||||||
@@ -97,6 +102,7 @@ typedef struct __attribute__((packed))
|
|||||||
char syncPhrase[10];
|
char syncPhrase[10];
|
||||||
uint32_t packetIndex;
|
uint32_t packetIndex;
|
||||||
uint8_t packetType;
|
uint8_t packetType;
|
||||||
|
uint32_t CRCCheck;
|
||||||
} UplinkPacket;
|
} UplinkPacket;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
|
@@ -6,11 +6,14 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_rom_crc.h"
|
#include "esp_rom_crc.h"
|
||||||
|
#include <hw/buscfg.h>
|
||||||
|
#include "sensors.h"
|
||||||
|
#include "sdcard.h"
|
||||||
|
|
||||||
#define TAG "LoRa"
|
#define TAG "LoRa"
|
||||||
|
|
||||||
#define ACK_TIMEOUT_MS 500 // Wait 300ms for ACK
|
#define ACK_TIMEOUT_MS 250 // Wait 300ms for ACK
|
||||||
#define MAX_RETRIES 3
|
#define MAX_RETRIES 1
|
||||||
|
|
||||||
uint32_t packetIndexTX = 0;
|
uint32_t packetIndexTX = 0;
|
||||||
uint32_t packetIndexRX = 0;
|
uint32_t packetIndexRX = 0;
|
||||||
@@ -44,31 +47,52 @@ void setup_lora(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t spreadingFactor = 6;
|
uint8_t spreadingFactor = 8;
|
||||||
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 = 4;
|
||||||
bool crcOn = true;
|
bool crcOn = true;
|
||||||
bool invertIrq = false;
|
bool invertIrq = false;
|
||||||
|
|
||||||
LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn, invertIrq);
|
LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn, invertIrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_downbound_packet(DownBoundPacket *packet, uint8_t type, uint64_t missionTimer)
|
static void prepare_downbound_packet(DownBoundPacket *packet, uint8_t type, uint64_t missionTimer, uint32_t crc)
|
||||||
{
|
{
|
||||||
memset(packet, 0, sizeof(DownBoundPacket));
|
memset(packet, 0, sizeof(DownBoundPacket));
|
||||||
packet->missionTimer = missionTimer;
|
packet->missionTimer = missionTimer;
|
||||||
packet->packetIndex = packetIndexTX++;
|
packet->packetIndex = packetIndexTX++;
|
||||||
ESP_LOGI(TAG_RADIO, "Sending downbound packet with index %ld", packetIndexTX - 1);
|
ESP_LOGI(TAG_RADIO, "Sending downbound packet with index %ld", packetIndexTX - 1);
|
||||||
packet->packetType = type;
|
packet->packetType = type;
|
||||||
|
packet->CRCCheck = crc;
|
||||||
strcpy(packet->syncPhrase, "PlechDole");
|
strcpy(packet->syncPhrase, "PlechDole");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_packet_without_retries(uint8_t *data, uint16_t size)
|
||||||
|
{
|
||||||
|
if (xSemaphoreTake(loraRadioMutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
writeFile(sensFile, data, size);
|
||||||
|
|
||||||
|
if (!LoRaSend(data, size, SX126x_TXMODE_SYNC))
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "LoRaSend failed");
|
||||||
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "%d byte packet sent", size);
|
||||||
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void send_packet_with_retries(uint8_t *data, uint16_t size)
|
static void send_packet_with_retries(uint8_t *data, uint16_t size)
|
||||||
{
|
|
||||||
for (int retry = 0; retry <= MAX_RETRIES; retry++)
|
|
||||||
{
|
{
|
||||||
if (xSemaphoreTake(loraRadioMutex, portMAX_DELAY) == pdTRUE)
|
if (xSemaphoreTake(loraRadioMutex, portMAX_DELAY) == pdTRUE)
|
||||||
|
{
|
||||||
|
writeFile(sensFile, data, size);
|
||||||
|
for (int retry = 0; retry <= MAX_RETRIES; retry++)
|
||||||
{
|
{
|
||||||
if (!LoRaSend(data, size, SX126x_TXMODE_SYNC))
|
if (!LoRaSend(data, size, SX126x_TXMODE_SYNC))
|
||||||
{
|
{
|
||||||
@@ -106,7 +130,8 @@ void prepare_and_send_telemetry(uint64_t missionTimer)
|
|||||||
uint8_t bufOut[256] = {0};
|
uint8_t bufOut[256] = {0};
|
||||||
|
|
||||||
DownBoundPacket downboundPacket;
|
DownBoundPacket downboundPacket;
|
||||||
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_Telemetry, missionTimer);
|
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)&telemetryPacket, sizeof(telemetryPacket));
|
||||||
|
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_Telemetry, missionTimer, crc);
|
||||||
|
|
||||||
uint16_t offset = 0;
|
uint16_t offset = 0;
|
||||||
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
||||||
@@ -114,7 +139,71 @@ void prepare_and_send_telemetry(uint64_t missionTimer)
|
|||||||
memcpy(bufOut + offset, &telemetryPacket, sizeof(telemetryPacket));
|
memcpy(bufOut + offset, &telemetryPacket, sizeof(telemetryPacket));
|
||||||
offset += sizeof(telemetryPacket);
|
offset += sizeof(telemetryPacket);
|
||||||
|
|
||||||
send_packet_with_retries(bufOut, offset);
|
if (csvFile != NULL) {
|
||||||
|
fprintf(csvFile,
|
||||||
|
"%llu,%lu,%u,%u," // missionTimer, packetIndex, telemetryIndex, packetType
|
||||||
|
"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d," // MPU
|
||||||
|
"%u,%u,%d,%u," // CCS
|
||||||
|
"%u,%u,%u,%lu,%u,%lu,%u," // INA, BME basic
|
||||||
|
"%s,%s,%u,%u," // bools and gas index/range
|
||||||
|
"%.2f,%.2f,%.2f,%.2f," // Bosch env data
|
||||||
|
"%u,%.2f,%.2f,%.2f," // IAQ + scores
|
||||||
|
"%lu,%ld,%ld,%d,%u,%u,%u,%u," // GPS data
|
||||||
|
"%ld,%ld,%d," // Predicted GPS
|
||||||
|
"%ld,%ld,%ld,%ld," // ADC
|
||||||
|
"%d,%d,%d,%d," // Servo
|
||||||
|
"%u\n", // presentDevices
|
||||||
|
|
||||||
|
missionTimer,
|
||||||
|
downboundPacket.packetIndex,
|
||||||
|
telemetryPacket.telemetryIndex,
|
||||||
|
downboundPacket.packetType,
|
||||||
|
|
||||||
|
telemetryPacket.accelerationX, telemetryPacket.accelerationY, telemetryPacket.accelerationZ,
|
||||||
|
telemetryPacket.gyroX, telemetryPacket.gyroY, telemetryPacket.gyroZ,
|
||||||
|
telemetryPacket.magnetX, telemetryPacket.magnetY, telemetryPacket.magnetZ,
|
||||||
|
telemetryPacket.accelerometer_temperature,
|
||||||
|
|
||||||
|
telemetryPacket.eCO2, telemetryPacket.tvoc, telemetryPacket.currentCCS, telemetryPacket.rawCCSData,
|
||||||
|
|
||||||
|
telemetryPacket.volts, telemetryPacket.current, telemetryPacket.power,
|
||||||
|
telemetryPacket.temperature, telemetryPacket.humidity, telemetryPacket.pressure, telemetryPacket.gas,
|
||||||
|
|
||||||
|
telemetryPacket.gas_valid ? "Yes" : "No",
|
||||||
|
telemetryPacket.heater_stable ? "Yes" : "No",
|
||||||
|
telemetryPacket.gas_range, telemetryPacket.gas_index,
|
||||||
|
|
||||||
|
telemetryPacket.air_temperature, telemetryPacket.relative_humidity,
|
||||||
|
telemetryPacket.barometric_pressure, telemetryPacket.gas_resistance,
|
||||||
|
|
||||||
|
telemetryPacket.iaq_score,
|
||||||
|
telemetryPacket.temperature_score, telemetryPacket.humidity_score, telemetryPacket.gas_score,
|
||||||
|
|
||||||
|
telemetryPacket.time_seconds,
|
||||||
|
telemetryPacket.latitude_centi_degrees,
|
||||||
|
telemetryPacket.longitude_centi_degrees,
|
||||||
|
telemetryPacket.altitude_centi_meters,
|
||||||
|
telemetryPacket.fix_quality,
|
||||||
|
telemetryPacket.num_satellites,
|
||||||
|
telemetryPacket.date_yyddmm,
|
||||||
|
telemetryPacket.speed_centi_knots,
|
||||||
|
|
||||||
|
telemetryPacket.predicted_latitude_centi_degrees,
|
||||||
|
telemetryPacket.predicted_longitude_centi_degrees,
|
||||||
|
telemetryPacket.predicted_altitude_centi_meters,
|
||||||
|
|
||||||
|
telemetryPacket.NH3, telemetryPacket.CO, telemetryPacket.NO2, telemetryPacket.UVC,
|
||||||
|
|
||||||
|
telemetryPacket.currentServoA, telemetryPacket.targetServoA,
|
||||||
|
telemetryPacket.currentServoB, telemetryPacket.targetServoB,
|
||||||
|
|
||||||
|
telemetryPacket.presentDevices);
|
||||||
|
fflush(csvFile);
|
||||||
|
fsync(fileno(csvFile)); // Critical: this ensures actual write to disk
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Sending %d byte packet hehe\n", offset);
|
||||||
|
send_packet_without_retries(bufOut, offset);
|
||||||
packetReadiness = 0;
|
packetReadiness = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,14 +211,16 @@ static void build_and_send_ack(uint32_t ackIndex, uint32_t crc32Checksum, uint64
|
|||||||
{
|
{
|
||||||
uint8_t bufOut[256] = {0};
|
uint8_t bufOut[256] = {0};
|
||||||
|
|
||||||
DownBoundPacket downboundPacket;
|
|
||||||
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_ACK, missionTimer);
|
|
||||||
|
|
||||||
ACKPacket ackPacket = {
|
ACKPacket ackPacket = {
|
||||||
.packetIndex = ackIndex,
|
.packetIndex = ackIndex,
|
||||||
.crc32Checksum = crc32Checksum,
|
.crc32Checksum = crc32Checksum,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)&ackPacket, sizeof(ackPacket));
|
||||||
|
|
||||||
|
DownBoundPacket downboundPacket;
|
||||||
|
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_ACK, missionTimer, crc);
|
||||||
|
|
||||||
uint16_t offset = 0;
|
uint16_t offset = 0;
|
||||||
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
||||||
offset += sizeof(downboundPacket);
|
offset += sizeof(downboundPacket);
|
||||||
@@ -167,13 +258,23 @@ void process_uplink_packet(uint8_t *data, uint8_t len, uint64_t missionTimer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Got uplink packet of type %d, index %d", uplinkPacket.packetType, uplinkPacket.packetIndex);
|
ESP_LOGI(TAG, "Got uplink packet of type %d, index %ld", uplinkPacket.packetType, uplinkPacket.packetIndex);
|
||||||
|
|
||||||
|
uint8_t *payload = data + sizeof(UplinkPacket);
|
||||||
|
|
||||||
uint8_t payloadRXLen = len - sizeof(UplinkPacket);
|
uint8_t payloadRXLen = len - sizeof(UplinkPacket);
|
||||||
|
|
||||||
|
uint32_t crc = esp_rom_crc32_le(0, payload, payloadRXLen);
|
||||||
|
|
||||||
|
if (crc != uplinkPacket.CRCCheck)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Received BAD CRC for packet %ld, crc is %ld, should be %ld", uplinkPacket.packetIndex, crc, uplinkPacket.CRCCheck);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (uplinkPacket.packetType == UplinkPacketType_ACK)
|
if (uplinkPacket.packetType == UplinkPacketType_ACK)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Received ACK for packet %d", uplinkPacket.packetIndex);
|
ESP_LOGI(TAG, "Received ACK for packet %ld", uplinkPacket.packetIndex);
|
||||||
ackReceived = true;
|
ackReceived = true;
|
||||||
lastAckIndex = uplinkPacket.packetIndex;
|
lastAckIndex = uplinkPacket.packetIndex;
|
||||||
return;
|
return;
|
||||||
@@ -194,6 +295,7 @@ void process_uplink_packet(uint8_t *data, uint8_t len, uint64_t missionTimer)
|
|||||||
{
|
{
|
||||||
SystemControlPacket sysCtrl;
|
SystemControlPacket sysCtrl;
|
||||||
memcpy(&sysCtrl, data + sizeof(UplinkPacket), sizeof(SystemControlPacket));
|
memcpy(&sysCtrl, data + sizeof(UplinkPacket), sizeof(SystemControlPacket));
|
||||||
|
setPowerMode(sysCtrl.powerMode);
|
||||||
// TODO: Process sysCtrl
|
// TODO: Process sysCtrl
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -213,12 +315,12 @@ void process_uplink_packet(uint8_t *data, uint8_t len, uint64_t missionTimer)
|
|||||||
}
|
}
|
||||||
else if (uplinkPacket.packetIndex > packetIndexRX + 1)
|
else if (uplinkPacket.packetIndex > packetIndexRX + 1)
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Skipped %d packets", uplinkPacket.packetIndex - (packetIndexRX + 1));
|
ESP_LOGW(TAG, "Skipped %ld packets", uplinkPacket.packetIndex - (packetIndexRX + 1));
|
||||||
packetIndexRX = uplinkPacket.packetIndex;
|
packetIndexRX = uplinkPacket.packetIndex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ESP_LOGW(TAG, "Duplicate packet: %d", (packetIndexRX + 1) - uplinkPacket.packetIndex);
|
ESP_LOGW(TAG, "Duplicate packet: %ld", (packetIndexRX + 1) - uplinkPacket.packetIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,14 +353,17 @@ void lora_receive_task(void *pvParameters)
|
|||||||
void lora_comms_task(void *pvParameters)
|
void lora_comms_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
|
|
||||||
ESP_LOGI(TAG, "lora_comms_task started");
|
// while (foundDevices[0] != 2) {
|
||||||
|
// vTaskDelay(10);
|
||||||
|
// }
|
||||||
|
|
||||||
// Initialize the semaphore for radio access (binary semaphore, 1 = available)
|
// Initialize the semaphore for radio access (binary semaphore, 1 = available)
|
||||||
loraRadioMutex = xSemaphoreCreateMutex();
|
loraRadioMutex = xSemaphoreCreateMutex();
|
||||||
xSemaphoreGive(loraRadioMutex); // Set semaphore as available
|
xSemaphoreGive(loraRadioMutex); // Set semaphore as available
|
||||||
|
|
||||||
const int64_t interval_us = 400000; // 400 ms
|
ESP_LOGI(TAG, "lora_comms_task started");
|
||||||
|
|
||||||
setup_lora();
|
setup_lora();
|
||||||
|
ESP_LOGI(TAG, "lora_comms_task continuing");
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
lora_receive_task,
|
lora_receive_task,
|
||||||
"LoraReceiveTask",
|
"LoraReceiveTask",
|
||||||
@@ -266,6 +371,7 @@ void lora_comms_task(void *pvParameters)
|
|||||||
NULL,
|
NULL,
|
||||||
(tskIDLE_PRIORITY + 2),
|
(tskIDLE_PRIORITY + 2),
|
||||||
NULL);
|
NULL);
|
||||||
|
ESP_LOGI(TAG, "loraInit");
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int64_t start_time = esp_timer_get_time();
|
int64_t start_time = esp_timer_get_time();
|
||||||
@@ -277,6 +383,8 @@ void lora_comms_task(void *pvParameters)
|
|||||||
prepare_and_send_telemetry(start_time);
|
prepare_and_send_telemetry(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int64_t interval_us = ((powerMode == HIGH_POWER_MODE) ? 10000 : 10000000); // 10 ms or 10 000 ms
|
||||||
|
|
||||||
int64_t end_time = esp_timer_get_time();
|
int64_t end_time = esp_timer_get_time();
|
||||||
int64_t elapsed = end_time - start_time;
|
int64_t elapsed = end_time - start_time;
|
||||||
|
|
||||||
@@ -286,49 +394,3 @@ 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));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
128
main/components/sdcard.c
Normal file
128
main/components/sdcard.c
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
#include "sdcard.h"
|
||||||
|
|
||||||
|
void writeFile(FILE *f, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
if (f != NULL)
|
||||||
|
{
|
||||||
|
fwrite(data, size, 1, f);
|
||||||
|
fflush(f);
|
||||||
|
fsync(fileno(f)); // Critical: this ensures actual write to disk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *csvFile = NULL;
|
||||||
|
FILE *sensFile = NULL;
|
||||||
|
|
||||||
|
void initSD(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
// Options for mounting the filesystem.
|
||||||
|
// If format_if_mount_failed is set to true, SD card will be partitioned and
|
||||||
|
// formatted in case when mounting fails.
|
||||||
|
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||||
|
.format_if_mount_failed = true,
|
||||||
|
.max_files = 100,
|
||||||
|
.allocation_unit_size = 16 * 1024};
|
||||||
|
sdmmc_card_t *card;
|
||||||
|
const char mount_point[] = MOUNT_POINT;
|
||||||
|
ESP_LOGI(TAGSD, "Initializing SD card");
|
||||||
|
|
||||||
|
// Use settings defined above to initialize SD card and mount FAT filesystem.
|
||||||
|
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
|
||||||
|
// Please check its source code and implement error recovery when developing
|
||||||
|
// production applications.
|
||||||
|
ESP_LOGI(TAGSD, "Using SPI peripheral");
|
||||||
|
|
||||||
|
// By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz)
|
||||||
|
// For setting a specific frequency, use host.max_freq_khz (range 400kHz - 20MHz for SDSPI)
|
||||||
|
// Example: for fixed frequency of 10MHz, use host.max_freq_khz = 10000;
|
||||||
|
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
|
||||||
|
host.slot = SPI3_HOST;
|
||||||
|
|
||||||
|
// This initializes the slot without card detect (CD) and write protect (WP) signals.
|
||||||
|
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
|
||||||
|
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
|
||||||
|
slot_config.gpio_cs = HSPI_SD_CS;
|
||||||
|
slot_config.host_id = host.slot;
|
||||||
|
|
||||||
|
ESP_LOGI(TAGSD, "Mounting filesystem");
|
||||||
|
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
|
||||||
|
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
if (ret == ESP_FAIL)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAGSD, "Failed to mount filesystem. "
|
||||||
|
"If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAGSD, "Failed to initialize the card (%s). "
|
||||||
|
"Make sure SD card lines have pull-up resistors in place.",
|
||||||
|
esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAGSD, "Filesystem mounted");
|
||||||
|
|
||||||
|
// Card has been initialized, print its properties
|
||||||
|
sdmmc_card_print_info(stdout, card);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
FILE *f = fopen(COUNTER_FILE, "r");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fscanf(f, "%d", &index);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 2. Increment and write back ===
|
||||||
|
f = fopen(COUNTER_FILE, "w");
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAGSD, "Failed to open counter file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
if (f != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
fprintf(f, "%d", index);
|
||||||
|
fflush(f);
|
||||||
|
fsync(fileno(f)); // Critical: this ensures actual write to disk
|
||||||
|
fclose(f);
|
||||||
|
ESP_LOGI(TAGSD, "Index is now %d", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 3. Make folder ===
|
||||||
|
char folder_path[MAX_PATH - 20];
|
||||||
|
snprintf(folder_path, MAX_PATH, MOUNT_POINT "/%d", index);
|
||||||
|
mkdir(folder_path, 0777); // safe if exists already
|
||||||
|
|
||||||
|
// === 4. Create CSV and BIN ===
|
||||||
|
char csv_path[MAX_PATH], bin_path[MAX_PATH];
|
||||||
|
snprintf(csv_path, MAX_PATH, "%s/data.csv", folder_path);
|
||||||
|
snprintf(bin_path, MAX_PATH, "%s/data.bin", folder_path);
|
||||||
|
|
||||||
|
csvFile = fopen(csv_path, "w");
|
||||||
|
sensFile = fopen(bin_path, "wb");
|
||||||
|
if (csvFile != NULL)
|
||||||
|
{
|
||||||
|
fprintf(csvFile,
|
||||||
|
"missionTimer,packetIndex,telemetryIndex,packetType,"
|
||||||
|
"accX,accY,accZ,gyroX,gyroY,gyroZ,magX,magY,magZ,accTemp,"
|
||||||
|
"eCO2,tVOC,currentCCS,rawCCS,"
|
||||||
|
"volts,current,power,rawtemperature,rawhumidity,rawpressure,rawgas,"
|
||||||
|
"gasValid,heaterStable,gasRange,gasIndex,"
|
||||||
|
"airTemp,relHumidity,baroPressure,gasResistance,"
|
||||||
|
"iaqScore,tempScore,humidityScore,gasScore,"
|
||||||
|
"gpsTime,latitude,longitude,altitude,fixQuality,numSatellites,date,speed,"
|
||||||
|
"predLatitude,predLongitude,predAltitude,"
|
||||||
|
"NH3,CO,NO2,UVC,"
|
||||||
|
"currentServoA,targetServoA,currentServoB,targetServoB,"
|
||||||
|
"presentDevices\n");
|
||||||
|
fflush(csvFile);
|
||||||
|
fsync(fileno(csvFile)); // Critical: this ensures actual write to disk
|
||||||
|
}
|
||||||
|
}
|
26
main/components/sdcard.h
Normal file
26
main/components/sdcard.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef SDCARD_COMPONENT
|
||||||
|
#define SDCARD_COMPONENT
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "sdmmc_cmd.h"
|
||||||
|
#include "../hw/buscfg.h"
|
||||||
|
|
||||||
|
#define TAGSD "SDSubsys"
|
||||||
|
|
||||||
|
#define COUNTER_FILE "cnt.txt"
|
||||||
|
|
||||||
|
#define MOUNT_POINT "/sdcard"
|
||||||
|
|
||||||
|
void writeFile(FILE *f, const void *data, size_t size);
|
||||||
|
|
||||||
|
extern FILE *csvFile;
|
||||||
|
extern FILE *sensFile;
|
||||||
|
|
||||||
|
#define MAX_PATH 80
|
||||||
|
|
||||||
|
void initSD(void);
|
||||||
|
|
||||||
|
#endif
|
@@ -4,12 +4,28 @@
|
|||||||
#include "../hw/gps.h"
|
#include "../hw/gps.h"
|
||||||
#include "servocontroller.h"
|
#include "servocontroller.h"
|
||||||
|
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "esp_vfs_fat.h"
|
||||||
|
#include "sdmmc_cmd.h"
|
||||||
|
|
||||||
|
#define MOUNT_POINT "/sdcard"
|
||||||
|
#define MAX_LINE_LENGTH 64
|
||||||
|
|
||||||
#define BLINK_GPIO 2
|
#define BLINK_GPIO 2
|
||||||
|
|
||||||
|
// uint8_t powerMode = LOW_POWER_MODE;
|
||||||
|
uint8_t powerMode = HIGH_POWER_MODE;
|
||||||
|
|
||||||
static uint8_t s_led_state = 0;
|
static uint8_t s_led_state = 0;
|
||||||
|
|
||||||
uint8_t foundDevices[128];
|
uint8_t telemetryIndex = 1;
|
||||||
uint8_t prevDevices[128];
|
|
||||||
|
const uint8_t expectedAdressesCount = 5;
|
||||||
|
const uint8_t expectedAdresses[] = {MCP23018_ADDRESS, BME680_ADDRESS, CCS811_ADDRESS, MPU9250_ADDRESS, INA260_ADDRESS};
|
||||||
|
|
||||||
|
uint8_t foundDevices[5];
|
||||||
|
uint8_t prevDevices[5];
|
||||||
|
|
||||||
static void configure_led(void)
|
static void configure_led(void)
|
||||||
{
|
{
|
||||||
@@ -17,74 +33,120 @@ static void configure_led(void)
|
|||||||
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
|
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void update_devices() {
|
void update_devices()
|
||||||
// memcpy(prevDevices, foundDevices, sizeof(prevDevices));
|
{
|
||||||
// memset(foundDevices, 0, sizeof(foundDevices));
|
memcpy(prevDevices, foundDevices, sizeof(prevDevices));
|
||||||
// for (uint8_t i = 0; i < 128; i++)
|
for (uint8_t i = 0; i < expectedAdressesCount; i++)
|
||||||
// {
|
{
|
||||||
// fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
// esp_err_t ret = i2c_master_probe(i2c0_bus_hdl, i, 20);
|
esp_err_t ret = i2c_master_probe(i2c0_bus_hdl, expectedAdresses[i], 20);
|
||||||
|
|
||||||
// if (ret == ESP_OK)
|
if (ret == ESP_OK)
|
||||||
// {
|
{
|
||||||
// foundDevices[i] = 1;
|
if (foundDevices[i] == 0)
|
||||||
|
{
|
||||||
|
foundDevices[i] = 1;
|
||||||
|
}
|
||||||
// printf("Found device at 0x%02X\n", i);
|
// printf("Found device at 0x%02X\n", i);
|
||||||
// }
|
}
|
||||||
// }
|
else
|
||||||
// }
|
{
|
||||||
|
foundDevices[i] = 0;
|
||||||
|
if (i == 1 && powerMode != HIGH_POWER_MODE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("Not found device at 0x%02X\n", expectedAdresses[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// void init_connected() {
|
void setPowerMode(uint8_t powerModeIn)
|
||||||
// for (uint8_t i = 0; i < 128; i++) {
|
{
|
||||||
// if (foundDevices[i] != prevDevices[i]) {
|
powerMode = powerModeIn;
|
||||||
// if (foundDevices[i]) {
|
if (foundDevices[0] == 2)
|
||||||
// switch (i)
|
{
|
||||||
// {
|
if (powerMode == HIGH_POWER_MODE)
|
||||||
// case MCP23018_ADDRESS:
|
{
|
||||||
// /* code */
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_WAKE, 0);
|
||||||
// if (mcp23018_init() == ESP_OK) {
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 1);
|
||||||
// foundDevices[i] = 2;
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_MICS_POWER, 1);
|
||||||
// }
|
}
|
||||||
// break;
|
else
|
||||||
|
{
|
||||||
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_WAKE, 1);
|
||||||
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 0);
|
||||||
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_MICS_POWER, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// case INA260_ADDRESS:
|
void init_connected()
|
||||||
// if (ina260_init() == ESP_OK) {
|
{
|
||||||
// foundDevices[i] = 2;
|
|
||||||
// }
|
|
||||||
// /* code */
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case CCS811_ADDRESS:
|
for (uint8_t i = 0; i < expectedAdressesCount; i++)
|
||||||
// if (ccs811_init() == ESP_OK) {
|
{
|
||||||
// foundDevices[i] = 2;
|
if (foundDevices[i] != prevDevices[i])
|
||||||
// }
|
{
|
||||||
// /* code */
|
if (foundDevices[i])
|
||||||
// break;
|
{
|
||||||
|
esp_err_t ret = ESP_FAIL;
|
||||||
|
bool foundUsed = true;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case MCP23018_ADDRESS:
|
||||||
|
/* code */
|
||||||
|
ret = mcp23018_init();
|
||||||
|
setPowerMode(powerMode);
|
||||||
|
mcp3550_spi_init();
|
||||||
|
break;
|
||||||
|
|
||||||
// case MPU9250_ADDRESS:
|
case INA260_ADDRESS:
|
||||||
// if (mpu9250_init() == ESP_OK) {
|
ret = ina260_init();
|
||||||
// foundDevices[i] = 2;
|
/* code */
|
||||||
// }
|
break;
|
||||||
// /* code */
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case BME680_ADDRESS:
|
case CCS811_ADDRESS:
|
||||||
// if (bme680b_init() == ESP_OK) {
|
ret = ccs811_init();
|
||||||
// foundDevices[i] = 2;
|
/* code */
|
||||||
// }
|
break;
|
||||||
// /* code */
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// default:
|
case MPU9250_ADDRESS:
|
||||||
// break;
|
ret = mpu9250_init();
|
||||||
// }
|
/* code */
|
||||||
// }
|
break;
|
||||||
// }
|
|
||||||
// }
|
case BME680_ADDRESS:
|
||||||
// }
|
ret = bme680b_init();
|
||||||
|
/* code */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
foundUsed = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (foundUsed)
|
||||||
|
{
|
||||||
|
if (ret == ESP_OK)
|
||||||
|
{
|
||||||
|
foundDevices[i] = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Device init error at 0x%02X - %s\n", expectedAdresses[i], esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void i2c_sensors_task(void *pvParameters)
|
void i2c_sensors_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
memset(foundDevices, 0, sizeof(foundDevices));
|
memset(foundDevices, 0, sizeof(foundDevices));
|
||||||
memset(prevDevices, 0, sizeof(prevDevices));
|
memset(prevDevices, 0, sizeof(prevDevices));
|
||||||
|
|
||||||
@@ -93,17 +155,15 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
ccs811_init();
|
ccs811_init();
|
||||||
ina260_init();
|
ina260_init();
|
||||||
|
|
||||||
|
|
||||||
// update_devices();
|
// update_devices();
|
||||||
// init_connected();
|
// init_connected();
|
||||||
// initialize the xLastWakeTime variable with the current time.
|
// initialize the xLastWakeTime variable with the current time.
|
||||||
const int64_t interval_us = 100000; // 100 ms
|
const int64_t interval_us = 50000; // 50 ms
|
||||||
int64_t start_time, end_time, elapsed;
|
int64_t start_time, end_time, elapsed;
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialize i2c device configuration
|
// initialize i2c device configuration
|
||||||
|
|
||||||
mcp3550_spi_init();
|
|
||||||
configure_led();
|
configure_led();
|
||||||
|
|
||||||
int16_t accel[3], gyro[3], temp, magnet[3];
|
int16_t accel[3], gyro[3], temp, magnet[3];
|
||||||
@@ -119,13 +179,22 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
uint16_t power;
|
uint16_t power;
|
||||||
|
|
||||||
bme680_data_t bmeData;
|
bme680_data_t bmeData;
|
||||||
|
|
||||||
|
mics_adc_data_t ADCData;
|
||||||
// task loop entry point
|
// task loop entry point
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
start_time = esp_timer_get_time(); // µs since boot
|
start_time = esp_timer_get_time(); // µs since boot
|
||||||
|
|
||||||
|
uint8_t presentDevices = 0xFF;
|
||||||
|
// update_devices();
|
||||||
|
// init_connected();
|
||||||
|
|
||||||
//
|
//
|
||||||
// handle sensor
|
// handle sensor
|
||||||
|
|
||||||
|
presentDevices |= BME680_PRESENT_BIT;
|
||||||
|
|
||||||
if (BME680_DEV_HANDLE)
|
if (BME680_DEV_HANDLE)
|
||||||
{
|
{
|
||||||
esp_err_t result = bme680_get_data(BME680_DEV_HANDLE, &bmeData);
|
esp_err_t result = bme680_get_data(BME680_DEV_HANDLE, &bmeData);
|
||||||
@@ -150,10 +219,12 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
bme680b_init();
|
bme680b_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
presentDevices |= CCS811_PRESENT_BIT;
|
||||||
ccs811_get_data(&eCO2, &tvoc, ¤tCCS, &rawData);
|
ccs811_get_data(&eCO2, &tvoc, ¤tCCS, &rawData);
|
||||||
ESP_LOGI(TAG_CCS, "eCO₂: %d ppm, TVOC: %d ppb", eCO2, tvoc);
|
ESP_LOGI(TAG_CCS, "eCO₂: %d ppm, TVOC: %d ppb", eCO2, tvoc);
|
||||||
ESP_LOGI(TAG_CCS, "Current: %d μA, Raw voltage: %d V", currentCCS, rawData);
|
ESP_LOGI(TAG_CCS, "Current: %d μA, Raw voltage: %d V", currentCCS, rawData);
|
||||||
|
|
||||||
|
presentDevices |= MPU9250_PRESENT_BIT;
|
||||||
if (mpu9250_read_sensor_data(MPU9250_DEV_HANDLE, accel, gyro, &temp, magnet) == ESP_OK)
|
if (mpu9250_read_sensor_data(MPU9250_DEV_HANDLE, accel, gyro, &temp, magnet) == ESP_OK)
|
||||||
{
|
{
|
||||||
mpu9250_convert_data(accel, gyro, temp, magnet, accel_f, gyro_f, &temp_f, magnet_f);
|
mpu9250_convert_data(accel, gyro, temp, magnet, accel_f, gyro_f, &temp_f, magnet_f);
|
||||||
@@ -168,33 +239,18 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
ESP_LOGE(TAG_MPU, "Failed to read sensor data");
|
ESP_LOGE(TAG_MPU, "Failed to read sensor data");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
presentDevices |= INA260_PRESENT_BIT;
|
||||||
ina260_readParams(&volts, ¤t, &power);
|
ina260_readParams(&volts, ¤t, &power);
|
||||||
ina260_printParams(volts, current, power);
|
ina260_printParams(volts, current, power);
|
||||||
|
|
||||||
|
presentDevices |= MCP23018_PRESENT_BIT;
|
||||||
float VREFVoltage = 2.5;
|
float VREFVoltage = 2.5;
|
||||||
|
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);
|
if (packetReadiness == 0)
|
||||||
|
|
||||||
//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);
|
|
||||||
/* Toggle the LED state */
|
|
||||||
s_led_state = !s_led_state;
|
|
||||||
end_time = esp_timer_get_time();
|
|
||||||
elapsed = end_time - start_time;
|
|
||||||
|
|
||||||
if (elapsed < interval_us)
|
|
||||||
{
|
{
|
||||||
vTaskDelay(pdMS_TO_TICKS((interval_us - elapsed) / 1000));
|
|
||||||
}
|
|
||||||
if (packetReadiness == 0) {
|
|
||||||
memset(&telemetryPacket, 0, sizeof(telemetryPacket));
|
memset(&telemetryPacket, 0, sizeof(telemetryPacket));
|
||||||
telemetryPacket.accelerationX = accel[0];
|
telemetryPacket.accelerationX = accel[0];
|
||||||
telemetryPacket.accelerationY = accel[1];
|
telemetryPacket.accelerationY = accel[1];
|
||||||
@@ -219,7 +275,6 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
telemetryPacket.current = current;
|
telemetryPacket.current = current;
|
||||||
telemetryPacket.power = power;
|
telemetryPacket.power = power;
|
||||||
|
|
||||||
|
|
||||||
telemetryPacket.temperature = bmeData.raw_data.temperature;
|
telemetryPacket.temperature = bmeData.raw_data.temperature;
|
||||||
telemetryPacket.humidity = bmeData.raw_data.humidity;
|
telemetryPacket.humidity = bmeData.raw_data.humidity;
|
||||||
telemetryPacket.pressure = bmeData.raw_data.pressure;
|
telemetryPacket.pressure = bmeData.raw_data.pressure;
|
||||||
@@ -261,9 +316,20 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
telemetryPacket.currentServoA = servoState.currentServoA;
|
telemetryPacket.currentServoA = servoState.currentServoA;
|
||||||
telemetryPacket.currentServoB = servoState.currentServoB;
|
telemetryPacket.currentServoB = servoState.currentServoB;
|
||||||
|
|
||||||
|
telemetryPacket.presentDevices = presentDevices;
|
||||||
|
|
||||||
|
telemetryPacket.telemetryIndex = telemetryIndex++;
|
||||||
}
|
}
|
||||||
packetReadiness = 1;
|
packetReadiness = 1;
|
||||||
|
|
||||||
|
s_led_state = !s_led_state;
|
||||||
|
end_time = esp_timer_get_time();
|
||||||
|
elapsed = end_time - start_time;
|
||||||
|
|
||||||
|
if (elapsed < interval_us)
|
||||||
|
{
|
||||||
|
vTaskDelay(pdMS_TO_TICKS((interval_us - elapsed) / 1000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// free resources
|
// free resources
|
||||||
|
@@ -18,9 +18,17 @@
|
|||||||
#include "../hw/mpu9250.h"
|
#include "../hw/mpu9250.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#define LOW_POWER_MODE 0
|
||||||
|
#define HIGH_POWER_MODE 1
|
||||||
|
extern uint8_t powerMode;
|
||||||
|
|
||||||
extern uint8_t foundDevices[128];
|
|
||||||
extern uint8_t prevDevices[128];
|
extern uint8_t foundDevices[5];
|
||||||
|
extern uint8_t prevDevices[5];
|
||||||
|
|
||||||
|
void init_connected();
|
||||||
|
void update_devices();
|
||||||
|
void setPowerMode(uint8_t powerModeIn);
|
||||||
|
|
||||||
void i2c_sensors_task(void *pvParameters);
|
void i2c_sensors_task(void *pvParameters);
|
||||||
|
|
||||||
|
@@ -8,11 +8,17 @@
|
|||||||
#define ESP_RXD0 GPIO_NUM_44
|
#define ESP_RXD0 GPIO_NUM_44
|
||||||
#define ESP_TXD0 GPIO_NUM_43
|
#define ESP_TXD0 GPIO_NUM_43
|
||||||
|
|
||||||
#define MCP23018_ADDRESS 0x20
|
#define BME680_ADDRESS 0x76
|
||||||
#define INA260_ADDRESS 0x40
|
|
||||||
#define CCS811_ADDRESS 0x5A
|
#define CCS811_ADDRESS 0x5A
|
||||||
#define MPU9250_ADDRESS 0x68
|
#define MPU9250_ADDRESS 0x68
|
||||||
#define BME680_ADDRESS 0x76
|
#define INA260_ADDRESS 0x40
|
||||||
|
#define MCP23018_ADDRESS 0x20
|
||||||
|
|
||||||
|
#define BME680_PRESENT_BIT (1 << 0)
|
||||||
|
#define CCS811_PRESENT_BIT (1 << 1)
|
||||||
|
#define MPU9250_PRESENT_BIT (1 << 2)
|
||||||
|
#define INA260_PRESENT_BIT (1 << 3)
|
||||||
|
#define MCP23018_PRESENT_BIT (1 << 4)
|
||||||
|
|
||||||
#define ESP_CONNECTOR_P1 MCP3550_MISO_GPIO
|
#define ESP_CONNECTOR_P1 MCP3550_MISO_GPIO
|
||||||
#define ESP_CONNECTOR_P2 MCP3550_MOSI_GPIO
|
#define ESP_CONNECTOR_P2 MCP3550_MOSI_GPIO
|
||||||
|
@@ -33,10 +33,6 @@ esp_err_t ccs811_init()
|
|||||||
{
|
{
|
||||||
esp_err_t ret =i2c_master_bus_add_device(i2c0_bus_hdl, &CCS811_DEV_CFG, &CCS811_DEV_HANDLE);
|
esp_err_t ret =i2c_master_bus_add_device(i2c0_bus_hdl, &CCS811_DEV_CFG, &CCS811_DEV_HANDLE);
|
||||||
if (ret != ESP_OK) {return ret;}
|
if (ret != ESP_OK) {return ret;}
|
||||||
ret = mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_WAKE, 0);
|
|
||||||
if (ret != ESP_OK) {return ret;}
|
|
||||||
ret = mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 1);
|
|
||||||
if (ret != ESP_OK) {return ret;}
|
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
uint8_t reset_seq[4] = {0x11, 0xE5, 0x72, 0x8A};
|
uint8_t reset_seq[4] = {0x11, 0xE5, 0x72, 0x8A};
|
||||||
ret = i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_SW_RESET, reset_seq, sizeof(reset_seq)); // Reset
|
ret = i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_SW_RESET, reset_seq, sizeof(reset_seq)); // Reset
|
||||||
|
@@ -26,11 +26,11 @@ void gps_init()
|
|||||||
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||||
.rx_flow_ctrl_thresh = 122,
|
.rx_flow_ctrl_thresh = 122,
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(uart_param_config(GPS_UART_NUM, &uart_config));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_param_config(GPS_UART_NUM, &uart_config));
|
||||||
ESP_ERROR_CHECK(uart_set_pin(GPS_UART_NUM, GPS_TXD, GPS_RXD, GPS_RTS, GPS_CTS));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_set_pin(GPS_UART_NUM, GPS_TXD, GPS_RXD, GPS_RTS, GPS_CTS));
|
||||||
|
|
||||||
const int uart_buffer_size = (1024 * 2);
|
const int uart_buffer_size = (1024 * 2);
|
||||||
ESP_ERROR_CHECK(uart_driver_install(GPS_UART_NUM, uart_buffer_size, uart_buffer_size, 10, &uart_queue, 0));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_driver_install(GPS_UART_NUM, uart_buffer_size, uart_buffer_size, 10, &uart_queue, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ void gps_task(void *arg)
|
|||||||
line[line_pos] = '\0';
|
line[line_pos] = '\0';
|
||||||
|
|
||||||
if (line[0] == '$') {
|
if (line[0] == '$') {
|
||||||
ESP_LOGV(TAG, "Received NMEA: %s", line);
|
ESP_LOGI(TAG, "Received NMEA: %s", line);
|
||||||
|
|
||||||
if (strstr(line, "$GPGGA") == line) {
|
if (strstr(line, "$GNGGA") == line) {
|
||||||
parse_gpgga(line);
|
parse_gpgga(line);
|
||||||
parse_gpgga_to_struct(line, &gpsDataOut);
|
parse_gpgga_to_struct(line, &gpsDataOut);
|
||||||
} else if (strstr(line, "$GPRMC") == line) {
|
} else if (strstr(line, "$GPRMC") == line) {
|
||||||
@@ -72,8 +72,7 @@ void gps_task(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_gpgga(const char *nmea)
|
void parse_gpgga(const char *nmea) {
|
||||||
{
|
|
||||||
char *fields[15];
|
char *fields[15];
|
||||||
char temp[GPS_LINE_MAX_LEN];
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
@@ -108,12 +107,11 @@ void parse_gpgga(const char *nmea)
|
|||||||
// Altitude
|
// Altitude
|
||||||
const char *altitude = fields[9];
|
const char *altitude = fields[9];
|
||||||
|
|
||||||
ESP_LOGI(TAG, "[GPGGA] Time: %s, Lat: %s %s, Lon: %s %s, Fix: %s, Sats: %s, Alt: %sm",
|
printf("[GPGGA] Time: %s, Lat: %s %s, Lon: %s %s, Fix: %s, Sats: %s, Alt: %sm\n",
|
||||||
utc_time, lat, lat_dir, lon, lon_dir, fix_quality, num_satellites, altitude);
|
utc_time, lat, lat_dir, lon, lon_dir, fix_quality, num_satellites, altitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_gprmc(const char *nmea)
|
void parse_gprmc(const char *nmea) {
|
||||||
{
|
|
||||||
char *fields[13];
|
char *fields[13];
|
||||||
char temp[GPS_LINE_MAX_LEN];
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
@@ -137,7 +135,7 @@ void parse_gprmc(const char *nmea)
|
|||||||
const char *speed_knots = fields[7];
|
const char *speed_knots = fields[7];
|
||||||
const char *date = fields[9];
|
const char *date = fields[9];
|
||||||
|
|
||||||
ESP_LOGI(TAG, "[GPRMC] Date: %s, Time: %s, Lat: %s %s, Lon: %s %s, Speed: %s knots, Status: %s",
|
printf("[GPRMC] Date: %s, Time: %s, Lat: %s %s, Lon: %s %s, Speed: %s knots, Status: %s\n",
|
||||||
date, utc_time, lat, lat_dir, lon, lon_dir, speed_knots, status);
|
date, utc_time, lat, lat_dir, lon, lon_dir, speed_knots, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,17 +152,22 @@ static uint32_t time_to_seconds_struct(const char *time_str) {
|
|||||||
// Function to convert DMS (degrees minutes.decimalminutes) to centi-degrees
|
// Function to convert DMS (degrees minutes.decimalminutes) to centi-degrees
|
||||||
static int32_t dms_to_centi_degrees_struct(const char *dms_str, const char *direction) {
|
static int32_t dms_to_centi_degrees_struct(const char *dms_str, const char *direction) {
|
||||||
if (dms_str == NULL || direction == NULL || strlen(dms_str) < 7) return 0;
|
if (dms_str == NULL || direction == NULL || strlen(dms_str) < 7) return 0;
|
||||||
char degrees_str[4] = {0};
|
char data_str[20] = {0};
|
||||||
char minutes_decimal_str[10] = {0};
|
char *dataStr = data_str;
|
||||||
strncpy(degrees_str, dms_str, 2);
|
for (int i = 0; i < 20; i++) {
|
||||||
strncpy(minutes_decimal_str, dms_str + 2, strlen(dms_str) - 2);
|
if (dms_str[i] == 0) {
|
||||||
double degrees = atof(degrees_str);
|
break;
|
||||||
double minutes = atof(minutes_decimal_str);
|
|
||||||
double decimal_degrees = degrees + (minutes / 60.0);
|
|
||||||
if (direction[0] == 'S' || direction[0] == 'W') {
|
|
||||||
decimal_degrees *= -1.0;
|
|
||||||
}
|
}
|
||||||
return (int32_t)(decimal_degrees * 10000);
|
if (dms_str[i] == '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*(dataStr++) = dms_str[i];
|
||||||
|
}
|
||||||
|
int32_t degrees = atoi(data_str);
|
||||||
|
if (direction[0] == 'S' || direction[0] == 'W') {
|
||||||
|
degrees *= -1;
|
||||||
|
}
|
||||||
|
return degrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to convert altitude string to centi-meters
|
// Function to convert altitude string to centi-meters
|
||||||
@@ -190,8 +193,7 @@ static uint16_t date_to_yyddmm_struct(const char *date_str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to parse GPGGA NMEA string and return the struct
|
// Function to parse GPGGA NMEA string and return the struct
|
||||||
void parse_gpgga_to_struct(const char *nmea, gps_binary_struct_t *data)
|
void parse_gpgga_to_struct(const char *nmea, gps_binary_struct_t *data) {
|
||||||
{
|
|
||||||
char *fields[15];
|
char *fields[15];
|
||||||
char temp[GPS_LINE_MAX_LEN];
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
@@ -212,13 +214,12 @@ void parse_gpgga_to_struct(const char *nmea, gps_binary_struct_t *data)
|
|||||||
data->num_satellites = atoi(fields[7]);
|
data->num_satellites = atoi(fields[7]);
|
||||||
data->altitude_centi_meters = altitude_to_centi_meters_struct(fields[9]);
|
data->altitude_centi_meters = altitude_to_centi_meters_struct(fields[9]);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "GPGGA: Not enough fields to parse struct");
|
printf("GPGGA: Not enough fields to parse struct");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to parse GPRMC NMEA string and return the struct
|
// Function to parse GPRMC NMEA string and return the struct
|
||||||
void parse_gprmc_to_struct(const char *nmea, gps_binary_struct_t *data)
|
void parse_gprmc_to_struct(const char *nmea, gps_binary_struct_t *data) {
|
||||||
{
|
|
||||||
char *fields[13];
|
char *fields[13];
|
||||||
char temp[GPS_LINE_MAX_LEN];
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
@@ -239,6 +240,6 @@ void parse_gprmc_to_struct(const char *nmea, gps_binary_struct_t *data)
|
|||||||
data->speed_centi_knots = speed_to_centi_knots_struct(fields[7]);
|
data->speed_centi_knots = speed_to_centi_knots_struct(fields[7]);
|
||||||
// Fix quality and num_satellites are typically in GPGGA, so they might be 0 here.
|
// Fix quality and num_satellites are typically in GPGGA, so they might be 0 here.
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "GPRMC: Not enough fields to parse struct");
|
printf("GPRMC: Not enough fields to parse struct");
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,21 +8,26 @@ i2c_device_config_t INA260_DEV_CFG = {
|
|||||||
|
|
||||||
i2c_master_dev_handle_t INA260_DEV_HANDLE;
|
i2c_master_dev_handle_t INA260_DEV_HANDLE;
|
||||||
|
|
||||||
|
void ina260_reset()
|
||||||
void ina260_reset() {
|
{
|
||||||
i2c_write_register_16(INA260_DEV_HANDLE, 0x00, 0x0FFF); // set ina max averaging and max time
|
i2c_write_register_16(INA260_DEV_HANDLE, 0x00, 0x0FFF); // set ina max averaging and max time
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t ina260_init()
|
esp_err_t ina260_init()
|
||||||
{
|
{
|
||||||
esp_err_t ret = i2c_master_bus_add_device(i2c0_bus_hdl, &INA260_DEV_CFG, &INA260_DEV_HANDLE);
|
esp_err_t ret = i2c_master_bus_add_device(i2c0_bus_hdl, &INA260_DEV_CFG, &INA260_DEV_HANDLE);
|
||||||
if (ret != ESP_OK) {return ret;}
|
if (ret != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG_INA, "%s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG_INA, "hehedstesfsewscdsfsrgerpodsvhdrsivhriuvjdreiv");
|
||||||
return i2c_write_register_16(INA260_DEV_HANDLE, INA260_CONFIG_REGISTER,
|
return i2c_write_register_16(INA260_DEV_HANDLE, INA260_CONFIG_REGISTER,
|
||||||
CONFIG_AVG_1024 | CONFIG_VBUSCT_8_244MS | CONFIG_ISHCT_8_244MS | CONFIG_MODE_CURRENT_VOLTAGE_CONTINOUS); // set ina max averaging and max time
|
CONFIG_AVG_1024 | CONFIG_VBUSCT_8_244MS | CONFIG_ISHCT_8_244MS | CONFIG_MODE_CURRENT_VOLTAGE_CONTINOUS); // set ina max averaging and max time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t i2c_master_read_register_transmit_receive(i2c_master_dev_handle_t device_handle, uint8_t reg_addr, uint8_t *data, size_t data_len)
|
||||||
esp_err_t i2c_master_read_register_transmit_receive(i2c_master_dev_handle_t device_handle, uint8_t reg_addr, uint8_t *data, size_t data_len) {
|
{
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
|
|
||||||
// The register address is what we want to send first (the "transmit" part)
|
// The register address is what we want to send first (the "transmit" part)
|
||||||
@@ -39,7 +44,8 @@ esp_err_t i2c_master_read_register_transmit_receive(i2c_master_dev_handle_t devi
|
|||||||
read_buffer, read_size,
|
read_buffer, read_size,
|
||||||
I2C_TIMEOUT_MS_VALUE);
|
I2C_TIMEOUT_MS_VALUE);
|
||||||
|
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK)
|
||||||
|
{
|
||||||
// Copy the data from the temporary read buffer to the output buffer
|
// Copy the data from the temporary read buffer to the output buffer
|
||||||
memcpy(data, read_buffer, read_size);
|
memcpy(data, read_buffer, read_size);
|
||||||
}
|
}
|
||||||
@@ -48,6 +54,8 @@ esp_err_t i2c_master_read_register_transmit_receive(i2c_master_dev_handle_t devi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ina260_readParams(uint16_t *volt, uint16_t *cur, uint16_t *pow)
|
void ina260_readParams(uint16_t *volt, uint16_t *cur, uint16_t *pow)
|
||||||
|
{
|
||||||
|
if (INA260_DEV_HANDLE)
|
||||||
{
|
{
|
||||||
*volt = 0;
|
*volt = 0;
|
||||||
*cur = 0;
|
*cur = 0;
|
||||||
@@ -56,7 +64,7 @@ void ina260_readParams(uint16_t *volt, uint16_t *cur, uint16_t *pow)
|
|||||||
{
|
{
|
||||||
uint8_t reg_value[2] = {0}; // Buffer for storing register data
|
uint8_t reg_value[2] = {0}; // Buffer for storing register data
|
||||||
|
|
||||||
ESP_ERROR_CHECK(i2c_master_read_register_transmit_receive(INA260_DEV_HANDLE, reg_addr, reg_value, sizeof(reg_value)));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_read_register_transmit_receive(INA260_DEV_HANDLE, reg_addr, reg_value, sizeof(reg_value)));
|
||||||
// Perform the register read
|
// Perform the register read
|
||||||
switch (reg_addr)
|
switch (reg_addr)
|
||||||
{
|
{
|
||||||
@@ -75,6 +83,7 @@ void ina260_readParams(uint16_t *volt, uint16_t *cur, uint16_t *pow)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ina260_printParams(uint16_t volt, uint16_t cur, uint16_t pow)
|
void ina260_printParams(uint16_t volt, uint16_t cur, uint16_t pow)
|
||||||
{
|
{
|
||||||
|
@@ -16,9 +16,7 @@ uint8_t gpiob_state = 0x00; // All LOW initially
|
|||||||
|
|
||||||
esp_err_t mcp23018_set_pin(i2c_master_dev_handle_t dev_handle, uint8_t pin, uint8_t value)
|
esp_err_t mcp23018_set_pin(i2c_master_dev_handle_t dev_handle, uint8_t pin, uint8_t value)
|
||||||
{
|
{
|
||||||
// while(foundDevices[MCP23018_ADDRESS] != 2) {
|
ESP_LOGI(TAG_MCP, "Setting %d to %d", pin, value);
|
||||||
// vTaskDelay(1);
|
|
||||||
// }
|
|
||||||
esp_err_t ret = ESP_FAIL;
|
esp_err_t ret = ESP_FAIL;
|
||||||
if (pin < 8)
|
if (pin < 8)
|
||||||
{
|
{
|
||||||
|
@@ -19,18 +19,17 @@ spi_device_handle_t mcp3550_handle;
|
|||||||
|
|
||||||
void mcp3550_spi_init()
|
void mcp3550_spi_init()
|
||||||
{
|
{
|
||||||
spi_device_interface_config_t devcfg = {
|
// spi_device_interface_config_t devcfg = {
|
||||||
.clock_speed_hz = 100000,
|
// .clock_speed_hz = 100000,
|
||||||
.mode = 0,
|
// .mode = 0,
|
||||||
.spics_io_num = -1, // We handle CS manually
|
// .spics_io_num = -1, // We handle CS manually
|
||||||
.queue_size = 1,
|
// .queue_size = 1,
|
||||||
};
|
// };
|
||||||
|
|
||||||
ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &mcp3550_handle));
|
// ESP_ERROR_CHECK_WITHOUT_ABORT(spi_bus_add_device(SPI2_HOST, &devcfg, &mcp3550_handle));
|
||||||
|
|
||||||
// Set MISO pin for input (needed for polling)
|
// Set MISO pin for input (needed for polling)
|
||||||
gpio_set_direction(MCP3550_MISO_GPIO, GPIO_MODE_INPUT);
|
gpio_set_direction(MCP3550_MISO_GPIO, GPIO_MODE_INPUT);
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_MICS_POWER, 1); // CS HIGH
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -133,9 +132,13 @@ int32_t mcp3550_read(uint8_t cs_pin)
|
|||||||
int64_t start = esp_timer_get_time();
|
int64_t start = esp_timer_get_time();
|
||||||
uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000;
|
uint32_t timeout_us = MCP3550_TIMEOUT_MS * 1000;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG_MCP, "Starting read from ADC CS %d", cs_pin);
|
||||||
|
|
||||||
// CS LOW
|
// CS LOW
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0);
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
// Wait for DR (MISO LOW)
|
// 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) {
|
||||||
|
30
main/main.c
30
main/main.c
@@ -25,6 +25,7 @@
|
|||||||
#include "hw/mcp23018.h"
|
#include "hw/mcp23018.h"
|
||||||
#include "hw/mpu9250.h"
|
#include "hw/mpu9250.h"
|
||||||
#include "hw/buscfg.h"
|
#include "hw/buscfg.h"
|
||||||
|
#include "components/sdcard.h"
|
||||||
|
|
||||||
#include "hw/gps.h"
|
#include "hw/gps.h"
|
||||||
|
|
||||||
@@ -36,18 +37,20 @@ void app_main(void)
|
|||||||
ESP_LOGI("BOOT", "BRN Systems incorporated CanSat flight firmware build at %s %s", __DATE__, __TIME__);
|
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_WITHOUT_ABORT(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));
|
||||||
|
|
||||||
spi_bus_config_t MCPBusCfg = {
|
// spi_bus_config_t MCPBusCfg = {
|
||||||
.mosi_io_num = -1,
|
// .mosi_io_num = -1,
|
||||||
.miso_io_num = MCP3550_MISO_GPIO,
|
// .miso_io_num = MCP3550_MISO_GPIO,
|
||||||
.sclk_io_num = MCP3550_SCK_GPIO,
|
// .sclk_io_num = MCP3550_SCK_GPIO,
|
||||||
.quadwp_io_num = -1,
|
// .quadwp_io_num = -1,
|
||||||
.quadhd_io_num = -1,
|
// .quadhd_io_num = -1,
|
||||||
.max_transfer_sz = 4,
|
// .max_transfer_sz = 4,
|
||||||
};
|
// };
|
||||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &MCPBusCfg, SPI_DMA_DISABLED));
|
// ESP_ERROR_CHECK_WITHOUT_ABORT(spi_bus_initialize(SPI2_HOST, &MCPBusCfg, SPI_DMA_DISABLED));
|
||||||
|
|
||||||
|
gpio_pullup_en(HSPI_MISO_GPIO);
|
||||||
|
gpio_pullup_en(HSPI_SD_CS);
|
||||||
spi_bus_config_t HighSpeedBusCfg = {
|
spi_bus_config_t HighSpeedBusCfg = {
|
||||||
// CONNECTED to LoRa and SD card
|
// CONNECTED to LoRa and SD card
|
||||||
.mosi_io_num = HSPI_MOSI_GPIO,
|
.mosi_io_num = HSPI_MOSI_GPIO,
|
||||||
@@ -57,12 +60,15 @@ void app_main(void)
|
|||||||
.quadhd_io_num = -1,
|
.quadhd_io_num = -1,
|
||||||
.max_transfer_sz = 64, // probably change
|
.max_transfer_sz = 64, // probably change
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &HighSpeedBusCfg, SPI_DMA_CH_AUTO));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(spi_bus_initialize(SPI3_HOST, &HighSpeedBusCfg, SPI_DMA_CH_AUTO));
|
||||||
|
|
||||||
/* scan i2c devices on i2c master bus 0 and print results */
|
/* scan i2c devices on i2c master bus 0 and print results */
|
||||||
ESP_ERROR_CHECK(i2c_master_bus_detect_devices(i2c0_bus_hdl));
|
ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_bus_detect_devices(i2c0_bus_hdl));
|
||||||
|
|
||||||
mcp23018_init();
|
mcp23018_init();
|
||||||
|
|
||||||
|
initSD();
|
||||||
|
|
||||||
void servoControllerInit();
|
void servoControllerInit();
|
||||||
|
|
||||||
ESP_LOGI(TAG, "BEGIN ESP TASKS");
|
ESP_LOGI(TAG, "BEGIN ESP TASKS");
|
||||||
|
@@ -426,39 +426,39 @@ static inline esp_err_t bme680_get_cal_factors(bme680_handle_t handle) {
|
|||||||
ESP_ARG_CHECK( handle );
|
ESP_ARG_CHECK( handle );
|
||||||
|
|
||||||
/* bme680 attempt to request T1-T3 calibration values from device */
|
/* bme680 attempt to request T1-T3 calibration values from device */
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0xe9, &handle->dev_cal_factors->par_T1) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0xe9, &handle->dev_cal_factors->par_T1) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x8a, (uint16_t *)&handle->dev_cal_factors->par_T2) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x8a, (uint16_t *)&handle->dev_cal_factors->par_T2) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x8c, (uint8_t *)&handle->dev_cal_factors->par_T3) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x8c, (uint8_t *)&handle->dev_cal_factors->par_T3) );
|
||||||
/* bme680 attempt to request H1-H7 calibration values from device */
|
/* bme680 attempt to request H1-H7 calibration values from device */
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_from(handle, 0xe2, rx, BIT16_UINT8_BUFFER_SIZE) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_from(handle, 0xe2, rx, BIT16_UINT8_BUFFER_SIZE) );
|
||||||
handle->dev_cal_factors->par_H1 = (uint16_t)(((uint16_t)rx[1] << 4) | (rx[0] & 0x0F));
|
handle->dev_cal_factors->par_H1 = (uint16_t)(((uint16_t)rx[1] << 4) | (rx[0] & 0x0F));
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_from(handle, 0xe1, rx, BIT16_UINT8_BUFFER_SIZE) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_from(handle, 0xe1, rx, BIT16_UINT8_BUFFER_SIZE) );
|
||||||
handle->dev_cal_factors->par_H2 = (uint16_t)(((uint16_t)rx[0] << 4) | (rx[1] >> 4));
|
handle->dev_cal_factors->par_H2 = (uint16_t)(((uint16_t)rx[0] << 4) | (rx[1] >> 4));
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xe4, (uint8_t *)&handle->dev_cal_factors->par_H3) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xe4, (uint8_t *)&handle->dev_cal_factors->par_H3) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xe5, (uint8_t *)&handle->dev_cal_factors->par_H4) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xe5, (uint8_t *)&handle->dev_cal_factors->par_H4) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xe6, (uint8_t *)&handle->dev_cal_factors->par_H5) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xe6, (uint8_t *)&handle->dev_cal_factors->par_H5) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xe7, &handle->dev_cal_factors->par_H6) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xe7, &handle->dev_cal_factors->par_H6) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xe8, (uint8_t *)&handle->dev_cal_factors->par_H7) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xe8, (uint8_t *)&handle->dev_cal_factors->par_H7) );
|
||||||
/* bme680 attempt to request P1-P10 calibration values from device */
|
/* bme680 attempt to request P1-P10 calibration values from device */
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x8e, &handle->dev_cal_factors->par_P1) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x8e, &handle->dev_cal_factors->par_P1) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x90, (uint16_t *)&handle->dev_cal_factors->par_P2) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x90, (uint16_t *)&handle->dev_cal_factors->par_P2) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x92, (uint8_t *)&handle->dev_cal_factors->par_P3) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x92, (uint8_t *)&handle->dev_cal_factors->par_P3) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x94, (uint16_t *)&handle->dev_cal_factors->par_P4) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x94, (uint16_t *)&handle->dev_cal_factors->par_P4) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x96, (uint16_t *)&handle->dev_cal_factors->par_P5) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x96, (uint16_t *)&handle->dev_cal_factors->par_P5) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x99, (uint8_t *)&handle->dev_cal_factors->par_P6) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x99, (uint8_t *)&handle->dev_cal_factors->par_P6) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x98, (uint8_t *)&handle->dev_cal_factors->par_P7) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x98, (uint8_t *)&handle->dev_cal_factors->par_P7) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x9c, (uint16_t *)&handle->dev_cal_factors->par_P8) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x9c, (uint16_t *)&handle->dev_cal_factors->par_P8) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0x9e, (uint16_t *)&handle->dev_cal_factors->par_P9) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0x9e, (uint16_t *)&handle->dev_cal_factors->par_P9) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xa0, &handle->dev_cal_factors->par_P10) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xa0, &handle->dev_cal_factors->par_P10) );
|
||||||
/* bme680 attempt to request G1-G3 calibration values from device */
|
/* bme680 attempt to request G1-G3 calibration values from device */
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xed, (uint8_t *)&handle->dev_cal_factors->par_G1) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xed, (uint8_t *)&handle->dev_cal_factors->par_G1) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_word_from(handle, 0xeb, (uint16_t *)&handle->dev_cal_factors->par_G2) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_word_from(handle, 0xeb, (uint16_t *)&handle->dev_cal_factors->par_G2) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0xee, (uint8_t *)&handle->dev_cal_factors->par_G3) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0xee, (uint8_t *)&handle->dev_cal_factors->par_G3) );
|
||||||
/* bme680 attempt to request gas range and switching error values from device */
|
/* bme680 attempt to request gas range and switching error values from device */
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x02, &handle->dev_cal_factors->res_heat_range) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x02, &handle->dev_cal_factors->res_heat_range) );
|
||||||
handle->dev_cal_factors->res_heat_range = (handle->dev_cal_factors->res_heat_range & 0x30) / 16;
|
handle->dev_cal_factors->res_heat_range = (handle->dev_cal_factors->res_heat_range & 0x30) / 16;
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x00, (uint8_t *)&handle->dev_cal_factors->res_heat_val) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x00, (uint8_t *)&handle->dev_cal_factors->res_heat_val) );
|
||||||
ESP_ERROR_CHECK( bme680_i2c_read_byte_from(handle, 0x04, (uint8_t *)&handle->dev_cal_factors->range_switching_error) );
|
ESP_ERROR_CHECK_WITHOUT_ABORT( bme680_i2c_read_byte_from(handle, 0x04, (uint8_t *)&handle->dev_cal_factors->range_switching_error) );
|
||||||
handle->dev_cal_factors->range_switching_error = (handle->dev_cal_factors->range_switching_error & 0xf0) / 16;
|
handle->dev_cal_factors->range_switching_error = (handle->dev_cal_factors->range_switching_error & 0xf0) / 16;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user