Skip to content

Commit 0edbe30

Browse files
committed
Added battery voltage and MCU temperature reading functions implementation for Nucleo platforms
1 parent 625cd6c commit 0edbe30

File tree

4 files changed

+304
-9
lines changed

4 files changed

+304
-9
lines changed

src/boards/NucleoL073/board.c

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Gpio_t Led2;
6060
/*
6161
* MCU objects
6262
*/
63+
Adc_t Adc;
6364
Uart_t Uart2;
6465

6566
#if defined( LR1110MB1XXS )
@@ -150,6 +151,8 @@ void BoardInitMcu( void )
150151
SystemClockReConfig( );
151152
}
152153

154+
AdcInit( &Adc, NC ); // Just initialize ADC
155+
153156
#if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
154157
SpiInit( &SX126x.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
155158
SX126xIoInit( );
@@ -193,6 +196,8 @@ void BoardResetMcu( void )
193196

194197
void BoardDeInitMcu( void )
195198
{
199+
AdcDeInit( &Adc );
200+
196201
#if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
197202
SpiDeInit( &SX126x.Spi );
198203
SX126xIoDeInit( );
@@ -225,19 +230,110 @@ void BoardGetUniqueId( uint8_t *id )
225230
id[0] = ( ( *( uint32_t* )ID2 ) );
226231
}
227232

233+
/*!
234+
* Factory power supply
235+
*/
236+
#define VDDA_VREFINT_CAL ( ( uint32_t ) 3000 ) // mV
237+
238+
/*!
239+
* VREF calibration value
240+
*/
241+
#define VREFINT_CAL ( *( uint16_t* ) ( ( uint32_t ) 0x1FF80078 ) )
242+
243+
/*
244+
* Internal temperature sensor, parameter TS_CAL1: TS ADC raw data acquired at
245+
* a temperature of 110 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV).
246+
*/
247+
#define TEMP30_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FF8007A ) )
248+
249+
/* Internal temperature sensor, parameter TS_CAL2: TS ADC raw data acquired at
250+
*a temperature of 30 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). */
251+
#define TEMP110_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FF8007E ) )
252+
253+
/* Vdda value with which temperature sensor has been calibrated in production
254+
(+-10 mV). */
255+
#define VDDA_TEMP_CAL ( ( uint32_t ) 3000 )
256+
257+
/*!
258+
* Battery thresholds
259+
*/
260+
#define BATTERY_MAX_LEVEL 3000 // mV
261+
#define BATTERY_MIN_LEVEL 2400 // mV
262+
#define BATTERY_SHUTDOWN_LEVEL 2300 // mV
263+
264+
#define BATTERY_LORAWAN_UNKNOWN_LEVEL 255
265+
#define BATTERY_LORAWAN_MAX_LEVEL 254
266+
#define BATTERY_LORAWAN_MIN_LEVEL 1
267+
#define BATTERY_LORAWAN_EXT_PWR 0
268+
269+
#define COMPUTE_TEMPERATURE( TS_ADC_DATA, VDDA_APPLI ) \
270+
( ( ( ( ( ( ( int32_t )( ( TS_ADC_DATA * VDDA_APPLI ) / VDDA_TEMP_CAL ) - ( int32_t ) TEMP30_CAL_ADDR ) ) * \
271+
( int32_t )( 110 - 30 ) ) \
272+
<< 8 ) / \
273+
( int32_t )( TEMP110_CAL_ADDR - TEMP30_CAL_ADDR ) ) + \
274+
( 30 << 8 ) )
275+
276+
static uint16_t BatteryVoltage = BATTERY_MAX_LEVEL;
277+
228278
uint16_t BoardBatteryMeasureVoltage( void )
229279
{
230-
return 0;
280+
uint16_t vref = 0;
281+
282+
// Read the current Voltage
283+
vref = AdcReadChannel( &Adc, ADC_CHANNEL_VREFINT );
284+
285+
// Compute and return the Voltage in millivolt
286+
return ( ( ( uint32_t ) VDDA_VREFINT_CAL * VREFINT_CAL ) / vref );
231287
}
232288

233289
uint32_t BoardGetBatteryVoltage( void )
234290
{
235-
return 0;
291+
return BatteryVoltage;
236292
}
237293

238294
uint8_t BoardGetBatteryLevel( void )
239295
{
240-
return 0;
296+
uint8_t batteryLevel = 0;
297+
298+
BatteryVoltage = BoardBatteryMeasureVoltage( );
299+
300+
if( GetBoardPowerSource( ) == USB_POWER )
301+
{
302+
batteryLevel = BATTERY_LORAWAN_EXT_PWR;
303+
}
304+
else
305+
{
306+
if( BatteryVoltage >= BATTERY_MAX_LEVEL )
307+
{
308+
batteryLevel = BATTERY_LORAWAN_MAX_LEVEL;
309+
}
310+
else if( ( BatteryVoltage > BATTERY_MIN_LEVEL ) && ( BatteryVoltage < BATTERY_MAX_LEVEL ) )
311+
{
312+
batteryLevel =
313+
( ( 253 * ( BatteryVoltage - BATTERY_MIN_LEVEL ) ) / ( BATTERY_MAX_LEVEL - BATTERY_MIN_LEVEL ) ) + 1;
314+
}
315+
else if( ( BatteryVoltage > BATTERY_SHUTDOWN_LEVEL ) && ( BatteryVoltage <= BATTERY_MIN_LEVEL ) )
316+
{
317+
batteryLevel = 1;
318+
}
319+
else // if( BatteryVoltage <= BATTERY_SHUTDOWN_LEVEL )
320+
{
321+
batteryLevel = BATTERY_LORAWAN_UNKNOWN_LEVEL;
322+
}
323+
}
324+
return batteryLevel;
325+
}
326+
327+
int16_t BoardGetTemperature( void )
328+
{
329+
uint16_t tempRaw = 0;
330+
331+
BatteryVoltage = BoardBatteryMeasureVoltage( );
332+
333+
tempRaw = AdcReadChannel( &Adc, ADC_CHANNEL_TEMPSENSOR );
334+
335+
// Compute and return the temperature in degree celcius * 256
336+
return ( int16_t ) COMPUTE_TEMPERATURE( tempRaw, BatteryVoltage );
241337
}
242338

243339
static void BoardUnusedIoInit( void )

src/boards/NucleoL152/board.c

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Gpio_t Led2;
6060
/*
6161
* MCU objects
6262
*/
63+
Adc_t Adc;
6364
Uart_t Uart2;
6465

6566
#if defined( LR1110MB1XXS )
@@ -150,6 +151,8 @@ void BoardInitMcu( void )
150151
SystemClockReConfig( );
151152
}
152153

154+
AdcInit( &Adc, NC ); // Just initialize ADC
155+
153156
#if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
154157
SpiInit( &SX126x.Spi, SPI_1, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC );
155158
SX126xIoInit( );
@@ -193,6 +196,8 @@ void BoardResetMcu( void )
193196

194197
void BoardDeInitMcu( void )
195198
{
199+
AdcDeInit( &Adc );
200+
196201
#if defined( SX1261MBXBAS ) || defined( SX1262MBXCAS ) || defined( SX1262MBXDAS )
197202
SpiDeInit( &SX126x.Spi );
198203
SX126xIoDeInit( );
@@ -225,19 +230,110 @@ void BoardGetUniqueId( uint8_t *id )
225230
id[0] = ( ( *( uint32_t* )ID2 ) );
226231
}
227232

233+
/*!
234+
* Factory power supply
235+
*/
236+
#define VDDA_VREFINT_CAL ( ( uint32_t ) 3000 ) // mV
237+
238+
/*!
239+
* VREF calibration value
240+
*/
241+
#define VREFINT_CAL ( *( uint16_t* ) ( ( uint32_t ) 0x1FF800F8 ) )
242+
243+
/*
244+
* Internal temperature sensor, parameter TS_CAL1: TS ADC raw data acquired at
245+
* a temperature of 110 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV).
246+
*/
247+
#define TEMP30_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FF8007A ) )
248+
249+
/* Internal temperature sensor, parameter TS_CAL2: TS ADC raw data acquired at
250+
*a temperature of 30 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). */
251+
#define TEMP110_CAL_ADDR ( *( uint16_t* ) ( ( uint32_t ) 0x1FF8007E ) )
252+
253+
/* Vdda value with which temperature sensor has been calibrated in production
254+
(+-10 mV). */
255+
#define VDDA_TEMP_CAL ( ( uint32_t ) 3000 )
256+
257+
/*!
258+
* Battery thresholds
259+
*/
260+
#define BATTERY_MAX_LEVEL 3000 // mV
261+
#define BATTERY_MIN_LEVEL 2400 // mV
262+
#define BATTERY_SHUTDOWN_LEVEL 2300 // mV
263+
264+
#define BATTERY_LORAWAN_UNKNOWN_LEVEL 255
265+
#define BATTERY_LORAWAN_MAX_LEVEL 254
266+
#define BATTERY_LORAWAN_MIN_LEVEL 1
267+
#define BATTERY_LORAWAN_EXT_PWR 0
268+
269+
#define COMPUTE_TEMPERATURE( TS_ADC_DATA, VDDA_APPLI ) \
270+
( ( ( ( ( ( ( int32_t )( ( TS_ADC_DATA * VDDA_APPLI ) / VDDA_TEMP_CAL ) - ( int32_t ) TEMP30_CAL_ADDR ) ) * \
271+
( int32_t )( 110 - 30 ) ) \
272+
<< 8 ) / \
273+
( int32_t )( TEMP110_CAL_ADDR - TEMP30_CAL_ADDR ) ) + \
274+
( 30 << 8 ) )
275+
276+
static uint16_t BatteryVoltage = BATTERY_MAX_LEVEL;
277+
228278
uint16_t BoardBatteryMeasureVoltage( void )
229279
{
230-
return 0;
280+
uint16_t vref = 0;
281+
282+
// Read the current Voltage
283+
vref = AdcReadChannel( &Adc, ADC_CHANNEL_VREFINT );
284+
285+
// Compute and return the Voltage in millivolt
286+
return ( ( ( uint32_t ) VDDA_VREFINT_CAL * VREFINT_CAL ) / vref );
231287
}
232288

233289
uint32_t BoardGetBatteryVoltage( void )
234290
{
235-
return 0;
291+
return BatteryVoltage;
236292
}
237293

238294
uint8_t BoardGetBatteryLevel( void )
239295
{
240-
return 0;
296+
uint8_t batteryLevel = 0;
297+
298+
BatteryVoltage = BoardBatteryMeasureVoltage( );
299+
300+
if( GetBoardPowerSource( ) == USB_POWER )
301+
{
302+
batteryLevel = BATTERY_LORAWAN_EXT_PWR;
303+
}
304+
else
305+
{
306+
if( BatteryVoltage >= BATTERY_MAX_LEVEL )
307+
{
308+
batteryLevel = BATTERY_LORAWAN_MAX_LEVEL;
309+
}
310+
else if( ( BatteryVoltage > BATTERY_MIN_LEVEL ) && ( BatteryVoltage < BATTERY_MAX_LEVEL ) )
311+
{
312+
batteryLevel =
313+
( ( 253 * ( BatteryVoltage - BATTERY_MIN_LEVEL ) ) / ( BATTERY_MAX_LEVEL - BATTERY_MIN_LEVEL ) ) + 1;
314+
}
315+
else if( ( BatteryVoltage > BATTERY_SHUTDOWN_LEVEL ) && ( BatteryVoltage <= BATTERY_MIN_LEVEL ) )
316+
{
317+
batteryLevel = 1;
318+
}
319+
else // if( BatteryVoltage <= BATTERY_SHUTDOWN_LEVEL )
320+
{
321+
batteryLevel = BATTERY_LORAWAN_UNKNOWN_LEVEL;
322+
}
323+
}
324+
return batteryLevel;
325+
}
326+
327+
int16_t BoardGetTemperature( void )
328+
{
329+
uint16_t tempRaw = 0;
330+
331+
BatteryVoltage = BoardBatteryMeasureVoltage( );
332+
333+
tempRaw = AdcReadChannel( &Adc, ADC_CHANNEL_TEMPSENSOR );
334+
335+
// Compute and return the temperature in degree celcius * 256
336+
return ( int16_t ) COMPUTE_TEMPERATURE( tempRaw, BatteryVoltage );
241337
}
242338

243339
static void BoardUnusedIoInit( void )

0 commit comments

Comments
 (0)