Compare commits
2 Commits
35a11734e2
...
5853bf849f
Author | SHA1 | Date | |
---|---|---|---|
5853bf849f
|
|||
9104869ecf
|
17
.vscode/settings.json
vendored
17
.vscode/settings.json
vendored
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"C_Cpp.intelliSenseEngine": "default",
|
"C_Cpp.intelliSenseEngine": "default",
|
||||||
"idf.espIdfPath": "/home/bruno/esp/v5.4.1/esp-idf",
|
"idf.espIdfPath": "/home/bruno/esp/master/esp-idf",
|
||||||
"idf.pythonInstallPath": "/usr/bin/python",
|
"idf.pythonInstallPath": "/usr/bin/python",
|
||||||
"idf.openOcdConfigs": [
|
"idf.openOcdConfigs": [
|
||||||
"board/esp32s3-builtin.cfg"
|
"board/esp32s3-builtin.cfg"
|
||||||
@@ -29,6 +29,19 @@
|
|||||||
"esp_mac.h": "c",
|
"esp_mac.h": "c",
|
||||||
"gpio.h": "c",
|
"gpio.h": "c",
|
||||||
"chrono": "c",
|
"chrono": "c",
|
||||||
"cstdint": "c"
|
"cstdint": "c",
|
||||||
|
"task.h": "c",
|
||||||
|
"compare": "c",
|
||||||
|
"uart_struct.h": "c",
|
||||||
|
"uart.h": "c",
|
||||||
|
"gpio_num.h": "c",
|
||||||
|
"mcp3550.h": "c",
|
||||||
|
"esp_timer.h": "c",
|
||||||
|
"math.h": "c",
|
||||||
|
"esp_check.h": "c",
|
||||||
|
"radio.h": "c",
|
||||||
|
"sx1262.h": "c",
|
||||||
|
"gps.h": "c",
|
||||||
|
"servocontroller.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
set(component_srcs "ra01s.c")
|
|
||||||
|
|
||||||
idf_component_register(SRCS "${component_srcs}"
|
|
||||||
PRIV_REQUIRES driver
|
|
||||||
INCLUDE_DIRS ".")
|
|
@@ -1,163 +0,0 @@
|
|||||||
menu "SX126X Configuration"
|
|
||||||
|
|
||||||
config GPIO_RANGE_MAX
|
|
||||||
int
|
|
||||||
default 33 if IDF_TARGET_ESP32
|
|
||||||
default 46 if IDF_TARGET_ESP32S2
|
|
||||||
default 48 if IDF_TARGET_ESP32S3
|
|
||||||
default 18 if IDF_TARGET_ESP32C2
|
|
||||||
default 19 if IDF_TARGET_ESP32C3
|
|
||||||
default 30 if IDF_TARGET_ESP32C6
|
|
||||||
|
|
||||||
choice FREQUENCY
|
|
||||||
prompt "Frequency to use"
|
|
||||||
default 433MHZ
|
|
||||||
help
|
|
||||||
Select Frequency to use.
|
|
||||||
config 433MHZ
|
|
||||||
bool "433MHz"
|
|
||||||
help
|
|
||||||
Frequency is 433MHz.
|
|
||||||
config 866MHZ
|
|
||||||
bool "866MHz"
|
|
||||||
help
|
|
||||||
Frequency is 866MHz.
|
|
||||||
config 915MHZ
|
|
||||||
bool "915MHz"
|
|
||||||
help
|
|
||||||
Frequency is 915MHz.
|
|
||||||
config OTHER
|
|
||||||
bool "Other"
|
|
||||||
help
|
|
||||||
Other Frequency.
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
config OTHER_FREQUENCY
|
|
||||||
depends on OTHER
|
|
||||||
int "Frequency to use[MHz]"
|
|
||||||
range 1 999
|
|
||||||
default 433
|
|
||||||
help
|
|
||||||
Frequency to use[MHz].
|
|
||||||
|
|
||||||
config ADVANCED
|
|
||||||
bool "Enable Advanced settings"
|
|
||||||
default false
|
|
||||||
help
|
|
||||||
Enable Advanced settings.
|
|
||||||
|
|
||||||
config CODING_RATE
|
|
||||||
depends on ADVANCED
|
|
||||||
int "Error coding rate"
|
|
||||||
range 1 4
|
|
||||||
default 1
|
|
||||||
help
|
|
||||||
Error coding rate.
|
|
||||||
|
|
||||||
config BANDWIDTH
|
|
||||||
depends on ADVANCED
|
|
||||||
int "Signal Bandwidth"
|
|
||||||
range 0 6
|
|
||||||
default 4
|
|
||||||
help
|
|
||||||
Signal Bandwidth.
|
|
||||||
|
|
||||||
config SF_RATE
|
|
||||||
depends on ADVANCED
|
|
||||||
int "Spreading Factor"
|
|
||||||
range 5 12
|
|
||||||
default 7
|
|
||||||
help
|
|
||||||
Spreading Factor.
|
|
||||||
|
|
||||||
config USE_TCXO
|
|
||||||
bool "Enable TCXO"
|
|
||||||
default false
|
|
||||||
help
|
|
||||||
Enable Temperature-Compensated Crystal Oscillator.
|
|
||||||
|
|
||||||
config MISO_GPIO
|
|
||||||
int "SX126X MISO GPIO"
|
|
||||||
range 0 GPIO_RANGE_MAX
|
|
||||||
default 19 if IDF_TARGET_ESP32
|
|
||||||
default 37 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 4 # C3 and others
|
|
||||||
help
|
|
||||||
Pin Number to be used as the MISO SPI signal.
|
|
||||||
|
|
||||||
config SCLK_GPIO
|
|
||||||
int "SX126X SCLK GPIO"
|
|
||||||
range 0 GPIO_RANGE_MAX
|
|
||||||
default 18 if IDF_TARGET_ESP32
|
|
||||||
default 36 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 5 # C3 and others
|
|
||||||
help
|
|
||||||
Pin Number to be used as the SCLK SPI signal.
|
|
||||||
|
|
||||||
config MOSI_GPIO
|
|
||||||
int "SX126X MOSI GPIO"
|
|
||||||
range 0 GPIO_RANGE_MAX
|
|
||||||
default 23 if IDF_TARGET_ESP32
|
|
||||||
default 35 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 6 # C3 and others
|
|
||||||
help
|
|
||||||
Pin Number to be used as the MOSI SPI signal.
|
|
||||||
|
|
||||||
config NSS_GPIO
|
|
||||||
int "SX126X NSS GPIO"
|
|
||||||
range 0 GPIO_RANGE_MAX
|
|
||||||
default 15 if IDF_TARGET_ESP32
|
|
||||||
default 34 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 7 # C3 and others
|
|
||||||
help
|
|
||||||
Pin Number to be used as the NSS SPI signal.
|
|
||||||
|
|
||||||
config RST_GPIO
|
|
||||||
int "SX126X RST GPIO"
|
|
||||||
range 0 GPIO_RANGE_MAX
|
|
||||||
default 16 if IDF_TARGET_ESP32
|
|
||||||
default 38 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 2 # C3 and others
|
|
||||||
help
|
|
||||||
Pin Number to be used as the RST signal.
|
|
||||||
|
|
||||||
config BUSY_GPIO
|
|
||||||
int "SX126X BUSY GPIO"
|
|
||||||
range 0 GPIO_RANGE_MAX
|
|
||||||
default 17 if IDF_TARGET_ESP32
|
|
||||||
default 39 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
default 3 # C3 and others
|
|
||||||
help
|
|
||||||
Pin Number to be used as the BUSY signal.
|
|
||||||
|
|
||||||
config TXEN_GPIO
|
|
||||||
int "SX126X TXEN GPIO"
|
|
||||||
range -1 GPIO_RANGE_MAX
|
|
||||||
default -1
|
|
||||||
help
|
|
||||||
Pin Number to be used as the TXEN signal.
|
|
||||||
|
|
||||||
config RXEN_GPIO
|
|
||||||
int "SX126X RXEN GPIO"
|
|
||||||
range -1 GPIO_RANGE_MAX
|
|
||||||
default -1
|
|
||||||
help
|
|
||||||
Pin Number to be used as the RXEN signal.
|
|
||||||
|
|
||||||
choice SPI_HOST
|
|
||||||
prompt "SPI peripheral that controls this bus"
|
|
||||||
default SPI2_HOST
|
|
||||||
help
|
|
||||||
Select SPI peripheral that controls this bus.
|
|
||||||
config SPI2_HOST
|
|
||||||
bool "SPI2_HOST"
|
|
||||||
help
|
|
||||||
Use SPI2_HOST. This is also called HSPI_HOST.
|
|
||||||
config SPI3_HOST
|
|
||||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
|
||||||
bool "SPI3_HOST"
|
|
||||||
help
|
|
||||||
USE SPI3_HOST. This is also called VSPI_HOST
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
endmenu
|
|
@@ -2,7 +2,7 @@ dependencies:
|
|||||||
idf:
|
idf:
|
||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
version: 5.4.1
|
version: 5.5.0
|
||||||
k0i05/esp_bme680:
|
k0i05/esp_bme680:
|
||||||
component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8
|
component_hash: 2df0cb14d4425565a8745d4a96bfaa8ff7e90bbec3e208a073821406dded23c8
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@@ -13,8 +13,18 @@ idf_component_register(SRCS
|
|||||||
"hw/mcp23018.h"
|
"hw/mcp23018.h"
|
||||||
"hw/mpu9250.c"
|
"hw/mpu9250.c"
|
||||||
"hw/mpu9250.h"
|
"hw/mpu9250.h"
|
||||||
|
"hw/gps.c"
|
||||||
|
"hw/gps.h"
|
||||||
|
"hw/mcp3550.c"
|
||||||
|
"hw/mcp3550.h"
|
||||||
|
"hw/sx1262.c"
|
||||||
|
"hw/sx1262.h"
|
||||||
"components/sensors.c"
|
"components/sensors.c"
|
||||||
"components/sensors.h"
|
"components/sensors.h"
|
||||||
|
"components/servocontroller.c"
|
||||||
|
"components/servocontroller.h"
|
||||||
|
"components/radio.c"
|
||||||
|
"components/radio.h"
|
||||||
"main.c"
|
"main.c"
|
||||||
|
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
88
main/components/packets.h
Normal file
88
main/components/packets.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#ifndef PACKETS_STRUCTS
|
||||||
|
#define PACKETS_STRUCTS
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
uint32_t packetIndex;
|
||||||
|
uint8_t packetType;
|
||||||
|
uint32_t missionTimer;
|
||||||
|
} DownBoundPacket;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
// MPU data
|
||||||
|
int16_t accelerationX;
|
||||||
|
int16_t accelerationY;
|
||||||
|
int16_t accelerationZ;
|
||||||
|
int16_t gyroX;
|
||||||
|
int16_t gyroY;
|
||||||
|
int16_t gyroZ;
|
||||||
|
int16_t magnetX;
|
||||||
|
int16_t magnetY;
|
||||||
|
int16_t magnetZ;
|
||||||
|
int16_t accelerometer_temperature;
|
||||||
|
|
||||||
|
// CCS data
|
||||||
|
uint16_t eCO2;
|
||||||
|
uint16_t tvoc;
|
||||||
|
uint8_t currentCCS;
|
||||||
|
uint16_t rawCCSData;
|
||||||
|
|
||||||
|
// INA data
|
||||||
|
uint16_t volts;
|
||||||
|
uint16_t current;
|
||||||
|
uint16_t power;
|
||||||
|
|
||||||
|
// BME DATA
|
||||||
|
uint32_t temperature;
|
||||||
|
uint16_t humidity;
|
||||||
|
uint32_t pressure;
|
||||||
|
uint16_t gas;
|
||||||
|
bool gas_valid;
|
||||||
|
bool heater_stable;
|
||||||
|
uint8_t gas_range;
|
||||||
|
uint8_t gas_index;
|
||||||
|
|
||||||
|
// GPS DATA
|
||||||
|
uint32_t time_seconds; // Seconds since start of day
|
||||||
|
int32_t latitude_centi_degrees; // Latitude * 10,000
|
||||||
|
int32_t longitude_centi_degrees; // Longitude * 10,000
|
||||||
|
int16_t altitude_centi_meters; // Altitude * 100
|
||||||
|
uint8_t fix_quality;
|
||||||
|
uint8_t num_satellites;
|
||||||
|
uint16_t date_yyddmm; // YYDDMM (from GPRMC)
|
||||||
|
uint16_t speed_centi_knots; // Speed * 100 (from GPRMC)
|
||||||
|
|
||||||
|
int32_t predicted_latitude_centi_degrees; // Latitude * 10,000
|
||||||
|
int32_t predicted_longitude_centi_degrees; // Longitude * 10,000
|
||||||
|
int16_t predicted_altitude_centi_meters; // Altitude * 100
|
||||||
|
|
||||||
|
// ADC DATA
|
||||||
|
int32_t NH3;
|
||||||
|
int32_t CO;
|
||||||
|
int32_t NO2;
|
||||||
|
int32_t UVC;
|
||||||
|
|
||||||
|
int16_t currentServoA;
|
||||||
|
int16_t targetServoA;
|
||||||
|
int16_t currentServoB;
|
||||||
|
int16_t targetServoB;
|
||||||
|
|
||||||
|
} TelemetryPacket;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
uint32_t packetIndex;
|
||||||
|
uint8_t packetType;
|
||||||
|
} UplinkPacket;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed))
|
||||||
|
{
|
||||||
|
uint8_t powerMode;
|
||||||
|
uint8_t controlMode;
|
||||||
|
uint16_t servoA;
|
||||||
|
uint16_t servoB;
|
||||||
|
} SystemControlPacket;
|
||||||
|
|
||||||
|
#endif
|
108
main/components/radio.c
Normal file
108
main/components/radio.c
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "../hw/sx1262.h"
|
||||||
|
#include "radio.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
const char *msg = "Testing 123 test why is this not on air";
|
||||||
|
|
||||||
|
#define TAG "LoRa"
|
||||||
|
|
||||||
|
uint32_t packetIndex = 0;
|
||||||
|
|
||||||
|
TelemetryPacket telemetryPacket;
|
||||||
|
uint8_t packetReadiness = 0;
|
||||||
|
|
||||||
|
void lora_comms_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
|
||||||
|
const int64_t interval_us = 100000; // 100 ms
|
||||||
|
int64_t start_time, end_time, elapsed;
|
||||||
|
LoRaInit();
|
||||||
|
int8_t txPowerInDbm = 20;
|
||||||
|
|
||||||
|
uint32_t frequencyInHz = 0;
|
||||||
|
frequencyInHz = 869525000;
|
||||||
|
ESP_LOGW(TAG, "Enable TCXO");
|
||||||
|
float tcxoVoltage = 2.2; // use TCXO
|
||||||
|
bool useRegulatorLDO = true; // use DCDC + LDO
|
||||||
|
|
||||||
|
// LoRaDebugPrint(true);
|
||||||
|
if (LoRaBegin(frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO) != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Does not recognize the module");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t spreadingFactor = 7;
|
||||||
|
uint8_t bandwidth = SX126X_LORA_BW_250_0;
|
||||||
|
uint8_t codingRate = SX126X_LORA_CR_4_8;
|
||||||
|
uint16_t preambleLength = 8;
|
||||||
|
uint8_t payloadLen = 0;
|
||||||
|
bool crcOn = true;
|
||||||
|
bool invertIrq = false;
|
||||||
|
LoRaConfig(spreadingFactor, bandwidth, codingRate, preambleLength, payloadLen, crcOn, invertIrq);
|
||||||
|
uint8_t bufIn[256]; // Maximum Payload size of SX1261/62/68 is 255
|
||||||
|
uint8_t bufOut[256]; // Maximum Payload size of SX1261/62/68 is 255
|
||||||
|
|
||||||
|
DownBoundPacket downboundPacket;
|
||||||
|
UplinkPacket uplinkPacket;
|
||||||
|
SystemControlPacket systemControlPacket;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
start_time = esp_timer_get_time(); // µs since boot
|
||||||
|
if (packetReadiness == 1)
|
||||||
|
{
|
||||||
|
uint8_t downPacketSize = 0;
|
||||||
|
memset(bufOut, 0, sizeof(bufOut));
|
||||||
|
downboundPacket.missionTimer = start_time;
|
||||||
|
downboundPacket.packetIndex = packetIndex++;
|
||||||
|
downboundPacket.packetType = 1;
|
||||||
|
|
||||||
|
memcpy(bufOut, &downboundPacket, sizeof(downboundPacket));
|
||||||
|
downPacketSize += sizeof(downboundPacket);
|
||||||
|
memcpy(((uint8_t *)bufOut) + downPacketSize, &telemetryPacket, sizeof(telemetryPacket));
|
||||||
|
downPacketSize += sizeof(telemetryPacket);
|
||||||
|
|
||||||
|
ESP_LOGI(pcTaskGetName(NULL), "%d byte packet sent...", downPacketSize);
|
||||||
|
|
||||||
|
// Wait for transmission to complete
|
||||||
|
if (LoRaSend(bufOut, downPacketSize, SX126x_TXMODE_SYNC) == false)
|
||||||
|
{
|
||||||
|
ESP_LOGE(pcTaskGetName(NULL), "LoRaSend fail");
|
||||||
|
} else {
|
||||||
|
packetReadiness = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rxLen = LoRaReceive(bufIn, sizeof(bufIn));
|
||||||
|
if (rxLen > 0)
|
||||||
|
{
|
||||||
|
ESP_LOGI(pcTaskGetName(NULL), "%d byte packet received:[%.*s]", rxLen, rxLen, bufIn);
|
||||||
|
|
||||||
|
int8_t rssi, snr;
|
||||||
|
GetPacketStatus(&rssi, &snr);
|
||||||
|
ESP_LOGI(pcTaskGetName(NULL), "rssi=%d[dBm] snr=%d[dB]", rssi, snr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lost = GetPacketLost();
|
||||||
|
if (lost != 0)
|
||||||
|
{
|
||||||
|
ESP_LOGW(pcTaskGetName(NULL), "%d packets lost", lost);
|
||||||
|
}
|
||||||
|
|
||||||
|
end_time = esp_timer_get_time();
|
||||||
|
elapsed = end_time - start_time;
|
||||||
|
|
||||||
|
if (elapsed < interval_us)
|
||||||
|
{
|
||||||
|
vTaskDelay(pdMS_TO_TICKS((interval_us - elapsed) / 1000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
main/components/radio.h
Normal file
19
main/components/radio.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef RADIO_COMPONENT
|
||||||
|
#define RADIO_COMPONENT
|
||||||
|
|
||||||
|
#define LORA_POWER_LOW 2
|
||||||
|
#define LORA_POWER_HIGH 20
|
||||||
|
#define LORA_POWER_MAX_MAYBE_UNSAFE 22
|
||||||
|
|
||||||
|
#define LORA_TX_POWER LORA_POWER_LOW
|
||||||
|
|
||||||
|
#define TAG_RADIO "RADIO"
|
||||||
|
|
||||||
|
#include "packets.h"
|
||||||
|
|
||||||
|
void lora_comms_task(void *pvParameters);
|
||||||
|
|
||||||
|
extern TelemetryPacket telemetryPacket;
|
||||||
|
extern uint8_t packetReadiness;
|
||||||
|
|
||||||
|
#endif
|
@@ -1,4 +1,8 @@
|
|||||||
#include "sensors.h"
|
#include "sensors.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "radio.h"
|
||||||
|
#include "../hw/gps.h"
|
||||||
|
#include "servocontroller.h"
|
||||||
|
|
||||||
#define BLINK_GPIO 2
|
#define BLINK_GPIO 2
|
||||||
|
|
||||||
@@ -13,64 +17,76 @@ static void configure_led(void)
|
|||||||
void i2c_sensors_task(void *pvParameters)
|
void i2c_sensors_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
// initialize the xLastWakeTime variable with the current time.
|
// initialize the xLastWakeTime variable with the current time.
|
||||||
TickType_t last_wake_time = xTaskGetTickCount();
|
const int64_t interval_us = 100000; // 100 ms
|
||||||
const TickType_t I2C0_TASK_SAMPLING_RATE = 5;
|
int64_t start_time, end_time, elapsed;
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialize i2c device configuration
|
// initialize i2c device configuration
|
||||||
|
|
||||||
bme680b_init();
|
bme680b_init();
|
||||||
mpu9250_init();
|
mpu9250_init();
|
||||||
mcp23018_init();
|
|
||||||
ina260_init();
|
ina260_init();
|
||||||
ccs811_init();
|
ccs811_init();
|
||||||
|
|
||||||
|
mcp3550_spi_init();
|
||||||
configure_led();
|
configure_led();
|
||||||
|
|
||||||
int16_t accel[3], gyro[3], temp;
|
int16_t accel[3], gyro[3], temp, magnet[3];
|
||||||
float accel_f[3], gyro_f[3], temp_f;
|
float accel_f[3], gyro_f[3], temp_f, magnet_f[3];
|
||||||
|
|
||||||
uint16_t eCO2;
|
uint16_t eCO2;
|
||||||
uint16_t tvoc;
|
uint16_t tvoc;
|
||||||
|
uint8_t currentCCS;
|
||||||
|
uint16_t rawData;
|
||||||
|
|
||||||
uint16_t volts;
|
uint16_t volts;
|
||||||
uint16_t current;
|
uint16_t current;
|
||||||
uint16_t power;
|
uint16_t power;
|
||||||
|
|
||||||
|
bme680_data_t bmeData;
|
||||||
// task loop entry point
|
// task loop entry point
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
packetReadiness = 2;
|
||||||
|
start_time = esp_timer_get_time(); // µs since boot
|
||||||
//
|
//
|
||||||
// handle sensor
|
// handle sensor
|
||||||
|
|
||||||
if (BME680_DEV_HANDLE)
|
if (BME680_DEV_HANDLE)
|
||||||
{
|
{
|
||||||
bme680_data_t data;
|
esp_err_t result = bme680_get_data(BME680_DEV_HANDLE, &bmeData);
|
||||||
esp_err_t result = bme680_get_data(BME680_DEV_HANDLE, &data);
|
|
||||||
if (result != ESP_OK)
|
if (result != ESP_OK)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG_BME, "bme680 device read failed (%s)", esp_err_to_name(result));
|
ESP_LOGE(TAG_BME, "bme680 device read failed (%s)", esp_err_to_name(result));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data.barometric_pressure = data.barometric_pressure / 100;
|
bmeData.barometric_pressure = bmeData.barometric_pressure / 100;
|
||||||
// ESP_LOGI(TAG, "dewpoint temperature:%.2f °C", data.dewpoint_temperature);
|
ESP_LOGI(TAG_BME, "dewpoint temperature:%.2f °C", bmeData.dewpoint_temperature);
|
||||||
ESP_LOGI(TAG_BME, "air temperature: %.2f °C", data.air_temperature);
|
ESP_LOGI(TAG_BME, "air temperature: %.2f °C", bmeData.air_temperature);
|
||||||
ESP_LOGI(TAG_BME, "relative humidity: %.2f %%", data.relative_humidity);
|
ESP_LOGI(TAG_BME, "relative humidity: %.2f %%", bmeData.relative_humidity);
|
||||||
ESP_LOGI(TAG_BME, "barometric pressure: %.2f hPa", data.barometric_pressure);
|
ESP_LOGI(TAG_BME, "barometric pressure: %.2f hPa", bmeData.barometric_pressure);
|
||||||
// ESP_LOGI(TAG, "gas resistance: %.2f kOhms", data.gas_resistance / 1000);
|
ccs811_set_env_data(bmeData.air_temperature, bmeData.relative_humidity);
|
||||||
// ESP_LOGI(TAG, "iaq score: %u (%s)", data.iaq_score, bme680_air_quality_to_string(data.iaq_score));
|
ESP_LOGI(TAG_BME, "gas resistance: %.2f kOhms", bmeData.gas_resistance / 1000);
|
||||||
|
ESP_LOGI(TAG_BME, "iaq score: %u (%s)", bmeData.iaq_score, bme680_air_quality_to_string(bmeData.iaq_score));
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
bme680b_init();
|
bme680b_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
ccs811_get_data(&eCO2, &tvoc);
|
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);
|
||||||
|
|
||||||
if (mpu9250_read_sensor_data(MPU9250_DEV_HANDLE, accel, gyro, &temp) == ESP_OK)
|
if (mpu9250_read_sensor_data(MPU9250_DEV_HANDLE, accel, gyro, &temp, magnet) == ESP_OK)
|
||||||
{
|
{
|
||||||
mpu9250_convert_data(accel, gyro, temp, accel_f, gyro_f, &temp_f);
|
mpu9250_convert_data(accel, gyro, temp, magnet, accel_f, gyro_f, &temp_f, magnet_f);
|
||||||
|
|
||||||
ESP_LOGI(TAG_MPU, "Accel: X=%.2f g, Y=%.2f g, Z=%.2f g", accel_f[0], accel_f[1], accel_f[2]);
|
ESP_LOGI(TAG_MPU, "Accel: X=%.2f g, Y=%.2f g, Z=%.2f g", accel_f[0], accel_f[1], accel_f[2]);
|
||||||
ESP_LOGI(TAG_MPU, "Gyro: X=%.2f°/s, Y=%.2f°/s, Z=%.2f°/s", gyro_f[0], gyro_f[1], gyro_f[2]);
|
ESP_LOGI(TAG_MPU, "Gyro: X=%.2f°/s, Y=%.2f°/s, Z=%.2f°/s", gyro_f[0], gyro_f[1], gyro_f[2]);
|
||||||
|
ESP_LOGI(TAG_MPU, "Magnet: X=%.2fμT, Y=%.2fμT, Z=%.2fμT", magnet_f[0], magnet_f[1], magnet_f[2]);
|
||||||
ESP_LOGI(TAG_MPU, "Temperature: %.2f °C", temp_f);
|
ESP_LOGI(TAG_MPU, "Temperature: %.2f °C", temp_f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -81,10 +97,86 @@ void i2c_sensors_task(void *pvParameters)
|
|||||||
ina260_readParams(&volts, ¤t, &power);
|
ina260_readParams(&volts, ¤t, &power);
|
||||||
ina260_printParams(volts, current, power);
|
ina260_printParams(volts, current, power);
|
||||||
|
|
||||||
|
float VREFVoltage = volts * 1.25 / 1000; // Mame vobec nieco na VREFE? Na scheme su len medzi sebou prepojene
|
||||||
|
|
||||||
|
mics_adc_data_t ADCData = mcp3550_read_all(5.0); // vref = 5.0V
|
||||||
|
log_mics_adc_values(&ADCData);
|
||||||
|
|
||||||
|
ADCData = mcp3550_read_all(VREFVoltage);
|
||||||
|
|
||||||
|
log_mics_adc_values(&ADCData);
|
||||||
|
|
||||||
gpio_set_level(BLINK_GPIO, s_led_state);
|
gpio_set_level(BLINK_GPIO, s_led_state);
|
||||||
/* Toggle the LED state */
|
/* Toggle the LED state */
|
||||||
s_led_state = !s_led_state;
|
s_led_state = !s_led_state;
|
||||||
vTaskDelaySecUntil(&last_wake_time, I2C0_TASK_SAMPLING_RATE);
|
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));
|
||||||
|
telemetryPacket.accelerationX = accel[0];
|
||||||
|
telemetryPacket.accelerationY = accel[1];
|
||||||
|
telemetryPacket.accelerationZ = accel[2];
|
||||||
|
|
||||||
|
telemetryPacket.gyroX = gyro[0];
|
||||||
|
telemetryPacket.gyroX = gyro[1];
|
||||||
|
telemetryPacket.gyroX = gyro[2];
|
||||||
|
|
||||||
|
telemetryPacket.magnetX = gyro[0];
|
||||||
|
telemetryPacket.magnetX = gyro[1];
|
||||||
|
telemetryPacket.magnetX = gyro[2];
|
||||||
|
|
||||||
|
telemetryPacket.accelerometer_temperature = temp;
|
||||||
|
|
||||||
|
telemetryPacket.eCO2 = eCO2;
|
||||||
|
telemetryPacket.tvoc = tvoc;
|
||||||
|
telemetryPacket.currentCCS = currentCCS;
|
||||||
|
telemetryPacket.rawCCSData = rawData;
|
||||||
|
|
||||||
|
telemetryPacket.volts = volts;
|
||||||
|
telemetryPacket.current = current;
|
||||||
|
telemetryPacket.power = power;
|
||||||
|
|
||||||
|
|
||||||
|
telemetryPacket.temperature = bmeData.raw_data.temperature;
|
||||||
|
telemetryPacket.humidity = bmeData.raw_data.humidity;
|
||||||
|
telemetryPacket.pressure = bmeData.raw_data.pressure;
|
||||||
|
telemetryPacket.gas = bmeData.raw_data.gas;
|
||||||
|
telemetryPacket.gas_range = bmeData.raw_data.gas_range;
|
||||||
|
telemetryPacket.heater_stable = bmeData.raw_data.heater_stable;
|
||||||
|
telemetryPacket.gas_valid = bmeData.raw_data.gas_valid;
|
||||||
|
|
||||||
|
telemetryPacket.NH3 = ADCData.raw_nh3;
|
||||||
|
telemetryPacket.CO = ADCData.raw_co;
|
||||||
|
telemetryPacket.NO2 = ADCData.raw_no2;
|
||||||
|
telemetryPacket.UVC = ADCData.raw_uvc;
|
||||||
|
|
||||||
|
//TODO MOVE THIS TO A BETTER PLACE FOR SYNC
|
||||||
|
telemetryPacket.time_seconds = gpsDataOut.time_seconds;
|
||||||
|
telemetryPacket.latitude_centi_degrees = gpsDataOut.latitude_centi_degrees;
|
||||||
|
telemetryPacket.longitude_centi_degrees = gpsDataOut.longitude_centi_degrees;
|
||||||
|
telemetryPacket.fix_quality = gpsDataOut.fix_quality;
|
||||||
|
telemetryPacket.num_satellites = gpsDataOut.num_satellites;
|
||||||
|
telemetryPacket.altitude_centi_meters = gpsDataOut.altitude_centi_meters;
|
||||||
|
telemetryPacket.date_yyddmm = gpsDataOut.date_yyddmm;
|
||||||
|
telemetryPacket.speed_centi_knots = gpsDataOut.speed_centi_knots;
|
||||||
|
|
||||||
|
telemetryPacket.predicted_altitude_centi_meters = predictedPosition.altitude_centi_meters;
|
||||||
|
telemetryPacket.predicted_latitude_centi_degrees = predictedPosition.latitude_centi_degrees;
|
||||||
|
telemetryPacket.predicted_longitude_centi_degrees = predictedPosition.longitude_centi_degrees;
|
||||||
|
|
||||||
|
telemetryPacket.targetServoA = servoState.targetServoA;
|
||||||
|
telemetryPacket.targetServoB = servoState.targetServoB;
|
||||||
|
telemetryPacket.currentServoA = servoState.currentServoA;
|
||||||
|
telemetryPacket.currentServoB = servoState.currentServoB;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
packetReadiness = 1;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// free resources
|
// free resources
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
#include <bme680.h>
|
#include <bme680.h>
|
||||||
#include "esp_mac.h"
|
#include "esp_mac.h"
|
||||||
|
|
||||||
|
#include "../hw/mcp3550.h"
|
||||||
|
|
||||||
#include "../hw/bme680b.h"
|
#include "../hw/bme680b.h"
|
||||||
#include "../hw/ccs811.h"
|
#include "../hw/ccs811.h"
|
||||||
#include "../hw/i2cbrn.h"
|
#include "../hw/i2cbrn.h"
|
||||||
|
10
main/components/servocontroller.c
Normal file
10
main/components/servocontroller.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "servocontroller.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
ServoState servoState;
|
||||||
|
|
||||||
|
//TODO add a task and implement
|
||||||
|
|
||||||
|
void servoControllerInit() {
|
||||||
|
memset(&servoState, 0, sizeof(servoState));
|
||||||
|
}
|
19
main/components/servocontroller.h
Normal file
19
main/components/servocontroller.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef SERVO_CONTROLLER_COMPONENT
|
||||||
|
#define SERVO_CONTROLLER_COMPONENT
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int16_t currentServoA;
|
||||||
|
int16_t targetServoA;
|
||||||
|
int16_t currentServoB;
|
||||||
|
int16_t targetServoB;
|
||||||
|
} ServoState;
|
||||||
|
|
||||||
|
|
||||||
|
extern ServoState servoState;
|
||||||
|
|
||||||
|
void servoControllerInit();
|
||||||
|
|
||||||
|
#endif
|
70
main/hw/buscfg.h
Normal file
70
main/hw/buscfg.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#ifndef BUSCFG_FILE
|
||||||
|
#define BUSCFG_FILE
|
||||||
|
|
||||||
|
#include "soc/gpio_num.h"
|
||||||
|
|
||||||
|
#define ESP_USB_DP GPIO_NUM_20
|
||||||
|
#define ESP_USB_DM GPIO_NUM_19
|
||||||
|
#define ESP_RXD0 GPIO_NUM_44
|
||||||
|
#define ESP_TXD0 GPIO_NUM_43
|
||||||
|
|
||||||
|
#define ESP_CONNECTOR_P1 MCP3550_MISO_GPIO
|
||||||
|
#define ESP_CONNECTOR_P2 MCP3550_MOSI_GPIO
|
||||||
|
#define ESP_CONNECTOR_P3 MCP3550_SCK_GPIO
|
||||||
|
#define ESP_CONNECTOR_P4 GPIO_NUM_39
|
||||||
|
#define ESP_CONNECTOR_P5 GPIO_NUM_38
|
||||||
|
#define ESP_CONNECTOR_P6 HSPI_UNKNOWN_CS
|
||||||
|
#define ESP_CONNECTOR_P9 HSPI_MISO_GPIO
|
||||||
|
#define ESP_CONNECTOR_P10 MCP3550_MOSI_GPIO
|
||||||
|
#define ESP_CONNECTOR_P11 MCP3550_SCK_GPIO
|
||||||
|
#define ESP_CONNECTOR_P12 HSPI_SD_CS
|
||||||
|
#define ESP_CONNECTOR_P13 HSPI_LORA_CS
|
||||||
|
#define ESP_CONNECTOR_P17 HWI2C_SDA
|
||||||
|
#define ESP_CONNECTOR_P18 HWI2C_SCL
|
||||||
|
#define ESP_CONNECTOR_P19 I2C2_SDA
|
||||||
|
#define ESP_CONNECTOR_P20 I2C2_SCL
|
||||||
|
#define ESP_CONNECTOR_P25 LORA_DIO1
|
||||||
|
#define ESP_CONNECTOR_P26 LORA_BUSY
|
||||||
|
#define ESP_CONNECTOR_P27 LORA_RXEN_MANUAL
|
||||||
|
#define ESP_CONNECTOR_P28 GPIO_NUM_6
|
||||||
|
#define ESP_CONNECTOR_P29 GPIO_NUM_5
|
||||||
|
#define ESP_CONNECTOR_P30 GPIO_NUM_4
|
||||||
|
#define ESP_CONNECTOR_P47 GPS_RXD
|
||||||
|
#define ESP_CONNECTOR_P48 GPS_TXD
|
||||||
|
#define ESP_CONNECTOR_P51 ESP_RXD0
|
||||||
|
#define ESP_CONNECTOR_P52 ESP_TXD0
|
||||||
|
#define ESP_CONNECTOR_P57 ESP_USB_DP
|
||||||
|
#define ESP_CONNECTOR_P58 ESP_USB_DM
|
||||||
|
|
||||||
|
|
||||||
|
#define HSPI_UNKNOWN_CS GPIO_NUM_42
|
||||||
|
#define LORA_RXEN_MANUAL GPIO_NUM_7
|
||||||
|
|
||||||
|
#define HSPI_MISO_GPIO GPIO_NUM_13
|
||||||
|
#define HSPI_MOSI_GPIO GPIO_NUM_11
|
||||||
|
//#define HSPI_MISO_GPIO GPIO_NUM_11
|
||||||
|
//#define HSPI_MOSI_GPIO GPIO_NUM_13
|
||||||
|
|
||||||
|
#define HSPI_SCK_GPIO GPIO_NUM_12
|
||||||
|
#define HSPI_LORA_CS GPIO_NUM_48
|
||||||
|
#define LORA_DIO1 GPIO_NUM_16
|
||||||
|
#define LORA_BUSY GPIO_NUM_15
|
||||||
|
#define HSPI_SD_CS GPIO_NUM_10
|
||||||
|
|
||||||
|
#define MCP3550_MOSI_GPIO GPIO_NUM_35
|
||||||
|
#define MCP3550_SCK_GPIO GPIO_NUM_36
|
||||||
|
#define MCP3550_MISO_GPIO GPIO_NUM_37
|
||||||
|
|
||||||
|
#define GPS_TXD GPIO_NUM_17
|
||||||
|
#define GPS_RXD GPIO_NUM_18
|
||||||
|
#define GPS_RTS UART_PIN_NO_CHANGE
|
||||||
|
#define GPS_CTS UART_PIN_NO_CHANGE
|
||||||
|
|
||||||
|
#define GPS_UART_NUM UART_NUM_2
|
||||||
|
|
||||||
|
#define HWI2C_SDA GPIO_NUM_8
|
||||||
|
#define HWI2C_SCL GPIO_NUM_9
|
||||||
|
#define I2C2_SDA GPIO_NUM_40
|
||||||
|
#define I2C2_SCL GPIO_NUM_41
|
||||||
|
|
||||||
|
#endif
|
@@ -10,6 +10,22 @@ i2c_device_config_t CCS811_DEV_CFG = {
|
|||||||
|
|
||||||
i2c_master_dev_handle_t CCS811_DEV_HANDLE;
|
i2c_master_dev_handle_t CCS811_DEV_HANDLE;
|
||||||
|
|
||||||
|
void ccs811_getStatus()
|
||||||
|
{
|
||||||
|
uint8_t errorID;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t hardwareVersion;
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t bootVersion;
|
||||||
|
|
||||||
|
i2c_read_register_8(CCS811_DEV_HANDLE, CCS811_REG_STATUS, &status);
|
||||||
|
i2c_read_register_16(CCS811_DEV_HANDLE, CCS811_REG_FW_APP_VERSION, &version);
|
||||||
|
i2c_read_register_16(CCS811_DEV_HANDLE, CCS811_REG_FW_BOOT_VERSION, &bootVersion);
|
||||||
|
i2c_read_register_8(CCS811_DEV_HANDLE, CCS811_REG_HW_VERSION, &hardwareVersion);
|
||||||
|
i2c_read_register_8(CCS811_DEV_HANDLE, CCS811_REG_ERROR_ID, &errorID);
|
||||||
|
ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d, boot version: %d, hardware version: %d, error ID: %d", status, version, bootVersion, hardwareVersion, errorID);
|
||||||
|
}
|
||||||
|
|
||||||
void ccs811_init()
|
void ccs811_init()
|
||||||
{
|
{
|
||||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &CCS811_DEV_CFG, &CCS811_DEV_HANDLE));
|
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &CCS811_DEV_CFG, &CCS811_DEV_HANDLE));
|
||||||
@@ -17,30 +33,47 @@ void ccs811_init()
|
|||||||
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 1);
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 1);
|
||||||
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};
|
||||||
i2c_write_register(CCS811_DEV_HANDLE, 0xFF, reset_seq, sizeof(reset_seq)); //Reset
|
i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_SW_RESET, reset_seq, sizeof(reset_seq)); // Reset
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
uint8_t status;
|
|
||||||
uint16_t version;
|
|
||||||
i2c_read_register_8(CCS811_DEV_HANDLE, 0x00, &status);
|
|
||||||
i2c_read_register_16(CCS811_DEV_HANDLE, 0x24, &version);
|
|
||||||
ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d", status, version);
|
|
||||||
i2c_write_register(CCS811_DEV_HANDLE, 0xF4, NULL, 0); //start
|
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
|
||||||
i2c_write_register_8(CCS811_DEV_HANDLE, 0x10, 0x0001); // MODE 1 interrupts vypnuté
|
|
||||||
i2c_read_register_8(CCS811_DEV_HANDLE, 0x00, &status);
|
|
||||||
i2c_read_register_16(CCS811_DEV_HANDLE, 0x24, &version);
|
|
||||||
ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d", status, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t ccs811_get_data(uint16_t * eCO2, uint16_t * tvoc)
|
ccs811_getStatus();
|
||||||
|
i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_APP_START, NULL, 0); // start
|
||||||
|
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_write_register_8(CCS811_DEV_HANDLE, CCS811_REG_MEAS_MODE, 0x40); // MODE 1 interrupts vypnuté
|
||||||
|
ccs811_getStatus();
|
||||||
|
}
|
||||||
|
esp_err_t ccs811_get_data(uint16_t *eCO2, uint16_t *tvoc, uint8_t *current, uint16_t *rawData)
|
||||||
{
|
{
|
||||||
uint8_t ccsResult[8];
|
uint8_t algResultData[8];
|
||||||
esp_err_t ret = i2c_read_register(CCS811_DEV_HANDLE, 0x05, ccsResult, 8);
|
esp_err_t ret = i2c_read_register(CCS811_DEV_HANDLE, CCS811_REG_ALG_RESULT_DATA, algResultData, 8);
|
||||||
|
|
||||||
if (ret == ESP_OK)
|
if (ret == ESP_OK)
|
||||||
{
|
{
|
||||||
*eCO2 = (((uint16_t)(ccsResult[0] & 0xFF)) << 8) | (ccsResult[1] & 0xFF);
|
*eCO2 = ((uint16_t)algResultData[0] << 8) | algResultData[1];
|
||||||
*tvoc = (((uint16_t)(ccsResult[2] & 0xFF)) << 8) | (ccsResult[3] & 0xFF);
|
*tvoc = ((uint16_t)algResultData[2] << 8) | algResultData[3];
|
||||||
ESP_LOGI(TAG_CCS, "CCS Status: %d, Error %d", ccsResult[4], ccsResult[5]);
|
*current = algResultData[6] >> 2;
|
||||||
|
*rawData = ((uint16_t)(algResultData[6] & 0x03) << 8) | algResultData[7];
|
||||||
|
|
||||||
|
ESP_LOGI(TAG_CCS, "CCS Status: %d, Error: %d", algResultData[4], algResultData[5]);
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t ccs811_set_env_data(float temperature, float humidity)
|
||||||
|
{
|
||||||
|
uint8_t envData[4];
|
||||||
|
|
||||||
|
// Convert humidity: %RH × 512 (rounding)
|
||||||
|
uint16_t hum_conv = (uint16_t)(humidity * 512.0f + 0.5f);
|
||||||
|
envData[0] = (hum_conv >> 8) & 0xFF;
|
||||||
|
envData[1] = hum_conv & 0xFF;
|
||||||
|
|
||||||
|
// Convert temperature: (°C + 25) × 512
|
||||||
|
uint16_t temp_conv = (uint16_t)((temperature + 25.0f) * 512.0f + 0.5f);
|
||||||
|
envData[2] = (temp_conv >> 8) & 0xFF;
|
||||||
|
envData[3] = temp_conv & 0xFF;
|
||||||
|
|
||||||
|
return i2c_write_register(CCS811_DEV_HANDLE, CCS811_REG_ENV_DATA, envData, 4);
|
||||||
|
}
|
||||||
|
@@ -5,11 +5,39 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#define TAG_CCS "CCS811"
|
#define TAG_CCS "CCS811"
|
||||||
|
|
||||||
|
// CCS811 Registers
|
||||||
|
#define CCS811_REG_STATUS 0x00
|
||||||
|
#define CCS811_REG_MEAS_MODE 0x01
|
||||||
|
#define CCS811_REG_ALG_RESULT_DATA 0x02
|
||||||
|
#define CCS811_REG_RAW_DATA 0x03
|
||||||
|
#define CCS811_REG_ENV_DATA 0x05
|
||||||
|
#define CCS811_REG_THRESHOLDS 0x10
|
||||||
|
#define CCS811_REG_BASELINE 0x11
|
||||||
|
#define CCS811_REG_HW_ID 0x20
|
||||||
|
#define CCS811_REG_HW_VERSION 0x21
|
||||||
|
#define CCS811_REG_FW_BOOT_VERSION 0x23
|
||||||
|
#define CCS811_REG_FW_APP_VERSION 0x24
|
||||||
|
#define CCS811_REG_INTERNAL_STATE 0xA0
|
||||||
|
#define CCS811_REG_ERROR_ID 0xE0
|
||||||
|
#define CCS811_REG_APP_ERASE 0xF1
|
||||||
|
#define CCS811_REG_APP_DATA 0xF2
|
||||||
|
#define CCS811_REG_APP_VERIFY 0xF3
|
||||||
|
#define CCS811_REG_APP_START 0xF4
|
||||||
|
#define CCS811_REG_SW_RESET 0xFF
|
||||||
|
|
||||||
|
// Measurement Modes
|
||||||
|
#define CCS811_MODE_IDLE 0x00
|
||||||
|
#define CCS811_MODE_CONSTANT_1S 0x10
|
||||||
|
#define CCS811_MODE_CONSTANT_10S 0x20
|
||||||
|
#define CCS811_MODE_CONSTANT_60S 0x30
|
||||||
|
#define CCS811_MODE_WAKEUP 0x40
|
||||||
|
|
||||||
extern i2c_device_config_t CCS811_DEV_CFG;
|
extern i2c_device_config_t CCS811_DEV_CFG;
|
||||||
|
|
||||||
extern i2c_master_dev_handle_t CCS811_DEV_HANDLE;
|
extern i2c_master_dev_handle_t CCS811_DEV_HANDLE;
|
||||||
|
|
||||||
void ccs811_init();
|
void ccs811_init();
|
||||||
esp_err_t ccs811_get_data(uint16_t * eCO2, uint16_t * tvoc);
|
esp_err_t ccs811_get_data(uint16_t *eCO2, uint16_t *tvoc, uint8_t *current, uint16_t *rawData);
|
||||||
|
esp_err_t ccs811_set_env_data(float temperature, float humidity);
|
||||||
#endif
|
#endif
|
244
main/hw/gps.c
Normal file
244
main/hw/gps.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
#include "driver/uart.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "gps.h"
|
||||||
|
|
||||||
|
#define TAG "GPS"
|
||||||
|
#define BUF_SIZE 1024
|
||||||
|
#define GPS_LINE_MAX_LEN 128
|
||||||
|
|
||||||
|
gps_binary_struct_t gpsDataOut;
|
||||||
|
static QueueHandle_t uart_queue;
|
||||||
|
|
||||||
|
predicted_binary_position_struct_t predictedPosition;
|
||||||
|
|
||||||
|
// Initializes UART for GPS
|
||||||
|
void gps_init()
|
||||||
|
{
|
||||||
|
memset(&gpsDataOut, 0, sizeof(gpsDataOut));
|
||||||
|
uart_config_t uart_config = {
|
||||||
|
.baud_rate = 9600,
|
||||||
|
.data_bits = UART_DATA_8_BITS,
|
||||||
|
.parity = UART_PARITY_DISABLE,
|
||||||
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
|
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
|
||||||
|
.rx_flow_ctrl_thresh = 122,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(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));
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gps_task(void *arg)
|
||||||
|
{
|
||||||
|
uint8_t byte;
|
||||||
|
char line[GPS_LINE_MAX_LEN];
|
||||||
|
size_t line_pos = 0;
|
||||||
|
|
||||||
|
gps_init();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int len = uart_read_bytes(GPS_UART_NUM, &byte, 1, pdMS_TO_TICKS(1000));
|
||||||
|
if (len > 0) {
|
||||||
|
if (byte == '\n') {
|
||||||
|
line[line_pos] = '\0';
|
||||||
|
|
||||||
|
if (line[0] == '$') {
|
||||||
|
ESP_LOGV(TAG, "Received NMEA: %s", line);
|
||||||
|
|
||||||
|
if (strstr(line, "$GPGGA") == line) {
|
||||||
|
parse_gpgga(line);
|
||||||
|
parse_gpgga_to_struct(line, &gpsDataOut);
|
||||||
|
} else if (strstr(line, "$GPRMC") == line) {
|
||||||
|
parse_gprmc(line);
|
||||||
|
parse_gprmc_to_struct(line, &gpsDataOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
line_pos = 0;
|
||||||
|
} else if (byte != '\r' && line_pos < (GPS_LINE_MAX_LEN - 1)) {
|
||||||
|
line[line_pos++] = byte;
|
||||||
|
} else if (line_pos >= GPS_LINE_MAX_LEN - 1) {
|
||||||
|
ESP_LOGW(TAG, "Line too long, discarded");
|
||||||
|
line_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_gpgga(const char *nmea)
|
||||||
|
{
|
||||||
|
char *fields[15];
|
||||||
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
|
temp[GPS_LINE_MAX_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
char *token = strtok(temp, ",");
|
||||||
|
while (token != NULL && i < 15) {
|
||||||
|
fields[i++] = token;
|
||||||
|
token = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 10) return; // Not enough fields
|
||||||
|
|
||||||
|
// Time (hhmmss.sss)
|
||||||
|
const char *utc_time = fields[1];
|
||||||
|
|
||||||
|
// Latitude (ddmm.mmmm)
|
||||||
|
const char *lat = fields[2];
|
||||||
|
const char *lat_dir = fields[3];
|
||||||
|
|
||||||
|
// Longitude (dddmm.mmmm)
|
||||||
|
const char *lon = fields[4];
|
||||||
|
const char *lon_dir = fields[5];
|
||||||
|
|
||||||
|
// Fix quality (0 = invalid, 1 = GPS fix, 2 = DGPS fix)
|
||||||
|
const char *fix_quality = fields[6];
|
||||||
|
|
||||||
|
// Number of satellites
|
||||||
|
const char *num_satellites = fields[7];
|
||||||
|
|
||||||
|
// Altitude
|
||||||
|
const char *altitude = fields[9];
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "[GPGGA] Time: %s, Lat: %s %s, Lon: %s %s, Fix: %s, Sats: %s, Alt: %sm",
|
||||||
|
utc_time, lat, lat_dir, lon, lon_dir, fix_quality, num_satellites, altitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_gprmc(const char *nmea)
|
||||||
|
{
|
||||||
|
char *fields[13];
|
||||||
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
|
temp[GPS_LINE_MAX_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
char *token = strtok(temp, ",");
|
||||||
|
while (token != NULL && i < 13) {
|
||||||
|
fields[i++] = token;
|
||||||
|
token = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 12) return;
|
||||||
|
|
||||||
|
const char *utc_time = fields[1];
|
||||||
|
const char *status = fields[2]; // A = active, V = void
|
||||||
|
const char *lat = fields[3];
|
||||||
|
const char *lat_dir = fields[4];
|
||||||
|
const char *lon = fields[5];
|
||||||
|
const char *lon_dir = fields[6];
|
||||||
|
const char *speed_knots = fields[7];
|
||||||
|
const char *date = fields[9];
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "[GPRMC] Date: %s, Time: %s, Lat: %s %s, Lon: %s %s, Speed: %s knots, Status: %s",
|
||||||
|
date, utc_time, lat, lat_dir, lon, lon_dir, speed_knots, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Function to convert time string (hhmmss.sss) to seconds since start of day
|
||||||
|
static uint32_t time_to_seconds_struct(const char *time_str) {
|
||||||
|
if (time_str == NULL || strlen(time_str) < 6) return 0;
|
||||||
|
uint32_t hours = (time_str[0] - '0') * 10 + (time_str[1] - '0');
|
||||||
|
uint32_t minutes = (time_str[2] - '0') * 10 + (time_str[3] - '0');
|
||||||
|
uint32_t seconds = (time_str[4] - '0') * 10 + (time_str[5] - '0');
|
||||||
|
return hours * 3600 + minutes * 60 + seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
if (dms_str == NULL || direction == NULL || strlen(dms_str) < 7) return 0;
|
||||||
|
char degrees_str[4] = {0};
|
||||||
|
char minutes_decimal_str[10] = {0};
|
||||||
|
strncpy(degrees_str, dms_str, 2);
|
||||||
|
strncpy(minutes_decimal_str, dms_str + 2, strlen(dms_str) - 2);
|
||||||
|
double degrees = atof(degrees_str);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to convert altitude string to centi-meters
|
||||||
|
static int16_t altitude_to_centi_meters_struct(const char *alt_str) {
|
||||||
|
if (alt_str == NULL) return 0;
|
||||||
|
return (int16_t)(atof(alt_str) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to convert speed from knots to centi-knots
|
||||||
|
static uint16_t speed_to_centi_knots_struct(const char *speed_str) {
|
||||||
|
if (speed_str == NULL) return 0;
|
||||||
|
return (uint16_t)(atof(speed_str) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to convert date string (ddmmyy) to yymmdd integer
|
||||||
|
static uint16_t date_to_yyddmm_struct(const char *date_str) {
|
||||||
|
if (date_str == NULL || strlen(date_str) != 6) return 0;
|
||||||
|
uint16_t day = (date_str[0] - '0') * 10 + (date_str[1] - '0');
|
||||||
|
uint16_t month = (date_str[2] - '0') * 10 + (date_str[3] - '0');
|
||||||
|
uint16_t year_short = (date_str[4] - '0') * 10 + (date_str[5] - '0');
|
||||||
|
// Assuming year is in the 21st century for simplicity
|
||||||
|
return (2000 + year_short) * 10000 + month * 100 + day;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to parse GPGGA NMEA string and return the struct
|
||||||
|
void parse_gpgga_to_struct(const char *nmea, gps_binary_struct_t *data)
|
||||||
|
{
|
||||||
|
char *fields[15];
|
||||||
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
|
temp[GPS_LINE_MAX_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
char *token = strtok(temp, ",");
|
||||||
|
while (token != NULL && i < 15) {
|
||||||
|
fields[i++] = token;
|
||||||
|
token = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= 10) {
|
||||||
|
data->time_seconds = time_to_seconds_struct(fields[1]);
|
||||||
|
data->latitude_centi_degrees = dms_to_centi_degrees_struct(fields[2], fields[3]);
|
||||||
|
data->longitude_centi_degrees = dms_to_centi_degrees_struct(fields[4], fields[5]);
|
||||||
|
data->fix_quality = atoi(fields[6]);
|
||||||
|
data->num_satellites = atoi(fields[7]);
|
||||||
|
data->altitude_centi_meters = altitude_to_centi_meters_struct(fields[9]);
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "GPGGA: Not enough fields to parse struct");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to parse GPRMC NMEA string and return the struct
|
||||||
|
void parse_gprmc_to_struct(const char *nmea, gps_binary_struct_t *data)
|
||||||
|
{
|
||||||
|
char *fields[13];
|
||||||
|
char temp[GPS_LINE_MAX_LEN];
|
||||||
|
strncpy(temp, nmea, GPS_LINE_MAX_LEN);
|
||||||
|
temp[GPS_LINE_MAX_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
char *token = strtok(temp, ",");
|
||||||
|
while (token != NULL && i < 13) {
|
||||||
|
fields[i++] = token;
|
||||||
|
token = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= 12) {
|
||||||
|
data->time_seconds = time_to_seconds_struct(fields[1]);
|
||||||
|
data->latitude_centi_degrees = dms_to_centi_degrees_struct(fields[3], fields[4]);
|
||||||
|
data->longitude_centi_degrees = dms_to_centi_degrees_struct(fields[5], fields[6]);
|
||||||
|
data->date_yyddmm = date_to_yyddmm_struct(fields[9]);
|
||||||
|
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.
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "GPRMC: Not enough fields to parse struct");
|
||||||
|
}
|
||||||
|
}
|
39
main/hw/gps.h
Normal file
39
main/hw/gps.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef GPS_COMPONENT
|
||||||
|
#define GPS_COMPONENT
|
||||||
|
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "soc/uart_struct.h"
|
||||||
|
#include "buscfg.h"
|
||||||
|
|
||||||
|
// Structure to hold parsed GPS data in a compact binary format
|
||||||
|
typedef struct {
|
||||||
|
uint32_t time_seconds; // Seconds since start of day
|
||||||
|
int32_t latitude_centi_degrees; // Latitude * 10,000
|
||||||
|
int32_t longitude_centi_degrees; // Longitude * 10,000
|
||||||
|
uint8_t fix_quality;
|
||||||
|
uint8_t num_satellites;
|
||||||
|
int16_t altitude_centi_meters; // Altitude * 100
|
||||||
|
uint16_t date_yyddmm; // YYDDMM (from GPRMC)
|
||||||
|
uint16_t speed_centi_knots; // Speed * 100 (from GPRMC)
|
||||||
|
} gps_binary_struct_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t latitude_centi_degrees; // Latitude * 10,000
|
||||||
|
int32_t longitude_centi_degrees; // Longitude * 10,000
|
||||||
|
int16_t altitude_centi_meters; // Altitude * 100
|
||||||
|
} predicted_binary_position_struct_t;
|
||||||
|
|
||||||
|
extern gps_binary_struct_t gpsDataOut;
|
||||||
|
|
||||||
|
extern predicted_binary_position_struct_t predictedPosition;
|
||||||
|
|
||||||
|
void gps_task(void *arg);
|
||||||
|
void parse_gpgga(const char *nmea);
|
||||||
|
void parse_gprmc(const char *nmea);
|
||||||
|
|
||||||
|
void parse_gprmc_to_struct(const char *nmea, gps_binary_struct_t *data);
|
||||||
|
void parse_gpgga_to_struct(const char *nmea, gps_binary_struct_t *data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@@ -3,50 +3,84 @@
|
|||||||
i2c_master_bus_config_t i2c0_bus_cfg = {
|
i2c_master_bus_config_t i2c0_bus_cfg = {
|
||||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||||
.i2c_port = I2C_NUM_0,
|
.i2c_port = I2C_NUM_0,
|
||||||
.scl_io_num = GPIO_NUM_9,
|
.scl_io_num = HWI2C_SCL,
|
||||||
.sda_io_num = GPIO_NUM_8,
|
.sda_io_num = HWI2C_SDA,
|
||||||
.glitch_ignore_cnt = 7,
|
.glitch_ignore_cnt = 7,
|
||||||
.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;
|
||||||
|
|
||||||
esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle)
|
// esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle)
|
||||||
{
|
// {
|
||||||
const uint16_t probe_timeout_ms = 50; // timeout in milliseconds
|
// const uint16_t probe_timeout_ms = 20; // timeout in milliseconds
|
||||||
uint8_t address;
|
// uint8_t address;
|
||||||
|
|
||||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
|
// printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
|
||||||
|
|
||||||
for (int i = 0; i < 128; i += 16)
|
// for (int i = 0; i < 128; i += 16)
|
||||||
{
|
// {
|
||||||
printf("%02x: ", i);
|
// printf("%02x: ", i);
|
||||||
|
|
||||||
for (int j = 0; j < 16; j++)
|
// for (int j = 0; j < 16; j++)
|
||||||
{
|
// {
|
||||||
fflush(stdout);
|
// fflush(stdout);
|
||||||
|
|
||||||
address = i + j;
|
// address = i + j;
|
||||||
|
|
||||||
esp_err_t ret = i2c_master_probe(handle, address, probe_timeout_ms);
|
// esp_err_t ret = i2c_master_probe(handle, address, probe_timeout_ms);
|
||||||
|
|
||||||
if (ret == ESP_OK)
|
// if (ret == ESP_OK)
|
||||||
{
|
// {
|
||||||
printf("%02x ", address);
|
// printf("%02x ", address);
|
||||||
}
|
// }
|
||||||
else if (ret == ESP_ERR_TIMEOUT)
|
// else if (ret == ESP_ERR_TIMEOUT)
|
||||||
{
|
// {
|
||||||
printf("UU ");
|
// printf("UU ");
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
printf("-- ");
|
// printf("-- ");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
printf("\r\n");
|
// printf("\r\n");
|
||||||
}
|
// }
|
||||||
|
|
||||||
return ESP_OK;
|
// return ESP_OK;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i2c master initialization
|
||||||
|
*/
|
||||||
|
|
||||||
|
esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle)
|
||||||
|
{
|
||||||
|
uint8_t address;
|
||||||
|
bool found_any = false;
|
||||||
|
|
||||||
|
printf("Scanning I2C bus...\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < 128; i++)
|
||||||
|
{
|
||||||
|
fflush(stdout);
|
||||||
|
address = i;
|
||||||
|
|
||||||
|
esp_err_t ret = i2c_master_probe(handle, address, 20);
|
||||||
|
|
||||||
|
if (ret == ESP_OK)
|
||||||
|
{
|
||||||
|
printf("Found device at 0x%02X\n", address);
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_any)
|
||||||
|
{
|
||||||
|
printf("No I2C devices found.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes data to a specific register of an I2C device.
|
* @brief Writes data to a specific register of an I2C device.
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#define I2C_TIMEOUT_MS_VALUE 20
|
#define I2C_TIMEOUT_MS_VALUE 20
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "buscfg.h"
|
||||||
|
|
||||||
#define TAG_I2C "cani2c"
|
#define TAG_I2C "cani2c"
|
||||||
|
|
||||||
|
@@ -16,7 +16,8 @@ void ina260_reset() {
|
|||||||
void ina260_init()
|
void ina260_init()
|
||||||
{
|
{
|
||||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &INA260_DEV_CFG, &INA260_DEV_HANDLE));
|
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &INA260_DEV_CFG, &INA260_DEV_HANDLE));
|
||||||
i2c_write_register_16(INA260_DEV_HANDLE, INA260_CONFIG_REGISTER, 0x0FFF); // set ina max averaging and max time
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,60 +16,57 @@ extern i2c_master_dev_handle_t INA260_DEV_HANDLE;
|
|||||||
#define INA260_DIE_ID_REGISTER (0xFF)
|
#define INA260_DIE_ID_REGISTER (0xFF)
|
||||||
|
|
||||||
// Bit masks
|
// Bit masks
|
||||||
#define CONFIG_RST_BIT (1 << 15)
|
#define CONFIG_RST_BIT (1 << 15)
|
||||||
#define CONFIG_AVG_MASK (0x7 << 9)
|
#define CONFIG_AVG_MASK (0x7 << 9)
|
||||||
#define CONFIG_VBUSCT_MASK (0x7 << 6)
|
#define CONFIG_VBUSCT_MASK (0x7 << 6)
|
||||||
#define CONFIG_ISHCT_MASK (0x7 << 3)
|
#define CONFIG_ISHCT_MASK (0x7 << 3)
|
||||||
#define CONFIG_MODE_MASK (0x7 << 0)
|
#define CONFIG_MODE_MASK (0x7 << 0)
|
||||||
|
|
||||||
// Read-only bits
|
// Read-only bits
|
||||||
#define CONFIG_RESERVED_BITS (0x7 << 12) // Bits 14–12 = 110b
|
#define CONFIG_RESERVED_BITS (0x7 << 12) // Bits 14–12 = 110b
|
||||||
|
|
||||||
// Averaging modes (AVG)
|
// Averaging modes (AVG)
|
||||||
#define CONFIG_AVG_1 (0x0 << 9)
|
#define CONFIG_AVG_1 (0x0 << 9)
|
||||||
#define CONFIG_AVG_4 (0x1 << 9)
|
#define CONFIG_AVG_4 (0x1 << 9)
|
||||||
#define CONFIG_AVG_16 (0x2 << 9)
|
#define CONFIG_AVG_16 (0x2 << 9)
|
||||||
#define CONFIG_AVG_64 (0x3 << 9)
|
#define CONFIG_AVG_64 (0x3 << 9)
|
||||||
#define CONFIG_AVG_128 (0x4 << 9)
|
#define CONFIG_AVG_128 (0x4 << 9)
|
||||||
#define CONFIG_AVG_256 (0x5 << 9)
|
#define CONFIG_AVG_256 (0x5 << 9)
|
||||||
#define CONFIG_AVG_512 (0x6 << 9)
|
#define CONFIG_AVG_512 (0x6 << 9)
|
||||||
#define CONFIG_AVG_1024 (0x7 << 9)
|
#define CONFIG_AVG_1024 (0x7 << 9)
|
||||||
|
|
||||||
// Bus voltage conversion time (VBUSCT)
|
// Bus voltage conversion time (VBUSCT)
|
||||||
#define CONFIG_VBUSCT_140US (0x0 << 6)
|
#define CONFIG_VBUSCT_140US (0x0 << 6)
|
||||||
#define CONFIG_VBUSCT_204US (0x1 << 6)
|
#define CONFIG_VBUSCT_204US (0x1 << 6)
|
||||||
#define CONFIG_VBUSCT_332US (0x2 << 6)
|
#define CONFIG_VBUSCT_332US (0x2 << 6)
|
||||||
#define CONFIG_VBUSCT_588US (0x3 << 6)
|
#define CONFIG_VBUSCT_588US (0x3 << 6)
|
||||||
#define CONFIG_VBUSCT_1_1MS (0x4 << 6)
|
#define CONFIG_VBUSCT_1_1MS (0x4 << 6)
|
||||||
#define CONFIG_VBUSCT_2_116MS (0x5 << 6)
|
#define CONFIG_VBUSCT_2_116MS (0x5 << 6)
|
||||||
#define CONFIG_VBUSCT_4_156MS (0x6 << 6)
|
#define CONFIG_VBUSCT_4_156MS (0x6 << 6)
|
||||||
#define CONFIG_VBUSCT_8_244MS (0x7 << 6)
|
#define CONFIG_VBUSCT_8_244MS (0x7 << 6)
|
||||||
|
|
||||||
// Shunt current conversion time (ISHCT)
|
// Shunt current conversion time (ISHCT)
|
||||||
#define CONFIG_ISHCT_140US (0x0 << 3)
|
#define CONFIG_ISHCT_140US (0x0 << 3)
|
||||||
#define CONFIG_ISHCT_204US (0x1 << 3)
|
#define CONFIG_ISHCT_204US (0x1 << 3)
|
||||||
#define CONFIG_ISHCT_332US (0x2 << 3)
|
#define CONFIG_ISHCT_332US (0x2 << 3)
|
||||||
#define CONFIG_ISHCT_588US (0x3 << 3)
|
#define CONFIG_ISHCT_588US (0x3 << 3)
|
||||||
#define CONFIG_ISHCT_1_1MS (0x4 << 3)
|
#define CONFIG_ISHCT_1_1MS (0x4 << 3)
|
||||||
#define CONFIG_ISHCT_2_116MS (0x5 << 3)
|
#define CONFIG_ISHCT_2_116MS (0x5 << 3)
|
||||||
#define CONFIG_ISHCT_4_156MS (0x6 << 3)
|
#define CONFIG_ISHCT_4_156MS (0x6 << 3)
|
||||||
#define CONFIG_ISHCT_8_244MS (0x7 << 3)
|
#define CONFIG_ISHCT_8_244MS (0x7 << 3)
|
||||||
|
|
||||||
// Operating mode (MODE)
|
// Operating mode (MODE)
|
||||||
#define CONFIG_MODE_POWERDOWN (0x0 << 0)
|
#define CONFIG_MODE_POWERDOWN 0x00
|
||||||
#define CONFIG_MODE_CURRENT_TRIGGER (0x1 << 0)
|
#define CONFIG_MODE_CURRENT_TRIGGER 0x01
|
||||||
#define CONFIG_MODE_VOLTAGE_TRIGGER (0x2 << 0)
|
#define CONFIG_MODE_VOLTAGE_TRIGGER 0x02
|
||||||
#define CONFIG_MODE_CURRENT_VOLTAGE_TRIGGER (0x3 << 0)
|
#define CONFIG_MODE_CURRENT_VOLTAGE_TRIGGER 0x03
|
||||||
#define CONFIG_MODE_POWERDOWN2 (0x4 << 0)
|
#define CONFIG_MODE_POWERDOWN2 0x04
|
||||||
#define CONFIG_MODE_POWERDOWN (0x5 << 0)
|
#define CONFIG_MODE_CURRENT_CONTINOUS 0x05
|
||||||
#define CONFIG_MODE_POWERDOWN (0x6 << 0)
|
#define CONFIG_MODE_VOLTAGE_CONTINOUS 0x06
|
||||||
#define CONFIG_MODE_POWERDOWN (0x7 << 0)
|
#define CONFIG_MODE_CURRENT_VOLTAGE_CONTINOUS 0x07
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ina260_init();
|
void ina260_init();
|
||||||
void ina260_readParams(uint16_t *volt, uint16_t *cur, uint16_t *pow);
|
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);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -1,4 +1,6 @@
|
|||||||
#include "mcp23018.h"
|
#include "mcp23018.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
// Local buffer for tracking GPIO state
|
// Local buffer for tracking GPIO state
|
||||||
|
|
||||||
i2c_device_config_t MCP23018_DEV_CFG = {
|
i2c_device_config_t MCP23018_DEV_CFG = {
|
||||||
@@ -36,6 +38,7 @@ void mcp23018_set_pin(i2c_master_dev_handle_t dev_handle, uint8_t pin, uint8_t v
|
|||||||
// Write updated buffer to MCP23018
|
// Write updated buffer to MCP23018
|
||||||
i2c_write_register_8(dev_handle, MCP23018_GPIOB, gpiob_state);
|
i2c_write_register_8(dev_handle, MCP23018_GPIOB, gpiob_state);
|
||||||
}
|
}
|
||||||
|
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mcp23018_init()
|
void mcp23018_init()
|
||||||
|
118
main/hw/mcp3550.c
Normal file
118
main/hw/mcp3550.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include "mcp3550.h"
|
||||||
|
#include "mcp23018.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include <esp_timer.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TAG_MICS "MICS_ADC"
|
||||||
|
#define MCP3550_SPS 3.75f
|
||||||
|
#define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms
|
||||||
|
#define MCP3550_TIMEOUT_MS 400
|
||||||
|
|
||||||
|
#define ADC_COUNT 4
|
||||||
|
const uint8_t adc_cs_pins[ADC_COUNT] = {
|
||||||
|
MCP_CS_ADC_NH3, MCP_CS_ADC_CO, MCP_CS_ADC_NO2, MCP_CS_ADC_UVC
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
spi_device_handle_t mcp3550_handle;
|
||||||
|
|
||||||
|
void mcp3550_spi_init()
|
||||||
|
{
|
||||||
|
spi_device_interface_config_t devcfg = {
|
||||||
|
.clock_speed_hz = 100000,
|
||||||
|
.mode = 0,
|
||||||
|
.spics_io_num = -1, // We handle CS manually
|
||||||
|
.queue_size = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &mcp3550_handle));
|
||||||
|
|
||||||
|
// Set MISO pin for input (needed for polling)
|
||||||
|
gpio_set_direction(MCP3550_MISO_GPIO, GPIO_MODE_INPUT);
|
||||||
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_MICS_POWER, 1); // CS HIGH
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t mcp3550_read(uint8_t cs_pin)
|
||||||
|
{
|
||||||
|
uint8_t rx_buf[4] = {0}; // 25 bits fits in 4 bytes
|
||||||
|
|
||||||
|
int64_t start = esp_timer_get_time(); // in microseconds
|
||||||
|
while (true) {
|
||||||
|
mcp23018_set_pin(MCP23018_DEV_HANDLE, cs_pin, 0); // CS LOW
|
||||||
|
|
||||||
|
spi_transaction_t trans = {
|
||||||
|
.length = 25,
|
||||||
|
.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
|
||||||
|
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG_MICS, "SPI transmit failed on CS pin %u", cs_pin);
|
||||||
|
return INT32_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dr = (rx_buf[0] & 0x80) != 0;
|
||||||
|
if (!dr) break;
|
||||||
|
|
||||||
|
if ((esp_timer_get_time() - start) > (MCP3550_TIMEOUT_MS * 1000)) {
|
||||||
|
ESP_LOGW(TAG_MICS, "Timeout waiting for DR=0 on CS pin %u", cs_pin);
|
||||||
|
return INT32_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10)); // Wait before retrying
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine 22-bit result (drop DR + status bits)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float mcp3550_to_voltage(int32_t value, float vref)
|
||||||
|
{
|
||||||
|
return ((float)value / (1 << 21)) * vref;
|
||||||
|
}
|
||||||
|
|
||||||
|
mics_adc_data_t mcp3550_read_all(float vref)
|
||||||
|
{
|
||||||
|
mics_adc_data_t data;
|
||||||
|
int32_t raw[ADC_COUNT];
|
||||||
|
float volts[ADC_COUNT];
|
||||||
|
|
||||||
|
for (int i = 0; i < ADC_COUNT; i++) {
|
||||||
|
raw[i] = mcp3550_read(adc_cs_pins[i]);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10)); // Wait before retrying
|
||||||
|
volts[i] = mcp3550_to_voltage(raw[i], vref);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.raw_nh3 = raw[0]; data.volts_nh3 = volts[0];
|
||||||
|
data.raw_co = raw[1]; data.volts_co = volts[1];
|
||||||
|
data.raw_no2 = raw[2]; data.volts_no2 = volts[2];
|
||||||
|
data.raw_uvc = raw[3]; data.volts_uvc = volts[3];
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_mics_adc_values(mics_adc_data_t *data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG_MICS,
|
||||||
|
"ADC Readings:\n"
|
||||||
|
" NH3 -> Raw: %8d, Voltage: %7.6f V\n"
|
||||||
|
" CO -> Raw: %8d, Voltage: %7.6f V\n"
|
||||||
|
" NO2 -> Raw: %8d, Voltage: %7.6f V\n"
|
||||||
|
" UVC -> Raw: %8d, Voltage: %7.6f V",
|
||||||
|
data->raw_nh3, data->volts_nh3,
|
||||||
|
data->raw_co, data->volts_co,
|
||||||
|
data->raw_no2, data->volts_no2,
|
||||||
|
data->raw_uvc, data->volts_uvc);
|
||||||
|
}
|
38
main/hw/mcp3550.h
Normal file
38
main/hw/mcp3550.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef MPC3550_COMPONENT
|
||||||
|
#define MPC3550_COMPONENT
|
||||||
|
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "buscfg.h"
|
||||||
|
|
||||||
|
#define CONFIG_FREERTOS_HZ 100
|
||||||
|
|
||||||
|
#define MCP3550_SPS 3.75f
|
||||||
|
#define MCP3550_CONVERSION_MS ((int)(1000.0f / MCP3550_SPS)) // ~267ms
|
||||||
|
|
||||||
|
|
||||||
|
extern spi_device_handle_t mcp3550_handle;
|
||||||
|
|
||||||
|
void mcp3550_spi_init();
|
||||||
|
int32_t mcp3550_read(uint8_t cs_pin);
|
||||||
|
float mcp3550_to_voltage(int32_t value, float vref);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t raw_nh3;
|
||||||
|
int32_t raw_co;
|
||||||
|
int32_t raw_no2;
|
||||||
|
int32_t raw_uvc;
|
||||||
|
float volts_nh3;
|
||||||
|
float volts_co;
|
||||||
|
float volts_no2;
|
||||||
|
float volts_uvc;
|
||||||
|
} mics_adc_data_t;
|
||||||
|
|
||||||
|
extern spi_device_handle_t mcp3550_handle;
|
||||||
|
|
||||||
|
void log_mics_adc_values(mics_adc_data_t *data);
|
||||||
|
mics_adc_data_t mcp3550_read_all(float vref);
|
||||||
|
|
||||||
|
#endif
|
@@ -1,4 +1,5 @@
|
|||||||
#include "mpu9250.h"
|
#include "mpu9250.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
i2c_device_config_t MPU9250_DEV_CFG = {
|
i2c_device_config_t MPU9250_DEV_CFG = {
|
||||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||||
@@ -6,9 +7,11 @@ i2c_device_config_t MPU9250_DEV_CFG = {
|
|||||||
.scl_speed_hz = 100000,
|
.scl_speed_hz = 100000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAG_SCALE (4912.0f / 32760.0f)
|
||||||
|
|
||||||
i2c_master_dev_handle_t MPU9250_DEV_HANDLE;
|
i2c_master_dev_handle_t MPU9250_DEV_HANDLE;
|
||||||
|
|
||||||
esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *accel, int16_t *gyro, int16_t *temp)
|
esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *accel, int16_t *gyro, int16_t *temp, int16_t *magnet)
|
||||||
{
|
{
|
||||||
uint8_t buffer[14]; // 6 (Accel) + 2 (Temp) + 6 (Gyro)
|
uint8_t buffer[14]; // 6 (Accel) + 2 (Temp) + 6 (Gyro)
|
||||||
esp_err_t ret = i2c_read_register(dev_handle, 0x3B, buffer, 14);
|
esp_err_t ret = i2c_read_register(dev_handle, 0x3B, buffer, 14);
|
||||||
@@ -16,18 +19,28 @@ esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// Convert raw data (Big-Endian)
|
// Convert raw data (Big-Endian)
|
||||||
accel[0] = (((uint16_t)(buffer[0] & 0xFF)) << 8) | (buffer[1] & 0xFF); // Accel X
|
accel[0] = (((uint16_t)(buffer[0] & 0xFF)) << 8) | (buffer[1] & 0xFF); // Accel X
|
||||||
accel[1] = (((uint16_t)(buffer[2] & 0xFF)) << 8) | (buffer[3] & 0xFF); // Accel Y
|
accel[1] = (((uint16_t)(buffer[2] & 0xFF)) << 8) | (buffer[3] & 0xFF); // Accel Y
|
||||||
accel[2] = (((uint16_t)(buffer[4] & 0xFF)) << 8) | (buffer[5] & 0xFF); // Accel Z
|
accel[2] = (((uint16_t)(buffer[4] & 0xFF)) << 8) | (buffer[5] & 0xFF); // Accel Z
|
||||||
*temp = (((uint16_t)(buffer[6] & 0xFF)) << 8) | (buffer[7] & 0xFF); // Temperature
|
*temp = (((uint16_t)(buffer[6] & 0xFF)) << 8) | (buffer[7] & 0xFF); // Temperature
|
||||||
gyro[0] = (((uint16_t)(buffer[8] & 0xFF)) << 8) | (buffer[9] & 0xFF);; // Gyro X
|
gyro[0] = (((uint16_t)(buffer[8] & 0xFF)) << 8) | (buffer[9] & 0xFF);
|
||||||
gyro[1] = (((uint16_t)(buffer[10] & 0xFF)) << 8) | (buffer[11] & 0xFF);; // Gyro Y
|
; // Gyro X
|
||||||
gyro[2] = (((uint16_t)(buffer[12] & 0xFF)) << 8) | (buffer[13] & 0xFF);; // Gyro Z
|
gyro[1] = (((uint16_t)(buffer[10] & 0xFF)) << 8) | (buffer[11] & 0xFF);
|
||||||
|
; // Gyro Y
|
||||||
|
gyro[2] = (((uint16_t)(buffer[12] & 0xFF)) << 8) | (buffer[13] & 0xFF);
|
||||||
|
; // Gyro Z
|
||||||
|
|
||||||
|
ret = i2c_read_register(dev_handle, 0x03, buffer, 6);
|
||||||
|
if (ret != ESP_OK)
|
||||||
|
return ret;
|
||||||
|
magnet[0] = (((uint16_t)(buffer[0] & 0xFF)) << 8) | (buffer[1] & 0xFF); // Magnet X
|
||||||
|
magnet[1] = (((uint16_t)(buffer[2] & 0xFF)) << 8) | (buffer[3] & 0xFF); // Magnet Y
|
||||||
|
magnet[2] = (((uint16_t)(buffer[4] & 0xFF)) << 8) | (buffer[5] & 0xFF); // Magnet Z
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, float *accel_out, float *gyro_out, float *temp_out)
|
void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, int16_t *magnet, float *accel_out, float *gyro_out, float *temp_out, float *magnet_out)
|
||||||
{
|
{
|
||||||
accel_out[0] = accel[0] / 16384.0; // Accel X in g
|
accel_out[0] = accel[0] / 16384.0; // Accel X in g
|
||||||
accel_out[1] = accel[1] / 16384.0; // Accel Y in g
|
accel_out[1] = accel[1] / 16384.0; // Accel Y in g
|
||||||
@@ -37,10 +50,16 @@ void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, float *ac
|
|||||||
gyro_out[1] = gyro[1] / 131.0; // Gyro Y in deg/s
|
gyro_out[1] = gyro[1] / 131.0; // Gyro Y in deg/s
|
||||||
gyro_out[2] = gyro[2] / 131.0; // Gyro Z in deg/s
|
gyro_out[2] = gyro[2] / 131.0; // Gyro Z in deg/s
|
||||||
|
|
||||||
|
magnet_out[0] = magnet[0] * MAG_SCALE; // Gyro X in deg/s
|
||||||
|
magnet_out[1] = magnet[1] * MAG_SCALE; // Gyro Y in deg/s
|
||||||
|
magnet_out[2] = magnet[2] * MAG_SCALE; // Gyro Z in deg/s
|
||||||
|
|
||||||
*temp_out = (temp / 333.87) + 21.0; // Temperature in °C
|
*temp_out = (temp / 333.87) + 21.0; // Temperature in °C
|
||||||
}
|
}
|
||||||
|
|
||||||
void mpu9250_init() {
|
void mpu9250_init()
|
||||||
|
{
|
||||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &MPU9250_DEV_CFG, &MPU9250_DEV_HANDLE));
|
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &MPU9250_DEV_CFG, &MPU9250_DEV_HANDLE));
|
||||||
i2c_write_register_16(MPU9250_DEV_HANDLE, 0x6B, 0x0001); // zapni uz tu hovadinu
|
i2c_write_register_16(MPU9250_DEV_HANDLE, 0x6B, 0x0001); // zapni uz tu hovadinu
|
||||||
|
i2c_write_register_16(MPU9250_DEV_HANDLE, 0x0A, 0x0012); // zapni uz tu hovadinu
|
||||||
}
|
}
|
@@ -8,8 +8,8 @@ extern i2c_device_config_t MPU9250_DEV_CFG;
|
|||||||
extern i2c_master_dev_handle_t MPU9250_DEV_HANDLE;
|
extern i2c_master_dev_handle_t MPU9250_DEV_HANDLE;
|
||||||
|
|
||||||
|
|
||||||
esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *accel, int16_t *gyro, int16_t *temp);
|
esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *accel, int16_t *gyro, int16_t *temp, int16_t *magnet);
|
||||||
void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, float *accel_out, float *gyro_out, float *temp_out);
|
void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, int16_t *magnet, float *accel_out, float *gyro_out, float *temp_out, float *magnet_out);
|
||||||
void mpu9250_init();
|
void mpu9250_init();
|
||||||
|
|
||||||
#endif
|
#endif
|
63
components/ra01s/ra01s.c → main/hw/sx1262.c
Executable file → Normal file
63
components/ra01s/ra01s.c → main/hw/sx1262.c
Executable file → Normal file
@@ -11,16 +11,18 @@
|
|||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
#include "ra01s.h"
|
#include "sx1262.h"
|
||||||
|
|
||||||
#define TAG "RA01S"
|
#define TAG "SX1262"
|
||||||
|
|
||||||
// SPI Stuff
|
|
||||||
#if CONFIG_SPI2_HOST
|
|
||||||
#define HOST_ID SPI2_HOST
|
|
||||||
#elif CONFIG_SPI3_HOST
|
|
||||||
#define HOST_ID SPI3_HOST
|
#define HOST_ID SPI3_HOST
|
||||||
#endif
|
|
||||||
|
#define CONFIG_MISO_GPIO GPIO_NUM_11
|
||||||
|
#define CONFIG_MOSI_GPIO GPIO_NUM_10
|
||||||
|
#define CONFIG_SCLK_GPIO GPIO_NUM_9
|
||||||
|
#define CONFIG_NSS_GPIO GPIO_NUM_8
|
||||||
|
#define CONFIG_RST_GPIO GPIO_NUM_12
|
||||||
|
#define CONFIG_BUSY_GPIO GPIO_NUM_13
|
||||||
|
|
||||||
static spi_device_handle_t SpiHandle;
|
static spi_device_handle_t SpiHandle;
|
||||||
|
|
||||||
@@ -32,8 +34,6 @@ static bool debugPrint;
|
|||||||
static int SX126x_SPI_SELECT;
|
static int SX126x_SPI_SELECT;
|
||||||
static int SX126x_RESET;
|
static int SX126x_RESET;
|
||||||
static int SX126x_BUSY;
|
static int SX126x_BUSY;
|
||||||
static int SX126x_TXEN;
|
|
||||||
static int SX126x_RXEN;
|
|
||||||
|
|
||||||
// Arduino compatible macros
|
// Arduino compatible macros
|
||||||
#define delayMicroseconds(us) esp_rom_delay_us(us)
|
#define delayMicroseconds(us) esp_rom_delay_us(us)
|
||||||
@@ -61,14 +61,10 @@ void LoRaInit(void)
|
|||||||
ESP_LOGI(TAG, "CONFIG_NSS_GPIO=%d", CONFIG_NSS_GPIO);
|
ESP_LOGI(TAG, "CONFIG_NSS_GPIO=%d", CONFIG_NSS_GPIO);
|
||||||
ESP_LOGI(TAG, "CONFIG_RST_GPIO=%d", CONFIG_RST_GPIO);
|
ESP_LOGI(TAG, "CONFIG_RST_GPIO=%d", CONFIG_RST_GPIO);
|
||||||
ESP_LOGI(TAG, "CONFIG_BUSY_GPIO=%d", CONFIG_BUSY_GPIO);
|
ESP_LOGI(TAG, "CONFIG_BUSY_GPIO=%d", CONFIG_BUSY_GPIO);
|
||||||
ESP_LOGI(TAG, "CONFIG_TXEN_GPIO=%d", CONFIG_TXEN_GPIO);
|
|
||||||
ESP_LOGI(TAG, "CONFIG_RXEN_GPIO=%d", CONFIG_RXEN_GPIO);
|
|
||||||
|
|
||||||
SX126x_SPI_SELECT = CONFIG_NSS_GPIO;
|
SX126x_SPI_SELECT = CONFIG_NSS_GPIO;
|
||||||
SX126x_RESET = CONFIG_RST_GPIO;
|
SX126x_RESET = CONFIG_RST_GPIO;
|
||||||
SX126x_BUSY = CONFIG_BUSY_GPIO;
|
SX126x_BUSY = CONFIG_BUSY_GPIO;
|
||||||
SX126x_TXEN = CONFIG_TXEN_GPIO;
|
|
||||||
SX126x_RXEN = CONFIG_RXEN_GPIO;
|
|
||||||
|
|
||||||
txActive = false;
|
txActive = false;
|
||||||
debugPrint = false;
|
debugPrint = false;
|
||||||
@@ -83,16 +79,6 @@ void LoRaInit(void)
|
|||||||
gpio_reset_pin(SX126x_BUSY);
|
gpio_reset_pin(SX126x_BUSY);
|
||||||
gpio_set_direction(SX126x_BUSY, GPIO_MODE_INPUT);
|
gpio_set_direction(SX126x_BUSY, GPIO_MODE_INPUT);
|
||||||
|
|
||||||
if (SX126x_TXEN != -1) {
|
|
||||||
gpio_reset_pin(SX126x_TXEN);
|
|
||||||
gpio_set_direction(SX126x_TXEN, GPIO_MODE_OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SX126x_RXEN != -1) {
|
|
||||||
gpio_reset_pin(SX126x_RXEN);
|
|
||||||
gpio_set_direction(SX126x_RXEN, GPIO_MODE_OUTPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_bus_config_t spi_bus_config = {
|
spi_bus_config_t spi_bus_config = {
|
||||||
.sclk_io_num = CONFIG_SCLK_GPIO,
|
.sclk_io_num = CONFIG_SCLK_GPIO,
|
||||||
.mosi_io_num = CONFIG_MOSI_GPIO,
|
.mosi_io_num = CONFIG_MOSI_GPIO,
|
||||||
@@ -102,10 +88,6 @@ void LoRaInit(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
ret = spi_bus_initialize( HOST_ID, &spi_bus_config, SPI_DMA_CH_AUTO );
|
|
||||||
ESP_LOGI(TAG, "spi_bus_initialize=%d",ret);
|
|
||||||
assert(ret==ESP_OK);
|
|
||||||
|
|
||||||
spi_device_interface_config_t devcfg = {
|
spi_device_interface_config_t devcfg = {
|
||||||
.clock_speed_hz = 9000000,
|
.clock_speed_hz = 9000000,
|
||||||
.mode = 0,
|
.mode = 0,
|
||||||
@@ -705,7 +687,6 @@ void SetRx(uint32_t timeout)
|
|||||||
ESP_LOGI(TAG, "----- SetRx timeout=%"PRIu32, timeout);
|
ESP_LOGI(TAG, "----- SetRx timeout=%"PRIu32, timeout);
|
||||||
}
|
}
|
||||||
SetStandby(SX126X_STANDBY_RC);
|
SetStandby(SX126X_STANDBY_RC);
|
||||||
SetRxEnable();
|
|
||||||
uint8_t buf[3];
|
uint8_t buf[3];
|
||||||
buf[0] = (uint8_t)((timeout >> 16) & 0xFF);
|
buf[0] = (uint8_t)((timeout >> 16) & 0xFF);
|
||||||
buf[1] = (uint8_t)((timeout >> 8) & 0xFF);
|
buf[1] = (uint8_t)((timeout >> 8) & 0xFF);
|
||||||
@@ -723,25 +704,12 @@ void SetRx(uint32_t timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetRxEnable(void)
|
|
||||||
{
|
|
||||||
if (debugPrint) {
|
|
||||||
ESP_LOGI(TAG, "SetRxEnable:SX126x_TXEN=%d SX126x_RXEN=%d", SX126x_TXEN, SX126x_RXEN);
|
|
||||||
}
|
|
||||||
if ((SX126x_TXEN != -1) && (SX126x_RXEN != -1)) {
|
|
||||||
gpio_set_level(SX126x_RXEN, HIGH);
|
|
||||||
gpio_set_level(SX126x_TXEN, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SetTx(uint32_t timeoutInMs)
|
void SetTx(uint32_t timeoutInMs)
|
||||||
{
|
{
|
||||||
if (debugPrint) {
|
if (debugPrint) {
|
||||||
ESP_LOGI(TAG, "----- SetTx timeoutInMs=%"PRIu32, timeoutInMs);
|
ESP_LOGI(TAG, "----- SetTx timeoutInMs=%"PRIu32, timeoutInMs);
|
||||||
}
|
}
|
||||||
SetStandby(SX126X_STANDBY_RC);
|
SetStandby(SX126X_STANDBY_RC);
|
||||||
SetTxEnable();
|
|
||||||
uint8_t buf[3];
|
uint8_t buf[3];
|
||||||
uint32_t tout = timeoutInMs;
|
uint32_t tout = timeoutInMs;
|
||||||
if (timeoutInMs != 0) {
|
if (timeoutInMs != 0) {
|
||||||
@@ -766,19 +734,6 @@ void SetTx(uint32_t timeoutInMs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetTxEnable(void)
|
|
||||||
{
|
|
||||||
if (debugPrint) {
|
|
||||||
ESP_LOGI(TAG, "SetTxEnable:SX126x_TXEN=%d SX126x_RXEN=%d", SX126x_TXEN, SX126x_RXEN);
|
|
||||||
}
|
|
||||||
if ((SX126x_TXEN != -1) && (SX126x_RXEN != -1)){
|
|
||||||
gpio_set_level(SX126x_RXEN, LOW);
|
|
||||||
gpio_set_level(SX126x_TXEN, HIGH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int GetPacketLost()
|
int GetPacketLost()
|
||||||
{
|
{
|
||||||
return txLost;
|
return txLost;
|
2
components/ra01s/ra01s.h → main/hw/sx1262.h
Executable file → Normal file
2
components/ra01s/ra01s.h → main/hw/sx1262.h
Executable file → Normal file
@@ -412,8 +412,6 @@ void SetCad();
|
|||||||
uint8_t GetStatus(void);
|
uint8_t GetStatus(void);
|
||||||
uint16_t GetIrqStatus(void);
|
uint16_t GetIrqStatus(void);
|
||||||
void ClearIrqStatus(uint16_t irq);
|
void ClearIrqStatus(uint16_t irq);
|
||||||
void SetTxEnable(void);
|
|
||||||
void SetRxEnable(void);
|
|
||||||
void SetRx(uint32_t timeout);
|
void SetRx(uint32_t timeout);
|
||||||
void SetTx(uint32_t timeoutInMs);
|
void SetTx(uint32_t timeoutInMs);
|
||||||
int GetPacketLost();
|
int GetPacketLost();
|
50
main/main.c
50
main/main.c
@@ -15,6 +15,7 @@
|
|||||||
#include "esp_mac.h"
|
#include "esp_mac.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "components/radio.h"
|
||||||
#include "components/sensors.h"
|
#include "components/sensors.h"
|
||||||
#include "components/util.h"
|
#include "components/util.h"
|
||||||
#include "hw/bme680b.h"
|
#include "hw/bme680b.h"
|
||||||
@@ -23,31 +24,72 @@
|
|||||||
#include "hw/ina260.h"
|
#include "hw/ina260.h"
|
||||||
#include "hw/mcp23018.h"
|
#include "hw/mcp23018.h"
|
||||||
#include "hw/mpu9250.h"
|
#include "hw/mpu9250.h"
|
||||||
|
#include "hw/buscfg.h"
|
||||||
|
|
||||||
|
#include "hw/gps.h"
|
||||||
|
|
||||||
#define TAG "cantest"
|
#define TAG "cantest"
|
||||||
|
|
||||||
|
|
||||||
#define CONFIG_FREERTOS_HZ 100
|
#define CONFIG_FREERTOS_HZ 100
|
||||||
|
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* instantiate i2c master bus 0 */
|
/* instantiate i2c master bus 0 */
|
||||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));
|
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));
|
||||||
|
|
||||||
|
spi_bus_config_t MCPBusCfg = {
|
||||||
|
.mosi_io_num = -1,
|
||||||
|
.miso_io_num = MCP3550_MISO_GPIO,
|
||||||
|
.sclk_io_num = MCP3550_SCK_GPIO,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
.max_transfer_sz = 4,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &MCPBusCfg, SPI_DMA_DISABLED));
|
||||||
|
|
||||||
|
spi_bus_config_t HighSpeedBusCfg = {
|
||||||
|
// CONNECTED to LoRa and SD card
|
||||||
|
.mosi_io_num = HSPI_MOSI_GPIO,
|
||||||
|
.miso_io_num = HSPI_MISO_GPIO,
|
||||||
|
.sclk_io_num = HSPI_SCK_GPIO,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
.max_transfer_sz = 64, // probably change
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(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(i2c_master_bus_detect_devices(i2c0_bus_hdl));
|
||||||
|
|
||||||
|
mcp23018_init();
|
||||||
|
|
||||||
|
void servoControllerInit();
|
||||||
|
|
||||||
/* create task pinned to the app core */
|
/* create task pinned to the app core */
|
||||||
xTaskCreatePinnedToCore(
|
xTaskCreate(
|
||||||
i2c_sensors_task,
|
i2c_sensors_task,
|
||||||
"I2CTaskBME",
|
"I2CTaskBME",
|
||||||
8192,
|
8192,
|
||||||
NULL,
|
NULL,
|
||||||
(tskIDLE_PRIORITY + 2),
|
(tskIDLE_PRIORITY + 2),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
xTaskCreate(
|
||||||
|
lora_comms_task,
|
||||||
|
"LoraCommsTask",
|
||||||
|
8192,
|
||||||
NULL,
|
NULL,
|
||||||
APP_CPU_NUM);
|
(tskIDLE_PRIORITY + 2),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
xTaskCreate(
|
||||||
|
gps_task,
|
||||||
|
"gps_task",
|
||||||
|
8192,
|
||||||
|
NULL,
|
||||||
|
(tskIDLE_PRIORITY + 2),
|
||||||
|
NULL);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@@ -1091,6 +1091,8 @@ esp_err_t bme680_get_data(bme680_handle_t handle, bme680_data_t *const data) {
|
|||||||
data->heater_stable = adc_data.heater_stable;
|
data->heater_stable = adc_data.heater_stable;
|
||||||
data->gas_valid = adc_data.gas_valid;
|
data->gas_valid = adc_data.gas_valid;
|
||||||
|
|
||||||
|
data->raw_data = adc_data;
|
||||||
|
|
||||||
/* compute scores */
|
/* compute scores */
|
||||||
bme680_compute_iaq(data);
|
bme680_compute_iaq(data);
|
||||||
|
|
||||||
|
@@ -308,6 +308,22 @@ typedef struct bme680_cal_factors_s {
|
|||||||
int8_t range_switching_error;
|
int8_t range_switching_error;
|
||||||
} bme680_cal_factors_t;
|
} bme680_cal_factors_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief BME680 ADC data structure definition.
|
||||||
|
*/
|
||||||
|
typedef struct bme680_adc_data_s {
|
||||||
|
uint32_t temperature;
|
||||||
|
uint16_t humidity;
|
||||||
|
uint32_t pressure;
|
||||||
|
uint16_t gas;
|
||||||
|
bool gas_valid;
|
||||||
|
uint8_t gas_range;
|
||||||
|
uint8_t gas_index;
|
||||||
|
bool heater_stable;
|
||||||
|
} bme680_adc_data_t;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief BME680 data structure definition.
|
* @brief BME680 data structure definition.
|
||||||
*/
|
*/
|
||||||
@@ -325,22 +341,9 @@ typedef struct bme680_data_s {
|
|||||||
float temperature_score;
|
float temperature_score;
|
||||||
float humidity_score;
|
float humidity_score;
|
||||||
float gas_score;
|
float gas_score;
|
||||||
|
bme680_adc_data_t raw_data;
|
||||||
} bme680_data_t;
|
} bme680_data_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief BME680 ADC data structure definition.
|
|
||||||
*/
|
|
||||||
typedef struct bme680_adc_data_s {
|
|
||||||
uint32_t temperature;
|
|
||||||
uint16_t humidity;
|
|
||||||
uint32_t pressure;
|
|
||||||
uint16_t gas;
|
|
||||||
bool gas_valid;
|
|
||||||
uint8_t gas_range;
|
|
||||||
uint8_t gas_index;
|
|
||||||
bool heater_stable;
|
|
||||||
} bme680_adc_data_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief BME680 configuration structure definition.
|
* @brief BME680 configuration structure definition.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user