ST7735R LCD showing weather data for Baldwin Park with the TM4C123 + CC3100 board in the background

Overview

CECS 447 project at Cal State Long Beach, built with Roy Mears, Jonathan Ramirez, and Luis Arevalo. We developed an IoT-based embedded weather station that connects to the internet over WiFi, queries the OpenWeatherMap API, parses the JSON response on a bare-metal ARM microcontroller, and displays the results on both a serial terminal and a color LCD with animated weather icons.

The system uses a TM4C123 LaunchPad paired with a CC3100 Booster Pack for WiFi connectivity, and an ST7735R 1.8" color LCD driven over SPI for the visual display. The user selects a query type through a serial terminal, and the system fetches and renders live weather data — city name, current temperature, min/max, humidity, and weather condition — all running on a 16 MHz ARM Cortex-M4 with no operating system.

Video Demo


How It Works

Program flowchart showing the full query-fetch-parse-display pipeline

The system follows a straightforward pipeline that loops continuously:

  1. Display menu on the serial terminal — user picks a query type (city name, city ID, geographic coordinates, or zip code)
  2. Build HTTP GET request — the MenuQuery() function formats the user input into a valid OpenWeatherMap API URL
  3. DNS resolutionsl_NetAppDnsGetHostByName() resolves api.openweathermap.org to an IP address
  4. TCP connectionsl_Connect() opens a socket to the API server
  5. Send request / receive responsesl_Send() transmits the HTTP GET, sl_Recv() captures the full JSON response
  6. Parse JSON — Custom string parsing extracts name, temp, temp_min, temp_max, humidity, and main fields from the raw JSON
  7. Display on UART — Full JSON response and formatted summary printed to the serial terminal at 115200 baud
  8. Display on LCD — Formatted weather data rendered on the ST7735R with multiple font sizes, colors, shapes, and animated weather icons
  9. Loop — Return to menu for the next query

Hardware

TM4C123 LaunchPad + CC3100 Booster Pack

TM4C123 LaunchPad with CC3100 WiFi Booster Pack, LEDs indicating active connection

The TM4C123GXL is a Texas Instruments ARM Cortex-M4 development board running at 16 MHz. The CC3100 Booster Pack stacks on top and provides full WiFi connectivity with an onboard TCP/IP stack — the microcontroller sends high-level SimpleLink API calls and the CC3100 handles all the wireless protocol details.

The CC3100 communicates with the TM4C123 over SPI. The SimpleLink library provides functions for WiFi connection, DNS resolution, socket management, and HTTP communication — all callable from bare-metal C.

ST7735R Color LCD

The 1.8" ST7735R TFT display (128x160, 16-bit color) connects over SPI to the TM4C123:

  • SCK on PA2 (SSI0Clk)
  • MOSI on PA5 (SSI0Tx)
  • TFT_CS on PA3 (SSI0Fss)
  • Data/Command on PA6 (GPIO)
  • Reset on PA7 (GPIO)

The LCD driver provides functions for drawing text at multiple sizes, pixels, lines, circles, diagonal lines, filled rectangles, and bitmap images — all used to compose the weather display layout.

Schematic

Hardware schematic showing TM4C123, CC3100 Booster Pack, and ST7735R LCD connections


Software Architecture

Software module diagram showing ST7735main.c and Systick.c function relationships

The firmware is organized into modular C files:

ST7735main.c — Main Application

The core module handles everything: WiFi initialization, user input, HTTP communication, JSON parsing, and LCD rendering. Key functions:

  • configureSimpleLinkToDefaultState() — Resets the CC3100 to a known state
  • MenuQuery() — Presents the serial menu and formats the HTTP GET request string
  • main() — Main loop that connects WiFi, sends queries, parses responses, and updates displays
  • SysTick_Handler() — Interrupt handler that cycles through animation frames at 10 Hz

JSON Parsing

Since this is bare-metal C with no JSON library, parsing is done by searching for specific tokens in the raw response string. The code locates keys like "name", "temp", "temp_min", "temp_max", "humidity", and "main", then extracts the values that follow. Temperatures are converted from Kelvin to Fahrenheit before display.

Serial Terminal Output

Serial terminal showing raw JSON response and parsed weather data for Baldwin Park

The UART output shows both the complete raw JSON from OpenWeatherMap and a clean formatted summary with city name, temperature (current, min, max), humidity, and weather condition. This runs at 115200 baud through the TM4C123’s built-in USB-to-serial interface.

Systick.c — Animation Timer

The SysTick timer is configured with a reload value of 1,600,000 (10 Hz at 16 MHz) and priority 2:

void SysTick_Init(){
  NVIC_ST_CTRL_R = 0;
  NVIC_ST_RELOAD_R = 1600000-1;  // 10 Hz at 16 MHz
  NVIC_ST_CURRENT_R = 0;
  NVIC_SYS_PRI3_R = (NVIC_SYS_PRI3_R&0x1FFFFFFF)|0x40000000;
  NVIC_ST_CTRL_R |= NVIC_ST_CTRL_CLK_SRC|NVIC_ST_CTRL_INTEN|NVIC_ST_CTRL_ENABLE;
}

Every 100ms, the SysTick_Handler in ST7735main.c advances the animation frame counter and draws the next bitmap for the current weather condition. This hardware-based timing ensures smooth animations without blocking the main loop’s network communication or data parsing.


LCD Display Design

The LCD layout is split into distinct zones with multiple visual elements:

  • Header — City name in small text with a weather icon animation area
  • Weather condition — Large bold text (“Clouds”, “Clear”, “Rain”) in a contrasting color
  • Temperature — Min, Max, and Average displayed with different text sizes
  • Humidity — Large percentage display at the bottom
  • Graphics — Horizontal/vertical divider lines, a circle, and a diagonal line as required design elements
  • Two background colors — Upper section uses a light tone, lower section uses green for visual separation

Weather Animations

Three sets of pre-defined bitmap frames stored in bmps.h:

  • Clear — Sun animation cycling through frames
  • Clouds — Cloud shapes shifting position
  • Rain — Raindrop animation with falling pattern

The SysTick_Handler selects which animation set to use based on the parsed "main" weather condition field, then cycles through the frames using ST7735_DrawBitmap() at 10 Hz.


Query Types

The system supports four methods for looking up weather data:

  1. City Name — e.g., “Los Angeles” or “Baldwin Park”
  2. City ID — OpenWeatherMap’s numeric city identifier
  3. Geographic Coordinates — Latitude and longitude
  4. Zip Code — US zip codes (e.g., 91706)

Each query type formats a different HTTP GET URL parameter, but all hit the same OpenWeatherMap API endpoint and return the same JSON structure.


What I Learned

  • Bare-metal networking is surprisingly approachable with the CC3100’s SimpleLink API — it abstracts TCP/IP but you still manage sockets, DNS, and HTTP manually
  • JSON parsing without a library forces you to really understand string manipulation in C and handle edge cases carefully
  • SPI display rendering at the pixel level gives you total control but requires careful buffer management to avoid flicker
  • SysTick interrupts for animations are a clean way to handle periodic tasks without blocking — this pattern carries directly to RTOS timer tasks

Tech Stack

  • MCU: TM4C123GXL (ARM Cortex-M4, 16 MHz)
  • WiFi: CC3100 Booster Pack (SimpleLink API)
  • Display: ST7735R 1.8" TFT LCD (128x160, SPI)
  • Language: C (bare-metal, no RTOS)
  • Protocols: SPI (LCD), UART (serial terminal), TCP/IP + HTTP (WiFi)
  • API: OpenWeatherMap (JSON response)
  • IDE: Keil uVision