Electronic Load  1.0
Programmable Constant Current Sink
Functions | Variables
spi.c File Reference

Routines for SPI connected peripherals (ADC, DAC and LEDs) More...

Include dependency graph for spi.c:

Functions

double ADCGetAs (void)
 Gets the Ampere Seconds consumed. More...
 
double ADCGetIavg (void)
 Returns the averaged Value for Load Current. More...
 
double ADCGetIByVal (uint16_t iRaw, bool isHigh)
 Returns the Current for a given Value. More...
 
uint16_t ADCGetIHighAvgRaw ()
 Returns the averaged Value for the Current. More...
 
uint16_t ADCGetIhighLifeRaw ()
 Returns the Life Value for the Current. More...
 
uint16_t ADCGetILowAvgRaw ()
 Returns the averaged Value for the Current. More...
 
uint16_t ADCGetIlowLifeRaw ()
 Returns the Life Value for the Current. More...
 
double ADCGetVavg (void)
 Returns the averaged Value for the Sink Voltage. More...
 
uint16_t ADCGetVAvgRaw ()
 Returns the averaged Value for the Sink Voltage. More...
 
uint16_t ADCGetVLifeRaw ()
 Returns the Life Value for the Sink Voltage. More...
 
void CalcIMaxLookupTable (void)
 Calculates the Lookup Table for IMax. More...
 
void CalcRChannel (void)
 
void DACSetAmps (double i)
 Sets the DAC to a certain Current. More...
 
void DACSetAmpsByStr (char *str)
 Sets the sink to the value of a string. More...
 
void DACSetRaw (uint16_t value)
 Sets the raw Value of the DAC. More...
 
void DACSetRawFast (uint16_t value)
 The same as DACSetRaw() but without updating the controls This function has been introduced to allow setting the DAC from ISRs. More...
 
 ISR (SPI_STC_vect)
 The Interrupt Service Routine for SPI. More...
 
void SetHighCurrentMode (void)
 Sets High Current Mode. More...
 
void SetLowCurrentMode (void)
 Sets Low Current Mode. More...
 
static void SoaLimit ()
 Calculates the maximum allowable Current This function is designed to be fast enough to be executed from the SPI interrupt. It uses the lookup table soaIMaxLUT and a fast integer multiplication for temperature derating if the current range is high. If the actual DAC value is higher than allowed, it is reduced and the SOA error is set. In low current range no derating is necessary and this function does nothing. More...
 
void SPIInit (void)
 Initializes the SPI Interface. More...
 
uint8_t SpiSendAndReceiveByte (uint8_t b)
 Sends and receives a Byte over the SPI Bus. More...
 
void SPISetLEDs (uint8_t mask)
 Sets the State of the 8 LEDs on the SPI-Shift-Register. More...
 

Variables

volatile ADC_RcvStruct_t ADC_RcvStruct
 
double DACAmps
 Saves the value last set for the DAC. More...
 
uint16_t derating
 Temperature Derating factor *65535. Maximum Power has to be derated by multiplication with derating. More...
 
uint16_t soaIMaxLUT [128]
 Lookup Table for maximum DAC-Value versus ADC-Voltage. More...
 
volatile SPIADCData_t SPIADCAvg
 Averaged Values over 16 measurements. These values may get up to 14 bits of precision. More...
 
volatile uint8_t SPIPtr
 Is set by SPIStartADC() and counted down to zero by the ADC Interrupt. More...
 
SPI_XmtStruct_t SPISendData ={{.array={0x00,0x00,0xa3,0x00,0x93,0x00,0x83}}}
 Send data buffer for the ADC. More...
 

Detailed Description

Routines for SPI connected peripherals (ADC, DAC and LEDs)

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Function Documentation

◆ CalcIMaxLookupTable()

void CalcIMaxLookupTable ( void  )

Calculates the Lookup Table for IMax.

Here is the call graph for this function:

◆ SPISetLEDs()

void SPISetLEDs ( uint8_t  mask)

Sets the State of the 8 LEDs on the SPI-Shift-Register.

Parameters
maskA Bitmask of the LEDs
Note
The LEDs are not set immediately but on the next SPI interrupt covering the LED shift register. This may introduce a small delay.

◆ SetLowCurrentMode()

void SetLowCurrentMode ( void  )

Sets Low Current Mode.

◆ SetHighCurrentMode()

void SetHighCurrentMode ( void  )

Sets High Current Mode.

◆ SpiSendAndReceiveByte()

uint8_t SpiSendAndReceiveByte ( uint8_t  b)

Sends and receives a Byte over the SPI Bus.

SPI implies the reception of a byte whenever one is sent. It depends on the hardware if it contains useful data.

Note
This function blocks for the time of the transfer.
Parameters
bThe Byte to transmit
Returns
The received Byte

◆ DACSetRawFast()

void DACSetRawFast ( uint16_t  value)
inline

The same as DACSetRaw() but without updating the controls This function has been introduced to allow setting the DAC from ISRs.

Note
Fast means the execution time. There is still a delay from the call of this function until the DAC is actually set!
Parameters
valueThe Value
Here is the caller graph for this function:

◆ DACSetRaw()

void DACSetRaw ( uint16_t  value)

Sets the raw Value of the DAC.

Parameters
valueThe Value
Here is the call graph for this function:

◆ DACSetAmps()

void DACSetAmps ( double  i)

Sets the DAC to a certain Current.

This function also switches the current range to high or low if the desired value is higher than rangeHighLimit or lower than rangeLowLimit.

Parameters
iThe Current
Here is the call graph for this function:

◆ DACSetAmpsByStr()

void DACSetAmpsByStr ( char *  str)

Sets the sink to the value of a string.

Parameters
strA Pointer to the string containing the value in amperes
Here is the call graph for this function:

◆ ADCGetIavg()

double ADCGetIavg ( void  )

Returns the averaged Value for Load Current.

This function honors the range setting and returns the value measured by the active sense resistor.

Returns
The averaged Load Current in A
Here is the call graph for this function:

◆ ADCGetAs()

double ADCGetAs ( void  )

Gets the Ampere Seconds consumed.

Returns
The As
Here is the call graph for this function:

◆ ADCGetIByVal()

double ADCGetIByVal ( uint16_t  iRaw,
bool  isHigh 
)

Returns the Current for a given Value.

Parameters
iRawThe raw value from the ADC, normalized to 16 bits
isHighTrue if the value represents a high current mode value
Returns
The Load Current in A

◆ ADCGetVavg()

double ADCGetVavg ( void  )

Returns the averaged Value for the Sink Voltage.

Note
The voltage over the sink may be reduced by cable and/or additional resistance and may not reflect the exact value of the source voltage.
Returns
The Voltage over the Sink in V

◆ ADCGetIhighLifeRaw()

uint16_t ADCGetIhighLifeRaw ( )

Returns the Life Value for the Current.

The current is measured over the lower of the two shunts representing the high current range. The value is normalized to 16 bit unsigned int.

Returns
The current in the range of 0000 to ffff

◆ ADCGetIlowLifeRaw()

uint16_t ADCGetIlowLifeRaw ( )

Returns the Life Value for the Current.

The current is measured over the higher of the two shunts representing the low current range. Note that this value is garbage if the resistor is shorted by the MOSFET. The value is normalized to 16 bit unsigned int.

Returns
The current in the range of 0000 to ffff

◆ ADCGetVLifeRaw()

uint16_t ADCGetVLifeRaw ( )

Returns the Life Value for the Sink Voltage.

The value is normalized to 16 bit unsigned int.

Returns
The Voltage over the Sink in the range of 0000 to ffff

◆ ADCGetIHighAvgRaw()

uint16_t ADCGetIHighAvgRaw ( )

Returns the averaged Value for the Current.

The current is measured over the lower of the two shunts representing the high current range. The value is normalized to 16 bit unsigned int.

Returns
The current in the range of 0000 to ffff

◆ ADCGetILowAvgRaw()

uint16_t ADCGetILowAvgRaw ( )

Returns the averaged Value for the Current.

The current is measured over the higher of the two shunts representing the low current range. Note that this value is garbage if the resistor is shorted by the MOSFET. The value is normalized to 16 bit unsigned int.

Returns
The current in the range of 0000 to ffff

◆ ADCGetVAvgRaw()

uint16_t ADCGetVAvgRaw ( )

Returns the averaged Value for the Sink Voltage.

The value is normalized to 16 bit unsigned int.

Returns
The Voltage over the Sink in the range of 0000 to ffff

◆ SPIInit()

void SPIInit ( void  )

Initializes the SPI Interface.

Here is the call graph for this function:

◆ SoaLimit()

static void SoaLimit ( )
inlinestatic

Calculates the maximum allowable Current This function is designed to be fast enough to be executed from the SPI interrupt. It uses the lookup table soaIMaxLUT and a fast integer multiplication for temperature derating if the current range is high. If the actual DAC value is higher than allowed, it is reduced and the SOA error is set. In low current range no derating is necessary and this function does nothing.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalcRChannel()

void CalcRChannel ( void  )
Here is the call graph for this function:

◆ ISR()

ISR ( SPI_STC_vect  )

The Interrupt Service Routine for SPI.

It collects the Data of the ADC and builds up averages. The life 12-bit value read out of the ADC starts at bit 15 in the receive struct. By averaging 16 values we gain additional 2 bits of accuracy. So the average value will be a 16-bit FSR-Value where the 2 LSBs are garbage and thus reflect 14 bits. It will occur at a frequency of ~12.5kHz with a 7.3728MHz crystal.

Here is the call graph for this function:

Variable Documentation

◆ SPISendData

SPI_XmtStruct_t SPISendData ={{.array={0x00,0x00,0xa3,0x00,0x93,0x00,0x83}}}

Send data buffer for the ADC.

Each conversion needs 3 bytes to send. The first one is the command byte followed by two "0"-bytes in which the ADC sends its result. Command byte is composed as:
S Start bit, always 1
A2-A0 Channel address
X Dummy bit
SGL/DIF 1 for single ended, 0 for differential
PD1-0 Power down mode
Simply by sending 7 Bytes all conversions for the three channels we use are done. The last byte is a dummy byte necessary to get the last ADC result.

◆ ADC_RcvStruct

volatile ADC_RcvStruct_t ADC_RcvStruct

◆ SPIADCAvg

volatile SPIADCData_t SPIADCAvg

Averaged Values over 16 measurements. These values may get up to 14 bits of precision.

◆ SPIPtr

volatile uint8_t SPIPtr

Is set by SPIStartADC() and counted down to zero by the ADC Interrupt.

◆ derating

uint16_t derating

Temperature Derating factor *65535. Maximum Power has to be derated by multiplication with derating.

◆ soaIMaxLUT

uint16_t soaIMaxLUT[128]

Lookup Table for maximum DAC-Value versus ADC-Voltage.

This table contains the maximum DAC-Values for the high byte of a given ADC voltage result. So the ADC interrupt can easily decide to reduce the current with each measurement if the SOA is violated.
This table has to be calculated by CalcIMaxLookupTable() on system startup!

Note
For now, we keep this as uint16_t but 256 values with two bytes each make a quarter of the controllers RAM. We could reduce this to only the upper byte of the DAC at the cost of usable SOA area. Further reduction is possible by using less bits of the ADC value.
Note also that the values still have to be degraded according to the case (heatsink) temperature!

◆ DACAmps

double DACAmps

Saves the value last set for the DAC.