save some implementation
This commit is contained in:
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);
|
||||
}
|
Reference in New Issue
Block a user