Compare commits
9 Commits
cb339e6b66
...
main
Author | SHA1 | Date | |
---|---|---|---|
22d9f1f32a | |||
ee54abb663
|
|||
76eb216716
|
|||
c26e5e012c | |||
5ea05fa209 | |||
8b9e72ef71
|
|||
0c71409c30
|
|||
3457b76938
|
|||
af4d8654de
|
@@ -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 ".")
|
||||||
|
@@ -2,79 +2,107 @@
|
|||||||
#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))
|
||||||
{
|
{
|
||||||
uint32_t packetIndex;
|
char syncPhrase[10]; //10
|
||||||
uint8_t packetType;
|
uint32_t packetIndex; //14
|
||||||
uint32_t missionTimer;
|
uint8_t packetType; //15
|
||||||
|
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 */ //70
|
||||||
|
float relative_humidity; /*!< relative humidity in percent */ //74
|
||||||
|
float barometric_pressure; /*!< barometric pressure in hecto-pascal */ //78
|
||||||
|
float gas_resistance; /*!< gas resistance in ohms */ //82
|
||||||
|
uint16_t iaq_score; /*!< air quality index (0..500) */ //84
|
||||||
|
float temperature_score; //88
|
||||||
|
float humidity_score; //92
|
||||||
|
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;
|
||||||
|
|
||||||
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 CRCCheck;
|
||||||
} UplinkPacket;
|
} UplinkPacket;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed))
|
||||||
@@ -85,4 +113,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,388 @@
|
|||||||
#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";
|
#include <hw/buscfg.h>
|
||||||
|
#include "sensors.h"
|
||||||
|
#include "sdcard.h"
|
||||||
|
|
||||||
#define TAG "LoRa"
|
#define TAG "LoRa"
|
||||||
|
|
||||||
uint32_t packetIndex = 0;
|
#define ACK_TIMEOUT_MS 250 // Wait 300ms for ACK
|
||||||
|
#define MAX_RETRIES 1
|
||||||
|
|
||||||
|
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 = 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;
|
||||||
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
|
LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn, invertIrq);
|
||||||
uint8_t bufOut[256]; // Maximum Payload size of SX1261/62/68 is 255
|
}
|
||||||
|
|
||||||
|
static void prepare_downbound_packet(DownBoundPacket *packet, uint8_t type, uint64_t missionTimer, uint32_t crc)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
packet->CRCCheck = crc;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
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...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
DownBoundPacket downboundPacket;
|
||||||
UplinkPacket uplinkPacket;
|
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)&telemetryPacket, sizeof(telemetryPacket));
|
||||||
SystemControlPacket systemControlPacket;
|
prepare_downbound_packet(&downboundPacket, DownlinkPacketType_Telemetry, missionTimer, crc);
|
||||||
|
|
||||||
while (1)
|
uint16_t offset = 0;
|
||||||
{
|
memcpy(bufOut + offset, &downboundPacket, sizeof(downboundPacket));
|
||||||
start_time = esp_timer_get_time(); // µs since boot
|
offset += sizeof(downboundPacket);
|
||||||
if (packetReadiness == 1)
|
memcpy(bufOut + offset, &telemetryPacket, sizeof(telemetryPacket));
|
||||||
{
|
offset += sizeof(telemetryPacket);
|
||||||
uint8_t downPacketSize = 0;
|
|
||||||
memset(bufOut, 0, sizeof(bufOut));
|
|
||||||
downboundPacket.missionTimer = start_time;
|
|
||||||
downboundPacket.packetIndex = packetIndex++;
|
|
||||||
downboundPacket.packetType = 1;
|
|
||||||
|
|
||||||
memcpy(bufOut, &downboundPacket, sizeof(downboundPacket));
|
if (csvFile != NULL) {
|
||||||
downPacketSize += sizeof(downboundPacket);
|
fprintf(csvFile,
|
||||||
memcpy(((uint8_t *)bufOut) + downPacketSize, &telemetryPacket, sizeof(telemetryPacket));
|
"%llu,%lu,%u,%u," // missionTimer, packetIndex, telemetryIndex, packetType
|
||||||
downPacketSize += sizeof(telemetryPacket);
|
"%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
|
||||||
|
|
||||||
ESP_LOGI(pcTaskGetName(NULL), "%d byte packet sent...", downPacketSize);
|
missionTimer,
|
||||||
|
downboundPacket.packetIndex,
|
||||||
|
telemetryPacket.telemetryIndex,
|
||||||
|
downboundPacket.packetType,
|
||||||
|
|
||||||
// Wait for transmission to complete
|
telemetryPacket.accelerationX, telemetryPacket.accelerationY, telemetryPacket.accelerationZ,
|
||||||
if (LoRaSend(bufOut, downPacketSize, SX126x_TXMODE_SYNC) == false)
|
telemetryPacket.gyroX, telemetryPacket.gyroY, telemetryPacket.gyroZ,
|
||||||
{
|
telemetryPacket.magnetX, telemetryPacket.magnetY, telemetryPacket.magnetZ,
|
||||||
ESP_LOGE(pcTaskGetName(NULL), "LoRaSend fail");
|
telemetryPacket.accelerometer_temperature,
|
||||||
} else {
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void build_and_send_ack(uint32_t ackIndex, uint32_t crc32Checksum, uint64_t missionTimer)
|
||||||
|
{
|
||||||
|
uint8_t bufOut[256] = {0};
|
||||||
|
|
||||||
|
ACKPacket ackPacket = {
|
||||||
|
.packetIndex = ackIndex,
|
||||||
|
.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;
|
||||||
|
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_LOGE(TAG, "Failed to send ACK");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "%d byte ACK sent", offset);
|
||||||
|
}
|
||||||
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 %ld", uplinkPacket.packetType, uplinkPacket.packetIndex);
|
||||||
|
|
||||||
|
uint8_t *payload = data + 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)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Received ACK for packet %ld", 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));
|
||||||
|
setPowerMode(sysCtrl.powerMode);
|
||||||
|
// 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 %ld packets", uplinkPacket.packetIndex - (packetIndexRX + 1));
|
||||||
|
packetIndexRX = uplinkPacket.packetIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Duplicate packet: %ld", (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));
|
uint8_t rxLen = LoRaReceive(bufIn, sizeof(bufIn));
|
||||||
if (rxLen > 0)
|
if (rxLen > 0)
|
||||||
{
|
{
|
||||||
ESP_LOGI(pcTaskGetName(NULL), "%d byte packet received:[%.*s]", rxLen, rxLen, bufIn);
|
ESP_LOGI(TAG, "%d byte packet received", rxLen);
|
||||||
|
process_uplink_packet(bufIn, rxLen, esp_timer_get_time());
|
||||||
int8_t rssi, snr;
|
int8_t rssi, snr;
|
||||||
GetPacketStatus(&rssi, &snr);
|
GetPacketStatus(&rssi, &snr);
|
||||||
ESP_LOGI(pcTaskGetName(NULL), "rssi=%d[dBm] snr=%d[dB]", rssi, snr);
|
ESP_LOGI(TAG, "rssi=%d[dBm], snr=%d[dB]", rssi, snr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lost = GetPacketLost();
|
// Release the semaphore when done with LoRa RX
|
||||||
if (lost != 0)
|
xSemaphoreGive(loraRadioMutex);
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10)); // Delay to prevent busy-waiting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lora_comms_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
ESP_LOGW(pcTaskGetName(NULL), "%d packets lost", lost);
|
|
||||||
|
// while (foundDevices[0] != 2) {
|
||||||
|
// vTaskDelay(10);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Initialize the semaphore for radio access (binary semaphore, 1 = available)
|
||||||
|
loraRadioMutex = xSemaphoreCreateMutex();
|
||||||
|
xSemaphoreGive(loraRadioMutex); // Set semaphore as available
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "lora_comms_task started");
|
||||||
|
setup_lora();
|
||||||
|
ESP_LOGI(TAG, "lora_comms_task continuing");
|
||||||
|
xTaskCreate(
|
||||||
|
lora_receive_task,
|
||||||
|
"LoraReceiveTask",
|
||||||
|
8192,
|
||||||
|
NULL,
|
||||||
|
(tskIDLE_PRIORITY + 2),
|
||||||
|
NULL);
|
||||||
|
ESP_LOGI(TAG, "loraInit");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int64_t start_time = esp_timer_get_time();
|
||||||
|
|
||||||
|
if (packetReadiness)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Preparing telemetry");
|
||||||
|
|
||||||
|
prepare_and_send_telemetry(start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
end_time = esp_timer_get_time();
|
const int64_t interval_us = ((powerMode == HIGH_POWER_MODE) ? 10000 : 10000000); // 10 ms or 10 000 ms
|
||||||
elapsed = end_time - start_time;
|
|
||||||
|
int64_t end_time = esp_timer_get_time();
|
||||||
|
int64_t elapsed = end_time - start_time;
|
||||||
|
|
||||||
if (elapsed < interval_us)
|
if (elapsed < interval_us)
|
||||||
{
|
{
|
||||||
|
@@ -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
|
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,14 +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 (;;)
|
||||||
{
|
{
|
||||||
packetReadiness = 2;
|
|
||||||
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);
|
||||||
@@ -151,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);
|
||||||
@@ -169,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;
|
log_mics_adc_values(&ADCData);
|
||||||
memset(&ADCData, 0, sizeof(ADCData));
|
|
||||||
//mics_adc_data_t ADCData = mcp3550_read_all(VREFVoltage);
|
|
||||||
|
|
||||||
//log_mics_adc_values(&ADCData);
|
if (packetReadiness == 0)
|
||||||
|
|
||||||
int32_t nh3val = mcp3550_read(MCP_CS_ADC_NH3);
|
|
||||||
|
|
||||||
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];
|
||||||
@@ -220,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;
|
||||||
@@ -229,6 +283,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;
|
||||||
@@ -253,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
|
||||||
|
@@ -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,
|
||||||
@@ -35,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -5,7 +5,7 @@ i2c_master_bus_config_t i2c0_bus_cfg = {
|
|||||||
.i2c_port = I2C_NUM_0,
|
.i2c_port = I2C_NUM_0,
|
||||||
.scl_io_num = HWI2C_SCL,
|
.scl_io_num = HWI2C_SCL,
|
||||||
.sda_io_num = HWI2C_SDA,
|
.sda_io_num = HWI2C_SDA,
|
||||||
.glitch_ignore_cnt = 7,
|
.glitch_ignore_cnt = 1,
|
||||||
.flags.enable_internal_pullup = true,
|
.flags.enable_internal_pullup = true,
|
||||||
};
|
};
|
||||||
i2c_master_bus_handle_t i2c0_bus_hdl;
|
i2c_master_bus_handle_t i2c0_bus_hdl;
|
||||||
|
@@ -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,15 +83,14 @@ 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)
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -84,41 +83,85 @@ 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
|
ESP_LOGI(TAG_MCP, "Starting read from ADC CS %d", cs_pin);
|
||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0); // CS LOW
|
|
||||||
|
|
||||||
// Wait until MISO/SDO goes LOW = DR ready
|
// CS LOW
|
||||||
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
35
main/main.c
35
main/main.c
@@ -25,29 +25,32 @@
|
|||||||
#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"
|
||||||
|
|
||||||
#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_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,14 +60,18 @@ 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");
|
||||||
|
|
||||||
/* create task pinned to the app core */
|
/* create task pinned to the app core */
|
||||||
xTaskCreate(
|
xTaskCreate(
|
||||||
|
@@ -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