AVR128DA Setting Bits in ADC0_CTRLA

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am still a bit perplexed at how to use the naming conventions on the new AVR128

Working through the data sheet I have the following code to set up an ADC

void SetupADC(void) 

{
// 1. Configure the ADC voltage reference in the Voltage Reference (VREF) peripheral
// Voltage Reference 2.5VDC also set AlwaysOn bit

VREF.ADC0REF = VREF_REFSEL_2V500_gc | VREF_ADC0REF;

// 2. Optional: Select between Single-Ended or Differential mode by writing to the Conversion Mode (CONVMODE)
//    bit in the Control A (ADCn.CTRLA) register.

ADC0.CTRLA = SingleEnded;

}

To configure VREF I searched for VREF

Vref Datasheet

REFSEL has 3 bits and the table gives the Name for the values of the three bits.

So the code VREF.ADC0 = REF_2V500_gc sets those bits.

I then search for "AlwaysOn" and got the Name for the bit7

Datasheet

It shows ADC0REF is the name of Bit 7 so I or'd VREF_ADC0REF to set that bit.

 

Second step is to set the ADC0_CTRLA to Single Ended

 

Datasheet

 

So we need to set bit 5 in ADC0_CTRLA

Trying various attempts like ADC0.CTRLA = ADC0_CTRLA_CONVMODE_SINGLEENDED; to set the bit I have failed.

 

Can someone walk me through getting this correctly figured out using the datasheet to guide me?

 

 

 

 

 

 

Last Edited: Tue. Nov 23, 2021 - 09:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CONVMODE is a single bit, so it is simply

 

ADC0.CTRLA = ADC_CONVMODE_bm;

sets this bit... Clearing it is the inverse

 

It's actually a good question why the SINGLEENDED and DIFF parts are not available as defines... 

:: Morten

 

(yes, I work for Microchip, yes, I do this in my spare time, now stop sending PMs)

 

The postings on this site are my own and do not represent Microchip’s positions, strategies, or opinions.

Last Edited: Tue. Nov 23, 2021 - 09:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jnorman wrote:
It shows ADC0REF is the name of Bit 7 so I or'd VREF_ADC0REF to set that bit.

No that is the name of the register that holds the ALWAYSON bit along with the ref level bits...

Set ADC0REF with a value to set the your ref level.

Note: single ended mode is the default, along with 12 bit resolution, in most cases no need to set this register, unless you need a different setup.

 

Jim

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

Lets go Brandon!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


I went to the .h file and started adding some code. It seems my intellisense is behaving badly. For example when entering the code below none of the names were recognized.

 

If I cut the code from the .h file and paste it in the main.c file intellisense is ok with it and it will compile.

 

I thought there was an IntelliSense menu function to read and update itself. Perhaps it's slow updating as this is the first time using these .h files.

 

 

 

Ok Think I have it, just the syntax and names, I will set or clear bits that are needed for the setup.

 

Also I think I understand now the _gc vs _bm  Both are bit masks but _gc simply belongs to a group of bits but uses the bit position on the left side of the shift.

 

 

I will run some code with debugger stepping to understand how this works a bit better. (no pun intended!)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have a read of AVR1000 (is it?) that explains things like _bp, _bm, _gc symbol names for Xmega and derivatives 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Yes I have that AVR1000: Getting Started Writing C-code for XMEGA

 

Here is the code outline with some sample calling code to read two ADC channels. Not tested as there is no simulator for these chips. I have a powerDebugger , tomorrow I will do some testing.

 

Thanks for the help. This is a vacuum forming machine controller. Just working on the ADC input for two sensors for now.

 

 


#include <avr/io.h>

#define Stopped 0
#define Heating 1
#define Prestretch 2

volatile int16_t PressureValue = 0;
volatile int16_t BubbleValue = 0;
volatile int8_t Operation = 0;

void SetupADC(void);

void ReadPressure(void);

void ReadBubble(void);

int main(void)
{

	/* Replace with your application code */

	SetupADC();

	while (1)
	{
		while(Operation = Stopped)
		{
		  // Check and turn off all modules
		}

		ReadPressure();
		if(PressureValue > 1500)
		{
			//Turn pump off
		}
		if(PressureValue < 1000)
		{
			// Turn Pump On
		}

		if(Operation  == Prestretch)
		{
			ReadBubble();
			if(BubbleValue >3000)
			{
				//Turn PreStretch Off
				// Flag next operation
			}
		}

	}
}

void SetupADC(void)
{
	// 1. Configure the ADC voltage reference in the Voltage Reference (VREF) peripheral
	// Voltage Reference 2.5VDC also set AlwaysOn bit
	VREF.ADC0REF = VREF_REFSEL_2V500_gc | VREF_ALWAYSON_bm;

	// 2. Optional: Select between Single-Ended or Differential mode by writing to the Conversion Mode (CONVMODE) bit in the Control A (ADCn.CTRLA) register.
	//    Set to Single-Ended
	// 3. Configure the resolution by writing to the Resolution Selection (RESSEL) bit field in the ADCn.CTRLA register.
	//    Set to 12-Bit resolution
	// 4. Optional: Configure to left adjust by writing a ‘1’ to the Left Adjust Result (LEFTADJ) bit in the ADCn.CTRLA register.
	//    Set to right adjust
	// 5. Optional: Select the Free-Running mode by writing a ‘1’ to the Free-Running (FREERUN) bit in the ADCn.CTRLA register.
	//    Not set to Free Running Mode

	ADC0.CTRLA = (0 << ADC_CONVMODE_bp) | ADC_RESSEL0_bm | (0 << ADC_LEFTADJ_bp) | (0 << ADC_FREERUN_bp) | (1 << ADC_RUNSTBY_bp)  |  (0 << ADC_ENABLE_bp) ;

	// 6. Optional: Configure the number of samples to be accumulated per conversion by writing to the Sample Accumulation Number Select (SAMPNUM) bit field in the Control B (ADCn.CTRLB) register.

	ADC0.CTRLB = ADC_SAMPNUM0_bm;

	// 7. Configure the ADC clock (CLK_ADC) by writing to the Prescaler (PRESC) bit field in the Control C (ADCn.CTRLC) register.
	//    Fcpu is 12MHZ ADC Clock = Fcpu /  64 = 187.5 KHZ
	ADC0.CTRLC = ADC_PRESC_DIV64_gc;

	// 8. Select the positive ADC input by writing to the MUXPOS bit field in the ADCn.MUXPOS register.
	//    Select PD5 pin 11

	ADC0.MUXPOS = ADC_MUXPOS_AIN5_gc;

	// 9. Optional: Select the negative ADC input by writing to the MUXNEG bit field in the ADCn.MUXNEG register.
	//    Not Used on this
	//    ADC0.MUXNEG = ADC_MUXNEG_DAC0_gc; // example

	//10. Optional: Enable Start Event input by writing a ‘1’ to the Start Event Input (STARTEI) bit in the Event Control(ADCn.EVCTRL) register, and configure the Event System accordingly.
	//    Not Used in this project
	//    ADC0.EVCTRL = ADC_STARTEI_bm; example

	//11. Enable the ADC by writing a 1 to the ADC Enable (ENABLE) bit in the ADCn.CTRLA register.

	ADC0.CTRLA |= ADC_ENABLE_bm;

}

void ReadPressure(void)
{
	//    Select PD5 pin 11 for pressure
	ADC0.MUXPOS = ADC_MUXPOS_AIN5_gc;
	ADC0.COMMAND = ADC_STCONV_bm;

	while ( !(ADC0.INTFLAGS && ADC_RESRDY_bm) )
	{
		PressureValue = ADC0.RES;
	}
}

void ReadBubble(void)
{
	//    Select PD6 pin 12 for PreStretch
	ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc;
	ADC0.COMMAND = ADC_STCONV_bm;

	while ( !(ADC0.INTFLAGS && ADC_RESRDY_bm) )
	{
		BubbleValue = ADC0.RES;
	}

}

 

 

Last Edited: Wed. Nov 24, 2021 - 06:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are using && when you really mean &  e.g.

	while ( !(ADC0.INTFLAGS && ADC_RESRDY_bm) )

From the ioavr128da48.h
 

/* ADC.INTCTRL  bit masks and bit positions */
#define ADC_RESRDY_bm  0x01  /* Result Ready Interrupt Enable bit mask. */
#define ADC_RESRDY_bp  0  /* Result Ready Interrupt Enable bit position. */
#define ADC_WCMP_bm  0x02  /* Window Comparator Interrupt Enable bit mask. */
#define ADC_WCMP_bp  1  /* Window Comparator Interrupt Enable bit position. */

So I would expect

	while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) )	

All these versions do exactly the same thing:

	while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) )
	while ( !(ADC0.INTFLAGS & (1 << ADC_RESRDY_bp)) )
	while ( !(ADC0.INTFLAGS & (1 << 0)) )
	while ( !(ADC0.INTFLAGS & 0x01) )	

In other words it is exactly the same way that you test a flag in the legacy Mega.

	while ( !(ADCSRA & (1 << ADIF)) )

Note that your && expression is always going to return true for any non-zero value in ADC0.INTFLAGS

In practice,  this means that your code will "work" i.e. it is a very dangerous misunderstanding.

 

David.

Last Edited: Wed. Nov 24, 2021 - 08:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
You are using && when you really mean & 

An easy mistake to make - only last week (with OR rather than AND): https://www.avrfreaks.net/commen...

 

Note that your && expression is always going to return true for any non-zero value in ADC0.INTFLAGS

In practice,  this means that your code will "work" i.e. it is a very dangerous misunderstanding.

Indeed - another example of how code that's wrong can appear to "work":  https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Nov 24, 2021 - 10:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
AVR1000 (is it?)

Yes, it is: https://ww1.microchip.com/downlo...

 

See also: https://www.avrfreaks.net/commen...

 

Quote:
To summarise:

 

_bm = bit mask - see 3.4.1

 

_bp = bit position - see 4.2

 

_gm = group mask - see 3.4.2

 

_gc  =  group configuration mask - see 3.5

 

(references to AVR1000 section numners)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the work looking at it , especially pointing out the potential it could be a nasty bug, have to do some homework on bit masking operators.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your use of && was perfectly legal.

Also this Warning is perfectly legal

 

        "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\AVR-Dx_DFP\1.9.103\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=avr128da48 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\AVR-Dx_DFP\1.9.103\gcc\dev\avr128da48" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c"
        .././main.c: In function 'main':
C:\Users\David Prentice\Documents\Atmel Studio\u8g2_avr\dummy_AVR128DA48\main.c(26,9): warning: suggest parentheses around assignment used as truth value [-Wparentheses]
                 while(Operation = Stopped)
                 ^

 

However I suspect that you really intended

                 while(Operation == Stopped)

 

It is very important to understand if and when to use logical operators.

 

I suggest that you fix all the ADC0.INTFLAGS expressions and then test your program in real life.   Preferably with the UPDI debugger that comes for free with the Curiosity board.

You can test a lot of code with the Simulator but things like ADC, TWI, USART, ... are best in real life.

 

Oh,  in an ideal world the Compiler would barf at the wrong enum being used in an SFR expression.   Both GCC and G++ seem to ignore this:

    ADC0.MUXPOS = ADC_MUXPOS_AIN5_gc;   // legal enum for MUXPOS register
    ADC0.CTRLC = ADC_MUXPOS_AIN5_gc;    // wrong enum for CTRLC register

 

C++ will complain for wrong enums in class expressions.

Java will complain about almost anything.

 

C is forgiving.   But that just means you are more likely to make mistakes.

Did you notice the obvious clue in the second line ?

 

David.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I realise the sequence is probably taken from a datasheet but can I at least complement you for the comments in SetupADC() ? I like that it documents the flow of what is going on (even the optional bits that you chose not to go with this time). That's the kind of comments that will really help the maintainer who comes back to this in 18 months !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Jnorman wrote:
have to do some homework on bit masking operators.

start here: https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I realise the sequence is probably taken from a datasheet but can I at least complement you for the comments in SetupADC() ? I like that it documents the flow of what is going on (even the optional bits that you chose not to go with this time). That's the kind of comments that will really help the maintainer who comes back to this in 18 months !

 

Yes and it might be be in just a few weeks I forget what the heck I have coded and sometimes wonder how the heck I ever did some of the code!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Update on some of the items in the ADC setup and reading the result after setting up the PowerDebugger.

One thing I did notice and something I like to use in the debugger is the stopwatch and #cycles are not available on the AVR128DA

 

On to the code changes,

In SetupADC()

Changed VREF after I tested the vacuum sensors range to     VREF.ADC0REF = VREF_REFSEL_2V048_gc | VREF_ALWAYSON_bm;

Voltage    Vacuum    ADC Value

0.7             -25         1400

0.9            -20          1800

1.11          -15          2220

1.33          -10          2660

1.53           -5           3060

1.786        0             3572

 

Modified the code that sets the resolution to 12 bits

I had used the format ADC0.CTRLA (0 << Something.bp) | ADC_RESSEL0_bm

That setting set bit 0 as it is suppose to but I thought it was suppose to clear the bit, the 0 in RESSEL0 means operate on bit Zero not set bit zero to 0

I think you can use !ADC_RESSEL0_bm have not tested

Code is now consistent format instead of mixing masks with bit positions.

  ADC0.CTRLA = (0 << ADC_CONVMODE_bp) | (0 << ADC_RESSEL_gp) | (0 << ADC_LEFTADJ_bp) | (0 << ADC_FREERUN_bp) | (1 << ADC_RUNSTBY_bp)  |  (0 << ADC_ENABLE_bp) ;

 

Increased sampling to 8, Maximum I could go with a top return value of 4096 to fit in a 16 bit return value

ADC0.CTRLB = ADC_SAMPNUM_ACC8_gc;

 

The reading code i removed the double &&

Something we all missed is the while loop had the assignment of the result only while the adc was NOT finished (INTFLAGS == 0)

So moved the assignments on both the Pressure and Bubble methods like this:

 

I think I will create a Project in the AVR Freaks Projects section when I am closer to being done since I constantly make errors along the way that could get confusing.

 

The Full code I have now I will list here , the main has two while loops,as the first one I was just working on the ADC sensor input.

I added a global variable CurrentEvent I will use to make sure the sequence of buttons pressed will be 1,2,3,4 and I realize I need a STOP Reset button to shut it all down so my next

dive into the datasheet will be how to use the Reset pin as a input since I have run out of pins. I could of course use a shift register for all those LED indicators to free up some pins.

447 lines of code so far but almost complete. (like when I tell my wife, I'm almost done at 5pm and the clock on the wall suddenly shows 3am in the morning.)

Not de bouncing inputs yet still a lot to do.

 

/*
* VacuumTableController.c
*
* Created: 11/10/2021 6:22:47 PM
* Author : 16128
*/

#define F_CPU 1000000UL  // 1mhz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdbool.h>

#define False 0
#define True  1
#define Stopped 0
#define Heating 1
#define Prestretch 2

volatile int8_t CurrentEvent = 0;

// Sensor inputs ADC Values ADC reference = 2.048
// Volts - Vacuum --  ADC Value
//	0.7		-25			2856
//	0.9		-20			2222
//	1.11	-15			1801
//	1.33	-10			1503
//	1.53	-5			1307
//	1.786	 0			1120

volatile int16_t PressureValue = 0;
volatile int16_t BubbleValue = 0;

volatile int16_t PV = 0;
volatile int16_t BV = 0;

volatile int8_t tmp = 0;


void CLK_init(void);
void PORT_init(void);
void Timer_init(void);
void VacuumPumpOn(void);
void VacuumPumpOff(void);
void HeaterOn(void);
void HeaterOff(void);
void PrestretchOn(void);
void PrestretchOff(void);
void MoldUp(void);
void MoldDown(void);
void VacuumOpen(void);
void VacuumClose(void);
void BlowBackOpen(void);
void BlowBackClose(void);
void SetupADC(void);
void ReadPressure(void);
void ReadBubble(void);

bool  Sw1_event = False;
bool  Sw2_event = False;
bool  Sw3_event = False;
bool  Sw4_event = False;


//1	Sw1PressedStatusLED PORT A
#define Sw1PressedStatusLED PIN7_bm
#define Sw1LEDOff PORTA_OUTSET = Sw1PressedStatusLED
#define Sw1LEDOn PORTA_OUTCLR = Sw1PressedStatusLED
//2		Sw2PressedStatusLED PORT C
#define Sw2PressedStatusLED PIN0_bm
#define Sw2LEDOff PORTC_OUTSET = Sw2PressedStatusLED
#define Sw2LEDOn PORTC_OUTCLR = Sw2PressedStatusLED
//3		Sw3PressedStatusLED PORT C
#define Sw3PressedStatusLED PIN1_bm
#define Sw3LEDOff PORTC_OUTSET = Sw3PressedStatusLED
#define Sw3LEDOn PORTC_OUTCLR = Sw3PressedStatusLED
//4		Sw4PressedStatusLED PORT C
#define Sw4PressedStatusLED PIN2_bm
#define Sw4LEDOff PORTC_OUTSET = Sw4PressedStatusLED
#define Sw4LEDOn PORTC_OUTCLR = Sw4PressedStatusLED

//5		HeaterSwitchRelayStatusLED PORT C
#define HeaterSwitchRelayStatusLED PIN3_bm
#define HeaterSwitchRelayStatusLEDOff PORTC_OUTSET = HeaterSwitchRelayStatusLED
#define HeaterSwitchRelayStatusLEDOn PORTC_OUTCLR = HeaterSwitchRelayStatusLED
//6		VacuumPumpRelayStatusLED PORT D
#define VacuumPumpRelayStatusLED PIN0_bm
#define VacuumPumpRelayStatusLEDOff PORTD_OUTSET = VacuumPumpRelayStatusLED
#define VacuumPumpRelayStatusLEDOn PORTD_OUTCLR = VacuumPumpRelayStatusLED
//7		PrestretchRelayStatusLED PORT D
#define PrestretchRelayStatusLED PIN1_bm
#define PrestretchRelayStatusLEDOff PORTD_OUTSET = PrestretchRelayStatusLED
#define PrestretchRelayStatusLEDOn PORTD_OUTCLR = PrestretchRelayStatusLED
//8		MoldRaiseRelayStatusLED PORT D
#define MoldRaiseRelayStatusLED PIN2_bm
#define MoldRaiseRelayStatusLEDOff PORTD_OUTSET = MoldRaiseRelayStatusLED
#define MoldRaiseRelayStatusLEDOn PORTD_OUTCLR = MoldRaiseRelayStatusLED
//9		VacuumSolonoidStatusLED PORT D
#define VacuumSolonoidStatusLED PIN3_bm
#define VacuumSolonoidStatusLEDOff PORTD_OUTSET = VacuumSolonoidStatusLED
#define VacuumSolonoidStatusLEDOn PORTD_OUTCLR = VacuumSolonoidStatusLED
//10	BlowbackRelayStatusLED PORT D
#define BlowbackRelayStatusLED PIN4_bm
#define BlowbackRelayStatusLEDOff PORTD_OUTSET = BlowbackRelayStatusLED
#define BlowbackRelayStatusLEDOn PORTD_OUTCLR = BlowbackRelayStatusLED

//11	VacuumPumpPressureSensorInput  PORT D
//12	PrestretchBubbleSensorInput  PORT D
//13	MoldRaiseRelay PORT D
#define MoldRaiseRelay PIN7_bm
#define MoldRaiseRelayOff PORTD_OUTSET = MoldRaiseRelay
#define MoldRaiseRelayOn PORTD_OUTCLR = MoldRaiseRelay
//14	AVDD
//28	Sw1Input PORT A
#define Sw1Input    PIN6_bm
//27	Sw2Input PORT A
#define Sw2Input	PIN5_bm
//26	Sw3Input PORT A
#define Sw3Input	PIN4_bm
//25	Sw4Input PORT A
#define Sw4Input	PIN3_bm
//24	HeaterRelay PORT A
#define HeaterRelay PIN2_bm
#define HeaterRelayOff PORTA_OUTSET = HeaterRelay
#define HeaterRelayOn PORTA_OUTCLR = HeaterRelay
//23	VacuumPumpRelay PORT A
#define VacuumPumpRelay PIN1_bm
#define VacuumPumpRelayOff PORTA_OUTSET = VacuumPumpRelay
#define VacuumPumpRelayOn PORTA_OUTCLR = VacuumPumpRelay
//22	VacuumSolonoid PORT A
#define VacuumSolonoid PIN0_bm
#define VacuumSolonoidOff PORTA_OUTSET = VacuumSolonoid
#define VacuumSolonoidOn PORTA_OUTCLR = VacuumSolonoid
//21	GND
//20	VDD
//19	UPDI
//18	Reset
//17	PrestretchRelay PORT F
#define PrestretchRelay PIN1_bm
#define PrestretchRelayOff PORTF_OUTSET = PrestretchRelay
#define PrestretchRelayOn PORTF_OUTCLR = PrestretchRelay
//16	BlowbackRelay PORT F
#define BlowbackRelay PIN1_bm
#define BlowbackRelayOff PORTF_OUTSET = BlowbackRelay
#define BlowbackRelayOn PORTF_OUTCLR = BlowbackRelay
//15	GND

int main(void)
{

	tmp = ADC_MUXPOS_AIN5_gc;
	cli();
	PORT_init();
	SetupADC();
	
	sei();
	while(1)
	{
		ReadPressure();
		PV=PressureValue/8;
		ReadBubble();
		BV=BubbleValue;
		
	}
	while (1)
	{
		if(Sw1_event == True)
		{
			Sw1_event=false;
			Sw1LEDOn;
			VacuumPumpOn();
			HeaterOn();
		}
		if(Sw2_event == True)
		{
			Sw2_event=false;
			Sw1LEDOff;
			Sw2LEDOn;
			HeaterOff();
			PrestretchOn();
		}
		if(Sw3_event == True)
		{
			Sw3_event=false;
			Sw1LEDOff;
			Sw2LEDOff;
			Sw3LEDOn;
			_delay_ms(500);
			MoldUp();
			PrestretchOff();
			VacuumOpen();
		}
		if(Sw4_event == True)
		{
			Sw4_event=false;
			Sw1LEDOff;
			Sw2LEDOff;
			Sw3LEDOff;
			Sw4LEDOn;
			VacuumClose();
			_delay_ms(1500);
			BlowBackOpen();
			_delay_ms(1000);
			MoldDown();
			_delay_ms(500);
			BlowBackClose();
			VacuumPumpOff();
			_delay_ms(1000);
			Sw4LEDOff;
		}
	}
}

ISR(TCA0_OVF_vect)
{
	//PORTD_OUTTGL = AirCylinderPin;
	//Timer0Count = TCA0_SINGLE_CNT;
	//TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
}

ISR(PORTA_PORT_vect)
{
	
	if(PORTA_INTFLAGS & Sw1Input)
	{
		Sw1_event = True;
		PORTA.INTFLAGS = Sw1Input;
	}
	if(PORTA_INTFLAGS & Sw2Input)
	{
		Sw2_event = True;
		PORTA.INTFLAGS = Sw2Input;
	}
	if(PORTA_INTFLAGS & Sw3Input)
	{
		Sw3_event = True;
		PORTA.INTFLAGS = Sw3Input;
	}
	if(PORTA_INTFLAGS & Sw4Input)
	{
		Sw4_event = True;
		PORTA.INTFLAGS = Sw4Input;
	}

}

void Timer_init(void)
{
	TCA0_SINGLE_PER = 138;
	TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV16_gc | TCA_SINGLE_ENABLE_bm;
}

void PORT_init(void)
{
	// INPUT PINS
	// Button Input
	//	PORTD.DIRCLR = BUTTON_PIN;
	// IRSensor Input Pin INPUT
	//	PORTD.DIRCLR = IRSensor;

	
	// OUTPUT PINS
	PORTA.DIRSET = Sw1PressedStatusLED;
	PORTC.DIRSET = Sw2PressedStatusLED;
	PORTC.DIRSET = Sw3PressedStatusLED;
	PORTC.DIRSET = Sw4PressedStatusLED;
	PORTC.DIRSET = HeaterSwitchRelayStatusLED;
	PORTD.DIRSET = VacuumPumpRelayStatusLED;
	PORTD.DIRSET = PrestretchRelayStatusLED;
	PORTD.DIRSET = MoldRaiseRelayStatusLED;
	PORTD.DIRSET = VacuumSolonoidStatusLED;
	PORTD.DIRSET = BlowbackRelayStatusLED;
	Sw1LEDOff;
	Sw2LEDOff;
	Sw3LEDOff;
	Sw4LEDOff;
	HeaterSwitchRelayStatusLEDOff;
	VacuumPumpRelayStatusLEDOff;
	PrestretchRelayStatusLEDOff;
	MoldRaiseRelayStatusLEDOff;
	VacuumSolonoidStatusLEDOff;
	BlowbackRelayStatusLEDOff;
	
	// INTERRUPTS
	// clear button interrupts
	PORTA.INTFLAGS = Sw1Input;
	PORTA.INTFLAGS = Sw2Input;
	PORTA.INTFLAGS = Sw3Input;
	PORTA.INTFLAGS = Sw4Input;
	PORTA.PIN6CTRL = PORT_ISC_FALLING_gc | PORT_PULLUPEN_bm;
	PORTA.PIN5CTRL = PORT_ISC_FALLING_gc | PORT_PULLUPEN_bm;
	PORTA.PIN4CTRL = PORT_ISC_FALLING_gc | PORT_PULLUPEN_bm;
	PORTA.PIN3CTRL = PORT_ISC_FALLING_gc | PORT_PULLUPEN_bm;

	
	
	
}

void CLK_init(void)
{
	// Set clock source and speed to 1mhz
	_PROTECTED_WRITE (CLKCTRL.OSCHFCTRLA, CLKCTRL_FREQSEL_12M_gc);
}

void VacuumPumpOn()
{
	VacuumPumpRelayOn;
	VacuumPumpRelayStatusLEDOn;
	
}
void VacuumPumpOff()
{
	VacuumPumpRelayOff;
	VacuumPumpRelayStatusLEDOff;
}
void HeaterOn()
{
	HeaterRelayOn;
	HeaterSwitchRelayStatusLEDOn;
}
void HeaterOff()
{
	HeaterRelayOff;
	HeaterSwitchRelayStatusLEDOff;
}
void PrestretchOn()
{
	PrestretchRelayOn;
	PrestretchRelayStatusLEDOn;
}

void PrestretchOff()
{
	PrestretchRelayOff;
	PrestretchRelayStatusLEDOff;
}
void MoldUp()
{
	MoldRaiseRelayOn;
	MoldRaiseRelayStatusLEDOn;
}
void MoldDown()
{
	MoldRaiseRelayOff;
	MoldRaiseRelayStatusLEDOff;
}
void VacuumOpen()
{
	VacuumSolonoidOn;
	VacuumSolonoidStatusLEDOn;
}
void VacuumClose()
{
	VacuumSolonoidOff;
	VacuumSolonoidStatusLEDOff;
}
void BlowBackOpen()
{
	BlowbackRelayOn;
	BlowbackRelayStatusLEDOn;
}
void BlowBackClose()
{
	BlowbackRelayOff;
	BlowbackRelayStatusLEDOff;
}

void SetupADC(void)
{
	// 1. Configure the ADC voltage reference in the Voltage Reference (VREF) peripheral
	// Voltage Reference 2.048VDC also set AlwaysOn bit
	VREF.ADC0REF = VREF_REFSEL_2V048_gc | VREF_ALWAYSON_bm;


	// 2. Optional: Select between Single-Ended or Differential mode by writing to the Conversion Mode (CONVMODE) bit in the Control A (ADCn.CTRLA) register.
	//    Set to Single-Ended
	// 3. Configure the resolution by writing to the Resolution Selection (RESSEL) bit field in the ADCn.CTRLA register.
	//    Set to 12-Bit resolution
	// 4. Optional: Configure to left adjust by writing a ‘1’ to the Left Adjust Result (LEFTADJ) bit in the ADCn.CTRLA register.
	//    Set to right adjust
	// 5. Optional: Select the Free-Running mode by writing a ‘1’ to the Free-Running (FREERUN) bit in the ADCn.CTRLA register.
	//    Not set to Free Running Mode




	ADC0.CTRLA = (0 << ADC_CONVMODE_bp) | (0 << ADC_RESSEL_gp) | (0 << ADC_LEFTADJ_bp) | (0 << ADC_FREERUN_bp) | (1 << ADC_RUNSTBY_bp)  |  (0 << ADC_ENABLE_bp) ;

	// 6. Optional: Configure the number of samples to be accumulated per conversion by writing to the Sample Accumulation Number Select (SAMPNUM) bit field in the Control B (ADCn.CTRLB) register.

	ADC0.CTRLB = ADC_SAMPNUM_ACC8_gc;
  
	

	// 7. Configure the ADC clock (CLK_ADC) by writing to the Prescaler (PRESC) bit field in the Control C (ADCn.CTRLC) register.
	//    Fcpu is 12MHZ ADC Clock = Fcpu /  64 = 187.5 KHZ
	ADC0.CTRLC = ADC_PRESC_DIV64_gc;


	// 8. Select the positive ADC input by writing to the MUXPOS bit field in the ADCn.MUXPOS register.
	//    Select PD5 pin 11

	ADC0.MUXPOS = ADC_MUXPOS_AIN5_gc;


	// 9. Optional: Select the negative ADC input by writing to the MUXNEG bit field in the ADCn.MUXNEG register.
	//    Not Used on this
	//    ADC0.MUXNEG = ADC_MUXNEG_DAC0_gc; // example

	//10. Optional: Enable Start Event input by writing a ‘1’ to the Start Event Input (STARTEI) bit in the Event Control(ADCn.EVCTRL) register, and configure the Event System accordingly.
	//    Not Used in this project
	//    ADC0.EVCTRL = ADC_STARTEI_bm; example

	//11. Enable the ADC by writing a ‘1’ to the ADC Enable (ENABLE) bit in the ADCn.CTRLA register.

	ADC0.CTRLA |= ADC_ENABLE_bm;

}


void ReadPressure(void)
{
	//    Select PD5 pin 11 for pressure
	ADC0.MUXPOS = ADC_MUXPOS_AIN5_gc;
	ADC0.COMMAND = ADC_STCONV_bm;
	
	while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) )
	{
	}
	PressureValue = ADC0.RES;

}

void ReadBubble(void)
{
	//    Select PD6 pin 12 for PreStretch
	ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc;
	ADC0.COMMAND = ADC_STCONV_bm;
	
	while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) )
	{
	}
	BubbleValue = ADC0.RES;
	
	
}

 

 

 

 

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did a "double take" on this:

int main(void)
{

    tmp = ADC_MUXPOS_AIN5_gc;
    cli();
    PORT_init();
    SetupADC();
    
    sei();
    while(1)
    {
        ReadPressure();
        PV=PressureValue/8;
        ReadBubble();
        BV=BubbleValue;
        
    }

    /* Is this code WIP? Don't expect this loop to run */
    while (1)
    {
        if(Sw1_event == True)
        {
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I noted in the post the first while loop is there just for debugging the ADC code and will be deleted.

 

"The Full code I have now I will list here , the main has two while loops,as the first one I was just working on the ADC sensor input."

 

tmp = ADC_MUXPOS_AIN5_gc;

is just a test testing the result of a group configuration mask and will be deleted.