Sun_sensor:FW add new class MLX75306 which could read data from photo sensor

Sun_sensor
Petr Malanik 2 years ago
parent 4c10e85cb8
commit dea2a2addb

@ -0,0 +1,78 @@
#include "MLX75306.hpp"
MLX75306::MLX75306(SPI_HandleTypeDef SPI_handle, Chip_select_pin SPI_CS) :
SPI_handle(SPI_handle), SPI_CS(SPI_CS){ }
void MLX75306::Init(){
Reset();
}
void MLX75306::Reset(){
Command(Commands::Chip_reset, { 0, 0 });
}
void MLX75306::Wake_up(){
Command(Commands::Wake_up, { 0, 0 });
}
void MLX75306::Zebra_pattern_1(){
Command(Commands::Test_zebra_pattern_1, { 0, 0 });
}
array<uint8_t, 159> MLX75306::Read_all_8bit(){
// Command is set to read all pixels
return Command<159>(Commands::Read_out_8b, { 0x02, 0x8f });
}
void MLX75306::Integrate(double time_us){
const unsigned int f_RCO = 10000000;
const double min_time_us = 0.1;
const double max_time_us = 100000;
int64_t integration_register = 0;
// Cap values
if (time_us < min_time_us) {
time_us = min_time_us;
}
if (time_us > max_time_us) {
time_us = max_time_us;
}
// Calculate value for short integration
integration_register = ((time_us / 1000000) * f_RCO) + 4;
// If integration time is longer then maximal short integration time used long integration command
if (integration_register > ((1 << 16) - (11 * 16))) {
integration_register = (((time_us / 1000000) * f_RCO) - 11) / 16;
// Handle overflow and underflow of integration register
if (integration_register > (1 << 16)) {
integration_register = (1 << 16) - 1;
} else if (integration_register < 0) {
integration_register = 1;
}
// Long integration
Command(Commands::Start_integration_long,
{
static_cast<uint8_t>((integration_register & 0xff00) >> 8),
static_cast<uint8_t>(integration_register & 0xff)
}
);
} else {
// Short integration
Command(Commands::Start_integration,
{
static_cast<uint8_t>((integration_register & 0xff00) >> 8),
static_cast<uint8_t>(integration_register & 0xff)
}
);
}
} // MLX75306::Integrate
MLX75306::Status_byte MLX75306::Status(){
array<uint8_t, 2> payload = { 0, 0 };
auto status = Command(Commands::Idle, payload)[0];
Status_byte status_struct = *((Status_byte *) &(status));
return status_struct;
}

@ -0,0 +1,186 @@
/**
* @file SPI_camera.hpp
* @author Petr Malaník (TheColonelYoung(at)gmail(dot)com)
* @brief
* @version 0.1
* @date 1.03.2023
*/
#pragma once
#include "stm32l4xx_hal.h"
#include <array>
using namespace std;
typedef unsigned int uint;
/**
* @brief Linear optical sensor array, including a 142 x 1 array of photodiodes
* associated charge amplifier circuitry and a pixel data-hold function that
* provides simultaneous integration start and stop times for all pixels.
*/
class MLX75306
{
public:
/**
* @brief Describes GPIO which serves as SPI chip select pin
*/
struct Chip_select_pin {
GPIO_TypeDef *port;
uint16_t pin;
};
/**
* @brief Command for MLX75306, whole command composes of 3 bytes, first byte is from enum below
* Other two bytes are payload which could be command specific or empty
*/
enum class Commands: uint8_t {
Idle = 0b00000000,
Chip_reset = 0b11110000,
Read_thresholds = 0b11011000,
Write_thresholds = 0b11001100,
Start_integration = 0b10111000,
Start_integration_long = 0b10110100,
Read_out_1b = 0b10011100,
Read_out_1b5 = 0b10010110,
Read_out_4b = 0b10010011,
Read_out_8b = 0b10011001,
Test_zebra_pattern_1 = 0b11101000,
Test_zebra_pattern_2 = 0b11100100,
Test_zebra_pattern_12 = 0b11100010,
Test_zebra_pattern_0 = 0b11100001,
Sleep_mode = 0b11000110,
Wake_up = 0b11000011,
};
/**
* @brief Structure of MLX75306 status byte
*/
struct __attribute__((packed)) __attribute__((__may_alias__)) Status_byte{
uint8_t command_counter : 5; // Counter of valid commands
uint8_t device_mode : 1; // Device mode: 0-Test 1-User
uint8_t power_up_in_progress : 1; // Set after first Chip_reset command, clear after power-up
uint8_t operational_mode : 1; // Device operational mode: 0-Sleep 1-Normal
};
protected:
/*
* @brief HAL handle of SPI to which is ArduChip connected
*/
SPI_HandleTypeDef SPI_handle;
/**
* @brief GPIO description which serves as SPI Chip select
*/
Chip_select_pin SPI_CS;
public:
/**
* @brief Construct a new MLX75306 object
*
* @param SPI_handle HAL handle of SPI to which is sensor connected
* @param SPI_CS GPIO description which serves as SPI Chip select
*/
MLX75306(SPI_HandleTypeDef SPI_handle, Chip_select_pin SPI_CS);
/**
* @brief Initialize sensor by reset
*/
void Init();
/**
* @brief Reset sensor, reset must be done after power-up, reset all registers
*/
void Reset();
/**
* @brief Change operational mode of sensor to Normal
* During normal mode an integration and readout could be performed.
*/
void Wake_up();
/**
* @brief Change operational mode of sensor to Sleep
* During sleep mode an integration and readout could not be performed.
* But power draw of sensor is reduced.
*/
void Sleep_mode();
/**
* @brief Sensor will charge photodiodes to defined levels to create test pattern
* Every odd pixel is charged to high level of charge, even pixel to low level of charge
* This command is used instead of Integration start
*/
void Zebra_pattern_1();
/**
* @brief Time in micro second to integrate charge photodiodes
* The shortest time is 0.1 us, the longest is 100 ms, values above or below are capped
*/
void Integrate(double time_us);
/**
* @brief Reads Status byte of sensor by using Idle command
*
* @return Status_byte Structured status byte of sensor
*/
Status_byte Status();
/**
* @brief Perform readout of all output registers and pixels from sensor
*
* @return array<uint8_t, 159> Output registers of sensor containing metadata and pixels
*/
array<uint8_t, 159> Read_all_8bit();
protected:
/**
* @brief Send command to sensor and return answer (mostly status byte and empty bytes)
*
* @tparam array_size Size of returned answer on bytes, default is 3
* @param command Command from available Commands of sensor
* @param payload Payload (parameters) of command, mostly empty but could contain integration time, atc.
* @return array<uint8_t, array_size> Answer to command, example: status byte, readout bytes, etc.
*/
template <size_t array_size = 3>
array<uint8_t, array_size> Command(Commands command, array<uint8_t, 2> payload){
array<uint8_t, array_size> byte_stream = { 0 };
byte_stream[0] = (uint8_t) command;
byte_stream[1] = payload[0];
byte_stream[2] = payload[1];
return Transmit_and_receive(byte_stream);
}
/**
* @brief Transmit bytes to sensor and receive answer
*
* @tparam array_size Amount of bytes to transfer and receive
* @param byte_stream Array of bytes to transmit
* @return array<uint8_t, array_size> Array of received bytes
*/
template <size_t array_size>
array<uint8_t, array_size> Transmit_and_receive(array<uint8_t, array_size> &byte_stream){
array<uint8_t, array_size> received = { 0 };
CS_enable();
HAL_SPI_TransmitReceive(&SPI_handle, byte_stream.data(), received.data(), byte_stream.size(), byte_stream.size());
CS_disable();
return received;
}
/**
* @brief Enables communication with sensor via SPI, CS signal is active low
*/
void CS_enable(){ HAL_GPIO_WritePin(SPI_CS.port, SPI_CS.pin, GPIO_PIN_RESET); };
/**
* @brief Disables communication with sensor via SPI, CS signal is active low
*/
void CS_disable(){ HAL_GPIO_WritePin(SPI_CS.port, SPI_CS.pin, GPIO_PIN_SET); };
};
Loading…
Cancel
Save