Start implementing AHT20 sensor reading

This commit is contained in:
2024-09-03 17:29:06 +02:00
parent 0e15d5b1e2
commit 83f6fa58a4
5 changed files with 173 additions and 0 deletions

View File

@@ -78,6 +78,11 @@ distclean: clean
$(E) "[REM] $(BINDIR)" $(E) "[REM] $(BINDIR)"
$(Q) $(RMR) $(BINDIR) $(Q) $(RMR) $(BINDIR)
.PHONY: listen
listen: ./opt/tools/serial-listen.py
$(E) "[PY3] $<"
$(Q) ./$<
$(TMPDIRS): $(TMPDIRS):
$(E) "[DIR] $@" $(E) "[DIR] $@"
$(Q) $(MKDIR) $@ $(Q) $(MKDIR) $@

Binary file not shown.

View File

@@ -77,6 +77,35 @@ int TWI_Write(unsigned char data)
return 0; return 0;
} }
unsigned char TWI_Read_ACK(void)
{
// Read data and acknowledge
TWCR = (1 << TWEN) // Enable TWI
| (1 << TWINT) // Clear interrupt flag
| (1 << TWEA); // Send acknowledgment
// Wait until data read
while ((TWCR & (1 << TWINT)) == 0);
return TWDR;
}
unsigned char TWI_Read_NACK(void)
{
// Read data, expect last byte
TWCR = (1 << TWEN) // Enable TWI
| (1 << TWINT); // Clear interrupt flag
// Wait until data read
while ((TWCR & (1 << TWINT)) == 0);
return TWDR;
}
int TWI_Wait_ACK(void) int TWI_Wait_ACK(void)
{ {
unsigned int status; unsigned int status;

View File

@@ -10,6 +10,8 @@ int TWI_Init(void);
int TWI_Start(unsigned char addr, unsigned char mode); int TWI_Start(unsigned char addr, unsigned char mode);
int TWI_SetChannel(int channel); int TWI_SetChannel(int channel);
int TWI_Write(unsigned char data); int TWI_Write(unsigned char data);
unsigned char TWI_Read_ACK(void);
unsigned char TWI_Read_NACK(void);
int TWI_Wait_ACK(void); int TWI_Wait_ACK(void);
int TWI_Stop(void); int TWI_Stop(void);

View File

@@ -6,6 +6,136 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
short TWI_ReadAHT20(void)
{
unsigned char data, crc;
// After the transmission is initiated, the first
// byte of the subsequent I2C transmission includes
// the 7-bit I2C device address 0x38 and a SDA
// direction bit.
// Soft reset device.
TWI_Start(0x38, 0);
TWI_Write(0xBA);
TWI_Wait_ACK();
TWI_Stop();
// Wait 40ms after power-on.
Sleep(40);
// Before reading the temperature and humidity
// values, first check whether the calibration
// enable bit Bit [3] of the status word is 1 (you
// can get a byte of status word by sending 0x71).
TWI_Start(0x38, 0);
TWI_Write(0x71);
TWI_Wait_ACK();
data = TWI_Read_NACK();
TWI_Stop();
Info("Received calibration status %02X.", data);
// If not 1, need to send 0xBE command (for
// initialization), this command parameter has two
// bytes, the first byte is 0x08, the second byte
// is 0x00, and then wait for 10ms.
if (data & ~BIT(3)) {
Info("Requesting calibration...");
TWI_Start(0x38, 0);
TWI_Write(0xBE);
TWI_Wait_ACK();
TWI_Write(0x08);
TWI_Wait_ACK();
TWI_Write(0x00);
TWI_Wait_ACK();
Sleep(10);
data = TWI_Read_NACK();
TWI_Stop();
if (data & ~BIT(3)) {
Info("Error: Calibration failed.");
return -1;
}
}
// Send the 0xAC command directly (trigger
// measurement). The parameter of this command has
// two bytes, the first byte is 0x33 and the second
// byte is 0x00.
Info("Triggering measurement...");
TWI_Start(0x38, 0);
TWI_Wait_ACK();
TWI_Write(0xAC);
TWI_Wait_ACK();
TWI_Write(0x33);
TWI_Wait_ACK();
TWI_Write(0x00);
TWI_Wait_ACK();
TWI_Stop();
// Wait for 80ms to wait for the measurement to be
// completed. If the read status word Bit [7] is 0,
// it indicates that the measurement is completed,
// and six bytes can be read in a row. Otherwise
// continue to wait.
Info("Reading measurement...");
TWI_Start(0x38, 1); // Read
TWI_Wait_ACK();
do {
Sleep(80);
data = TWI_Read_ACK();
} while (data & BIT(7));
data = TWI_Read_ACK();
Info("Received data byte %02X.", data);
data = TWI_Read_ACK();
Info("Received data byte %02X.", data);
data = TWI_Read_ACK();
Info("Received data byte %02X.", data);
data = TWI_Read_ACK();
Info("Received data byte %02X.", data);
data = TWI_Read_ACK();
Info("Received data byte %02X.", data);
data = TWI_Read_ACK();
Info("Received data byte %02X.", data);
// After receiving six bytes, the next byte is the
// CRC check data, the user can read it as needed,
// if the receiving end needs CRC check, then send
// it after receiving the sixth byte ACK response,
// otherwise NACK is sent out, CRC initial value is
// 0xFF. The CRC8 check polynomial is:
// CRC[7:0]= 1 + (x^4) + (x^5) + (x^8)
crc = TWI_Read_NACK();
Info("Received CRC8 byte %02X.", crc);
// Calculate the temperature and humidity values.
// Note: The calibration status check in the first
// step only needs to be checked at power-on. No
// operation is required during the normal
// acquisition process.
// TODO: Calculate values
TWI_Stop();
return 0;
}
int main(void) int main(void)
{ {
USART_Init(); USART_Init();
@@ -27,7 +157,14 @@ int main(void)
// TODO: Set FAN03 timer frequency // TODO: Set FAN03 timer frequency
// TODO: Implement ADS1115 and AHT20 // TODO: Implement ADS1115 and AHT20
// TEM01, TEM02, TEM03
// HUM01, HUM02, HUM03
// TWI_GetValue(TEM03)
// TWI_GetValue(HUM03)
TWI_SetChannel(AHT01); // I2C Mux TWI_SetChannel(AHT01); // I2C Mux
TWI_ReadAHT20(); // TEMP and RH
Info("Running idle loop..."); Info("Running idle loop...");