ATmega32a / ATmega32al outputs not working?

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

Ok, so I am fairly new to AVR microcontrollers and I am having trouble applying what I thought was a simple solution to a senior engineering design project for my undergrad. The project is using a total of 14 double pole double throw relays (TQ2-L2-3V) which allow an analog interface board to change between impedances for analog signal testing. I selected the ATmega32A because it can has the 32 general purpose input outputs. 

 

5 of the pins on the atmega32 are used as an input that receive a 3.3 V. (currently using ports pd3-7) From these 5 inputs a simple truth table can be constructed giving a total of 32 distinct possible outputs (I only actually need 26 but need 5 'bits' to get enough to output up to 26).

d03 = 1 , d04 =2, d05= 4, d06=8, and d07 = 16. Inside the source code I set a variable to store the corresponding value for each port and then add the together to get the total output. This total output then designates which port to output that flips the relay either on or off.

 

Currently, the only port I can get to work correctly as an output correctly is porta. ie.. I provide an input to port pd3 and it causes an output of 5v on port a0. When I provide an input to pd3 & pd6 (value of 9 from the truth table) I get a jump in voltage that my meter isn't quick enough to read and then it settles at roughly .3volts. This happens for all of ports b,c,and d.

 

Any help is appreciated. Attached is my source code. Be gentle... I'm new to this! 

Attachment(s): 

-AVRnoob86

Last Edited: Sat. Jan 27, 2018 - 09:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You set all of port D as outputs.

 

</p>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
	DDRA = 0b00000111;
	DDRC = 0b11111111;
	DDRD = 0b11111111;
	DDRB = 0b11111111;</pre><p>

 

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

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

Sure enough.... What a silly mistake. Thanks for pointing it out! Now, after fixing that..... I don't get any outputs anywhere! 

Attachment(s): 

-AVRnoob86

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

5 of the pins on the atmega32 are used as an input that receive a 3.3 V.

 

I think Brian nailed the current issue.

 

I might add a thought or two, as you mentioned you are new to micros.

If you post a schematic diagram of your circuit you may get some feedback.

 

How are you generating a 3.3 V input for your input signals?

Are you running the micro on Vcc = 5 V?

(Presumably so, as you mentioned a 5 V output on a pin.)

 

The Minimum voltage to be detected as a high input on the Mega32 is 0.6 x Vcc, (0.6 * 5 = 3 V).

If your 5 V regulator is actually outputting 5.2 volts, (common), then the threshold is 3.12 V for a High signal input.

If your 3.3 V is actually 3V, then you won't ever read a High input signal...

 

Anyway, as a general rule, try not to operate never boundary conditions.

 

Your input signals should be solid 5 V inputs if the inputs are coming from switches, and the mirco is running on 5 V.

 

Classically, one would set a pin as an input.

Then one would enable the micro's internal pull-up resistor for that pin.

That will now hold that pin's input signal to a valid high, (input is tied to Vcc via the resistor).

 

Now one uses a switch connected from that pin to Ground.

If the switch is open, the input is read as a high.

If the switch is closed, then the switch holds the input pin at 0 V, (Ground), a Low input.

With the switch closed current flows from Vcc through the resistor, through the switch to Ground.

 

If you want to be safe, you can put a small resistor in series with the switch.

The resistor will limit the current flow if your code accidentally makes the pin an output, and high, while you have the switch shorting the high output to Ground.

The resistor needs to be high enough to limit current, yet low enough that the resultant voltage divider, (with the internal pull up resistor), still keeps the input in the very valid low range).

510 ohms would be fine.  The range of values for the internal pull up resistor is in the data sheet.

the input for a valid low must be < 0.2 * Vcc, (Data Sheet: Electrical Characteristics: DC Characteristics).

You can determine the worst case scenario and hence the maximum value that resistor could be.

 

Lets talk more about hardware.

20+ relays!  Wow.

Are you actually building this with all of those relays, or simulating some of them with an LED?

If you are actually building this, then make sure your power supply can source the current required to turn on all of the relays.

 

Do you know about putting a reversed biased diode across each relay coil to absorb the back EMF (voltage spike), when the relay turns off?

Ask about this if you are familiar with it.

 

Unless you are using sub-micro relays, with very low current requirements, you will likely want to switch the relays using an NFet transistor.

You didn't mention much about your hardware.

There is a limit to how much current each pin can source, and to how much various ports and pin combinations can source.

 

Are you using your own PCB or a commercial design?

 

Finally, welcome to the Forum.

 

Good luck with your project.

 

JC

 

 

 

 

 

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

BTW:

 

Start by reading one pin as an input, and controlling one pin as an output, with an LED and a series resistor, (470 - 510 ohms).

 

When that works, then expand the system.

 

JC

 

Perhaps a Moderator could move this to the Mega Forum? * Done. *

Last Edited: Sat. Jan 27, 2018 - 10:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This project is using an sbRIO that National Instruments makes to take analog signals and convert them into digital for the LABVIEW environment to analyze. Before the signals are actually received by the sbRIO they need to be sent through a specific line of impedance, depending on the test the technician wants to do. In order to do t his an 'analog interface board' provides the inpedances that are attached to the relays. The tech selects the impedance they want in the labview environment and that sends a signal to the sbrio, which then outputs the 5 'bit' logic to the micro controller. The microcontroller then decides which relay(s) to turn on. The sbRIO is used to provide a 5volts to run the atmega32a and the sbrio is able to output 3.3 volts from its DIO's to provide the logic inputs that I am looking for.

 

I have tested this previously on an atmega168a that I had been using to learn about avr microcontrollers. I only tested it with 6 outputs that turned on and off 3 of the relays that we plan to use. The test was successful and we had no problems flipping the relays.

 

The relays are the TQ2-L2-3V https://www.mouser.com/productde...

 

Although there are 14 total relays, only 1 or 2 will ever be on at any one time. 

 

There was a previous group that used a similar setup (sbrio to power the relays) but they used many logic gates (and, ors, xors) to achieve what we are trying to do with just a single microcontroller with the logic built in. 

 

I want to be able to use the pin read to read the value as a high when the sbrio sends a voltage to a pin that we designate from the labview environment.

 

Currently I am just breadboarding to find a complete solution before moving to a pcb that I will design.

 

I have the atmega32aL which can operate at a lower voltage. If I supply Vcc at 3.5 volts to the atmega32aL then does this hold true :    3.5*.6 = 2.1 V now being the lower limit? Its operating voltage range listed is 2.7 - 5.5 volts

 

attached is a roughly drawn example of what is trying to get accomplished. 

 

Thanks for the welcome! I find this technology fun and interesting and I am glad a place like this exists!

 

Thankyou for your input! it is greatly appreciated!

Attachment(s): 

-AVRnoob86

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

I have a video of the atmega168 doing what we are trying to do with the atmega32a. we used the atemega168 to test the concept because I had it laying around.

 

If you would like to see it, e-mail me at dgannon2@uco.edu

 

They won't let me attach it here.

-AVRnoob86

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

From the photo:

When you close your switches the connected pin is pulled to 5V.

But when you open the switch again the pin is "floating" and the voltage is unknown.

You can chech the voltage with a multimeter, but the impedance of the multimeter is probably goin to pull the voltage on you pin low (and make the circuit work).

Normaly this is solved by enabling the internal pullup resistors and using the switch to pull the voltage to GND.

As an easy to understand alternative you can put resistors between GND and you port pins with the input switches.

 

Also: This code conflicts with the comment:

	_delay_us(1000);					// delay 0.1 second

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Thanks for the reply, I guess I should have mentioned this. The switches to d3-d7 will not actually be there. While just working with the microcontroller today I am using the switches because I do not have the sbrio with me. But it sounds like the best way to read a pin is the way you and the person before you suggested...... maybe i need to rethink this a bit.

-AVRnoob86

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

AVRnoob86 wrote:
The switches to d3-d7 will not actually be there.
So why show us a schematic if it is not what you use?

AVRnoob86 wrote:
maybe i need to rethink this a bit.
  I Agree.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Your schematic show +5V on AREF. You need to provide power to AVCC and have bypass caps on the power pins...

You also have a typo:

E = 8;			// If HIGH, E = 16

As you suggest in your drawing, having the switch pull the input to GND and use the internal pullup resistors on the pins (PORTA = 0xF8;  // Turn on pullups to PINS PA3-PA7)

 

Then I would probably do:

uint8_t switch_input = (~(PINA >> 3) & 0x1F);   // Read PINA, shift PA3-PA7 to bits 0-4 of switch_input and invert for active low switches 

which eliminates the need to add the individual bits and converts the input to compensate for the active low pins.

 

David (aka frog_jr)

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

Others beat me to it, but for emphasis:

 

Yes, switch your switch configuration, to the pin being pulled high by either the internal pull up resistor, or an external one, (10K, or whatever).

 

As mentioned, DON'T connect ARef to Vcc.

 

As mentioned, DO connect AVcc to Vcc.

 

As mentioned, Vcc and AVcc both need a by-pass cap to ground, (0.1 uF), for reliable operation.

 

You did not include any Diodes in your relay driver.

Read what I wrote above before you fry your micro.

 

Finally, although I understand that you EXPECT to only have 1 or 2 relays on at a time, I think it is very poor form to design a circuit which CAN permanently damage itself.

Read what I wrote above about current limits for driving external devices.

 

Adding an NFet and a 10K pull DOWN resistor on its gate, for each relay, is a trivial cost and a trivial design change, and makes your hardware safe from self destruction.

 

When you are a beginner with micros, the main goal is to get the project up and running.

 

Once you have developed a little more experience  with micros, you will learn to add failure mode analysis to your design methodology.

 

JC

 

 

The small maroon cap on the left side of the micro, and the small yellow cap on the right side of the micro, placed as close to the micro's pins as possible, are the by-pass caps.

 

JC

 

Last Edited: Sat. Jan 27, 2018 - 10:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thankyou for all the advice.

 

Currently I have it working up to the 19th logic step flipping the relays like expected. I have been playing with both pull up and down resistors and currently have the inputs to PD3-7 utilizing pull down resistors to keep the logic state at 0 untill the voltage is applied. Seem to be working quite well...... Not sure what is causing the logic above 19 to not work but I plan to hash it out and then moved to a full breadboard of the entire circuit this week!

 

I added in the capacitors across VCC to GND and AVCC to GND. I don't have any more with me or I would add them to the input ports for de-bouncing when the voltage is no longer applied.

 

The addition of the transistors and diodes are a great idea. I really wasn't thinking about making sure the MCU doesn't get overloaded. We are given a project and a short amount of time to get it done in! surprise But now that I have it in mind your suggestion is an easy add on!

 

My earlier schematic had a few errors in in. Drew it up too quickly. I never had the AREF attacahed to a voltage and I do have AVCC connected to VCC. I learned early on that portA wont come on without AVCC!

 

Thanks again!

-AVRnoob86

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

Thanks! I fixed that and all of a sudden more ports began working! haha!

-AVRnoob86

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

My C is ... a bit rusty and I was bored so I started a bit of typing.

I noticed that you have a lot of repetition in your code.

Repetion is bad for humans, good for automation.

Because I did not want to give you untested code I decided to test it :)

This is the final version of my code:

// Test project from: https://www.avrfreaks.net/forum/atmega32a-atmega32al-outputs-not-working
// 2018-01-28

#define DEBUG 1				// 0 = AVR, 1 = Debug on PC.

#if DEBUG
#include <stdio.h>
int DDRA, DDRB, DDRC, DDRD;
int PINA, PINB, PINC, PIND;
int PORTA, PORTB, PORTC, PORTD;

#else
#include <avr/io.h>
#include <util/delay.h>

#endif

int main(void)
{
	DDRA = 0b00000111;
	DDRC = 0b11111111;
	DDRD = 0b11111111;
	DDRB = 0b11111111;
	int quickmath, tmp;

#if DEBUG
	// Step through all values in the debug mode
	printf( "   m     D    B    C    A\n");	// Print legenda.
	for( quickmath = 0; quickmath < 35; ++quickmath) {
	printf( "%4x  %4x %4x %4x %4x\n", quickmath, PORTD, PORTB, PORTC, PORTA);

#else
	// Normal program for the AVR.
	while (1) {
		quickmath = PIND >> 4;
		_delay_us(1000);	// delay 0.1 second
#endif
		PORTA = 0;	// Set all outputs to 0.
		PORTB = 0;	// This intoduces glitches on the outputs !!!
		PORTC = 0;
		PORTD = 0;
		tmp = quickmath ;

		if( tmp < 8){
			PORTD =  1 << tmp;
		}
		else if( tmp < 16){
			tmp -= 8;
			PORTB = 1 << tmp;
		}
		else if( tmp < 24){
			tmp -= 16;
			PORTC = 1 << tmp;
		}
		else if( tmp < 32){
			tmp -= 24;
			// Which port does what ???
			PORTA = 1 << tmp;
		}
	}
}

On the 4th line of the code I put a #define DEBUG statement.

If you define it as 0 then your code should run on an AVR.

If you define it as 1 then you can compile the code on a pc with any decent C compiler.

It will then also output debug statements to a terminal window ( "command line console")

I saved the code in a file with the name asdf.c and compiled it with:

gcc asdf.c -o asdf.o

And then I executed it with:

./asdf.o

Note that this is on a linux box. On windows you might have to do a slight change.

This is the test output:

   m     D    B    C    A
   0     0    0    0    0
   1     1    0    0    0
   2     2    0    0    0
   3     4    0    0    0
   4     8    0    0    0
   5    10    0    0    0
   6    20    0    0    0
   7    40    0    0    0
   8    80    0    0    0
   9     0    1    0    0
   a     0    2    0    0
   b     0    4    0    0
   c     0    8    0    0
   d     0   10    0    0
   e     0   20    0    0
   f     0   40    0    0
  10     0   80    0    0
  11     0    0    1    0
  12     0    0    2    0
  13     0    0    4    0
  14     0    0    8    0
  15     0    0   10    0
  16     0    0   20    0
  17     0    0   40    0
  18     0    0   80    0
  19     0    0    0    1
  1a     0    0    0    2
  1b     0    0    0    4
  1c     0    0    0    8
  1d     0    0    0   10
  1e     0    0    0   20
  1f     0    0    0   40
  20     0    0    0   80
  21     0    0    0    0
  22     0    0    0    0

With this technique you can test a lot of your code fast on a PC without having to re progam an AVR.

It can also help in deciding wether an error is in your algorithm, or in the way you use the AVR hardware.

 

Have fun.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

Last Edited: Sun. Jan 28, 2018 - 04:03 PM