Skip to main content

Sensor Reading Example

This example demonstrates reading data from an I2C temperature sensor using the ALP SDK. It periodically reads the sensor and prints the result over UART.

Prerequisites

  • An E1M module on a carrier board with I2C and UART accessible
  • An I2C temperature sensor connected to I2C bus 0 (e.g., TMP102, LM75, or similar)
  • UART channel 0 connected to a serial terminal at 115200 baud

Source Code

/**
* Sensor Reading Example - ALP SDK
*
* Reads temperature from an I2C sensor (TMP102) and
* prints the value over UART every second.
*/

#include <stdio.h>
#include <stdint.h>
#include "alp_board.h"
#include "alp_i2c.h"
#include "alp_uart.h"

/* TODO: Change this address to match your sensor */
#define SENSOR_I2C_ADDR 0x48 /* TMP102 default address */
#define TEMP_REG 0x00 /* Temperature register */

static ALP_I2C_Driver_t *i2c;
static ALP_UART_Driver_t *uart;

/**
* Read the temperature register from the sensor.
* Returns temperature in degrees Celsius (fixed-point, 0.0625 resolution).
*/
static float read_temperature(void)
{
uint8_t reg = TEMP_REG;
uint8_t data[2] = {0};

/* Write register address with repeated START */
i2c->MasterTransmit(SENSOR_I2C_ADDR, &reg, 1, true);
while (i2c->GetStatus().busy);

/* Read 2 bytes of temperature data */
i2c->MasterReceive(SENSOR_I2C_ADDR, data, 2, false);
while (i2c->GetStatus().busy);

/* Convert raw data to temperature (TMP102 format) */
int16_t raw = ((int16_t)data[0] << 4) | (data[1] >> 4);
if (raw & 0x0800) {
raw |= 0xF000; /* Sign extend for negative temperatures */
}

return raw * 0.0625f;
}

/**
* Simple blocking print over UART.
*/
static void uart_print(const char *str)
{
uart->Send((const uint8_t *)str, strlen(str));
while (uart->GetStatus().tx_busy);
}

/* Simple busy-wait delay */
static void delay_ms(uint32_t ms)
{
volatile uint32_t count;
for (uint32_t i = 0; i < ms; i++) {
for (count = 0; count < 8000; count++) {
__asm volatile("nop");
}
}
}

int main(void)
{
char buf[64];

/* Initialize board (clocks, pin mux) */
ALP_Board_Init();

/* Initialize I2C bus 0 */
i2c = ALP_I2C_GetDriver(0);
i2c->Initialize(NULL);
i2c->PowerControl(ALP_POWER_FULL);
i2c->Control(ALP_I2C_BUS_SPEED, ALP_I2C_BUS_SPEED_STANDARD);

/* Initialize UART channel 0 for debug output */
uart = ALP_UART_GetDriver(0);
uart->Initialize(NULL);
uart->PowerControl(ALP_POWER_FULL);
uart->Control(ALP_UART_MODE_ASYNCHRONOUS |
ALP_UART_DATA_BITS_8 |
ALP_UART_PARITY_NONE |
ALP_UART_STOP_BITS_1,
115200);
uart->Control(ALP_UART_CONTROL_TX, 1);

uart_print("[ALP SDK] Sensor Reading example started\r\n");

while (1) {
float temp = read_temperature();
int temp_int = (int)temp;
int temp_frac = (int)((temp - temp_int) * 100);
if (temp_frac < 0) temp_frac = -temp_frac;

snprintf(buf, sizeof(buf),
"Temperature: %d.%02d C\r\n", temp_int, temp_frac);
uart_print(buf);

delay_ms(1000);
}

return 0;
}

Building

mkdir build && cd build
cmake -DBOARD=e1m_x_v2n -DEXAMPLE=sensor_reading ..
cmake --build . --parallel

Expected Output

Connect a serial terminal at 115200 baud to see:

[ALP SDK] Sensor Reading example started
Temperature: 24.56 C
Temperature: 24.62 C
Temperature: 24.50 C
...

Adapting for Other Sensors

To use a different I2C sensor:

  1. Change SENSOR_I2C_ADDR to the sensor's 7-bit I2C address.
  2. Update TEMP_REG and the register read sequence to match the sensor's datasheet.
  3. Adjust the raw-to-engineering-unit conversion in read_temperature().

Next Steps

  • Add error handling for I2C NACK and bus errors
  • Use FreeRTOS tasks and queues for non-blocking sensor reads
  • Log data to an SD card or transmit over the network
  • Explore other peripheral APIs: SPI, GPIO, UART