Skip to content

Commit 5179c2a

Browse files
committed
Pull request #1: Feature/addcode
MPAE-9710 Initial example code and readme added
1 parent 35e0b5c commit 5179c2a

File tree

7 files changed

+541
-38
lines changed

7 files changed

+541
-38
lines changed

.main-meta/main.json

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@
44
"content": {
55
"metaDataVersion": "1.1.0",
66
"name": "com.microchip.mcu8.studio.project.avr128db48-overcurrent-protection-studio",
7-
"version": "",
8-
"displayName": "",
7+
"version": "1.0.0",
8+
"displayName": "Overcurrent Protection Using the Integrated Op Amps on AVR DB",
99
"projectName": "avr128db48-overcurrent-protection-studio",
10-
"shortDescription": "",
10+
"shortDescription": "This repository provides a bare metal Microchip Studio project for a core independent overcurrent protection and handling with auto-calibration of current draw trigger level using the internal OPAMP, TCD and AC.",
1111
"ide": {
1212
"name": "STUDIO",
13-
"semverRange": ""
13+
"semverRange": ">=7.0.2542"
1414
},
1515
"compiler": [
1616
{
17-
"name": "",
18-
"semverRange": ""
17+
"name": "AVR GCC",
18+
"semverRange": "^5.4.0"
1919
}
2020
],
2121
"dfp": {
22-
"name": "",
23-
"semverRange": ""
22+
"name": "AVR-Dx_DFP",
23+
"semverRange": "^1.6.76"
2424
},
2525
"configurator": {
26-
"name": "",
26+
"name": "N/A",
2727
"semverRange": ""
2828
},
2929
"device": {
@@ -32,17 +32,48 @@
3232
"content": {
3333
"metaDataVersion": "1.0.0",
3434
"category": "com.microchip.device",
35-
"name": "",
35+
"name": "AVR128DB48",
3636
"versionRange": "*"
3737
}
3838
},
39-
"author": "",
39+
"author": "Johan Vaarlid",
4040
"subcategories": [
41+
[
42+
"Peripherals", "OPAMP"
43+
],
44+
[
45+
"Peripherals", "AC"
46+
],
47+
[
48+
"Peripherals", "EVSYS"
49+
],
50+
[
51+
"Peripherals", "CCL"
52+
],
53+
[
54+
"Peripherals", "TCD"
55+
],
56+
[
57+
"Development Kit", "AVR128DB48 Curiosity Nano"
58+
]
4159
],
4260
"peripherals": [
43-
],
61+
62+
"OPAMP","AC","EVSYS","CCL", "TCD"
63+
],
4464
"keywords": [
45-
],
65+
"Analog Signal Conditioning",
66+
"Operational Amplifier",
67+
"Op Amp",
68+
"Resistor Ladder",
69+
"D/A Converters",
70+
"Low BOM",
71+
"CIP",
72+
"Motor Control",
73+
"Comparators",
74+
"Fan Controllers",
75+
"overcurrent-protection"
76+
],
4677
"additionalData": {
4778
"longDescription": {
4879
"metaDataVersion": "1.0.0",

README.md

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
1-
<!-- Please do not change this logo with link -->
2-
[![MCHP](images/microchip.png)](https://www.microchip.com)
1+
<!-- Please do not change this html logo with link -->
2+
<a href="https://www.microchip.com" rel="nofollow"><img src="images/microchip.png" alt="MCHP" width="300"/></a>
33

4-
# Update the title for avr128db48-overcurrent-protection-studio here
5-
6-
<!-- This is where the introduction to the example goes, including mentioning the peripherals used -->
4+
# AVR128DB48 Current Spike Detection
5+
A new feature introduced in the AVR® DB family is the Analog Signal Conditioning (OPAMP) peripheral. In this example, the OPAMP is used together with an Analog Comparator (AC) to form a current spike detector. The fan is enabled by a TCD waveform output. This output will be shut off automatically when the current spike is detected by the detector, making it an ideal solution for applications where functional safety is needed. An example of an application where a current spike might indicate failure or danger, is a computer fan. Under normal operation, the current consumption is nonlinear, but does not exceed a certain threshold, dependent on the fans spec. By autotuning the gain of the internal OPAMP by using the internal resistor ladders, we can automatically boost the signal to a measurable range, and automatically set a trigger level for the AC by use of the on board DAC to define what an "unnaturally" high current consumtion is, indicating a touch or something stuck in the fan.
76

87
## Related Documentation
98

10-
<!-- Any information about an application note or tech brief can be linked here. Use unbreakable links!
11-
In addition a link to the device family landing page and relevant peripheral pages as well:
12-
- [AN3381 - Brushless DC Fan Speed Control Using Temperature Input and Tachometer Feedback](https://microchip.com/00003381/)
13-
- [PIC18F-Q10 Family Product Page](https://www.microchip.com/design-centers/8-bit/pic-mcus/device-selection/pic18f-q10-product-family) -->
9+
* [AN3860 - Overcurrent Protection Using the Integrated Op Amps on AVR® DB](https://microchip.com/DS00003860)
10+
* [AVR128DB48 device page](https://www.microchip.com/wwwproducts/en/AVR128DB48)
11+
* [AVR128DB48 Curiosity Nano User Guide](https://www.microchip.com/DS50003037)
1412

1513
## Software Used
1614

17-
<!-- All software used in this example must be listed here. Use unbreakable links!
18-
- MPLAB® X IDE 5.30 or newer [(microchip.com/mplab/mplab-x-ide)](http://www.microchip.com/mplab/mplab-x-ide)
19-
- MPLAB® XC8 2.10 or a newer compiler [(microchip.com/mplab/compilers)](http://www.microchip.com/mplab/compilers)
20-
- MPLAB® Code Configurator (MCC) 3.95.0 or newer [(microchip.com/mplab/mplab-code-configurator)](https://www.microchip.com/mplab/mplab-code-configurator)
21-
- MPLAB® Code Configurator (MCC) Device Libraries PIC10 / PIC12 / PIC16 / PIC18 MCUs [(microchip.com/mplab/mplab-code-configurator)](https://www.microchip.com/mplab/mplab-code-configurator)
22-
- Microchip PIC18F-Q Series Device Support (1.4.109) or newer [(packs.download.microchip.com/)](https://packs.download.microchip.com/) -->
15+
* [Microchip Studio](https://www.microchip.com/mplab/microchip-studio) 7.0.2542 or later
16+
* [Atmel AVR-Dx_DFP version 1.6.76](http://packs.download.atmel.com/#collapse-Atmel-AVR-Dx-DFP-pdsc) or later
17+
* For the MCC MPLAB® X version of this project, please go to [this repository](https://github.com/microchip-pic-avr-examples/avr128db48-overcurrent-protection-mplab-mcc.git)
18+
* For the Atmel START version of this project, please go to [this repository](https://github.com/microchip-pic-avr-examples/avr128db48-overcurrent-protection-studio-start.git)
2319

2420
## Hardware Used
2521

26-
<!-- All hardware used in this example must be listed here. Use unbreakable links!
27-
- PIC18F47Q10 Curiosity Nano [(DM182029)](https://www.microchip.com/Developmenttools/ProductDetails/DM182029)
28-
- Curiosity Nano Base for Click boards™ [(AC164162)](https://www.microchip.com/Developmenttools/ProductDetails/AC164162)
29-
- POT Click board™ [(MIKROE-3402)](https://www.mikroe.com/pot-click) -->
22+
* [AVR128DB48 Curiosity Nano](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/EV35L43A)
23+
* A small computer fan (M1)
24+
* 3x 1 kOhm resistor (R2, R3, R5)
25+
* 1x 10 kOhm resistor (R6)
26+
* 1x 0.1 Ohm current sense resistor (R1)
27+
* 2x 100nF capasitors (C1, C2)
28+
* 1x N-Channel MOSFET transistor (Q1)
29+
* 1x Signal Diode (D1)
3030

31-
## Setup
3231

33-
<!-- Explain how to connect hardware and set up software. Depending on complexity, step-by-step instructions and/or tables and/or images can be used -->
3432

35-
## Operation
33+
## Setup
34+
* Hook up the circuit as shown in the figure below
35+
* For minimal noise, soldering the circuit onto a perfboard/stripboard is prefered, although a breadboard could be used with worse performance
36+
<p><img src="images/circuit_drawing.png" alt="Circuit Drawing" width="400"/></p>
3637

37-
<!-- Explain how to operate the example. Depending on complexity, step-by-step instructions and/or tables and/or images can be used -->
38+
## Operation
39+
* Connect the AVR128DB48 Curiosity Nano to a computer using a USB cable
40+
* Download the zip file or clone the example to get the source code
41+
* Open the .atsln with Atmel Studio
42+
* Press *Start without debugging* or use CTRL+ALT+F5 hotkeys to run the application
43+
* After the LED stops flashing, it is done calibrating
44+
* Gently apply preassure to the fan, being very careful not to hurt yourself. The fan should now stop.
45+
* Click the onboard button (SW1) to re-enable the fan
3846

39-
## Summary
4047

41-
<!-- Summarize what the example has shown -->
48+
## Conclusion
49+
After going through this example, you should have a better understanding of how to combine the OPAMP and AC peripherals to make a current spike detector.

images/circuit_drawing.png

1.56 MB
Loading

src/overcurrent-protection/main.c

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* overcurrent-protection.c
3+
*
4+
* Created: 25-Feb-21 15:47:49
5+
* Author : M19939
6+
*/
7+
8+
#define F_CPU 4000000ul
9+
#define CLK_PER 4000000ul
10+
#define OPAMP_MAX_SETTLE_TIME 0x7F
11+
#define VREF_AC_MV 4096
12+
#define AC_TRIGGER_VOLTAGE_MV_INIT 1100
13+
14+
#include <avr/io.h>
15+
#include <math.h>
16+
#include <util/delay.h>
17+
#include <avr/cpufunc.h>
18+
#include <avr/interrupt.h>
19+
20+
21+
void opamp_init(void);
22+
void tcd_init(void);
23+
void ac_init(void);
24+
void fan_start(void);
25+
void button_init(void);
26+
void ac_trig_event_enable(void);
27+
void ccl_init(void);
28+
29+
int main(void)
30+
{
31+
opamp_init();
32+
tcd_init();
33+
ac_init();
34+
ccl_init();
35+
fan_start();
36+
button_init();
37+
PORTC.DIRSET = PIN4_bm | PIN5_bm;
38+
PORTC.OUTCLR = PIN4_bm | PIN5_bm;
39+
PORTD.DIRSET = PIN2_bm;
40+
sei();
41+
while (1)
42+
{
43+
}
44+
}
45+
46+
void opamp_init(void)
47+
{
48+
/*Disable input on op amp output pin*/
49+
PORTD.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc;
50+
PORTE.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc;
51+
PORTE.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;
52+
53+
/*Set up op amp*/
54+
OPAMP.CTRLA = OPAMP_ENABLE_bm;
55+
OPAMP.TIMEBASE = (uint8_t) ceil(CLK_PER*0.000001)-1; /*Number of peripheral clock cycles that amounts to 1us*/
56+
57+
//OP2 setup
58+
OPAMP.OP2CTRLA = OPAMP_RUNSTBY_bm | OPAMP_ALWAYSON_bm | OPAMP_OP2CTRLA_OUTMODE_NORMAL_gc;
59+
OPAMP.OP2SETTLE = OPAMP_MAX_SETTLE_TIME; //As the settle time is unknown, the maximums should be set
60+
OPAMP.OP2INMUX = OPAMP_OP2INMUX_MUXNEG_WIP_gc | OPAMP_OP2INMUX_MUXPOS_LINKOUT_gc;
61+
OPAMP.OP2RESMUX = OPAMP_OP2RESMUX_MUXWIP_WIP5_gc | OPAMP_OP2RESMUX_MUXBOT_GND_gc|OPAMP_OP2RESMUX_MUXTOP_OUT_gc;
62+
63+
//OP1 setup
64+
OPAMP.OP1CTRLA = OPAMP_RUNSTBY_bm | OPAMP_ALWAYSON_bm | OPAMP_OP1CTRLA_OUTMODE_NORMAL_gc;
65+
OPAMP.OP1SETTLE = OPAMP_MAX_SETTLE_TIME; //As the settle time is unknown, the maximums should be set
66+
OPAMP.OP1INMUX = OPAMP_OP1INMUX_MUXNEG_WIP_gc | OPAMP_OP1INMUX_MUXPOS_INP_gc;
67+
OPAMP.OP1RESMUX = OPAMP_OP1RESMUX_MUXWIP_WIP7_gc | OPAMP_OP1RESMUX_MUXBOT_INN_gc | OPAMP_OP1RESMUX_MUXTOP_OUT_gc;
68+
}
69+
70+
void ccl_init(void)
71+
{
72+
CCL.SEQCTRL0 = CCL_SEQSEL_RS_gc; // Create a RS latch
73+
/*Set up LUT0*/
74+
CCL.LUT0CTRLB = CCL_INSEL0_AC0_gc; // AC0 and mask all other bits
75+
CCL.TRUTH0 = 0x02; // When AC is hight hight output, otherwise low output
76+
CCL.LUT0CTRLA = CCL_ENABLE_bm | CCL_OUTEN_bm;
77+
PORTA.DIRSET = PIN3_bm;
78+
79+
/*Set up LUT1*/
80+
EVSYS.USERCCLLUT1A = EVSYS_USER_CHANNEL1_gc;
81+
CCL.LUT1CTRLB = CCL_INSEL0_EVENTA_gc; // Event A as input and mask all other bits
82+
CCL.TRUTH1 = 0x02; // When Event A is hight hight output, otherwise low output
83+
CCL.LUT1CTRLA = CCL_ENABLE_bm;
84+
85+
CCL.CTRLA = CCL_ENABLE_bm;
86+
}
87+
88+
void tcd_init(void)
89+
{
90+
PORTMUX.TCDROUTEA = PORTMUX_TCD0_ALT2_gc;
91+
PORTF.DIRSET=PIN0_bm;
92+
93+
TCD0.CTRLB = TCD_WGMODE_TWORAMP_gc;
94+
95+
TCD0.CMPASET = 0; /* Compare A Set: 0 */
96+
97+
TCD0.CMPACLR = 1000; /* Compare A Clear: 1000 */
98+
99+
TCD0.CMPBSET = 0; /* Compare B Set: 0 */
100+
101+
TCD0.CMPBCLR = 1000; /* Compare B Clear: 1000 */
102+
103+
ccp_write_io((void*)&(TCD0.FAULTCTRL),1 << TCD_CMPAEN_bp /* Compare A enable: enabled */
104+
| 0 << TCD_CMPA_bp /* Compare A value: disabled */
105+
| 0 << TCD_CMPB_bp /* Compare B value: disabled */
106+
| 0 << TCD_CMPBEN_bp /* Compare B enable: disabled */
107+
| 0 << TCD_CMPC_bp /* Compare C value: disabled */
108+
| 0 << TCD_CMPCEN_bp /* Compare C enable: disabled */
109+
| 0 << TCD_CMPD_bp /* Compare D vaule: disabled */
110+
| 0 << TCD_CMPDEN_bp /* Compare D enable: disabled */);
111+
112+
TCD0.EVCTRLA
113+
= TCD_CFG_ASYNC_gc /* Asynchronous Event output qualification enabled */
114+
| TCD_ACTION_FAULT_gc /* Event trigger a fault */
115+
| TCD_EDGE_RISE_HIGH_gc /* The rising edge or high level of event generates retrigger or fault action */
116+
| 1 << TCD_TRIGEI_bp; /* Trigger event enable: enabled */
117+
118+
TCD0.INPUTCTRLA=TCD_INPUTMODE_WAITSW_gc; //Wait for a reset command
119+
TCD0.INPUTCTRLB=TCD_INPUTMODE_WAITSW_gc; //Wait for a reset command
120+
121+
while ((TCD0.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high.
122+
123+
TCD0.CTRLA = 0 << TCD_ENABLE_bp /* Enable: disabled */
124+
| TCD_CLKSEL_OSCHF_gc /* */
125+
| TCD_CNTPRES_DIV1_gc /* Sync clock divided by 1 */
126+
| TCD_SYNCPRES_DIV1_gc;
127+
128+
129+
}
130+
131+
void tcd_enable(void)
132+
{
133+
TCD0.CTRLA = TCD_ENABLE_bm;
134+
TCD0.CTRLE = TCD_RESTART_bm;
135+
}
136+
137+
uint8_t ac_calculate_trigger_voltage(uint16_t mV)
138+
{
139+
uint8_t triggerVoltage = (((uint32_t)mV*256)/VREF_AC_MV);
140+
return triggerVoltage;
141+
}
142+
143+
void ac_init(void)
144+
{
145+
PORTA.DIRSET=PIN7_bm;
146+
VREF.ACREF = VREF_REFSEL_4V096_gc;
147+
148+
AC0.MUXCTRL = 0 << AC_INVERT_bp /* Invert AC Output: disabled */
149+
| AC_MUXNEG_DACREF_gc /* DAC Reference */
150+
| AC_MUXPOS_AINP2_gc; /* Positive Pin 2 */
151+
152+
153+
AC0.DACREF = ac_calculate_trigger_voltage(AC_TRIGGER_VOLTAGE_MV_INIT); /* DAC Voltage Reference: 0x64 */
154+
155+
AC0.CTRLA = 1 << AC_ENABLE_bp /* Enable: enabled */
156+
| AC_HYSMODE_NONE_gc /* No hysteresis */
157+
| AC_POWER_PROFILE0_gc /* Power profile 0, lowest consumption and highest response time. */
158+
| 1 << AC_OUTEN_bp /* Output Buffer Enable: enabled */
159+
| 0 << AC_RUNSTDBY_bp; /* Run in Standby Mode: disabled */
160+
}
161+
162+
void ac_calibration(void)
163+
{
164+
PORTB.DIRSET = PIN3_bm;
165+
PORTB.OUTCLR = PIN3_bm;
166+
uint8_t calibrating = 1;
167+
uint16_t ac_trigger_voltage_mv=AC_TRIGGER_VOLTAGE_MV_INIT;
168+
AC0.INTCTRL = AC_INTMODE_NORMAL_POSEDGE_gc;
169+
while (calibrating)
170+
{
171+
ac_trigger_voltage_mv += 50;
172+
AC0.DACREF = ac_calculate_trigger_voltage(ac_trigger_voltage_mv);
173+
_delay_ms(100);//Allow some time for the flag to be raised
174+
if (!(AC0.STATUS & AC_CMPIF_bm))
175+
{
176+
calibrating=0;
177+
PORTB.OUTSET =PIN3_bm;
178+
}
179+
AC0.STATUS=AC_CMPIF_bm;
180+
}
181+
182+
}
183+
184+
void ac_trig_event_enable(void)
185+
{
186+
AC0.INTCTRL = AC_INTMODE_NORMAL_POSEDGE_gc | AC_CMP_bm;
187+
EVSYS.SWEVENTA = EVSYS_SWEVENTA_CH1_gc;
188+
EVSYS.CHANNEL0=EVSYS_CHANNEL0_CCL_LUT0_gc; //Output from the RS latch as trigger
189+
EVSYS.USERTCD0INPUTA=EVSYS_USER_CHANNEL0_gc;
190+
EVSYS.USEREVSYSEVOUTD = EVSYS_USER_CHANNEL0_gc;
191+
}
192+
193+
void ac_trig_event_disable(void)
194+
{
195+
AC0.INTCTRL &= ~AC_CMP_bm;
196+
EVSYS.CHANNEL0=EVSYS_CHANNEL0_OFF_gc;
197+
EVSYS.USERTCD0INPUTA = EVSYS_USER_OFF_gc;
198+
EVSYS.USEREVSYSEVOUTD = EVSYS_USER_OFF_gc;
199+
}
200+
201+
void fan_start(void)
202+
{
203+
ac_trig_event_disable();
204+
tcd_enable();
205+
ac_calibration();
206+
_delay_ms(1000);
207+
ac_trig_event_enable();
208+
209+
}
210+
211+
void button_init(void)
212+
{
213+
PORTB.DIRCLR=PIN2_bm;
214+
PORTB.PIN2CTRL=PORT_ISC_FALLING_gc | PORT_PULLUPEN_bm;
215+
sei();
216+
}
217+
218+
ISR(PORTB_PORT_vect)
219+
{
220+
fan_start();
221+
PORTB.INTFLAGS=0xff;
222+
}
223+
224+
ISR(AC0_AC_vect)
225+
{
226+
AC0.STATUS = AC_CMPIF_bm; // Clear interrupt flag
227+
PORTC.OUTTGL = PIN4_bm;
228+
}

0 commit comments

Comments
 (0)