Vladimir N. Shilov 3 lat temu
rodzic
commit
2f7af2c441
5 zmienionych plików z 240 dodań i 73 usunięć
  1. 22 22
      Dryer.layout
  2. 7 2
      ReadMe.txt
  3. 10 9
      inc/sensor.h
  4. 8 8
      src/main.c
  5. 193 32
      src/sensor.c

+ 22 - 22
Dryer.layout

@@ -2,9 +2,9 @@
 <CodeBlocks_layout_file>
 	<FileVersion major="1" minor="0" />
 	<ActiveTarget name="Debug" />
-	<File name="lib\ssd1306xled\ssd1306xledtx.h" open="1" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="src\sensor.c" open="1" top="1" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="951" topLine="0" />
+			<Cursor1 position="3121" topLine="150" />
 		</Cursor>
 	</File>
 	<File name="lib\ssd1306xled\ssd1306xledtx.c" open="1" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
@@ -12,19 +12,19 @@
 			<Cursor1 position="2451" topLine="66" />
 		</Cursor>
 	</File>
-	<File name="lib\tinyavrlib\num2str.c" open="1" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="inc\sensor.h" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="3534" topLine="60" />
+			<Cursor1 position="274" topLine="0" />
 		</Cursor>
 	</File>
-	<File name="src\i2c.c" open="0" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="inc\main.h" open="1" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="1062" topLine="33" />
+			<Cursor1 position="2252" topLine="56" />
 		</Cursor>
 	</File>
-	<File name="src\main.c" open="1" top="1" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="lib\ssd1306xled\font8x16.h" open="1" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="1393" topLine="41" />
+			<Cursor1 position="1017" topLine="24" />
 		</Cursor>
 	</File>
 	<File name="inc\i2c.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
@@ -32,9 +32,9 @@
 			<Cursor1 position="88" topLine="0" />
 		</Cursor>
 	</File>
-	<File name="lib\rtos\rtos.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="src\i2c.c" open="0" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="2098" topLine="0" />
+			<Cursor1 position="2571" topLine="71" />
 		</Cursor>
 	</File>
 	<File name="lib\ssd1306xled\ssd1306xled.h" open="1" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
@@ -42,34 +42,34 @@
 			<Cursor1 position="1177" topLine="0" />
 		</Cursor>
 	</File>
-	<File name="inc\sensor.h" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="src\main.c" open="1" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="371" topLine="0" />
+			<Cursor1 position="1393" topLine="41" />
 		</Cursor>
 	</File>
-	<File name="lib\ssd1306xled\font8x16.h" open="1" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="lib\ssd1306xled\ssd1306xled.c" open="1" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="1017" topLine="24" />
+			<Cursor1 position="5259" topLine="23" />
 		</Cursor>
 	</File>
-	<File name="src\sensor.c" open="1" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="lib\rtos\rtos.c" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="2212" topLine="96" />
+			<Cursor1 position="4343" topLine="110" />
 		</Cursor>
 	</File>
-	<File name="lib\ssd1306xled\ssd1306xled.c" open="1" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="lib\tinyavrlib\num2str.c" open="1" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="5259" topLine="131" />
+			<Cursor1 position="3534" topLine="43" />
 		</Cursor>
 	</File>
-	<File name="inc\main.h" open="1" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="lib\rtos\rtos.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="2252" topLine="56" />
+			<Cursor1 position="2615" topLine="0" />
 		</Cursor>
 	</File>
-	<File name="lib\rtos\rtos.c" open="0" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
+	<File name="lib\ssd1306xled\ssd1306xledtx.h" open="1" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
 		<Cursor>
-			<Cursor1 position="4343" topLine="110" />
+			<Cursor1 position="951" topLine="0" />
 		</Cursor>
 	</File>
 </CodeBlocks_layout_file>

+ 7 - 2
ReadMe.txt

@@ -3,8 +3,8 @@
 В корпусе от старой микроволновки, принудительный вентелятор, управляя теном 
 поддерживать заданную температуру.
 
-MCU	: Atmega328a (Arduino ProMini)
-Sensor	: AHT10 (Temperature + Humidity)
+MCU	: Atmega168p (Arduino ProMini)
+Sensor	: AHT20 (Temperature + Humidity)
 Display	: I2C OLED SSD1306
 Control	: Управление нагревом тэна посредством симмистора через оптопару с датчиком "0".
 Input	: 9-ти позиционый переключатель, задачик темпертуры: 50..90 градусов, шаг 5 градусов.
@@ -26,3 +26,8 @@ SSD1306 - 400 kHz, I2C addr 0x78 (0x7a ?)
 04.08.2022
 
 Угробил все 328-е атмеги, проба на 168-ой.
+---
+18.08.2022
+
+AHT10 работает только при условии, что на шине нет других устройств.
+Переходим на AHT20

+ 10 - 9
inc/sensor.h

@@ -12,21 +12,22 @@
 
 /* Status code */
 typedef enum {
-  AHT10_St_OK = 0,
-  AHT10_St_Err,
-  AHT10_St_Bsy
-} aht10_st_t;
+  AHT_St_OK = 0,
+  AHT_St_Err,
+  AHT_St_Bsy,
+  AHT_St_CRC
+} aht20_st_t;
 
 /* Data type */
 typedef struct {
   uint8_t Humidity;
    int8_t Temperature;
-} aht10_t;
+} aht20_t;
 
 /* Function */
-aht10_st_t AHT10_Init(void);
-aht10_st_t AHT10_StartMeasure(void);
-aht10_st_t AHT10_SoftReset(void);
-aht10_st_t AHT10_GetData(aht10_t * data);
+aht20_st_t AHT20_Init(void);
+aht20_st_t AHT20_StartMeasure(void);
+aht20_st_t AHT20_SoftReset(void);
+aht20_st_t AHT20_GetData(aht20_t * data);
 
 #endif /* _SENSOR_H_ */

+ 8 - 8
src/main.c

@@ -21,7 +21,7 @@ static volatile struct {
   uint8_t rezerv:     6;
 } Flag;
 uint8_t TemperatureSetpoint;
-aht10_t Sensor;
+aht20_t Sensor;
 
 /* Function prototypes */
 static void board_Init(void);
@@ -36,7 +36,7 @@ int main(void) {
   board_Init();
   RTOS_Init();
   I2C_Init();
-  AHT10_Init();
+  AHT20_Init();
   tdelay_ms(40);
   ssd1306_init();
 
@@ -190,11 +190,11 @@ static void checkTemperatureSetpoint(void) {
 }
 
 static void sensorStart(void) {
-  aht10_st_t status;
+  aht20_st_t status;
 
-  status = AHT10_StartMeasure();
+  status = AHT20_StartMeasure();
 
-  if (status != AHT10_St_OK) {
+  if (status != AHT_St_OK) {
     Flag.AHT10state = 1;
   } else {
     Flag.AHT10state = 0;
@@ -202,11 +202,11 @@ static void sensorStart(void) {
 }
 
 static void sensorGetData(void) {
-  aht10_st_t status;
+  aht20_st_t status;
 
-  status = AHT10_GetData(&Sensor);
+  status = AHT20_GetData(&Sensor);
 
-  if (status != AHT10_St_OK) {
+  if (status != AHT_St_OK) {
     Flag.AHT10state = 1;
   } else {
     Flag.AHT10state = 0;

+ 193 - 32
src/sensor.c

@@ -2,107 +2,173 @@
 #include "i2c.h"
 
 /* Defines */
-#define I2C_ADDR    0x70
+#define AHT_I2C_ADDR    0x70
 
-#define CMD_INIT    0xe1
-#define CMD_MEASURE 0xac
-#define CMD_SRESET  0xba
+#define CMD_GET_STATUS  0x71
+#define CMD_INIT        0xbe
+#define CMD_MEASURE     0xac
+#define CMD_MEASURE_CTL 0x33
+#define CMD_MEASURE_NOP 0x00
+#define CMD_SRESET      0xba
+#define CMD_CALIBR1     0x1b
+#define CMD_CALIBR2     0x1c
+#define CMD_CALIBR3     0x1e
 
 #define STATUS_BUSY 0x80
 #define STATUS_CMD  0x40
 #define STATUS_CYC  0x20
-#define STATUS_CAL  0x04
+#define STATUS_CAL  0x08
+#define STATUS_CALB 0x18
 
-aht10_st_t AHT10_Init(void)
+/* Functions prototypes */
+extern void tdelay_ms(uint16_t msek);
+uint8_t Calc_CRC8(uint8_t *message, uint8_t Num);
+aht20_st_t JH_Reset_REG(uint8_t addr);
+
+/**
+ * Initialization
+ */
+aht20_st_t AHT20_Init(void)
 {
   i2c_status_t res;
+  uint8_t data;
+
+  // Just powered on, it takes time for the product chip to be ready internally,
+  // the delay is 100~500ms, and 500ms is recommended
+  tdelay_ms(500);
 
+  // When power on, send 0x71 to read the status word for the first time,
+  // and judge whether the status word is 0x18.
   I2C_Start();
 
-  res = I2C_WriteByte(I2C_ADDR);
+  res = I2C_WriteByte(AHT_I2C_ADDR);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
 
-  res = I2C_WriteByte(CMD_SRESET);
+  res = I2C_WriteByte(CMD_GET_STATUS);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+
+  /* get one byte with NACK */
+  res = I2C_ReadByte(&data, 1);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
 
   I2C_Stop();
 
-  return AHT10_St_OK;
+  if ((data & STATUS_CALB) != STATUS_CALB) {
+    //reinitialize registers
+    aht20_st_t rest;
+    rest = JH_Reset_REG(0x1b);
+    if (rest != AHT_St_OK) {
+      return AHT_St_Err;
+    }
+    rest = JH_Reset_REG(0x1c);
+    if (rest != AHT_St_OK) {
+      return AHT_St_Err;
+    }
+    rest = JH_Reset_REG(0x1e);
+    if (rest != AHT_St_OK) {
+      return AHT_St_Err;
+    }
+
+    tdelay_ms(1);
+  }
+
+  return AHT_St_OK;
 }
 
-aht10_st_t AHT10_SoftReset(void)
+aht20_st_t AHT20_SoftReset(void)
 {
   i2c_status_t res;
 
   I2C_Start();
 
-  res = I2C_WriteByte(I2C_ADDR);
+  res = I2C_WriteByte(AHT_I2C_ADDR);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
 
   res = I2C_WriteByte(CMD_SRESET);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
 
   I2C_Stop();
 
-  return AHT10_St_OK;
+  return AHT_St_OK;
 }
 
-aht10_st_t AHT10_StartMeasure(void)
+aht20_st_t AHT20_StartMeasure(void)
 {
   i2c_status_t res;
 
   I2C_Start();
 
-  res = I2C_WriteByte(I2C_ADDR);
+  res = I2C_WriteByte(AHT_I2C_ADDR);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
 
   res = I2C_WriteByte(CMD_MEASURE);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(CMD_MEASURE_CTL);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(CMD_MEASURE_NOP);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
   }
 
   I2C_Stop();
 
-  return AHT10_St_OK;
+  return AHT_St_OK;
 }
 
-aht10_st_t AHT10_GetData(aht10_t * data)
+aht20_st_t AHT20_GetData(aht20_t * data)
 {
   i2c_status_t res;
 
   I2C_Start();
 
   /* Send I2C read addr */
-  res = I2C_WriteByte(I2C_ADDR | 0x1);
+  res = I2C_WriteByte(AHT_I2C_ADDR | 0x1);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
 
-  /* Now read the value with NACK */
-  uint8_t buf[6];
-  res = I2C_ReadByte(buf, 0);
+  /* Now read the data */
+  uint8_t buf[8];
+  uint8_t rd, i;
+  /* read status and data */
+  for (i=0; i<6; i++) {
+    res = I2C_ReadByte(&rd, 0);
+    if (res != I2C_Ret_OK) {
+      return AHT_St_Err;
+    }
+    buf[i] = rd;
+  }
+  /* read crc */
+  res = I2C_ReadByte(&rd, 1);
   if (res != I2C_Ret_OK) {
-    return AHT10_St_Err;
+    return AHT_St_Err;
   }
+  buf[6] = rd;
 
   I2C_Stop();
 
   if ((buf[0] & STATUS_BUSY) != 0) {
-    return AHT10_St_Bsy;
+    return AHT_St_Bsy;
   }
+
   /* Calculate values */
   uint32_t result;
-  //nt32_t result = {0};
 
   /* Humidity = Srh * 100% / 2^20 */
   result = buf[1];
@@ -112,7 +178,8 @@ aht10_st_t AHT10_GetData(aht10_t * data)
   result |= buf[3];
   result >>= 4;
   result *= 100;
-  result /= 1048576;
+  result += 524288;
+  result /= 10248576;
   data->Humidity = (uint8_t)result;
 
   /* Temperature = St * 200 / 2^20 - 50 */
@@ -122,9 +189,103 @@ aht10_st_t AHT10_GetData(aht10_t * data)
   result <<= 8;
   result |= buf[5];
   result *= 200;
+  result += 524288;
   result /= 1048576;
   result -= 50;
   data->Temperature = (int8_t)result;
 
-  return AHT10_St_OK;
+  return AHT_St_OK;
+}
+
+/**
+ * CRC check type: CRC8/MAXIM
+ * Polynomial: X8+X5+X4+1
+ * Poly: 0011 0001 0x31
+ * When the high bit is placed in the back, it becomes 1000 1100 0x8c
+ */
+uint8_t Calc_CRC8(uint8_t *message, uint8_t Num)
+{
+  uint8_t i;
+  uint8_t byte;
+  uint8_t crc = 0xFF;
+
+  for (byte=0; byte<Num; byte++) {
+    crc ^= (message[byte]);
+    for (i=8; i>0; --i) {
+      if (crc & 0x80) {
+        crc = (crc << 1) ^ 0x31;
+      } else {
+        crc = (crc << 1);
+      }
+    }
+  }
+
+  return crc;
+}
+
+/* Reset register */
+aht20_st_t JH_Reset_REG(uint8_t addr) {
+  i2c_status_t res;
+  uint8_t Byte_first, Byte_second, Byte_third;
+
+  I2C_Start();
+  res = I2C_WriteByte(0x70); //It turned out to be 0x70
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(addr);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(0x00);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(0x00);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  I2C_Stop();
+
+  tdelay_ms(5); //Delay about 5ms
+  I2C_Start();
+  res = I2C_WriteByte(0x71);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_ReadByte(&Byte_first, 0);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_ReadByte(&Byte_second, 0);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_ReadByte(&Byte_third, 1);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  I2C_Stop();
+
+  tdelay_ms(10); //Delay about 10ms
+  I2C_Start();
+  res = I2C_WriteByte(0x70);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(0xB0|addr); //register command
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(Byte_second);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  res = I2C_WriteByte(Byte_third);
+  if (res != I2C_Ret_OK) {
+    return AHT_St_Err;
+  }
+  I2C_Stop();
+
+  return AHT_St_OK;
 }