Skip to content

Instantly share code, notes, and snippets.

@racka98
Last active December 31, 2022 09:45
Show Gist options
  • Save racka98/a3aed23b1355e7d37d84430472262ee7 to your computer and use it in GitHub Desktop.
Save racka98/a3aed23b1355e7d37d84430472262ee7 to your computer and use it in GitHub Desktop.
AM2320 Sensor failing example
#include "am2320.h"
static uint16_t readRegister16(uint8_t reg);
static uint16_t crc16(uint8_t *buffer, uint8_t nbytes);
static void sensor_read() {
sleep_ms(3000);
am2320_data values;
while (true) {
sleep_ms(8000);
printf("Reading Values... \n");
values = am2320_read_data();
printf("Temp: %f C\n", values.temp);
printf("Humidity: %f%%\n", values.hum);
}
}
void test_temp_sensor() {
// Configure the I2C
printf("Configuring I2C\n");
i2c_init(DEFAULT_I2C_PORT, 400 * 1000);
gpio_set_function(DEFAULT_SDA, GPIO_FUNC_I2C);
gpio_set_function(DEFAULT_SCL, GPIO_FUNC_I2C);
gpio_pull_up(DEFAULT_SDA);
gpio_pull_up(DEFAULT_SCL);
// initialize
sensor_read();
}
am2320_data am2320_read_data() {
// Create Empty sensor data
am2320_data data = {.temp = -40.0, .hum = 0.0};
// use an 8 byte buffer for sending and receiving data
uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
// write to the dht to wake it up
i2c_write_blocking(DEFAULT_I2C_PORT, AM2320_ADDRESS, buffer, 1, false);
sleep_ms(10);
// send request to read all data from the dht (4 bytes of temp and hum data)
uint8_t write_buff[3] = {AM2320_CMD_READREG, AM2320_START_ADDRESS, AM2320_DATA_END_ADDRESS};
i2c_write_blocking(DEFAULT_I2C_PORT, AM2320_ADDRESS, write_buff, 3, true);
sleep_ms(5);
// dht sends us back 8 bytes, read them
/*
* Read out 8 bytes of data
* Byte 0: Should be Modbus function code 0x03
* Byte 1: Should be number of registers to read (0x04)
* Byte 2: Humidity msb
* Byte 3: Humidity lsb
* Byte 4: Temperature msb
* Byte 5: Temperature lsb
* Byte 6: CRC lsb byte
* Byte 7: CRC msb byte
*/
i2c_read_blocking(DEFAULT_I2C_PORT, AM2320_ADDRESS, buffer, 8, false);
// if echoed command was not to read 4 bytes of data registers, error
printf("Is read addr correct: %d\n", buffer[0] == AM2320_ADDRESS || buffer[0] == _u(0x03));
printf("[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
if (buffer[0] != AM2320_CMD_READREG || buffer[1] != AM2320_DATA_END_ADDRESS) {
printf("Invalid data read!\n");
return data;
}
// calulate checksum and compare vs recived checksum (2 last bytes)
// if no match, error
uint16_t the_crc = (buffer[7] << 8) | buffer[6];
uint16_t calc_crc = crc16(buffer, 6);
if (the_crc != calc_crc) {
printf("CRC Checksum no match!\n");
return data;
}
// extract the temp and hum data from recived data
// temp: high is byte 4, low is byte 5
// hum: high is byte 2, low is byte 3
uint16_t tempData = (buffer[4] << 8) | buffer[5];
uint16_t humData = (buffer[2] << 8) | buffer[3];
// fill struct with temp and hum data by dividing recived values by 10,
// clearing high of temp as it only communicates sign data
data.temp = (tempData & 0x7FFF) / 10;
data.hum = humData / 10;
// if first bit of temp is set, it is negative
if (tempData & 0x8000) {
data.temp *= -1;
}
return data;
}
/**************************************************************************/
/*!
@brief perfor a CRC check to verify data
@param buffer the pointer to the data to check
@param nbytes the number of bytes to calculate the CRC over
@return the calculated CRC
*/
/**************************************************************************/
static uint16_t crc16(uint8_t *buffer, uint8_t nbytes) {
unsigned short crc = 0xFFFF;
unsigned char i;
while (nbytes--) {
crc ^= *buffer++;
for (i = 0; i < 8; i++) {
if (crc & 0x01) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
#pragma once
#include <hardware/i2c.h>
#include <pico/stdlib.h>
#include <stdio.h>
#define DEFAULT_SDA 10 // GPIO 10 (Physical PIN 14)
#define DEFAULT_SCL 11 // GPIO 11 (Pysical PIN 15)
#define DEFAULT_I2C_PORT i2c1 // i2c1 instance
#define AM2320_ADDRESS 0x5C // < Address of sensor
#define AM2320_START_ADDRESS 0x00 // < start address of the data
#define AM2320_DATA_END_ADDRESS 0x04 // < end address of the temp & humidity data
#define AM2320_CMD_READREG 0x03 // < read register command
#define AM2320_REG_TEMP_H 0x02 // < high temp register address
#define AM2320_REG_HUM_H 0x00 // < high humidity register address
typedef struct {
uint8_t address; /**< i2c address of display*/
i2c_inst_t *i2c_i; /**< i2c connection instance */
} am2320_t;
typedef struct {
float temp; // < temperature reading from the sensor in °C
float hum; // < humidity reading from the sensor
} am2320_data;
// Calling this in main to test it.
void test_temp_sensor();
am2320_data am2320_read_data();
#include <pico/cyw43_arch.h>
#include <pico/stdlib.h>
#include "am2320.h"
int main() {
stdio_init_all(); // Initialize
printf("Main Program Executation start!\n");
// Testing the sensor here
test_temp_sensor();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment