From e7c4ade170f351f1a5a9aafb0cfba2da2b112a77 Mon Sep 17 00:00:00 2001 From: Alexey Zholtikov Date: Sat, 31 Oct 2026 08:06:35 +0300 Subject: [PATCH] style: big renaming --- src/{main.c => zh_avr_bme280_sensor.c} | 498 ++++++++++++------------- wiki_ru.md | 234 ++++++------ 2 files changed, 377 insertions(+), 355 deletions(-) rename src/{main.c => zh_avr_bme280_sensor.c} (63%) diff --git a/src/main.c b/src/zh_avr_bme280_sensor.c similarity index 63% rename from src/main.c rename to src/zh_avr_bme280_sensor.c index 8bb3a5e..a3a1cca 100644 --- a/src/main.c +++ b/src/zh_avr_bme280_sensor.c @@ -120,14 +120,14 @@ * * @return Stored device id, or DEVICE_ID_UNASSIGNED if none is stored */ -static uint8_t zh_load_device_id(void); +static uint8_t _zh_load_device_id(void); /** * @brief Save the device identifier to EEPROM. * * @param id Device identifier to store */ -static void zh_save_device_id(uint8_t id); +static void _zh_save_device_id(uint8_t id); /** * @brief Initialize the SPI peripheral for nRF24L01 communication. @@ -137,7 +137,7 @@ static void zh_save_device_id(uint8_t id); * clock divider. The SS pin is not managed by hardware and must be * controlled manually via PB2. */ -static void zh_spi_init(void); +static void _zh_spi_init(void); /** * @brief Transfer one byte over SPI and return the received byte. @@ -149,7 +149,7 @@ static void zh_spi_init(void); * * @return Received byte */ -static uint8_t zh_spi_transfer(uint8_t data); +static uint8_t _zh_spi_transfer(uint8_t data); /** * @brief Initialize the hardware TWI (I2C) peripheral. @@ -159,7 +159,7 @@ static uint8_t zh_spi_transfer(uint8_t data); * in master mode. The hardware TWI is used for communication with * the BME280 sensor. */ -static void zh_i2c_init(void); +static void _zh_i2c_init(void); /** * @brief Wait for the TWI interrupt flag with a timeout. @@ -170,7 +170,7 @@ static void zh_i2c_init(void); * @return true if TWINT was set before the timeout expired * @return false on timeout */ -static bool zh_i2c_wait(void); +static bool _zh_i2c_wait(void); /** * @brief Generate a TWI start (or repeated start) condition. @@ -181,7 +181,7 @@ static bool zh_i2c_wait(void); * @return true when the start condition was acknowledged by the controller * @return false on timeout or unexpected status */ -static bool zh_i2c_start(void); +static bool _zh_i2c_start(void); /** * @brief Generate a TWI stop condition. @@ -189,7 +189,7 @@ static bool zh_i2c_start(void); * Asserts STOP and waits (bounded by a timeout loop) until the TWSTO * bit is cleared by hardware. */ -static void zh_i2c_stop(void); +static void _zh_i2c_stop(void); /** * @brief Write one byte on the TWI bus and return the ACK status. @@ -203,7 +203,7 @@ static void zh_i2c_stop(void); * @return true if the slave acknowledged the byte * @return false on timeout or NACK */ -static bool zh_i2c_write(uint8_t data); +static bool _zh_i2c_write(uint8_t data); /** * @brief Read one byte from the TWI bus and send an ACK after reading. @@ -213,7 +213,7 @@ static bool zh_i2c_write(uint8_t data); * * @return Received byte */ -static uint8_t zh_i2c_read_ack(void); +static uint8_t _zh_i2c_read_ack(void); /** * @brief Read one byte from the TWI bus and send a NACK after reading. @@ -223,7 +223,7 @@ static uint8_t zh_i2c_read_ack(void); * * @return Received byte */ -static uint8_t zh_i2c_read_nack(void); +static uint8_t _zh_i2c_read_nack(void); /** * @brief Initialize the BME280 sensor and read calibration data. @@ -235,7 +235,7 @@ static uint8_t zh_i2c_read_nack(void); * @return true if the sensor is present and initialized successfully * @return false if the device ID does not match or a register operation fails */ -static bool zh_bme280_init(void); +static bool _zh_bme280_init(void); /** * @brief Write a register value to the BME280 sensor over TWI. @@ -250,7 +250,7 @@ static bool zh_bme280_init(void); * @return true on success * @return false if the start/stop condition or any byte transfer failed */ -static bool zh_bme280_write_reg(uint8_t reg, uint8_t value); +static bool _zh_bme280_write_reg(uint8_t reg, uint8_t value); /** * @brief Read multiple bytes from a BME280 register over TWI. @@ -266,7 +266,7 @@ static bool zh_bme280_write_reg(uint8_t reg, uint8_t value); * @return true on success * @return false if any start condition or byte transfer failed */ -static bool zh_bme280_read_reg(uint8_t reg, uint8_t *buf, uint8_t len); +static bool _zh_bme280_read_reg(uint8_t reg, uint8_t *buf, uint8_t len); /** * @brief Read raw sensor data from the BME280. @@ -282,20 +282,20 @@ static bool zh_bme280_read_reg(uint8_t reg, uint8_t *buf, uint8_t len); * @return true on success * @return false if the register write or read operation fails */ -static bool zh_bme280_read(int32_t *temperature, int32_t *pressure, int32_t *humidity); +static bool _zh_bme280_read(int32_t *temperature, int32_t *pressure, int32_t *humidity); /** * @brief Compensate raw temperature using Bosch calibration coefficients. * * Applies the 32-bit compensation algorithm defined in the BME280 datasheet * using calibration data read during initialization. The result is stored - * in bme280_t_fine for use by the pressure and humidity compensators. + * in _bme280_temp_fine for use by the pressure and humidity compensators. * * @param adc_t Raw temperature ADC value * * @return Compensated temperature in degrees Celsius */ -static float zh_bme280_compensate_temperature(int32_t adc_t); +static float _zh_bme280_compensate_temperature(int32_t adc_t); /** * @brief Compensate raw pressure using Bosch calibration coefficients. @@ -307,7 +307,7 @@ static float zh_bme280_compensate_temperature(int32_t adc_t); * * @return Compensated pressure in Pascals */ -static float zh_bme280_compensate_pressure(int32_t adc_p); +static float _zh_bme280_compensate_pressure(int32_t adc_p); /** * @brief Compensate raw humidity using Bosch calibration coefficients. @@ -319,7 +319,7 @@ static float zh_bme280_compensate_pressure(int32_t adc_p); * * @return Compensated relative humidity in percent */ -static float zh_bme280_compensate_humidity(int32_t adc_h); +static float _zh_bme280_compensate_humidity(int32_t adc_h); /** * @brief Initialize the nRF24L01 radio module. @@ -328,16 +328,16 @@ static float zh_bme280_compensate_humidity(int32_t adc_h); * the channel, enables automatic retransmission, and enables CRC. The * module is left in standby mode with RX and TX interrupts masked. */ -static void zh_nrf24_init(void); +static void _zh_nrf24_init(void); /** * @brief Initialize INT0 external interrupt for the nRF24 IRQ signal. * * Configures PD2 as a falling-edge triggered external interrupt source and - * enables the INT0 interrupt mask bit. The ISR sets the nrf_event flag used + * enables the INT0 interrupt mask bit. The ISR sets the _nrf_event flag used * by the pairing state machine. */ -static void zh_nrf24_interrupt_init(void); +static void _zh_nrf24_interrupt_init(void); /** * @brief Transmit a packet via the nRF24L01 module. @@ -350,7 +350,7 @@ static void zh_nrf24_interrupt_init(void); * @param buf Pointer to the data buffer to transmit (must not be NULL) * @param size Number of bytes to transmit */ -static void zh_nrf24_send(uint8_t *buf, uint8_t size); +static void _zh_nrf24_send(uint8_t *buf, uint8_t size); /** * @brief Start a transmission without blocking on completion. @@ -361,7 +361,7 @@ static void zh_nrf24_send(uint8_t *buf, uint8_t size); * @param buf Pointer to the payload data to transmit (must not be NULL) * @param size Number of bytes in the payload buffer (must be > 0) */ -static void zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size); +static void _zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size); /** * @brief Send a command to the nRF24L01 without a data payload. @@ -373,7 +373,7 @@ static void zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size); * * @return SPI status register value after the command byte */ -static uint8_t zh_nrf24_send_command(uint8_t cmd); +static uint8_t _zh_nrf24_send_command(uint8_t cmd); /** * @brief Write a payload to the nRF24L01 using a write command. @@ -387,7 +387,7 @@ static uint8_t zh_nrf24_send_command(uint8_t cmd); * * @return SPI status register value after the command byte */ -static uint8_t zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count); +static uint8_t _zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count); /** * @brief Write a single byte to an nRF24L01 register. @@ -400,7 +400,7 @@ static uint8_t zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count); * * @return SPI status register value after the command byte */ -static uint8_t zh_nrf24_write_register(uint8_t reg, uint8_t val); +static uint8_t _zh_nrf24_write_register(uint8_t reg, uint8_t val); /** * @brief Write a buffer of data to an nRF24L01 register block. @@ -414,7 +414,7 @@ static uint8_t zh_nrf24_write_register(uint8_t reg, uint8_t val); * * @return SPI status register value after the command byte */ -static uint8_t zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count); +static uint8_t _zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count); /** * @brief Read the received payload from the nRF24L01+ into a buffer. @@ -422,43 +422,43 @@ static uint8_t zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t c * @param buf Pointer to the destination buffer (must not be NULL) * @param count Number of bytes to read from the RX FIFO */ -static void zh_nrf24_read_payload(uint8_t *buf, uint8_t count); +static void _zh_nrf24_read_payload(uint8_t *buf, uint8_t count); /** * @brief Read the width of the payload in the nRF24L01+ RX FIFO. * * @return Payload width in bytes */ -static uint8_t zh_nrf24_read_payload_width(void); +static uint8_t _zh_nrf24_read_payload_width(void); /** * @brief Switch the nRF24L01+ to RX mode on pipe 0. */ -static void zh_nrf24_enter_rx(void); +static void _zh_nrf24_enter_rx(void); /** * @brief Put the nRF24L01+ into power-down mode. */ -static void zh_nrf24_enter_power_down(void); +static void _zh_nrf24_enter_power_down(void); /** * @brief Start the watchdog timer in interrupt mode with the given timeout. * * @param timeout_bits Watchdog timeout prescaler bits (WDP3:0) */ -static void zh_wdt_start(uint8_t timeout_bits); +static void _zh_wdt_start(uint8_t timeout_bits); /** * @brief Stop the watchdog timer. */ -static void zh_wdt_stop(void); +static void _zh_wdt_stop(void); /** * @brief Generate a pseudo-random token from MCU state and ADC noise. * * @return 16-bit random token (never zero) */ -static uint16_t zh_get_random_token(void); +static uint16_t _zh_get_random_token(void); /** * @brief Run the non-blocking pairing procedure to obtain a device id. @@ -469,7 +469,7 @@ static uint16_t zh_get_random_token(void); * * @return Device identifier assigned by the gateway */ -static uint8_t zh_do_pairing(void); +static uint8_t _zh_do_pairing(void); /** * @brief Enter permanent power-down sleep until the next reset. @@ -477,7 +477,7 @@ static uint8_t zh_do_pairing(void); * Disables all interrupts, the watchdog, the radio, the ADC, SPI and all * unused peripheral clocks, then loops in power-down sleep mode. */ -static void zh_enter_final_sleep(void); +static void _zh_enter_final_sleep(void); /** * @brief Measure the battery voltage using the AVR ADC. @@ -488,63 +488,63 @@ static void zh_enter_final_sleep(void); * * @return Battery voltage in volts */ -static float zh_get_battery_voltage(void); +static float _zh_get_battery_voltage(void); -static volatile uint8_t wdt_wake_count = 0; -static volatile uint8_t nrf_event = false; -static uint8_t bme280_calib[33] = {0}; -static int32_t bme280_t_fine = 0; -static bool bme280_present = false; +static volatile uint8_t _wdt_wake_count = 0; +static volatile bool _nrf_event = false; +static uint8_t _bme280_calib[33] = {0}; +static int32_t _bme280_temp_fine = 0; +static bool _bme280_present = false; -zh_nrf24_sensor_transmitted_data_t transmitted_data = {0}; +zh_nrf24_sensor_transmitted_data_t _transmitted_data = {0}; int main(void) { - transmitted_data.type = ZH_NRF24_SENSOR_BME280; + _transmitted_data.type = ZH_NRF24_SENSOR_BME280; MCUSR &= ~(1 << WDRF); wdt_disable(); cli(); - zh_i2c_init(); - bme280_present = zh_bme280_init(); - zh_spi_init(); - zh_nrf24_init(); + _zh_i2c_init(); + _bme280_present = _zh_bme280_init(); + _zh_spi_init(); + _zh_nrf24_init(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); - uint8_t device_id = zh_load_device_id(); + uint8_t device_id = _zh_load_device_id(); if (device_id == DEVICE_ID_UNASSIGNED) { - device_id = zh_do_pairing(); + device_id = _zh_do_pairing(); } - transmitted_data.id = (int16_t)device_id; + _transmitted_data.id = (int16_t)device_id; { uint8_t probe[ZH_NRF24_MAX_PAYLOAD_SIZE]; - if (zh_nrf24_sensor_build_payload(&transmitted_data, probe, sizeof(probe)) == 0) + if (zh_nrf24_sensor_build_payload(&_transmitted_data, probe, sizeof(probe)) == 0) { - zh_enter_final_sleep(); + _zh_enter_final_sleep(); } } - zh_wdt_start(WDT_T_8S); + _zh_wdt_start(WDT_T_8S); int32_t adc_t = 0; int32_t adc_p = 0; int32_t adc_h = 0; - if (bme280_present == true) + if (_bme280_present == true) { - if (zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) + if (_zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) { - transmitted_data.battery = (int16_t)lroundf(zh_get_battery_voltage() * 100.0); - transmitted_data.value_2 = (int16_t)lroundf(zh_bme280_compensate_temperature(adc_t) * 10.0); - transmitted_data.value_3 = (int16_t)lroundf(zh_bme280_compensate_pressure(adc_p) * 0.00750062 * 10.0); - transmitted_data.value_1 = (int16_t)lroundf(zh_bme280_compensate_humidity(adc_h) * 10.0); + _transmitted_data.battery = (int16_t)lroundf(_zh_get_battery_voltage() * 100.0); + _transmitted_data.value_2 = (int16_t)lroundf(_zh_bme280_compensate_temperature(adc_t) * 10.0); + _transmitted_data.value_3 = (int16_t)lroundf(_zh_bme280_compensate_pressure(adc_p) * 0.00750062 * 10.0); + _transmitted_data.value_1 = (int16_t)lroundf(_zh_bme280_compensate_humidity(adc_h) * 10.0); uint8_t payload[ZH_NRF24_MAX_PAYLOAD_SIZE]; - uint8_t size = zh_nrf24_sensor_build_payload(&transmitted_data, payload, sizeof(payload)); + uint8_t size = zh_nrf24_sensor_build_payload(&_transmitted_data, payload, sizeof(payload)); if (size > 0) { - zh_nrf24_send(payload, size); + _zh_nrf24_send(payload, size); } } else { - bme280_present = false; + _bme280_present = false; } } for (;;) @@ -552,31 +552,31 @@ int main(void) sleep_enable(); sleep_cpu(); sleep_disable(); - if (wdt_wake_count >= WDT_WAKE_COUNT) + if (_wdt_wake_count >= WDT_WAKE_COUNT) { - wdt_wake_count = 0; - if (bme280_present == false) + _wdt_wake_count = 0; + if (_bme280_present == false) { - bme280_present = zh_bme280_init(); + _bme280_present = _zh_bme280_init(); } - if (bme280_present == true) + if (_bme280_present == true) { - if (zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) + if (_zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) { - transmitted_data.battery = (int16_t)lroundf(zh_get_battery_voltage() * 100.0); - transmitted_data.value_2 = (int16_t)lroundf(zh_bme280_compensate_temperature(adc_t)); - transmitted_data.value_3 = (int16_t)lroundf(zh_bme280_compensate_pressure(adc_p) * 0.00750062); - transmitted_data.value_1 = (int16_t)lroundf(zh_bme280_compensate_humidity(adc_h)); + _transmitted_data.battery = (int16_t)lroundf(_zh_get_battery_voltage() * 100.0); + _transmitted_data.value_2 = (int16_t)lroundf(_zh_bme280_compensate_temperature(adc_t)); + _transmitted_data.value_3 = (int16_t)lroundf(_zh_bme280_compensate_pressure(adc_p) * 0.00750062); + _transmitted_data.value_1 = (int16_t)lroundf(_zh_bme280_compensate_humidity(adc_h)); uint8_t payload[ZH_NRF24_MAX_PAYLOAD_SIZE]; - uint8_t size = zh_nrf24_sensor_build_payload(&transmitted_data, payload, sizeof(payload)); + uint8_t size = zh_nrf24_sensor_build_payload(&_transmitted_data, payload, sizeof(payload)); if (size > 0) { - zh_nrf24_send(payload, size); + _zh_nrf24_send(payload, size); } } else { - bme280_present = false; + _bme280_present = false; } } } @@ -587,18 +587,18 @@ int main(void) ISR(WDT_vect) { WDTCSR |= (1 << WDIE); - if (wdt_wake_count < WDT_WAKE_COUNT) + if (_wdt_wake_count < WDT_WAKE_COUNT) { - ++wdt_wake_count; + ++_wdt_wake_count; } } ISR(INT0_vect) { - nrf_event = true; + _nrf_event = true; } -static uint8_t zh_load_device_id(void) +static uint8_t _zh_load_device_id(void) { uint8_t id = eeprom_read_byte(EEPROM_DEVICE_ID_ADDR); if (id == 0xFF || id == 0x00) @@ -608,19 +608,19 @@ static uint8_t zh_load_device_id(void) return id; } -static void zh_save_device_id(uint8_t id) +static void _zh_save_device_id(uint8_t id) { eeprom_update_byte(EEPROM_DEVICE_ID_ADDR, id); } -static void zh_spi_init(void) +static void _zh_spi_init(void) { DDRB |= (1 << PB2) | (1 << PB3) | (1 << PB5); PORTB |= (1 << PB2); SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); } -static uint8_t zh_spi_transfer(uint8_t data) +static uint8_t _zh_spi_transfer(uint8_t data) { SPDR = data; while ((SPSR & (1 << SPIF)) == 0) @@ -629,7 +629,7 @@ static uint8_t zh_spi_transfer(uint8_t data) return SPDR; } -static void zh_i2c_init(void) +static void _zh_i2c_init(void) { DDRC &= ~((1 << PC4) | (1 << PC5)); PORTC |= (1 << PC4) | (1 << PC5); @@ -638,7 +638,7 @@ static void zh_i2c_init(void) TWCR = (1 << TWEN); } -static bool zh_i2c_wait(void) +static bool _zh_i2c_wait(void) { uint16_t timeout = 65535; while ((TWCR & (1 << TWINT)) == 0) @@ -651,10 +651,10 @@ static bool zh_i2c_wait(void) return true; } -static bool zh_i2c_start(void) +static bool _zh_i2c_start(void) { TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); - if (zh_i2c_wait() == false) + if (_zh_i2c_wait() == false) { return false; } @@ -662,7 +662,7 @@ static bool zh_i2c_start(void) return (status == 0x08 || status == 0x10); } -static void zh_i2c_stop(void) +static void _zh_i2c_stop(void) { TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); uint16_t timeout = 1000; @@ -671,11 +671,11 @@ static void zh_i2c_stop(void) } } -static bool zh_i2c_write(uint8_t data) +static bool _zh_i2c_write(uint8_t data) { TWDR = data; TWCR = (1 << TWINT) | (1 << TWEN); - if (zh_i2c_wait() == false) + if (_zh_i2c_wait() == false) { return false; } @@ -683,129 +683,129 @@ static bool zh_i2c_write(uint8_t data) return (status == 0x18 || status == 0x28 || status == 0x40); } -static uint8_t zh_i2c_read_ack(void) +static uint8_t _zh_i2c_read_ack(void) { TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); - if (zh_i2c_wait() == false) + if (_zh_i2c_wait() == false) { return 0xFF; } return TWDR; } -static uint8_t zh_i2c_read_nack(void) +static uint8_t _zh_i2c_read_nack(void) { TWCR = (1 << TWINT) | (1 << TWEN); - if (zh_i2c_wait() == false) + if (_zh_i2c_wait() == false) { return 0xFF; } return TWDR; } -static bool zh_bme280_init(void) +static bool _zh_bme280_init(void) { _delay_ms(100); uint8_t id = 0; - if (zh_bme280_read_reg(BME280_REG_ID, &id, sizeof(id)) == false || id != 0x60) + if (_zh_bme280_read_reg(BME280_REG_ID, &id, sizeof(id)) == false || id != 0x60) { return false; } - if (zh_bme280_write_reg(BME280_REG_RESET, 0xB6) == false) + if (_zh_bme280_write_reg(BME280_REG_RESET, 0xB6) == false) { return false; } _delay_ms(10); - if (zh_bme280_read_reg(BME280_REG_CALIB00, bme280_calib, 26) == false) + if (_zh_bme280_read_reg(BME280_REG_CALIB00, _bme280_calib, 26) == false) { return false; } - if (zh_bme280_read_reg(BME280_REG_CALIB26, bme280_calib + 26, 7) == false) + if (_zh_bme280_read_reg(BME280_REG_CALIB26, _bme280_calib + 26, 7) == false) { return false; } - if (zh_bme280_write_reg(BME280_REG_CTRL_HUM, 0x01) == false) + if (_zh_bme280_write_reg(BME280_REG_CTRL_HUM, 0x01) == false) { return false; } - if (zh_bme280_write_reg(BME280_REG_CONFIG, 0x00) == false) + if (_zh_bme280_write_reg(BME280_REG_CONFIG, 0x00) == false) { return false; } return true; } -static bool zh_bme280_write_reg(uint8_t reg, uint8_t value) +static bool _zh_bme280_write_reg(uint8_t reg, uint8_t value) { - if (zh_i2c_start() == false) + if (_zh_i2c_start() == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_write(BME280_ADDR << 1) == false) + if (_zh_i2c_write(BME280_ADDR << 1) == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_write(reg) == false) + if (_zh_i2c_write(reg) == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_write(value) == false) + if (_zh_i2c_write(value) == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - zh_i2c_stop(); + _zh_i2c_stop(); _delay_ms(2); return true; } -static bool zh_bme280_read_reg(uint8_t reg, uint8_t *buf, uint8_t len) +static bool _zh_bme280_read_reg(uint8_t reg, uint8_t *buf, uint8_t len) { - if (zh_i2c_start() == false) + if (_zh_i2c_start() == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_write(BME280_ADDR << 1) == false) + if (_zh_i2c_write(BME280_ADDR << 1) == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_write(reg) == false) + if (_zh_i2c_write(reg) == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_start() == false) + if (_zh_i2c_start() == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } - if (zh_i2c_write((BME280_ADDR << 1) | 1) == false) + if (_zh_i2c_write((BME280_ADDR << 1) | 1) == false) { - zh_i2c_stop(); + _zh_i2c_stop(); return false; } for (uint8_t i = 0; i < len; ++i) { - buf[i] = (i == len - 1) ? zh_i2c_read_nack() : zh_i2c_read_ack(); + buf[i] = (i == len - 1) ? _zh_i2c_read_nack() : _zh_i2c_read_ack(); } - zh_i2c_stop(); + _zh_i2c_stop(); return true; } -static bool zh_bme280_read(int32_t *temperature, int32_t *pressure, int32_t *humidity) +static bool _zh_bme280_read(int32_t *temperature, int32_t *pressure, int32_t *humidity) { - if (zh_bme280_write_reg(BME280_REG_CTRL_MEAS, 0x25) == false) + if (_zh_bme280_write_reg(BME280_REG_CTRL_MEAS, 0x25) == false) { return false; } _delay_ms(10); uint8_t raw[8] = {0}; - if (zh_bme280_read_reg(BME280_REG_DATA, raw, sizeof(raw)) == false) + if (_zh_bme280_read_reg(BME280_REG_DATA, raw, sizeof(raw)) == false) { return false; } @@ -815,29 +815,29 @@ static bool zh_bme280_read(int32_t *temperature, int32_t *pressure, int32_t *hum return true; } -static float zh_bme280_compensate_temperature(int32_t adc_t) +static float _zh_bme280_compensate_temperature(int32_t adc_t) { - int32_t dig_t1 = (int32_t)(uint16_t)(bme280_calib[1] << 8 | bme280_calib[0]); - int32_t dig_t2 = (int16_t)(bme280_calib[3] << 8 | bme280_calib[2]); - int32_t dig_t3 = (int16_t)(bme280_calib[5] << 8 | bme280_calib[4]); + int32_t dig_t1 = (int32_t)(uint16_t)(_bme280_calib[1] << 8 | _bme280_calib[0]); + int32_t dig_t2 = (int16_t)(_bme280_calib[3] << 8 | _bme280_calib[2]); + int32_t dig_t3 = (int16_t)(_bme280_calib[5] << 8 | _bme280_calib[4]); int32_t var1 = ((((adc_t >> 3) - (dig_t1 << 1))) * dig_t2) >> 11; int32_t var2 = (((((adc_t >> 4) - dig_t1) * ((adc_t >> 4) - dig_t1)) >> 12) * dig_t3) >> 14; - bme280_t_fine = var1 + var2; - return (float)((bme280_t_fine * 5 + 128) >> 8) / 100.0; + _bme280_temp_fine = var1 + var2; + return (float)((_bme280_temp_fine * 5 + 128) >> 8) / 100.0; } -static float zh_bme280_compensate_pressure(int32_t adc_p) +static float _zh_bme280_compensate_pressure(int32_t adc_p) { - int32_t dig_p1 = (int32_t)(uint16_t)(bme280_calib[7] << 8 | bme280_calib[6]); - int32_t dig_p2 = (int16_t)(bme280_calib[9] << 8 | bme280_calib[8]); - int32_t dig_p3 = (int16_t)(bme280_calib[11] << 8 | bme280_calib[10]); - int32_t dig_p4 = (int16_t)(bme280_calib[13] << 8 | bme280_calib[12]); - int32_t dig_p5 = (int16_t)(bme280_calib[15] << 8 | bme280_calib[14]); - int32_t dig_p6 = (int16_t)(bme280_calib[17] << 8 | bme280_calib[16]); - int32_t dig_p7 = (int16_t)(bme280_calib[19] << 8 | bme280_calib[18]); - int32_t dig_p8 = (int16_t)(bme280_calib[21] << 8 | bme280_calib[20]); - int32_t dig_p9 = (int16_t)(bme280_calib[23] << 8 | bme280_calib[22]); - int32_t var1 = (((int32_t)bme280_t_fine) >> 1) - 64000; + int32_t dig_p1 = (int32_t)(uint16_t)(_bme280_calib[7] << 8 | _bme280_calib[6]); + int32_t dig_p2 = (int16_t)(_bme280_calib[9] << 8 | _bme280_calib[8]); + int32_t dig_p3 = (int16_t)(_bme280_calib[11] << 8 | _bme280_calib[10]); + int32_t dig_p4 = (int16_t)(_bme280_calib[13] << 8 | _bme280_calib[12]); + int32_t dig_p5 = (int16_t)(_bme280_calib[15] << 8 | _bme280_calib[14]); + int32_t dig_p6 = (int16_t)(_bme280_calib[17] << 8 | _bme280_calib[16]); + int32_t dig_p7 = (int16_t)(_bme280_calib[19] << 8 | _bme280_calib[18]); + int32_t dig_p8 = (int16_t)(_bme280_calib[21] << 8 | _bme280_calib[20]); + int32_t dig_p9 = (int16_t)(_bme280_calib[23] << 8 | _bme280_calib[22]); + int32_t var1 = (((int32_t)_bme280_temp_fine) >> 1) - 64000; int32_t var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * dig_p6; var2 = var2 + ((var1 * dig_p5) << 1); var2 = (var2 >> 2) + (((int32_t)dig_p4) << 16); @@ -861,15 +861,15 @@ static float zh_bme280_compensate_pressure(int32_t adc_p) return (float)((int32_t)p + ((var1 + var2 + dig_p7) >> 4)); } -static float zh_bme280_compensate_humidity(int32_t adc_h) +static float _zh_bme280_compensate_humidity(int32_t adc_h) { - int32_t dig_h1 = bme280_calib[25]; - int32_t dig_h2 = (int16_t)(bme280_calib[27] << 8 | bme280_calib[26]); - int32_t dig_h3 = bme280_calib[28]; - int32_t dig_h4 = (int16_t)((bme280_calib[29] << 4) | (bme280_calib[30] & 0x0F)); - int32_t dig_h5 = (int16_t)((bme280_calib[31] << 4) | ((bme280_calib[30] >> 4) & 0x0F)); - int8_t dig_h6 = (int8_t)bme280_calib[32]; - int32_t v_x1_u32r = (bme280_t_fine - ((int32_t)76800)); + int32_t dig_h1 = _bme280_calib[25]; + int32_t dig_h2 = (int16_t)(_bme280_calib[27] << 8 | _bme280_calib[26]); + int32_t dig_h3 = _bme280_calib[28]; + int32_t dig_h4 = (int16_t)((_bme280_calib[29] << 4) | (_bme280_calib[30] & 0x0F)); + int32_t dig_h5 = (int16_t)((_bme280_calib[31] << 4) | ((_bme280_calib[30] >> 4) & 0x0F)); + int8_t dig_h6 = (int8_t)_bme280_calib[32]; + int32_t v_x1_u32r = (_bme280_temp_fine - ((int32_t)76800)); v_x1_u32r = (((((adc_h << 14) - (dig_h4 << 20) - (dig_h5 * v_x1_u32r)) + 16384) >> 15) * (((((((v_x1_u32r * dig_h6) >> 10) * (((v_x1_u32r * dig_h3) >> 11) + 32768)) >> 10) + 2097152) * dig_h2 + 8192) >> 14)); v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * dig_h1) >> 4)); if (v_x1_u32r < 0) @@ -883,7 +883,7 @@ static float zh_bme280_compensate_humidity(int32_t adc_h) return (float)(v_x1_u32r >> 12) / 1024.0; } -static void zh_nrf24_init(void) +static void _zh_nrf24_init(void) { _delay_ms(100); DDRB |= (1 << PB1); @@ -892,23 +892,23 @@ static void zh_nrf24_init(void) PORTD |= (1 << PD2); uint64_t gateway_address = GATEWAY_ADDRESS; uint8_t activation_key = 0x73; - zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); - zh_nrf24_write_register(NRF_REG_EN_AA, 0x01); - zh_nrf24_write_register(NRF_REG_EN_RXADDR, 0x01); - zh_nrf24_write_register(NRF_REG_SETUP_AW, 0x01); - zh_nrf24_write_register(NRF_REG_SETUP_RETR, 0xFF); - zh_nrf24_write_register(NRF_REG_RF_CH, GATEWAY_CHANNEL); - zh_nrf24_write_register(NRF_REG_RF_SETUP, 0x26); - zh_nrf24_write_buff_register(NRF_REG_TX_ADDR, (uint8_t *)&gateway_address, 3); - zh_nrf24_write_buff_register(NRF_REG_RX_ADDR_P0, (uint8_t *)&gateway_address, 3); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); - zh_nrf24_write_buffer(NRF_CMD_ACTIVATE, &activation_key, sizeof(activation_key)); - zh_nrf24_write_register(NRF_REG_FEATURE, NRF_FEATURE_EN_DPL); - zh_nrf24_write_register(NRF_REG_DYNPD, NRF_DYNPD_DPL_P0); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); + _zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); + _zh_nrf24_write_register(NRF_REG_EN_AA, 0x01); + _zh_nrf24_write_register(NRF_REG_EN_RXADDR, 0x01); + _zh_nrf24_write_register(NRF_REG_SETUP_AW, 0x01); + _zh_nrf24_write_register(NRF_REG_SETUP_RETR, 0xFF); + _zh_nrf24_write_register(NRF_REG_RF_CH, GATEWAY_CHANNEL); + _zh_nrf24_write_register(NRF_REG_RF_SETUP, 0x26); + _zh_nrf24_write_buff_register(NRF_REG_TX_ADDR, (uint8_t *)&gateway_address, 3); + _zh_nrf24_write_buff_register(NRF_REG_RX_ADDR_P0, (uint8_t *)&gateway_address, 3); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); + _zh_nrf24_write_buffer(NRF_CMD_ACTIVATE, &activation_key, sizeof(activation_key)); + _zh_nrf24_write_register(NRF_REG_FEATURE, NRF_FEATURE_EN_DPL); + _zh_nrf24_write_register(NRF_REG_DYNPD, NRF_DYNPD_DPL_P0); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); } -static void zh_nrf24_interrupt_init(void) +static void _zh_nrf24_interrupt_init(void) { DDRD &= ~(1 << PD2); PORTD |= (1 << PD2); @@ -918,12 +918,12 @@ static void zh_nrf24_interrupt_init(void) EIMSK |= (1 << INT0); } -static void zh_nrf24_send(uint8_t *buf, uint8_t size) +static void _zh_nrf24_send(uint8_t *buf, uint8_t size) { - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); _delay_ms(5); - zh_nrf24_send_command(NRF_CMD_FLUSH_TX); - zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); + _zh_nrf24_send_command(NRF_CMD_FLUSH_TX); + _zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); PORTB |= (1 << PB1); uint8_t count = 0; while ((PIND & (1 << PD2)) != 0) @@ -935,97 +935,97 @@ static void zh_nrf24_send(uint8_t *buf, uint8_t size) _delay_ms(1); } PORTB &= ~(1 << PB1); - uint8_t status = zh_nrf24_send_command(NRF_CMD_NOP); - zh_nrf24_write_register(NRF_REG_STATUS, status); - zh_nrf24_send_command(NRF_CMD_FLUSH_TX); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); + uint8_t status = _zh_nrf24_send_command(NRF_CMD_NOP); + _zh_nrf24_write_register(NRF_REG_STATUS, status); + _zh_nrf24_send_command(NRF_CMD_FLUSH_TX); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC); } -static void zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size) +static void _zh_nrf24_send_no_wait(uint8_t *buf, uint8_t size) { PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_MASK_RX_DR | NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP); _delay_ms(2); - zh_nrf24_send_command(NRF_CMD_FLUSH_TX); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); - zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); + _zh_nrf24_send_command(NRF_CMD_FLUSH_TX); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); + _zh_nrf24_write_buffer(NRF_CMD_W_TX_PAYLOAD, buf, size); PORTB |= (1 << PB1); _delay_us(15); PORTB &= ~(1 << PB1); } -static uint8_t zh_nrf24_send_command(uint8_t cmd) +static uint8_t _zh_nrf24_send_command(uint8_t cmd) { PORTB &= ~(1 << PB2); - uint8_t status = zh_spi_transfer(cmd); + uint8_t status = _zh_spi_transfer(cmd); PORTB |= (1 << PB2); return status; } -static uint8_t zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count) +static uint8_t _zh_nrf24_write_buffer(uint8_t cmd, uint8_t *buf, uint8_t count) { PORTB &= ~(1 << PB2); - uint8_t status = zh_spi_transfer(cmd); + uint8_t status = _zh_spi_transfer(cmd); while (count-- != 0) { - zh_spi_transfer(*(buf++)); + _zh_spi_transfer(*(buf++)); } PORTB |= (1 << PB2); return status; } -static uint8_t zh_nrf24_write_register(uint8_t reg, uint8_t val) +static uint8_t _zh_nrf24_write_register(uint8_t reg, uint8_t val) { PORTB &= ~(1 << PB2); - uint8_t status = zh_spi_transfer(reg | NRF_CMD_W_REGISTER); - zh_spi_transfer(val); + uint8_t status = _zh_spi_transfer(reg | NRF_CMD_W_REGISTER); + _zh_spi_transfer(val); PORTB |= (1 << PB2); return status; } -static uint8_t zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count) +static uint8_t _zh_nrf24_write_buff_register(uint8_t reg, uint8_t *buf, uint8_t count) { - return zh_nrf24_write_buffer((reg | NRF_CMD_W_REGISTER), buf, count); + return _zh_nrf24_write_buffer((reg | NRF_CMD_W_REGISTER), buf, count); } -static void zh_nrf24_read_payload(uint8_t *buf, uint8_t count) +static void _zh_nrf24_read_payload(uint8_t *buf, uint8_t count) { PORTB &= ~(1 << PB2); - zh_spi_transfer(NRF_CMD_R_RX_PAYLOAD); + _zh_spi_transfer(NRF_CMD_R_RX_PAYLOAD); while (count-- != 0) { - *buf++ = zh_spi_transfer(0xFF); + *buf++ = _zh_spi_transfer(0xFF); } PORTB |= (1 << PB2); } -static uint8_t zh_nrf24_read_payload_width(void) +static uint8_t _zh_nrf24_read_payload_width(void) { PORTB &= ~(1 << PB2); - zh_spi_transfer(NRF_CMD_R_RX_PL_WID); - uint8_t width = zh_spi_transfer(0xFF); + _zh_spi_transfer(NRF_CMD_R_RX_PL_WID); + uint8_t width = _zh_spi_transfer(0xFF); PORTB |= (1 << PB2); return width; } -static void zh_nrf24_enter_rx(void) +static void _zh_nrf24_enter_rx(void) { PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP | NRF_CONFIG_PRIM_RX); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC | NRF_CONFIG_PWR_UP | NRF_CONFIG_PRIM_RX); _delay_ms(2); PORTB |= (1 << PB1); _delay_us(130); } -static void zh_nrf24_enter_power_down(void) +static void _zh_nrf24_enter_power_down(void) { PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC); + _zh_nrf24_write_register(NRF_REG_CONFIG, NRF_CONFIG_EN_CRC); } -static void zh_wdt_start(uint8_t timeout_bits) +static void _zh_wdt_start(uint8_t timeout_bits) { uint8_t wdp = (timeout_bits & 0x07) | ((timeout_bits & 0x08) ? (1 << WDP3) : 0); cli(); @@ -1035,7 +1035,7 @@ static void zh_wdt_start(uint8_t timeout_bits) sei(); } -static void zh_wdt_stop(void) +static void _zh_wdt_stop(void) { cli(); wdt_reset(); @@ -1044,7 +1044,7 @@ static void zh_wdt_stop(void) sei(); } -static uint16_t zh_get_random_token(void) +static uint16_t _zh_get_random_token(void) { uint16_t token = MCUSR; MCUSR = 0; @@ -1067,16 +1067,16 @@ static uint16_t zh_get_random_token(void) return token; } -static uint8_t zh_do_pairing(void) +static uint8_t _zh_do_pairing(void) { - uint16_t token = zh_get_random_token(); + uint16_t token = _zh_get_random_token(); zh_nrf24_sensor_pairing_data_t pairing_request; - pairing_request.type = (uint8_t)transmitted_data.type; + pairing_request.type = (uint8_t)_transmitted_data.type; pairing_request.magic = ZH_NRF24_PAIRING_REQ_MAGIC; pairing_request.token_hi = (uint8_t)(token >> 8); pairing_request.token_lo = (uint8_t)(token & 0xFF); pairing_request.id = 0; - zh_nrf24_interrupt_init(); + _zh_nrf24_interrupt_init(); zh_nrf24_sensor_pairing_state_t state = ZH_NRF24_PAIR_SEND; uint8_t attempts = 0; for (;;) @@ -1084,34 +1084,34 @@ static uint8_t zh_do_pairing(void) switch (state) { case ZH_NRF24_PAIR_SEND: - nrf_event = false; - zh_nrf24_send_no_wait((uint8_t *)&pairing_request, ZH_NRF24_PAIRING_PACKET_SIZE); + _nrf_event = false; + _zh_nrf24_send_no_wait((uint8_t *)&pairing_request, ZH_NRF24_PAIRING_PACKET_SIZE); state = ZH_NRF24_PAIR_TX_WAIT; break; case ZH_NRF24_PAIR_TX_WAIT: if ((PIND & (1 << PD2)) == 0) { - nrf_event = true; + _nrf_event = true; } else { - nrf_event = false; - zh_wdt_start(WDT_T_250MS); + _nrf_event = false; + _zh_wdt_start(WDT_T_250MS); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); - zh_wdt_stop(); + _zh_wdt_stop(); sei(); } - if (nrf_event == true) + if (_nrf_event == true) { - nrf_event = false; - uint8_t status = zh_nrf24_send_command(NRF_CMD_NOP); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); + _nrf_event = false; + uint8_t status = _zh_nrf24_send_command(NRF_CMD_NOP); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT | NRF_STATUS_RX_DR); if ((status & NRF_STATUS_TX_DS) != 0) { - zh_nrf24_enter_rx(); + _zh_nrf24_enter_rx(); state = ZH_NRF24_PAIR_RX_WAIT; } else @@ -1127,53 +1127,53 @@ static uint8_t zh_do_pairing(void) case ZH_NRF24_PAIR_RX_WAIT: if ((PIND & (1 << PD2)) == 0) { - nrf_event = true; + _nrf_event = true; } else { - nrf_event = false; - zh_wdt_start(WDT_T_250MS); + _nrf_event = false; + _zh_wdt_start(WDT_T_250MS); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); - zh_wdt_stop(); + _zh_wdt_stop(); sei(); } - if (nrf_event == true) + if (_nrf_event == true) { - nrf_event = false; - uint8_t status = zh_nrf24_send_command(NRF_CMD_NOP); + _nrf_event = false; + uint8_t status = _zh_nrf24_send_command(NRF_CMD_NOP); if ((status & NRF_STATUS_RX_DR) != 0) { - uint8_t width = zh_nrf24_read_payload_width(); + uint8_t width = _zh_nrf24_read_payload_width(); if (width > ZH_NRF24_MAX_PAYLOAD_SIZE) { - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); state = ZH_NRF24_PAIR_BACKOFF; break; } if (width != ZH_NRF24_PAIRING_PACKET_SIZE) { uint8_t dummy[ZH_NRF24_MAX_PAYLOAD_SIZE]; - zh_nrf24_read_payload(dummy, width); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_read_payload(dummy, width); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); state = ZH_NRF24_PAIR_BACKOFF; break; } zh_nrf24_sensor_pairing_data_t pairing_response; - zh_nrf24_read_payload((uint8_t *)&pairing_response, width); - zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); - zh_nrf24_send_command(NRF_CMD_FLUSH_RX); + _zh_nrf24_read_payload((uint8_t *)&pairing_response, width); + _zh_nrf24_write_register(NRF_REG_STATUS, NRF_STATUS_RX_DR | NRF_STATUS_TX_DS | NRF_STATUS_MAX_RT); + _zh_nrf24_send_command(NRF_CMD_FLUSH_RX); if (pairing_response.magic == ZH_NRF24_PAIRING_ACK_MAGIC && pairing_response.type == pairing_request.type && pairing_response.token_hi == pairing_request.token_hi && pairing_response.token_lo == pairing_request.token_lo && pairing_response.id != 0 && pairing_response.id != DEVICE_ID_UNASSIGNED) { - zh_nrf24_enter_power_down(); + _zh_nrf24_enter_power_down(); EIMSK &= ~(1 << INT0); - zh_save_device_id(pairing_response.id); + _zh_save_device_id(pairing_response.id); return pairing_response.id; } } @@ -1185,18 +1185,18 @@ static uint8_t zh_do_pairing(void) } break; case ZH_NRF24_PAIR_BACKOFF: - zh_nrf24_enter_power_down(); - nrf_event = false; - zh_wdt_start(WDT_T_4S); + _zh_nrf24_enter_power_down(); + _nrf_event = false; + _zh_wdt_start(WDT_T_4S); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); - zh_wdt_stop(); + _zh_wdt_stop(); sei(); if (++attempts >= PAIRING_TIMEOUT_ATTEMPTS) { - zh_enter_final_sleep(); + _zh_enter_final_sleep(); } state = ZH_NRF24_PAIR_SEND; break; @@ -1204,14 +1204,14 @@ static uint8_t zh_do_pairing(void) } } -static void zh_enter_final_sleep(void) +static void _zh_enter_final_sleep(void) { cli(); EIMSK = 0; EIFR = 0xFF; - zh_wdt_stop(); + _zh_wdt_stop(); PORTB &= ~(1 << PB1); - zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); + _zh_nrf24_write_register(NRF_REG_CONFIG, 0x00); ADCSRA = 0; TWCR = 0; SPCR = 0; @@ -1224,7 +1224,7 @@ static void zh_enter_final_sleep(void) } } -static float zh_get_battery_voltage(void) +static float _zh_get_battery_voltage(void) { ADMUX = (1 << REFS0) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1); ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); diff --git a/wiki_ru.md b/wiki_ru.md index bd69c0d..5308ba4 100644 --- a/wiki_ru.md +++ b/wiki_ru.md @@ -23,11 +23,11 @@ ### Структура данных -Компонент не использует динамическое выделение памяти. Сырые показания хранятся в статических переменных, калибровочные коэффициенты BME280 — в массиве `bme280_calib[33]`. Перед передачей данные сериализуются функцией `zh_nrf24_sensor_build_payload()` из внешней библиотеки `zh_nrf24_config` в буфер `uint8_t[ZH_NRF24_MAX_PAYLOAD_SIZE]` (32 байта) в формате little-endian. +Компонент не использует динамическое выделение памяти. Сырые показания хранятся в статических переменных, калибровочные коэффициенты BME280 — в массиве `_bme280_calib[33]`. Перед передачей данные сериализуются функцией `zh_nrf24_sensor_build_payload()` из внешней библиотеки `zh_nrf24_config` в буфер `uint8_t[ZH_NRF24_MAX_PAYLOAD_SIZE]` (32 байта) в формате little-endian. #### Формат передаваемого пакета -Данные формируются в глобальной переменной `transmitted_data` типа `zh_nrf24_sensor_transmitted_data_t` из библиотеки `zh_nrf24_config`, затем сериализуются в полезную нагрузку. Для типа `ZH_NRF24_SENSOR_BME280` полный размер пакета — 12 байт (заголовок id + type + battery и три поля измерений, каждое `int16_t` в little-endian). +Данные формируются в глобальной переменной `_transmitted_data` типа `zh_nrf24_sensor_transmitted_data_t` из библиотеки `zh_nrf24_config`, затем сериализуются в полезную нагрузку. Для типа `ZH_NRF24_SENSOR_BME280` полный размер пакета — 12 байт (заголовок id + type + battery и три поля измерений, каждое `int16_t` в little-endian). | Поле | Тип | Описание | | ------ | ----- | ---------- | @@ -67,89 +67,102 @@ ### Управление памятью -Компонент не использует динамическую память. Все данные хранятся в статической области и регистрах микроконтроллера. Глобальная переменная `transmitted_data` заполняется при старте (тип устройства, затем идентификатор из EEPROM или из сопряжения). В цикле обновляются поля `battery`, `value_1` (влажность), `value_2` (температура), `value_3` (давление). Идентификатор устройства сохраняется в EEPROM адресом `0x00` (`eeprom_update_byte`). +Компонент не использует динамическую память. Все данные хранятся в статической области и регистрах микроконтроллера. Глобальная переменная `_transmitted_data` заполняется при старте (тип устройства, затем идентификатор из EEPROM или из сопряжения). В цикле обновляются поля `battery`, `value_1` (влажность), `value_2` (температура), `value_3` (давление). Идентификатор устройства сохраняется в EEPROM адресом `0x00` (`eeprom_update_byte`). --- ## API (интерфейс) -Все функции являются `static` и доступны только внутри модуля `main.c`. +Все функции являются `static` и доступны только внутри модуля `zh_avr_bme280_sensor.c`. ### Инициализация | Функция | Описание | | --------- | ---------- | -| `zh_wdt_start()` | Запуск watchdog-таймера в режиме прерывания с указанным таймаутом (биты WDP3:0) | -| `zh_wdt_stop()` | Остановка watchdog-таймера | -| `zh_i2c_init()` | Инициализация аппаратного TWI (I2C) на пинах PC4 (SDA), PC5 (SCL), TWBR = 32 | -| `zh_bme280_init()` | Инициализация датчика BME280: проверка CHIP_ID, сброс, чтение калибровки, настройка режима | -| `zh_spi_init()` | Инициализация аппаратного SPI в режиме мастера (Fosc/16) | -| `zh_nrf24_init()` | Инициализация трансивера nRF24L01+: адреса TX/RX, канал, ретрансмиты, динамические пакеты, CRC | -| `zh_nrf24_interrupt_init()` | Настройка внешнего прерывания INT0 (PD2, падающий фронт) для сигнала IRQ трансивера | +| `_zh_wdt_start()` | Запуск watchdog-таймера в режиме прерывания с указанным таймаутом (биты WDP3:0) | +| `_zh_wdt_stop()` | Остановка watchdog-таймера | +| `_zh_i2c_init()` | Инициализация аппаратного TWI (I2C) на пинах PC4 (SDA), PC5 (SCL), TWBR = 32 | +| `_zh_bme280_init()` | Инициализация датчика BME280: проверка CHIP_ID, сброс, чтение калибровки, настройка режима | +| `_zh_spi_init()` | Инициализация аппаратного SPI в режиме мастера (Fosc/16) | +| `_zh_nrf24_init()` | Инициализация трансивера nRF24L01+: адреса TX/RX, канал, ретрансмиты, динамические пакеты, CRC | +| `_zh_nrf24_interrupt_init()` | Настройка внешнего прерывания INT0 (PD2, падающий фронт) для сигнала IRQ трансивера | ### Идентификатор устройства и сопряжение | Функция | Описание | | --------- | ---------- | -| `zh_load_device_id()` | Чтение ID устройства из EEPROM (возвращает `DEVICE_ID_UNASSIGNED` при 0x00/0xFF) | -| `zh_save_device_id()` | Сохранение ID устройства в EEPROM через `eeprom_update_byte` | -| `zh_get_random_token()` | Генерация 16-битного псевдослучайного токена из MCUSR и шума АЦП (никогда не 0) | -| `zh_do_pairing()` | Неблокирующая процедура сопряжения: запрос → ожидание ACK в RX-режиме → backoff; возвращает назначенный ID | -| `zh_enter_final_sleep()` | Переход в постоянный сон Power-down до сброса (отключение прерываний, WDT, радио, тактов периферии) | +| `_zh_load_device_id()` | Чтение ID устройства из EEPROM (возвращает `DEVICE_ID_UNASSIGNED` при 0x00/0xFF) | +| `_zh_save_device_id()` | Сохранение ID устройства в EEPROM через `eeprom_update_byte` | +| `_zh_get_random_token()` | Генерация 16-битного псевдослучайного токена из MCUSR и шума АЦП (никогда не 0) | +| `_zh_do_pairing()` | Неблокирующая процедура сопряжения: запрос → ожидание ACK в RX-режиме → backoff; возвращает назначенный ID | +| `_zh_enter_final_sleep()` | Переход в постоянный сон Power-down до сброса (отключение прерываний, WDT, радио, тактов периферии) | ### Измерение | Функция | Описание | -|---------|----------| -| `zh_get_battery_voltage()` | Измерение напряжения батареи через внутренний АЦП с опорой 1,1 В (две конверсии, усреднение) | +| --------- | ---------- | +| `_zh_get_battery_voltage()` | Измерение напряжения батареи через внутренний АЦП с опорой 1,1 В (две конверсии, усреднение) | ### Чтение данных BME280 | Функция | Описание | | --------- | ---------- | -| `zh_bme280_read()` | Перевод BME280 в forced mode, чтение 8 сырых байт и распаковка ADC значений температуры, давления, влажности | -| `zh_bme280_compensate_temperature()` | Компенсация сырой температуры по калибровочным коэффициентам (результат в °C) | -| `zh_bme280_compensate_pressure()` | Компенсация сырого давления по калибровочным коэффициентам (результат в Па) | -| `zh_bme280_compensate_humidity()` | Компенсация сырой влажности по калибровочным коэффициентам (результат в %) | +| `_zh_bme280_read()` | Перевод BME280 в forced mode, чтение 8 сырых байт и распаковка ADC значений температуры, давления, влажности | +| `_zh_bme280_compensate_temperature()` | Компенсация сырой температуры по калибровочным коэффициентам (результат в °C) | +| `_zh_bme280_compensate_pressure()` | Компенсация сырого давления по калибровочным коэффициентам (результат в Па) | +| `_zh_bme280_compensate_humidity()` | Компенсация сырой влажности по калибровочным коэффициентам (результат в %) | ### Передача данных nRF24L01+ | Функция | Описание | | --------- | ---------- | -| `zh_nrf24_send()` | Передача буфера: Power Up, `FLUSH_TX`, `W_TX_PAYLOAD`, импульс CE, ожидание IRQ с таймаутом ~100 мс, сброс статуса | -| `zh_nrf24_send_no_wait()` | Запуск передачи без ожидания завершения (импульс CE 15 мкс), завершение сигнализируется IRQ | -| `zh_nrf24_enter_rx()` | Переход в режим приёма на pipe 0 (PRIM_RX, очистка FIFO, CE) | -| `zh_nrf24_enter_power_down()` | Перевод трансивера в режим Power Down | +| `_zh_nrf24_send()` | Передача буфера: Power Up, `FLUSH_TX`, `W_TX_PAYLOAD`, импульс CE, ожидание IRQ с таймаутом ~100 мс, сброс статуса | +| `_zh_nrf24_send_no_wait()` | Запуск передачи без ожидания завершения (импульс CE 15 мкс), завершение сигнализируется IRQ | +| `_zh_nrf24_enter_rx()` | Переход в режим приёма на pipe 0 (PRIM_RX, очистка FIFO, CE) | +| `_zh_nrf24_enter_power_down()` | Перевод трансивера в режим Power Down | ### Низкоуровневые SPI-операции | Функция | Описание | | --------- | ---------- | -| `zh_spi_transfer()` | Обмен одного байта по SPI (полный дуплекс) | -| `zh_nrf24_write_register()` | Запись одного байта в регистр nRF24L01+ | -| `zh_nrf24_write_buff_register()` | Запись многобайтового буфера в регистр nRF24L01+ | -| `zh_nrf24_write_buffer()` | Запись буфера данных с указанной командой (CSN управляется вручную через PB2) | -| `zh_nrf24_send_command()` | Отправка однобайтовой команды и чтение статуса | -| `zh_nrf24_read_payload()` | Чтение принятой полезной нагрузки из RX FIFO (`R_RX_PAYLOAD`) | -| `zh_nrf24_read_payload_width()` | Чтение длины пакета в RX FIFO (`R_RX_PL_WID`) | +| `_zh_spi_transfer()` | Обмен одного байта по SPI (полный дуплекс) | +| `_zh_nrf24_write_register()` | Запись одного байта в регистр nRF24L01+ | +| `_zh_nrf24_write_buff_register()` | Запись многобайтового буфера в регистр nRF24L01+ | +| `_zh_nrf24_write_buffer()` | Запись буфера данных с указанной командой (CSN управляется вручную через PB2) | +| `_zh_nrf24_send_command()` | Отправка однобайтовой команды и чтение статуса | +| `_zh_nrf24_read_payload()` | Чтение принятой полезной нагрузки из RX FIFO (`R_RX_PAYLOAD`) | +| `_zh_nrf24_read_payload_width()` | Чтение длины пакета в RX FIFO (`R_RX_PL_WID`) | ### Низкоуровневые TWI-операции (аппаратный I2C) | Функция | Описание | | --------- | ---------- | -| `zh_i2c_wait()` | Ожидание флага `TWINT` с таймаутом 65535 итераций (возвращает false при зависании шины) | -| `zh_i2c_start()` | Генерация стартового (или повторного стартового) условия, проверка статусов `0x08`/`0x10` | -| `zh_i2c_stop()` | Генерация стоп-условия с ограниченным ожиданием сброса бита `TWSTO` | -| `zh_i2c_write()` | Передача одного байта через `TWDR`, проверка статусов ACK (`0x18`, `0x28`, `0x40`) | -| `zh_i2c_read_ack()` | Чтение байта из `TWDR` с подтверждением ACK (возвращает `0xFF` при таймауте) | -| `zh_i2c_read_nack()` | Чтение последнего байта из `TWDR` без подтверждения NACK (возвращает `0xFF` при таймауте) | +| `_zh_i2c_wait()` | Ожидание флага `TWINT` с таймаутом 65535 итераций (возвращает false при зависании шины) | +| `_zh_i2c_start()` | Генерация стартового (или повторного стартового) условия, проверка статусов `0x08`/`0x10` | +| `_zh_i2c_stop()` | Генерация стоп-условия с ограниченным ожиданием сброса бита `TWSTO` | +| `_zh_i2c_write()` | Передача одного байта через `TWDR`, проверка статусов ACK (`0x18`, `0x28`, `0x40`) | +| `_zh_i2c_read_ack()` | Чтение байта из `TWDR` с подтверждением ACK (возвращает `0xFF` при таймауте) | +| `_zh_i2c_read_nack()` | Чтение последнего байта из `TWDR` без подтверждения NACK (возвращает `0xFF` при таймауте) | ### Служебные TWI-функции BME280 | Функция | Описание | | --------- | ---------- | -| `zh_bme280_write_reg()` | Запись одного байта в регистр BME280 (start, адрес, регистр, данные, stop, задержка 2 мс) | -| `zh_bme280_read_reg()` | Чтение нескольких байт из регистров BME280 (repeated-start, ACK/NACK) | +| `_zh_bme280_write_reg()` | Запись одного байта в регистр BME280 (start, адрес, регистр, данные, stop, задержка 2 мс) | +| `_zh_bme280_read_reg()` | Чтение нескольких байт из регистров BME280 (repeated-start, ACK/NACK) | + +### Статические переменные модуля + +Все переменные объявлены `static` и доступны только внутри модуля. + +| Переменная | Объявление | Описание | +| --------- | ---------- | ---------- | +| `_wdt_wake_count` | `static volatile uint8_t` | Счётчик прерываний WDT, инкрементируется в `ISR(WDT_vect)` до предела `WDT_WAKE_COUNT` | +| `_nrf_event` | `static volatile bool` | Флаг события трансивера, выставляется в `ISR(INT0_vect)` и сбрасывается в машине состояний сопряжения | +| `_bme280_calib` | `static uint8_t [33]` | Калибровочные коэффициенты BME280, загружаются при инициализации датчика | +| `_bme280_temp_fine` | `static int32_t` | Промежуточное значение `t_fine`, общее для компенсаторов давления и влажности | +| `_bme280_present` | `static bool` | Признак доступности датчика BME280 (сбрасывается при ошибке чтения, восстанавливается повторной инициализацией) | +| `_transmitted_data` | `zh_nrf24_sensor_transmitted_data_t` | Глобальная (в пределах модуля) структура формируемого пакета | --- @@ -157,8 +170,8 @@ Компонент работает на bare-metal AVR без RTOS. Точки синхронизации — два ISR: -- `ISR(WDT_vect)` — увеличивает `wdt_wake_count` (объявлен как `static volatile uint8_t`, инкремент защищён проверкой верхнего предела), заново включает бит `WDIE`. -- `ISR(INT0_vect)` — выставляет флаг `nrf_event` (`static volatile uint8_t`) при фронте на пине IRQ трансивера. +- `ISR(WDT_vect)` — увеличивает `_wdt_wake_count` (объявлен как `static volatile uint8_t`, инкремент защищён проверкой верхнего предела), заново включает бит `WDIE`. +- `ISR(INT0_vect)` — выставляет флаг `_nrf_event` (`static volatile bool`) при фронте на пине IRQ трансивера. Главный цикл и машина состояний сопряжения проверяют эти флаги после выхода из сна. Атомарная запись одного байта на AVR гарантирует отсутствие состояний гонки. Весь остальной обмен с периферией (I2C, SPI, АЦП) выполняется последовательно в главном цикле. @@ -169,13 +182,13 @@ ### Алгоритм загрузки идентификатора и сопряжения - При старте читается ID из EEPROM (`eeprom_read_byte`, адрес `0x00`); значения `0x00` и `0xFF` считаются признаком несопряжённого устройства. -- При отсутствии ID выполняется `zh_do_pairing()` — неблокирующая машина состояний (`ZH_NRF24_PAIR_SEND` → `ZH_NRF24_PAIR_TX_WAIT` → `ZH_NRF24_PAIR_RX_WAIT` → `ZH_NRF24_PAIR_BACKOFF`): - - генерируется токен (`zh_get_random_token()` из MCUSR и шума АЦП); - - отправляется запрос `zh_nrf24_sensor_pairing_data_t` (magic `0xA5`) без ожидания (`zh_nrf24_send_no_wait`); +- При отсутствии ID выполняется `_zh_do_pairing()` — неблокирующая машина состояний (`ZH_NRF24_PAIR_SEND` → `ZH_NRF24_PAIR_TX_WAIT` → `ZH_NRF24_PAIR_RX_WAIT` → `ZH_NRF24_PAIR_BACKOFF`): + - генерируется токен (`_zh_get_random_token()` из MCUSR и шума АЦП); + - отправляется запрос `zh_nrf24_sensor_pairing_data_t` (magic `0xA5`) без ожидания (`_zh_nrf24_send_no_wait`); - после TX_DS трансивер переводится в RX-режим, ожидание ответа со сном и WDT-таймаутом 250 мс; - ответ валидируется по magic `0x5A`, типу, токену и ненулевому ID; ширина пакета проверяется через `R_RX_PL_WID`; - при неудаче — backoff-пауза ~4 с (WDT), не более `PAIRING_TIMEOUT_ATTEMPTS` (7) попыток. -- Назначенный ID сохраняется в EEPROM и записывается в `transmitted_data.id`. +- Назначенный ID сохраняется в EEPROM и записывается в `_transmitted_data.id`. - После инициализации выполняется пробная сборка пакета `zh_nrf24_sensor_build_payload()`; при нулевом результате (неизвестный тип) — переход в постоянный сон. ### Алгоритм инициализации BME280 @@ -183,18 +196,18 @@ - Задержка 100 мс после включения. - Проверка `CHIP_ID` (регистр `BME280_REG_ID`, ожидается `0x60`). - Сброс записью `0xB6` в регистр `BME280_REG_RESET`, задержка 10 мс. -- Чтение калибровочных коэффициентов: 26 байт из `BME280_REG_CALIB00` и 7 байт из `BME280_REG_CALIB26` (всего 33 байта, массив `bme280_calib`). +- Чтение калибровочных коэффициентов: 26 байт из `BME280_REG_CALIB00` и 7 байт из `BME280_REG_CALIB26` (всего 33 байта, массив `_bme280_calib`). - Конфигурация влажности: `ctrl_hum = 0x01` (oversampling x1). - Конфигурация режима: `config = 0x00` (фильтр off, standby off). -- Запуск измерения: `ctrl_meas = 0x25` (temp/pressure oversampling x16, forced mode) в `zh_bme280_read()` перед каждым чтением. +- Запуск измерения: `ctrl_meas = 0x25` (temp/pressure oversampling x16, forced mode) в `_zh_bme280_read()` перед каждым чтением. ### Алгоритм компенсации BME280 Сырые ADC-значения пересчитываются в физические величины по алгоритмам производителя из datasheet BME280. -- **Температура**: `zh_bme280_compensate_temperature()` — вычисляет `bme280_t_fine` (используется для давления и влажности), возвращает результат в °C. -- **Давление**: `zh_bme280_compensate_pressure()` — возвращает результат в Па. При `var1 == 0` (знаменатель ноль) возвращает 0.0. -- **Влажность**: `zh_bme280_compensate_humidity()` — результат ограничивается диапазоном [0, 419430400] на промежуточном шаге, затем делится на 1024.0 и возвращается в процентах. +- **Температура**: `_zh_bme280_compensate_temperature()` — вычисляет `_bme280_temp_fine` (используется для давления и влажности), возвращает результат в °C. +- **Давление**: `_zh_bme280_compensate_pressure()` — возвращает результат в Па. При `var1 == 0` (знаменатель ноль) возвращает 0.0. +- **Влажность**: `_zh_bme280_compensate_humidity()` — результат ограничивается диапазоном [0, 419430400] на промежуточном шаге, затем делится на 1024.0 и возвращается в процентах. ### Алгоритм аппаратного TWI @@ -203,7 +216,7 @@ - Передача байта: запись в `TWDR`, сброс `TWINT`, ожидание завершения, проверка статусов подтверждения (`0x18`/`0x28` — данные, `0x40` — адрес чтения). - Приём байта: установка `TWEA` для всех байт кроме последнего, чтение `TWDR` после `TWINT`. - Останов: установка `TWSTO`, ограниченное ожидание (1000 итераций) сброса бита аппаратно. -- Обработка ошибок: каждая операция возвращает `false` при таймауте ожидания или неверном статусе, вызывающая сторона выполняет `zh_i2c_stop()`. +- Обработка ошибок: каждая операция возвращает `false` при таймауте ожидания или неверном статусе, вызывающая сторона выполняет `_zh_i2c_stop()`. ### Алгоритм передачи через nRF24L01+ @@ -215,16 +228,16 @@ - Ожидание завершения по пину IRQ (PD2) с таймаутом ~100 мс. - Сброс флагов статуса, очистка FIFO, переход в Power Down. -Для процедуры сопряжения используется вариант без блокировки (`zh_nrf24_send_no_wait`, импульс CE 15 мкс) с завершением по прерыванию INT0. +Для процедуры сопряжения используется вариант без блокировки (`_zh_nrf24_send_no_wait`, импульс CE 15 мкс) с завершением по прерыванию INT0. ### Алгоритм сна и пробуждения - Инициализация WDT: прерывание по таймауту ~8 секунд (`WDT_T_8S`), без сброса MCU. -- ISR `WDT_vect`: увеличивает `wdt_wake_count` (до предела `WDT_WAKE_COUNT`), заново включает бит `WDIE`. -- Главный цикл: переход в Power-down (`sleep_cpu()`). После пробуждения проверяется `wdt_wake_count >= WDT_WAKE_COUNT` (38 × 8 с ≈ 5 минут). +- ISR `WDT_vect`: увеличивает `_wdt_wake_count` (до предела `WDT_WAKE_COUNT`), заново включает бит `WDIE`. +- Главный цикл: переход в Power-down (`sleep_cpu()`). После пробуждения проверяется `_wdt_wake_count >= WDT_WAKE_COUNT` (38 × 8 с ≈ 5 минут). - При достижении порога: обнуление счётчика, повторная инициализация BME280 (если датчик недоступен), чтение показаний, сериализация пакета и передача через nRF24L01+. - Первое измерение выполняется сразу после инициализации и сопряжения, до входа в цикл. -- `zh_enter_final_sleep()` — аварийный постоянный сон: отключение прерываний, WDT, радио, АЦП, TWI, SPI и тактов всей неиспользуемой периферии (PRR). +- `_zh_enter_final_sleep()` — аварийный постоянный сон: отключение прерываний, WDT, радио, АЦП, TWI, SPI и тактов всей неиспользуемой периферии (PRR). --- @@ -235,45 +248,54 @@ ```c int main(void) { - transmitted_data.type = ZH_NRF24_SENSOR_BME280; + _transmitted_data.type = ZH_NRF24_SENSOR_BME280; MCUSR &= ~(1 << WDRF); wdt_disable(); cli(); - zh_i2c_init(); - bme280_present = zh_bme280_init(); - zh_spi_init(); - zh_nrf24_init(); + _zh_i2c_init(); + _bme280_present = _zh_bme280_init(); + _zh_spi_init(); + _zh_nrf24_init(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); - uint8_t device_id = zh_load_device_id(); + uint8_t device_id = _zh_load_device_id(); if (device_id == DEVICE_ID_UNASSIGNED) { - device_id = zh_do_pairing(); + device_id = _zh_do_pairing(); } - transmitted_data.id = (int16_t)device_id; + _transmitted_data.id = (int16_t)device_id; - zh_wdt_start(WDT_T_8S); + // Пробная сборка пакета: неизвестный тип — переход в постоянный сон + { + uint8_t probe[ZH_NRF24_MAX_PAYLOAD_SIZE]; + if (zh_nrf24_sensor_build_payload(&_transmitted_data, probe, + sizeof(probe)) == 0) { + _zh_enter_final_sleep(); + } + } + + _zh_wdt_start(WDT_T_8S); int32_t adc_t = 0, adc_p = 0, adc_h = 0; // Первое измерение сразу после инициализации и сопряжения - if (bme280_present == true) { - if (zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) { - transmitted_data.battery = - (int16_t)lroundf(zh_get_battery_voltage() * 100.0); - transmitted_data.value_2 = - (int16_t)lroundf(zh_bme280_compensate_temperature(adc_t) * 10.0); - transmitted_data.value_3 = - (int16_t)lroundf(zh_bme280_compensate_pressure(adc_p) * 0.00750062 * 10.0); - transmitted_data.value_1 = - (int16_t)lroundf(zh_bme280_compensate_humidity(adc_h) * 10.0); + if (_bme280_present == true) { + if (_zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) { + _transmitted_data.battery = + (int16_t)lroundf(_zh_get_battery_voltage() * 100.0); + _transmitted_data.value_2 = + (int16_t)lroundf(_zh_bme280_compensate_temperature(adc_t) * 10.0); + _transmitted_data.value_3 = + (int16_t)lroundf(_zh_bme280_compensate_pressure(adc_p) * 0.00750062 * 10.0); + _transmitted_data.value_1 = + (int16_t)lroundf(_zh_bme280_compensate_humidity(adc_h) * 10.0); uint8_t payload[ZH_NRF24_MAX_PAYLOAD_SIZE]; - uint8_t size = zh_nrf24_sensor_build_payload(&transmitted_data, + uint8_t size = zh_nrf24_sensor_build_payload(&_transmitted_data, payload, sizeof(payload)); if (size > 0) { - zh_nrf24_send(payload, size); + _zh_nrf24_send(payload, size); } } else { - bme280_present = false; + _bme280_present = false; } } @@ -282,29 +304,29 @@ int main(void) sleep_enable(); sleep_cpu(); sleep_disable(); - if (wdt_wake_count >= WDT_WAKE_COUNT) { - wdt_wake_count = 0; - if (bme280_present == false) { - bme280_present = zh_bme280_init(); + if (_wdt_wake_count >= WDT_WAKE_COUNT) { + _wdt_wake_count = 0; + if (_bme280_present == false) { + _bme280_present = _zh_bme280_init(); } - if (bme280_present == true) { - if (zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) { - transmitted_data.battery = - (int16_t)lroundf(zh_get_battery_voltage() * 100.0); - transmitted_data.value_2 = - (int16_t)lroundf(zh_bme280_compensate_temperature(adc_t)); - transmitted_data.value_3 = - (int16_t)lroundf(zh_bme280_compensate_pressure(adc_p) * 0.00750062); - transmitted_data.value_1 = - (int16_t)lroundf(zh_bme280_compensate_humidity(adc_h)); + if (_bme280_present == true) { + if (_zh_bme280_read(&adc_t, &adc_p, &adc_h) == true) { + _transmitted_data.battery = + (int16_t)lroundf(_zh_get_battery_voltage() * 100.0); + _transmitted_data.value_2 = + (int16_t)lroundf(_zh_bme280_compensate_temperature(adc_t)); + _transmitted_data.value_3 = + (int16_t)lroundf(_zh_bme280_compensate_pressure(adc_p) * 0.00750062); + _transmitted_data.value_1 = + (int16_t)lroundf(_zh_bme280_compensate_humidity(adc_h)); uint8_t payload[ZH_NRF24_MAX_PAYLOAD_SIZE]; - uint8_t size = zh_nrf24_sensor_build_payload(&transmitted_data, + uint8_t size = zh_nrf24_sensor_build_payload(&_transmitted_data, payload, sizeof(payload)); if (size > 0) { - zh_nrf24_send(payload, size); + _zh_nrf24_send(payload, size); } } else { - bme280_present = false; + _bme280_present = false; } } } @@ -348,17 +370,17 @@ int main(void) ## Ошибки -Компонент не возвращает коды ошибок. Функции `zh_bme280_init`, `zh_bme280_read`, `zh_bme280_write_reg`, `zh_bme280_read_reg` возвращают `bool` (true при успехе). `zh_load_device_id` возвращает `DEVICE_ID_UNASSIGNED` при отсутствии сохранённого ID. Остальные функции имеют тип `void` или возвращают однобайтовый статус SPI (`uint8_t`). +Компонент не возвращает коды ошибок. Функции `_zh_bme280_init`, `_zh_bme280_read`, `_zh_bme280_write_reg`, `_zh_bme280_read_reg` возвращают `bool` (true при успехе). `_zh_load_device_id` возвращает `DEVICE_ID_UNASSIGNED` при отсутствии сохранённого ID. Остальные функции имеют тип `void` или возвращают однобайтовый статус SPI (`uint8_t`). | Условие | Поведение | | --------- | ---------- | -| Нулевое показание АЦП | `zh_get_battery_voltage()` возвращает 0.0 | -| Неверный `CHIP_ID` BME280 | `zh_bme280_init()` возвращает false, флаг `bme280_present = false`, при следующем цикле предпринимается повторная попытка инициализации | -| Таймаут ожидания `TWINT` | `zh_i2c_wait()` возвращает false, операция TWI прерывается | -| Неверный статус TWI (NACK, ошибка шины) | `zh_i2c_start()` / `zh_i2c_write()` возвращают false, вызывающая функция выполняет `zh_i2c_stop()` | -| Таймаут при чтении TWI | `zh_i2c_read_ack()` / `zh_i2c_read_nack()` возвращают `0xFF` | -| Ошибка чтения BME280 | `zh_bme280_read()` возвращает false, пакет не формируется, `bme280_present = false` | -| `var1 == 0` при компенсации давления | `zh_bme280_compensate_pressure()` возвращает 0.0 | +| Нулевое показание АЦП | `_zh_get_battery_voltage()` возвращает 0.0 | +| Неверный `CHIP_ID` BME280 | `_zh_bme280_init()` возвращает false, флаг `_bme280_present = false`, при следующем цикле предпринимается повторная попытка инициализации | +| Таймаут ожидания `TWINT` | `_zh_i2c_wait()` возвращает false, операция TWI прерывается | +| Неверный статус TWI (NACK, ошибка шины) | `_zh_i2c_start()` / `_zh_i2c_write()` возвращают false, вызывающая функция выполняет `_zh_i2c_stop()` | +| Таймаут при чтении TWI | `_zh_i2c_read_ack()` / `_zh_i2c_read_nack()` возвращают `0xFF` | +| Ошибка чтения BME280 | `_zh_bme280_read()` возвращает false, пакет не формируется, `_bme280_present = false` | +| `var1 == 0` при компенсации давления | `_zh_bme280_compensate_pressure()` возвращает 0.0 | | Превышение таймаута передачи (~100 мс) | Цикл ожидания IRQ прерывается, передача может быть неполной | | Нет ответа шлюза при сопряжении | После 7 попыток (`PAIRING_TIMEOUT_ATTEMPTS`) — переход в постоянный сон до сброса | | Ширина принятого пакета ≠ 5 байт / > 32 байт | FIFO очищается, состояние сопряжения переходит в backoff | @@ -375,7 +397,7 @@ int main(void) 5. **Точность измерения батареи** — зависит от стабильности внутреннего опорного напряжения 1,1 В. 6. **Программные задержки в TWI** — обмен с BME280 выполняется на аппаратном TWI, но ожидание `TWINT` реализовано поллингом с таймаутом; прерывания TWI не используются. 7. **Задержка между измерениями ~5 минут** — определяется произведением `WDT_WAKE_COUNT` (38) на интервал WDT (~8 секунд). В течение этого времени пакет не передаётся. -8. **Давление в мм рт. ст.** — `zh_bme280_compensate_pressure()` возвращает давление в Паскалях, для перевода в пакет умножается на `0.00750062` (коэффициент пересчёта Па → мм рт. ст.). +8. **Давление в мм рт. ст.** — `_zh_bme280_compensate_pressure()` возвращает давление в Паскалях, для перевода в пакет умножается на `0.00750062` (коэффициент пересчёта Па → мм рт. ст.). 9. **Масштабирование значений ×10 только в первом цикле** — при первом измерении температура, влажность и давление умножаются на 10 (одна дробная цифра); в цикле пробуждения значения записываются без масштабирования (см. `main`). 10. **Сопряжение требует шлюза** — без ответившего шлюза устройство после 7 попыток уходит в постоянный сон до сброса/перепрошивки. @@ -401,7 +423,7 @@ pio run -e ATmega328P -t upload ### Подключение в проекте -Компонент является самодостаточной прошивкой — не подключается как библиотека. Для интеграции в другой проект скопируйте `src/main.c`, добавьте зависимость `zh_nrf24_config` и адаптируйте макросы конфигурации. +Компонент является самодостаточной прошивкой — не подключается как библиотека. Для интеграции в другой проект скопируйте `src/zh_avr_bme280_sensor.c`, добавьте зависимость `zh_nrf24_config` и адаптируйте макросы конфигурации. ```ini ; platformio.ini