Skip to content

Commit

Permalink
MPAE-14690: Changed to 10MHz clock and 3.3V VDD
Browse files Browse the repository at this point in the history
  • Loading branch information
Erling Holten Wiken authored and egilro committed Jun 21, 2023
1 parent 54d7b01 commit 43c5ac2
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 74 deletions.
43 changes: 19 additions & 24 deletions analog-current-sensing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,30 @@ This example shows how to use the AVR EA microcontoller to measure a current by

## Setup

[![current_measure_block_diagram](../images/current_measure-resistor_setup.png)
![current_measure_block_diagram](../images/current_measure-resistor_setup.png)

- The DAC0 OUT pin (PD6 on AVR64EA48) is connected to the ADC0 IN1 pin (PD1 on AVR64EA48) via resistor R<sub>1</sub>. The DAC0 OUT pin will generate the voltage (V<sub>0</sub>) we use as basis for emulating a current source.
- The ADC0 IN1 input pin (PD1 on AVR64EA48) is connected to the ADC0 IN0 pin (PD0 on AVR64EA48) via resistor R<sub>SENSE</sub>. This is the sensing resistor that is used to calculate the current I<sub>0</sub>.
- The ADC0 IN0 input pin (PD0 on AVR64EA48) is connected to ground (GND) via resistor R<sub>2</sub>

## Operation

- Connect the AVR64EA48 Curiosity Nano to a computer using a USB cable
- Connect the AVR64EA48 Curiosity Nano (Cnano) to a computer using a USB cable
- Download the zip file or clone the example to get the source code
- Open the .atsln file with Microchip Studio
- Press Start Without Debugging (CTRL+ALT+F5) to run the application
- Press Start Without Debugging (CTRL+ALT+F5) to run the application

## Setting the target voltage on the Curiosity Nano board

This example uses the maximum allowed main clock frequency (10 MHz) at the default board voltage (3.3V). To use a higher clock frequency, the AVR64EA48 Curiosity Nano board target voltage must be set accordingly (V<sub>DD</sub> > 4.5V, see <i>Electrical Characteristics</i> in the Data Sheet). To do this, click the **Device Programming** button or enter (Ctrl + Shift + P) in Microchip Studio. Select the correct tool and device (if nothing else is connected, this is your default selected) and press the **Apply** button next to "Interface: UPDI". Now click "Tool Settings" in the left side menu, and write "5" in the "Generated" text field. Click the **Write** button, and the new voltage will be applied to the cnano board. This voltage will remain set until a new target voltage is written to the board.

![set_cnano_voltage](../images/cnano_voltage_setting.png)

## View USART data in a terminal

This example uses USART1 to send data to the virtual serial port of the Curiosity Nano board. The data can be captured using a terminal application on the computer where the Curiosity Nano board is connected. This example uses a baud rate of 115200 with 8 bit data, 1 stop bit, no parity (standard format). This example shows the terminal view in the Atmel Data Visualizer standalone version.

[![current_measure_terminal](../images/csense_terminal.png)
![current_measure_terminal](../images/csense_terminal.png)

## Theory

Expand Down Expand Up @@ -121,7 +127,7 @@ $$

In the example code, USART1 is used to output the measured voltage and calculated current to a terminal. To enable this the "#define USART_ON" must be included.

The Periodic Interrupt Timer (PIT), a part of the Real-Time Counter (RTC), is set up to generate an interrupt approximately each second to bring the device out of Sleep mode. When this happens, a counter is incremented and checked against a predefined period (10 seconds). During the Power-Down Sleep mode the 20 MHz clock source is disabled and only the internal 32 kHz oscillator and the RTC clock source is running.
The Periodic Interrupt Timer (PIT), a part of the Real-Time Counter (RTC), is set up to generate an interrupt approximately each second to bring the device out of Sleep mode. When this happens, a counter is incremented and checked against a predefined period (10 seconds). During the Power-Down Sleep mode the 10 MHz clock source is disabled and only the internal 32 kHz oscillator and the RTC clock source is running.

If the value matches this period, the DAC is enabled to produce an output voltage of 1.8V and the ADC is enabled. The ADC is commanded to start a differential conversion immediately. While the AD conversion is in progress, the CPU performs the calculations necessary for converting the previous ADC value into a voltage and a current. The results are printed to the terminal. As soon as this happens, the AD conversion is complete, the DAC and ADC are disabled, and the device goes back into sleep mode.

Expand All @@ -133,28 +139,17 @@ When measuring low-value signals like in this example, the PGA should be enabled

The following table shows the average current consumptions using different configurations (V<sub>DD</sub> = 3.3V):

|Main Clock | PGA Disabled (ADC), Average Current | PGA Enabled (ADC), Average Current | Relative Difference |
|:--------|:-------:|:------:|:-----:|
|2 MHz |1.63 µA |1.42 µA | -13% |
|3.33 MHz |1.41 µA |1.33 µA | -6% |
|20 MHz |1.14 µA |1.12 µA | -2% |

The measured current is reduced with increasing clock speeds, which seems somewhat counterintuitive. Since the device spend most of the time in a power-down sleep state and only wake for a brief period, this means that the total time in the Wake state is shorter with higher clock frequencies.

The average current consumption in the Wake state will be higher with increasing clock frequencies. But since the time spent in the Wake state is lowered with increasing clock frequency, this effect is more significant for this example, leading to lower average current consumption with increasing clock frequency.

The average current consumption done with the PGA enabled was lower than when the PGA was off. This does not follow the theoretical expected result that using the PGA should result in higher current consumption. Testing showed that by not entering sleep and sampling the ADC on each interrupt (each second) with the main clock at 20 MHz, the results were as expected:

| PGA | Average Current Consumption |
|:----|:---:|
|PGA OFF | 8.44 mA |
|PGA ON | 9.01 mA |
|Main Clock | PGA Disabled (ADC), Average Current | PGA Enabled (ADC), Average Current
|:--------|:-------:|:------:|
|2 MHz |1.7 µA |1.6 µA |
|3.33 MHz |1.4 µA |1.3 µA |
|10 MHz |1.2 µA |1.1 µA |

When re-enabling the "timeout counter" so the ADC sampling only happens every 10 seconds, the measurements were:
The average current consumption done with the PGA enabled was lower than when the PGA was off. This does not follow the theoretical expected result that using the PGA should result in higher current consumption. Testing showed that by not entering Sleep and sampling the ADC on each interrupt (each second) with the main clock at 10 MHz, the results were as expected:

| PGA | Average Current Consumption |
|:----|:---:|
|PGA OFF | 6.06 mA |
|PGA ON | 6.06 mA |
|PGA OFF | 3.476 mA |
|PGA ON | 3.498 mA |

This suggests that the higher average current consumption measured when PGA is off as compared to when the PGA is enabled in the initial measurement is due to a combination of the time between each ADC measurement and the code executing order.
41 changes: 22 additions & 19 deletions analog-current-sensing/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

// Define Main clock
#define F_CPU (20000000UL) // 20 MHz clock
#define F_CPU (10000000UL) // 10 MHz clock

// USART Defines
#define BAUD_RATE 115200 // Define the baud rate for the USART
Expand All @@ -23,7 +23,7 @@

// General Defines
#define TIMEBASE_VALUE ((uint8_t) ceil(F_CPU * 0.000001))
// TIMEBASE_VALUE = number of clock ticks in 1us
// TIMEBASE_VALUE = number of clock ticks in 1us
#define WAKEUP_TIME 10 // Wakeup and sample ADC each 10 seconds
#define R_SENSE 10000 // Sense resistor value in Ohm
#define BIAS_ADJUST // add bias and offset adjustment to measurement
Expand Down Expand Up @@ -213,13 +213,16 @@ void ftostr(float n, char* res, int decimals)
* init_clock(void)
*
* Set main clock
* For 3.33 MHz just comment out and do nothing (default)
*
**************************************************************************/
void init_clock(void)
{
// Main clock no divider --> CLK_PER = 20 MHz
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0);
// Main clock divide by 2 --> CLK_PER = 20 MHz / 2 = 10 MHz
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, (CLKCTRL_PDIV_DIV2_gc | CLKCTRL_PEN_bm));

while(CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm)
; // Wait for clock change to complete
}


Expand All @@ -233,12 +236,12 @@ void init_clock(void)
**************************************************************************/
void init_PORT(void)
{
PORTA.PINCONFIG = PORT_ISC_INPUT_DISABLE_gc;
PORTA.PINCTRLUPD = 0xff;
PORTB.PINCTRLUPD = 0xff;
PORTC.PINCTRLUPD = 0xff;
PORTD.PINCTRLUPD = 0xff;
PORTE.PINCTRLUPD = 0xff;
PORTA.PINCONFIG = PORT_ISC_INPUT_DISABLE_gc;
PORTA.PINCTRLUPD = 0xff;
PORTB.PINCTRLUPD = 0xff;
PORTC.PINCTRLUPD = 0xff;
PORTD.PINCTRLUPD = 0xff;
PORTE.PINCTRLUPD = 0xff;
PORTF.PINCTRLUPD = 0xff;
}

Expand Down Expand Up @@ -481,7 +484,15 @@ void do_ADC0_measurement(void)
// Start differential ADC conversion, burst mode (16x)
ADC0.COMMAND = ADC_DIFF_bm | ADC_MODE_BURST_gc | ADC_START_IMMEDIATE_gc;

//While ADC is sampling, calculate previous measurement
while( !(ADC0.INTFLAGS & ADC_RESRDY_bm) ) // wait until RESRDY flag is set
;

sample_acc = ADC0.RESULT; // Read ADC result

ADC0.CTRLA = 0; // Disable ADC
DAC0.CTRLA = 0; // Disable DAC

//Calculate measurement
#ifdef BIAS_ADJUST
sample_acc = sample_acc - adc_offset - adc_center; // Adjust for offset and bias
#endif
Expand All @@ -507,14 +518,6 @@ void do_ADC0_measurement(void)
usart1_sendString(res);
usart1_sendString("uA\n");
#endif

while( !(ADC0.INTFLAGS & ADC_RESRDY_bm) ) // wait until RESRDY flag is set
;

sample_acc = ADC0.RESULT; // Read ADC result

ADC0.CTRLA = 0; // Disable ADC
DAC0.CTRLA = 0; // Disable DAC
}


Expand Down
55 changes: 27 additions & 28 deletions analog-voltage-sensing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,32 @@ DAC0OUT (PD6 on AVR EA) pin to the ADC0 AIN0 (PD0 on AVR EA) pin

## Operation

- Connect the AVR64EA48 Curiosity Nano to a computer using a USB cable
- Connect the AVR64EA48 Curiosity Nano (Cnano) to a computer using a USB cable
- Download the zip file or clone the example to get the source code
- Open the .atsln file with Microchip Studio
- Press Start Without Debugging (CTRL+ALT+F5) to run the application

## Setting the target voltage on the Curiosity Nano board

This example uses the maximum allowed main clock frequency (10 MHz) at the default board voltage (3.3V). To use a higher clock frequency, the AVR64EA48 Curiosity Nano board target voltage must be set accordingly (V<sub>DD</sub> > 4.5V, see <i>Electrical Characteristics</i> in the Data Sheet). To do this, click the **Device Programming** button or enter (Ctrl + Shift + P) in Microchip Studio. Select the correct tool and device (if nothing else is connected, this is your default selected) and press the **Apply** button next to "Interface: UPDI". Now click "Tool Settings" in the left side menu, and write "5" in the "Generated" text field. Click the **Write** button, and the new voltage will be applied to the cnano board. This voltage will remain set until a new target voltage is written to the board.

![set_cnano_voltage](../images/cnano_voltage_setting.png)

## Theory

To measure the RTD, the DAC is enabled to produce an output of
approximately 1.8V. Since the DAC voltage is applied to a 1.8 kΩ fixed resistor in series with the RTD, the current flowing through the RTD will be under 1 mA. A current under 1mA prevents the RTD from any significant self-heating. The ADC is used to measure the voltage across the RTD, and this allows the resistance and temperature of the RTD to be computed.
To measure the RTD, the DAC is enabled to produce an output of approximately 1.8V. Since the DAC voltage is applied to a 1.8 kΩ fixed resistor in series with the RTD, the current flowing through the RTD will be under 1 mA. A current below 1 mA prevents the RTD from any significant self-heating. The ADC is used to measure the voltage across the RTD, and this allows the resistance and temperature of the RTD to be computed.

The resistance of the RTD varies in a known way as a function of temperature (T), in accordance with the following equations, where A, B, and C are constants associated with the specific RTD and R<sub>0</sub> is the resistance of the RTD at a temperature of 0 Celsius:

For T of 0°C or higher, R(T) = R<sub>0</sub>(1 + AT + BT<sup>2</sup>)
For T of 0°C or higher, R(T) = R<sub>0</sub> * (1 + AT + BT<sup>2</sup>)

For T of -200°C to 0°C, R(T) = R<sub>0</sub>(1 + AT + BT<sup>2</sup> + CT<sup>3</sup>(T -100))
For T of -200°C to 0°C, R(T) = R<sub>0</sub> * (1 + AT + BT<sup>2</sup> + CT<sup>3</sup> * (T -100) )

If the resistance of the RTD is known, then the above formulas can be
used to determine the temperature.
If the resistance of the RTD is known, then the above formulas can be used to determine the temperature.

Here are the relevant formulas for determining the resistance of the RTD:
Here are the relevant formulas for determining the resistance of the RTD:

First, the voltage across the RTD is determined by the voltage divider
equation, where R<sub>F</sub> is resistance of the fixed resistor and R<sub>TD</sub> is
resistance of the RTD:
First, the voltage across the RTD is determined by the voltage divider equation, where R<sub>F</sub> is resistance of the fixed resistor and R<sub>TD</sub> is resistance of the RTD:

<!-- If your markdown viewer support equations, you can replace the image with this formula
$$
Expand All @@ -64,8 +66,7 @@ $$
-->
![vsense_eq1](../images/V_RTD_equation.png)

The ADC digital result x, when the ADC is used in Differential mode, is
determined by the following equation (from the data sheet):
The ADC digital result x, when the ADC is used in Differential mode, is determined by the following equation (from the data sheet):

<!-- If your markdown viewer support equations, you can replace the image with this formula
$$
Expand All @@ -74,8 +75,7 @@ $$
-->
![vsense_eq2](../images/x_equation.png)

The voltage divider equation from above can be substituted in for V<sub>RTD</sub>
and V<sub>REF</sub> cancels out:
The voltage divider equation from above can be substituted in for V<sub>RTD</sub> and V<sub>REF</sub> cancels out:

<!-- If your markdown viewer support equations, you can replace the image with this formula
$$
Expand All @@ -84,7 +84,7 @@ $$
-->
![vsense_eq3](../images/x_equation2.png)

This equation can be solved for R<sub>TD</sub>, the resistance of the RTD:
This equation can be solved for R<sub>TD</sub>, the resistance of the RTD:

<!-- If your markdown viewer support equations, you can replace the image with this formula
$$
Expand All @@ -97,24 +97,23 @@ Note that V<sub>REF</sub> does not appear in the equation at all, so errors in t

To minimize power consumption, the AVR EA is configured to stay in Power-Down Sleep mode whenever a measurement is not in progress. In this Sleep mode, AVR EA consumption was measured to approximately 0.9 µA (with V<sub>DD</sub> = 3.3V). The PIT (Periodic Interrupt Timer), a part of the RTC (Real Time Counter), is set up to periodically generate an interrupt to bring the device out of Sleep mode. In this example the period is set to 512, for 1 measurement every 0.5 seconds. When this happens, the DAC is enabled to produce an output voltage of 1.8V and the ADC is enabled. The ADC is commanded to start a differential conversion immediately. While the AD conversion is in progress, the CPU performs the calculations necessary for converting the previous ADC value into resistance and temperature. As soon as the AD conversion is complete and the result is saved, DAC and ADC are disabled and the device is put back to sleep.

When the DAC and ADC are both enabled after the device comes out of sleep, the DAC output
stabilizes before the ADC is ready to start its first conversion, so there is no need for additional delays in the software.
When the DAC and ADC are both enabled after the device comes out of sleep, the DAC output stabilizes before the ADC is ready to start its first conversion, so there is no need for additional delays in the software.

## Conclusion

Various strategies were tested to minimize power consumption (higher/lower CPU+ADC clock speeds, PGA on/off with less/more conversions), but in this case the overriding issue is the fact that the DAC must supply nearly 1 mA of current to the RTD sensor while AD conversions are in progress. Therefore the best strategy is to run both the CPU and ADC as fast as possible (20 MHz and 5 MHz clocks, respectively) with maximum PGA gain so the conversion time, and the time that the DAC must supply 1 mA, is minimized. During the Power-Down sleep mode the 20 MHz clock source is disabled and only the internal 32 kHz oscillator and the RTC clock source is running. With this configuration, a burst of 16 ADC conversions takes only 119 µs.
Various strategies were tested to minimize power consumption (higher/lower CPU and ADC clock speeds, PGA on/off with less/more conversions), but in this case the overriding issue is the fact that the DAC must supply nearly 1 mA of current to the RTD sensor while AD conversions are in progress. Therefore the best strategy is to run both the CPU and ADC as fast as possible (10 MHz and 5 MHz clocks, respectively) with maximum PGA gain so the conversion time, and the time that the DAC must supply 1 mA, is minimized. During the Power-Down Sleep mode the 10 MHz clock source is disabled and only the internal 32 kHz oscillator and the RTC clock source are running. With this configuration, a burst of 16 ADC conversions takes only 155 µs.

During that 119 microseconds of conversion time with DAC enabled, microcontroller supply current was measured as 8.0 mA (this includes what is needed by the DAC to drive the RTD, with V<sub>DD</sub> = 3.3V). Note that, if there is one conversion per second, the average current will be:
119 µs / 1s × 8 mA = 1.19e-4 × 8 mA = 0.95 µA
During that 155 microseconds of conversion time with DAC enabled, microcontroller supply current was measured as 4.7 mA (this includes what is needed by the DAC to drive the RTD, with V<sub>DD</sub> = 3.3V). If there is one conversion per second, the average current will be:
155 µs / 1s × mA = 1.55e-4 × 4.7 mA = 0.73 µA

Measured average current consumption is 0.9µA + (0.95µA)*n, where
Measured average current consumption is 0.9 µA + (0.73 µA) * n, where
n is the number of RTD temperature measurements per second:

|n |Current Consumption (with V<sub>DD</sub> = 3.3V) |
|:--------:|------------------:|
|2 |2.8 µA |
|4 |4.7 µA |
|8 |8.5 µA |
|16 |16 µA |
|32 |31 µA |
|64 |62 µA |
|2 |2.4 µA |
|4 |3.7 µA |
|8 |6.6 µA |
|16 |12.3 µA |
|32 |23.8 µA |
|64 |46.8 µA |
6 changes: 3 additions & 3 deletions analog-voltage-sensing/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

#define F_CPU (20000000UL) // CPU frequency in Hz
#define F_CPU (10000000UL) // CPU frequency in Hz
#define TIMEBASE_VALUE ((uint8_t) ceil(F_CPU*0.000001))

#include <avr/io.h>
Expand Down Expand Up @@ -54,8 +54,8 @@ int main(void)
PORTE.PINCTRLUPD = 0xff;
PORTF.PINCTRLUPD = 0xff;

// Change main clock to 20 MHz by disabling the prescaler
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0);
// Change main clock to 10 MHz by dividing by 2 (20MHz/2=10MHz)
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, (CLKCTRL_PDIV_DIV2_gc | CLKCTRL_PEN_bm));
while(CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm){
; // Wait for clock change to complete
}
Expand Down
Binary file added images/cnano_voltage_setting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 43c5ac2

Please sign in to comment.