Launching a weather balloon design
Extracting and monitoring the data from the sensors is critical for meteorological organizations. A standalone Weather Data logger is used for logging the temperature, humidity, rainfall, leaf wetness, pressure, sun radiation etc, but, standalone data loggers are restricted to collect data on the ground stations only. To supervise the environmental parameters like temperature, humidity, pressure, wind speed and wind direction in the sky, this logging technique is not feasible. To overcome this problem, it is necessary to change the design strategy.
Presented here is a case study of environmental weather balloon that monitors the atmospheric parameters over the air using the RF module AX5042. Weather balloons are often called Radiosonde or GPSsonde . The aim of this design is to capture the data from a sensor and send it to the receiver located on the ground.
The weather balloon is divided into three blocks. They are UHF transmitter (for RF transmission), sensor unit, and Time synchronization modules (GPS and RTC).
Flying Weather Balloon (Source: WNEP)
First of all, I will go through the block diagram of Radiosonde. Later, we will explore the inner details of hardware and their interfacing.
Block Diagram of RadioSonde (Weather Balloon) (Source: Kumar B)
Working of Weather Balloon
The AX5042 RF chip generates the required transmission frequency. You can also set the transmission time interval for sending the data.
Any microcontroller can be used to interface various external peripherals like GPS, RTC (Real Time Clock) and Sensors.
The data is captured from the sensors and sent to the remote location using RF communication.
To have correct transmission, a Real time clock (RTC) DS3231 with an accuracy of ±1ppm is preferred.
But, how to get the time and date?
A GPS receiver Ublox is put upon to get the date and time from the INSAT satellite installed at space.
Not only the date and time, you can also get the latitude, longitude etc. from the MAX7C GPS module.
The obtained date and time from the GPS unit is loaded into the microcontroller.
Generally, the radiosondes use frequencies in the range of 400 MHz to 600 MHz.
Algorithm
This algorithm describes the basic idea of implementing weather balloon.
-
Sync the GPS with the satellite.
-
Get the time from the GPS.
-
Load this time into RTC (Real time clock).
-
Lock the frequency using AX5042.
-
Send and receive the sensor data periodically.
Software Environment (Source: Kumar B)
Getting Started with AX5042
By now, you’re probably wondering, How to know the underlying hardware? Don’t worry.
On semiconductor provides Evaluation kit DVK-BASE-2-GEVK with necessary add on modules.
The AXsem integrated circuits use AX−RadioLAB GUI and AX-MicroLab code generators, AXSDB Debugger, and AXCode: Blocks IDE.
Here I have used AT89C2051 microcontroller for working out the prototype. The microcontroller is communicated with AX5042 using SPI interface.
First of all, the AX5042 has to be loaded with certain frequency. To do that PLL bits has to be programmed.
Hardware and Software Design
I have written the application code in embedded C using keil µVision IDE. The below interface shows the connection between microcontroller, AX5042 and HYT 271 humidity sensor.
The humidity sensor runs on 3.3V pull-up resistors. It is advisable to use 2.2K resistors for better response.
AX5042 and Microcontroller Connection (Source: Kumar B)
AX5042 has to be programmed for producing the required frequency. The microcontroller writes and read the data using SPI interface.
/*This code will generate the RF frequency using AX5042. */#include <REG52.H>#include <at892051.h#include <stdio.h>#define SyDataO P1_4#define SyDataI P1_5#define SyClock P1_6#define SythLE P1_7LoadPLL (void);DataFrame (void);spi_write (unsigned long spi_addr);init_ax5042 (void);unsigned char spi_read (unsigned int spi_addr);
This function will generate external interrupt has occurred from AX5042. AX5042 acts as slave and the microcontroller as master.
/*********interrupt Function for Ext.Interrupt-0 *********/unsigned char ex0_isr_counter = 0;void ex0_isr (void) interrupt 0{ ex0_isr_counter++; // Increment the count LoadPLL ( ); P3_2 = 1;}
The application code starts from here. The serial port is configured at 9600 baud rate for sending the characters to the serial terminal.
/*******main function *******/void main (void){ unsigned char W;/*Set serial port for 9600 baud at 11.0592 MHz. Note that we use Timer 1 for the baud rate generator.*/ SCON = 0x50; TMOD |= 0x20; TH1 = 0xFA; TR1 = 1; RI = 1; TI = 1; PCON |= 0x80; IT0 = 1; // Configure interrupt 0 for falling edge on /INT0 (P3.2) EX0 = 1; // Enable EX0 Interrupt EA = 1; // Enable Global Interrupt Flag // Frequency Loading Program P1=0; P3=4; SythLE = 1; SyClock= 0; SyDataO= 0; while (1) //Infinite loop {
The getchar function waits to receive the character from the serial terminal. If the received character matches, function will get executed.
/*Wait for the pulse to start. */ W = getchar ( ); if (W== 'r') { printf ("RF"); init_ax5042 ( ); LoadPLL ( ); } if (W== 'w') { printf ("Wd"); LoadPLL ( ); } if (W==‘t’) { init_ax5042 (); } }}
This function creates delay in seconds.
delay (int n) /* Wait for ‘n’ seconds */{ int i; for (i=0; i< n; i++) { ; }}
To use the configuration registers for 2051, header file is included for AT89C2051 .
/* Header file for AT89C2051 */#ifndef __AT892051_H__#define __AT892051_H__/*------------------------------------------------P1 Bit Registers------------------------------------------------*/sbit P1_4 = 0x94;sbit P1_5 = 0x95;sbit P1_6 = 0x96;sbit P1_7 = 0x97;/*------------------------------------------------P3 Bit Registers (Mnemonics & Ports)------------------------------------------------*/sbit P3_0 = 0xB0;sbit P3_1 = 0xB1;sbit P3_2 = 0xB2;sbit P3_3 = 0xB3;sbit P3_4 = 0xB4;sbit P3_5 = 0xB5;/* P3_6 Hardwired as AOUT */sbit P3_7 = 0xB7;/*------------------------------------------------Interrupt Vectors:Interrupt Address = (Number * 8) + 3------------------------------------------------*/#define IE0_VECTOR 0 /* 0x03 External interrupt 0 */#define IE1_VECTOR 2 /* 0x13 External interrupt 1 */#define SIO_VECTOR 4 /* 0x23 Serial port */#endif
The AX5042 has to be configured to send and receive the data. The AX5042 registers has to be enabled. (Scroll to see full code below.)
/*Header file for AX5042*//*AX 5042 registers which have to be modified or read in course of transmission or reception of data*/ #ifndef __AX5042_H_#define __AX5042_H_#define AX5042_REG_REVISION 0x00#define AX5042_REG_SCRATCH 0x01#define AX5042_REG_POWERMODE 0x02 #define AX5042_REG_FIFOCTRL 0x04#define AX5042_REG_FIFODATA 0x05 #define AX5042_REG_IRQMASK 0x06 #define AX5042_REG_PINCFG1 0x0C#define AX5042_REG_PINCFG2 0x0D#define AX5042_REG_PINCFG3 0x0E /*******************************//* AX5042 Static Register Definition*//*******************************/// AX5042 register names#define AX5042_REG_XTALOSC 0x03#define AX5042_REG_IFMODE 0x08#define AX5042_REG_MODULATION 0x10#define AX5042_REG_ENCODING 0x11#define AX5042_REG_FRAMING 0x12#define AX5042_REG_CRCINIT3 0x14#define AX5042_REG_CRCINIT2 0x15#define AX5042_REG_CRCINIT1 0x16#define AX5042_REG_CRCINIT0 0x17#define AX5042_REG_FEC 0x18#define AX5042_REG_FECSYNC 0x19#define AX5042_REG_FREQ3 0x20#define AX5042_REG_FREQ2 0x21#define AX5042_REG_FREQ1 0x22#define AX5042_REG_FREQ0 0x23#define AX5042_REG_FSKDEV2 0x25#define AX5042_REG_FSKDEV1 0x26#define AX5042_REG_FSKDEV0 0x27#define AX5042_REG_IFFREQHI 0x28#define AX5042_REG_IFFREQLO 0x29#define AX5042_REG_PLLLOOP 0x2c#define AX5042_REG_PLLRANGING 0x2d#define AX5042_REG_PLLRNGCLK 0x2e#define AX5042_REG_TXPWR 0x30#define AX5042_REG_TXRATEHI 0x31#define AX5042_REG_TXRATEMID 0x32#define AX5042_REG_TXRATELO 0x33#define AX5042_REG_MODMISC 0x34#define AX5042_REG_ADCMISC 0x38#define AX5042_REG_AGCTARGET 0x39#define AX5042_REG_AGCATTACK 0x3a#define AX5042_REG_AGCDECAY 0x3b#define AX5042_REG_AGCCOUNTER 0x3c#define AX5042_REG_CICDECHI 0x3e#define AX5042_REG_CICDECLO 0x3f#define AX5042_REG_DATARATEHI 0x40#define AX5042_REG_DATARATELO 0x41#define AX5042_REG_TMGGAINHI 0x42#define AX5042_REG_TMGGAINLO 0x43#define AX5042_REG_PHASEGAIN 0x44#define AX5042_REG_FREQGAIN 0x45#define AX5042_REG_FREQGAIN2 0x46#define AX5042_REG_AMPLGAIN 0x47#define AX5042_REG_SPAREOUT 0x60#define AX5042_REG_TESTOBS 0x68#define AX5042_REG_APEOVER 0x70#define AX5042_REG_TMMUX 0x71#define AX5042_REG_PLLVCOI 0x72#define AX5042_REG_PLLCPEN 0x73#define AX5042_REG_PLLRNGMISC 0x74#define AX5042_REG_AGCMANUAL 0x78#define AX5042_REG_ADCDCLEVEL 0x79#define AX5042_REG_RFMISC 0x7a#define AX5042_REG_TXDRIVER 0x7b#define AX5042_REG_REF 0x7c#define AX5042_REG_RXMISC 0x7d#define AX5042_idle 0x00// receive states#define AX5042_RX_preamble 0x01#define AX5042_RX_delimiter_start 0x02#define AX5042_RX_data 0x03#define AX5042_RX_CRC 0x04#define AX5042_RX_packet_end 0x05#define AX5042_RX_abort 0x06 // Transmit States#define AX5042_TX_preamble 0x81#define AX5042_TX_delimiter_start 0x82#define AX5042_TX_data 0x83#define AX5042_TX_CRC 0x84#define AX5042_TX_delimiter_stop 0x85#define AX5042_TX_postamble 0x86#define AX5042_RX 0x00#define AX5042_TX 0x01#define DONE 0x00#define PROCESSING 0x01#endif /* __AX5042_H_ */ The registers are configured for AX5042. /*This function initialises the AX5042 using SPI interface */ /* to initialise ax5042*/init_ax5042 (void){/*register settings are calculated by the AXEVK software */spi_write (0x0200); //modeOFFAX5042_REG_POWERMODEspi_write (0x0C10); // AX5042_REG_PINCFG1spi_write (0x7201); //PLLARNG=1 AX5042_REG_PLLVCOIspi_write (0x7401); //PLLARNG AX5042_REG_PLLRNGMISC spi_write (0x0302); // AX5042_REG_XTALOSCspi_write (0x0800); // AX5042_REG_IFMODEspi_write (0x1009); //AX5042_REG_MODULATIONspi_write (0x1104); // AX5042_REG_ENCODINGspi_write (0x1204); // AX5042_REG_FRAMINGspi_write (0x14ff); // AX5042_REG_CRCINIT3spi_write (0x15ff); // AX5042_REG_CRCINIT2spi_write (0x16ff); // AX5042_REG_CRCINIT1spi_write (0x17ff); // AX5042_REG_CRCINIT0spi_write (0x1810); // AX5042_REG_FECspi_write (0x1962); // AX5042_REG_FECSYNCspi_write (0x2036); // AX5042_REG_FREQ3spi_write (0x2145); // AX5042_REG_FREQ2spi_write (0x227b); // AX5042_REG_FREQ1spi_write (0x2387); // AX5042_REG_FREQ0spi_write (0x2c1d); // AX5042_REG_PLLLOOPspi_write (0x2d08); // AX5042_REG_PLLRANGINGspi_write (0x2e03); // AX5042_REG_PLLRNGCLKspi_write (0x3403); // AX5042_REG_MODMISCspi_write (0x6000); // AX5042_REG_SPAREOUTspi_write (0x6800); // AX5042_REG_TESTOBSspi_write (0x7000); //AX5042_REG_APEOVERspi_write (0x7100); // AX5042_REG_TMMUXspi_write (0x7204); // AX5042_REG_PLLVCOIspi_write (0x7301); // AX5042_REG_PLLCPENspi_write (0x7400); // AX5042_REG_PLLRNGMISCspi_write (0x7a30); // AX5042_REG_RFMISCspi_write (0x7c23); // AX5042_REG_REF spi_write (0x2500); // AX5042_REG_FSKDEV2spi_write (0x2666); // AX5042_REG_FSKDEV1spi_write (0x2767); // AX5042_REG_FSKDEV0spi_write (0x300f); // AX5042_REG_TXPWRspi_write (0x3101); // AX5042_REG_TXRATEHIspi_write (0x3299); // AX5042_REG_TXRATEMIDspi_write (0x339b); // AX5042_REG_TXRATELOspi_write (0x7b88); // AX5042_REG_TXDRIVER}
The configured frequency is loaded into the PLL IC.
/*This function will store the PLL values into AX5042*/LoadPLL ( ){ unsigned int SyncDividend;spi_write (0xaaaa);spi_write (0xaaaa);SyncDividend=spi_read (0x10aa);DataFrame ( );}
This function will write the data to AX5042.
/*Function to write the data to AX5042*/spi_write (unsigned long spi_addr){ unsigned int j; spi_addr = spi_addr | 0x8000; SythLE = 0; delay (3); for (j=0; j<=15; j++) { SyClock= 0; if((spi_addr & 0x8000) ==0) SyDataO=0; else SyDataO=1; delay(3); SyClock=1; spi_addr = (spi_addr<<1); delay(3); } delay(3); SythLE = 1; SyClock= 0; SyDataO = 0; }
This function will read the data from AX5042.
/*Function to read the data from AX5042*/unsigned char spi_read (unsigned int spi_addr){ unsigned int d; unsigned int j; d= 0x0000; spi_addr = spi_addr & 0x7fff; SythLE = 1; delay(3); SythLE = 0; delay(3); for(j=0; j<=15; j++) { delay(3); SyClock= 0; if((spi_addr & 0x8000) ==0) SyDataO=0; else SyDataO=1; delay(3); SyClock=1; spi_addr= (spi_addr<<1); d=d<<1; d= d ^ SyDataO; delay(3); } SythLE = 1; SyClock= 0; SyDataO = 0; return d;}
This function constructs the data packet for transmission. The data is taken from the humidity module.
DataFrame ( ){unsigned int Sensordata;SythLE = 0;Sensordata=humidity;SythLE = 1;SyClock= 0;}
After setting the RF frequency, we have to construct the data frame and send to the receiver.
The data may be captured from any sensor. I have used HYT 271 Humidity sensor and read the humidity and temperature using I2C.
As AX5042 acts as transmitter as well as receiver, we can transmit and receive the data using the same module.
But AX5042 is just part of the Weather balloon.
Weather balloons are precise in their timing due to implementation of GPS and real time clock.
In the upcoming article, we will explore on how to use GPS and RTC for the radiosonde application.
References:
[1] Serial Peripheral Interface Bus – Wikipedia
[2] On Semi DVK-BASE-2-GEVK: DVK-2 Base Evaluation Kit
[3] HYT271 Humidity sensor interface using I2C
[4] http://ww1.microchip.com/downloads/en/DeviceDoc/doc0368.pdf
[5] http://www.onsemi.com/pub/Collateral/AND9354-D.PDF
Kumar B is a device driver developer w orking as an embedded software engineer in Qualcomm having 6+ years of working experience in developing embedded devices on various target boards. His areas of interest include Internet of Things, Artificial Intelligence, Machine Learning and Image processing.